Page MenuHomec4science

database.pyx
No OneTemporary

File Metadata

Created
Thu, May 9, 16:41

database.pyx

from libcpp.map cimport map as cmap
from libcpp.pair cimport pair
from memory cimport shared_ptr
from database cimport Database, DataContainer
# Used to indicate that something does not exist
cdef enum:
no_equation = -1
cdef class DatabaseManager:
""" The Python database handler
Use this class for checking values in the database
or switching basis/dropping minerals or components...
"""
cdef Database *database
cdef shared_ptr[DataContainer] container
def __cinit__(self, bytes filepath):
"""filepath is the path to the database file"""
self.database = new Database(filepath)
self.container = self.database.get_database()
cdef shared_ptr[DataContainer] get_raw_db(self):
return self.container
cdef DataContainer* _get(self):
return self.container.get()
def is_canonical(self):
"""Return true if the databse is canonical.
Should be true if the database has been correctly initialized.
"""
return self.database.is_database_canonical()
# --------- #
# Component #
# --------- #
property nb_component:
"""The number of component in the database."""
def __get__(self): return self._get().nb_component
# labels and id
# --------------
def component_label_to_id(self, bytes comp):
""" Return the id of a component."""
cdef int ans = self.database.component_label_to_id(comp)
if (ans == no_equation):
raise ValueError("Species : '"+comp.decode()+"' is not a component.")
return ans
def component_id_to_label(self, int idc):
""" Return the label of a component."""
if (idc >= self.nb_component):
raise ValueError("'"+str(idc)+
"' is not a valid index for a component")
return bytes(self._get().labels_basis[idc])
def print_basis(self):
"""Print the components in the basis, with their ID"""
print("The basis is :")
cdef int i
for i in range(self._get().nb_component):
print(" - "+str(i)+" : "+bytes(self._get().labels_basis[i]).decode())
# basis switch
# ------------
def swap_components(self, dict swapping):
"""Swap components in the basis
swapping is a dictionnary where the keys are the labels of the
components to replace and the values are the labels of the secondary
species to add in the basis.
Raise value errors if the labels are invalid
"""
cdef cmap[string,string] input_map
cdef int idsp
for (key, value) in swapping.items():
idsp = self.component_label_to_id(key)
if (idsp == no_equation):
raise ValueError("'"+key.decode()+"' is not a valid component.")
idsp = self.aqueous_label_to_id(value)
if (idsp == no_equation):
raise ValueError("'"+key.decode()+
"' is not a valid secondary aqueous species.")
input_map.insert(pair[string, string](key, value))
self.database.swap_components(input_map)
# --------------- #
# Aqueous species #
# --------------- #
property nb_aqueous:
"""The number of aqueous species in the database"""
def __get__(self): return self._get().nb_aqueous
# labels and id
# -------------
def aqueous_id_to_label(self, int ids):
if (ids >= self.nb_aqueous):
raise ValueError("'"+str(ids)+
"' is not a valid index for a secondary aqueous species")
return bytes(self._get().labels_aqueous[ids])
def aqueous_label_to_id(self, bytes aqueous):
""" Return the id of a secondary aqueous species"""
cdef int ans = self.database.aqueous_label_to_id(aqueous)
if (ans == no_equation):
raise ValueError("Species : '"+aqueous.decode()+
"' is not a secondary aqueous species.")
return ans
def print_aqueous(self):
""" Print the secondary species"""
print("The secondary aqueous species are :")
cdef int i
for i in range(self._get().nb_aqueous):
print(" - "+str(i)+" : "+bytes(self._get().labels_aqueous[i]).decode())
# properties
# ----------
def nu_aqueous(self, int ids, int idc):
"""Return stoichiometric coefficient of a secondary aqueous species"""
if (ids >= self._get().nb_aqueous or idc >= self._get().nb_component):
raise ValueError("uncorrect bounds")
return self._get().nu_aqueous(ids, idc)
def l_nu_aqueous(self, bytes aqueous, bytes component):
"""Return stoichiometric coefficient of a secondary aqueous species"""
return self._get().nu_aqueous(self.aqueous_label_to_id(aqueous),
self.component_label_to_id(component))
def logk_aqueous(self, int ids):
"""Return the equilibrium constant of a secondary aqueous species"""
if (ids >= self._get().nb_aqueous):
raise ValueError("Index : '"+str(ids)
+"' is not valid for an aqueous species")
return self._get().logk_aqueous(ids)
def l_logk_aqueous(self, bytes aqueous):
"""Return the equilibrium constant of a secondary aqueous species"""
return self._get().logk_aqueous(self.aqueous_label_to_id(aqueous))
# ------------ #
# Solid phases #
# ------------ #
property nb_mineral:
"""The number of mineral in the database"""
def __get__(self): return self._get().nb_mineral
# labels and id
# -------------
def mineral_id_to_label(self, int idm):
"""Return the label of a mineral."""
if (idm >= self.nb_mineral):
raise ValueError("'"+str(idm)+
"' is not a valid index for a solid phase")
return bytes(self._get().labels_minerals[idm])
def mineral_label_to_id(self, bytes mineral):
""" Return the id of a secondary aqueous species"""
ans = self.database.mineral_label_to_id(mineral)
if (ans == no_equation):
raise ValueError("Species : '"+mineral.decode()+
"' is not a solid phase at equilibrium in the database.")
return ans
def print_minerals(self):
""" Print the solid phases at equilibrium"""
print("The solid phases at equilibrium are :")
cdef int i
for i in range(self._get().nb_mineral):
print(" - "+str(i)+" : "+bytes(self._get().labels_minerals[i]).decode())
def minerals_keep_only(self, list_mineral_to_keep):
"""Keep only the solid phases in 'list_mineral_to_keep'"""
# we first verify that the list is valid
for label in list_mineral_to_keep:
self.mineral_label_to_id(label) # just check that it is not raising any error
self.database.minerals_keep_only(list_mineral_to_keep)
# properties
# ----------
def logk_mineral(self, int idm):
"""Return the equilibrium constant of a solid phase"""
if (idm >= self._get().nb_mineral):
raise ValueError("Index : '"+str(idm)
+"'is not valid for a solid phase")
return self._get().logk_mineral(idm)
def l_logk_mineral(self, bytes mineral):
"""Return the equilibrium constant of a solid phase"""
return self._get().logk_mineral(self.mineral_label_to_id(mineral))
def nu_mineral(self, int idm, int idc):
"""Return stoichometric coefficient of a mineral"""
if (idm >= self._get().nb_mineral or idc >= self._get().nb_component):
raise ValueError("uncorrect argument, exceed bounds")
return self._get().nu_mineral(idm, idc)
def l_nu_mineral(self, bytes mineral, bytes component):
"""Return stoichometric coefficient of a mineral"""
return self._get().nu_mineral(self.mineral_label_to_id(mineral),
self.component_label_to_id(component))

Event Timeline