In [8]:
import operator
import os
import re
import sys
from numpy.linalg import solve, lstsq
import numpy as np
from sqlalchemy import orm, Column, Integer, String, Float, create_engine, ForeignKey
from sqlalchemy.orm import sessionmaker, relationship, backref
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.ext.associationproxy import association_proxy
from sqlalchemy.ext.hybrid import hybrid_property, hybrid_method
_minwidth = 15
Base = declarative_base()
class BaseChemical(object):
def formula_to_tex(self):
'''
Convert the formula string to tex string.
'''
return re.sub(ur'(\d+)', ur'$_{\1}$', self.formula)
def formula_to_html(self):
'''
Convert the formula string to html string.
'''
return re.sub(ur'(\d+)', ur'<sub>\1</sub>', self.formula)
def listctrl_label(self):
'''
Return the string to be displayed in the ListCtrl's.
'''
if self.is_undefined(self.short_name):
res = self.name
else:
res = self.short_name
return res
def label(self):
'''
Return a label to be used in printable tables (tex, html).
'''
if self.is_undefined(self.short_name):
res = self.formula_to_tex() + u" ({0:>4.1f}\%)".format(100*self.concentration)
else:
res = self.short_name + u" ({0:>4.1f}\%)".format(100*self.concentration)
return res
@staticmethod
def is_undefined(item):
if item is None or item.lower() in ["", "null", "none"]:
return True
else:
return False
class Category(Base):
__tablename__ = 'categories'
id = Column(Integer, primary_key=True)
name = Column(String, nullable=False)
full_name = Column(String)
def __repr__(self):
return "<Category(id={i}, name={n}, full_name={f})>".format(i=self.id,
n=self.name, f=self.full_name)
class Electrolyte(Base):
__tablename__ = 'electrolytes'
id = Column(Integer, primary_key=True)
name = Column(String, nullable=False)
def __repr__(self):
return "<Electrolyte(id={i}, form={n})>".format(i=self.id, n=self.name)
class PhysicalForm(Base):
__tablename__ = 'physical_forms'
id = Column(Integer, primary_key=True)
form = Column(String, nullable=False)
def __repr__(self):
return "<PhysicalForm(id={i}, form={n})>".format(i=self.id, n=self.form)
class Kind(Base):
__tablename__ = 'kinds'
id = Column(Integer, primary_key=True)
name = Column(String, nullable=False)
def __repr__(self):
return "<Kind(id={i}, name={n})>".format(i=self.id, n=self.name)
class Reaction(Base):
__tablename__ = 'reactions'
id = Column(Integer, primary_key=True)
reaction = Column(String, nullable=False)
def __repr__(self):
return "<Reaction(id={i}, reaction={n})>".format(i=self.id, n=self.reaction)
class Batch(Base):
__tablename__ = 'batch'
id = Column(Integer, primary_key=True)
chemical_id = Column(Integer, ForeignKey('chemicals.id'), nullable=False)
component_id = Column(Integer, ForeignKey('components.id'), nullable=False)
reaction_id = Column(Integer, ForeignKey('reactions.id'), nullable=True)
coefficient = Column(Float, nullable=True)
chemical = relationship("Chemical")
component = relationship("Component")
reaction= relationship("Reaction")
def __repr__(self):
return "<Batch(id={i:>2d}, chemical='{n:s}', component='{z:s}', coefficient={c:8.2f})>".format(
i=self.id, n=self.chemical.name, z=self.component.name, c=self.coefficient)
class Component(BaseChemical, Base):
'''
Class representing the Component object. The component can belong to one of
the 3 categories:
* Zeolite component
* Template
* Zeolite Growth Modifier
'''
__tablename__ = 'components'
id = Column(Integer, primary_key=True)
name = Column(String, nullable=False)
formula = Column(String, nullable=False)
molwt = Column(Float, nullable=False)
short_name = Column(String)
_category_id = Column("category_id", Integer, ForeignKey('categories.id'))
_category = relationship("Category")
category = association_proxy("_category", "name")
@orm.reconstructor
def init_on_load(self):
self.moles = 0.0
@hybrid_property
def mass(self):
return self.moles*self.molwt
def __repr__(self):
return "<Component(id={i:>2d}, name='{n:s}', formula='{f:s}')>".format(
i=self.id, n=self.name, f=self.formula)
class Chemical(BaseChemical, Base):
'''
Class representing the Chemical object, (off the shelf reactants).
'''
__tablename__ = 'chemicals'
id = Column(Integer, primary_key=True)
name = Column(String, nullable=False)
formula = Column(String, nullable=False)
molwt = Column(Float, nullable=False)
short_name = Column(String)
concentration = Column(Float)
cas = Column(String)
density = Column(Float)
pk = Column(Float)
smiles = Column(String)
_kind_id = Column("kind_id", Integer, ForeignKey('kinds.id'))
_kind = relationship("Kind")
kind = association_proxy("_kind", "name")
_electrolyte_id = Column("electrolyte_id", Integer, ForeignKey('electrolytes.id'))
_electrolyte = relationship("Electrolyte")
electrolyte = association_proxy("_electrolyte", "name")
_physical_form_id = Column("physical_form_id", Integer, ForeignKey('physical_forms.id'))
_physical_form = relationship("PhysicalForm")
physical_form = association_proxy("_physical_form", "form")
@orm.reconstructor
def init_on_load(self):
self.mass = 0.0
@hybrid_property
def moles(self):
return self.mass/self.molwt
@hybrid_property
def volume(self):
return self.mass/self.density
def __repr__(self):
return "<Chemical(id={i:>2d}, name='{n:s}', formula='{f:s}')>".format(
i=self.id, n=self.name, f=self.formula)
In [2]:
engine = create_engine("sqlite:///{path:s}".format(path="zeolite.db"))
DBSession = sessionmaker(bind=engine)
dbsession = DBSession()
In [9]:
naoh = dbsession.query(Batch).filter(Batch.chemical_id == 1).all()
naoh
Out[9]:
In [10]:
comps = dbsession.query(Component).filter(Component.id <= 5).all()
comps
Out[10]:
In [18]:
compset = set()
for comp in comps:
temp = dbsession.query(Chemical).join(Batch).\
filter(Batch.component_id == comp.id).all()
compset.update(temp)
query = sorted(list(compset), key=lambda x: x.id)
In [19]:
query
Out[19]:
In [7]:
comps = self.session.query(BComponent).\
filter(Batch.chemical_id == chemical.id).\
filter(Component.id == Batch.component_id).all()
Out[7]:
In [8]:
b = dbsession.query(Batch).first()
In [9]:
b.component.name
Out[9]:
In [10]:
petp = Chemical(name="pentaerythritol", formula="C5H12O4", molwt=136.15, short_name="PETP", concentration=0.98, cas="115-77-5",
density=1.399, pk=14.1)
In [11]:
petp._kind = dbsession.query(Kind).get(3)
In [12]:
petp._kind
Out[12]:
In [13]:
petp._physical_form = dbsession.query(PhysicalForm).get(1)
In [14]:
petp._physical_form
Out[14]:
In [58]:
petp = dbsession.query(Chemical).get(21)
dbsession.delete(petp)
dbsession.query(Chemical).all()
Out[58]:
In [16]:
dbsession.commit()
In [59]:
dbsession.query(Chemical).all()
Out[59]:
In [64]:
petp_dict = {"name":"pentaerythritol", "formula":"C5H12O4", "molwt":136.15, "short_name":"PETP", "concentration":0.98, "cas":"115-77-5",
"density":1.399, "pk":14.1, "_kind_id" :1}
pery = Chemical(**petp_dict)
In [33]:
pery.cas
Out[33]:
In [61]:
def add_chemical_record(session, data):
"""
Add a Chemical record to the database, the data should be in the form of a dictionary:
data = {'name' : 'water', 'formula' : 'H2O', 'molwt' : 18.0152,
'kind_id' : 3, 'concentration' : 1.0, 'cas' : '7732-18-5',
'physical_form_id' : 3, 'density' : 0.997}
"""
chemical = Chemical(**data)
if data.get("_kind_id", None) is not None:
chemical._kind = session.query(Kind).get(data["_kind_id"])
if data.get("_physical_form_id") is not None:
chemical._physical_form = session.query(PhysicalForm).get(data["_physical_form_id"])
if data.get("_electrolyte_id") is not None:
chemical._electrolyte = session.query(Electrolyte).get(data["_electrolyte_id"])
session.add(chemical)
session.commit()
In [66]:
dbsession.rollback()
add_chemical_record(dbsession, petp_dict)
In [67]:
dbsession.query(Chemical).all()
Out[67]:
In [69]:
a = dbsession.query(Chemical).get(22)
In [70]:
a.kind
Out[70]:
In [20]:
import wx
wx.CheckBox.