22# Functionality exposed as an API
33# Author: Evgeny Blokhin
44
5- __version__ = "0.9.1 "
5+ __version__ = "0.9.3 "
66
77import os , sys
88import re
3434class API :
3535 version = __version__
3636 __shared_state = {}
37- formula_sequence = ['Fr' ,'Cs' ,'Rb' ,'K' ,'Na' ,'Li' , 'Be' ,'Mg' ,'Ca' ,'Sr' ,'Ba' ,'Ra' , 'Sc' ,'Y' ,'La' ,'Ce' ,'Pr' ,'Nd' ,'Pm' ,'Sm' ,'Eu' ,'Gd' ,'Tb' ,'Dy' ,'Ho' ,'Er' ,'Tm' ,'Yb' , 'Ac' ,'Th' ,'Pa' ,'U' ,'Np' ,'Pu' , 'Ti' ,'Zr' ,'Hf' , 'V' ,'Nb' ,'Ta' , 'Cr' ,'Mo' ,'W' , 'Fe' ,'Ru' ,'Os' , 'Co' ,'Rh' ,'Ir' , 'Mn' ,'Tc' ,'Re' , 'Ni' ,'Pd' ,'Pt' , 'Cu' ,'Ag' ,'Au' , 'Zn' ,'Cd' ,'Hg' , 'B' ,'Al' ,'Ga' ,'In' ,'Tl' , 'Pb' ,'Sn' ,'Ge' ,'Si' ,'C' , 'N' ,'P' ,'As' ,'Sb' ,'Bi' , 'H' , 'Po' ,'Te' ,'Se' ,'S' ,'O' , 'At' ,'I' ,'Br' ,'Cl' ,'F' , 'He' ,'Ne' ,'Ar' ,'Kr' ,'Xe' ,'Rn' ]
37+ formula_sequence = [
38+ 'Fr' ,'Cs' ,'Rb' ,'K' ,'Na' ,'Li' ,
39+ 'Be' ,'Mg' ,'Ca' ,'Sr' ,'Ba' ,'Ra' ,
40+ 'Sc' ,'Y' ,'La' ,'Ce' ,'Pr' ,'Nd' ,'Pm' ,'Sm' ,'Eu' ,'Gd' ,'Tb' ,'Dy' ,'Ho' ,'Er' ,'Tm' ,'Yb' ,
41+ 'Ac' ,'Th' ,'Pa' ,'U' ,'Np' ,'Pu' ,
42+ 'Ti' ,'Zr' ,'Hf' ,
43+ 'V' ,'Nb' ,'Ta' ,
44+ 'Cr' ,'Mo' ,'W' ,
45+ 'Fe' ,'Ru' ,'Os' ,
46+ 'Co' ,'Rh' ,'Ir' ,
47+ 'Mn' ,'Tc' ,'Re' ,
48+ 'Ni' ,'Pd' ,'Pt' ,
49+ 'Cu' ,'Ag' ,'Au' ,
50+ 'Zn' ,'Cd' ,'Hg' ,
51+ 'B' ,'Al' ,'Ga' ,'In' ,'Tl' ,
52+ 'Pb' ,'Sn' ,'Ge' ,'Si' ,'C' ,
53+ 'N' ,'P' ,'As' ,'Sb' ,'Bi' ,
54+ 'H' ,
55+ 'Po' ,'Te' ,'Se' ,'S' ,'O' ,
56+ 'At' ,'I' ,'Br' ,'Cl' ,'F' ,
57+ 'He' ,'Ne' ,'Ar' ,'Kr' ,'Xe' ,'Rn'
58+ ]
3859
3960 def __init__ (self , settings = settings ):
4061 self .settings = settings
@@ -58,14 +79,14 @@ def __init__(self, settings=settings):
5879 if not os .path .isfile ( os .path .realpath (BASE_DIR + '/../parsers' ) + '/' + parsername + '/' + parsername + '.py' ):
5980 raise RuntimeError ('Parser API Error: Parser code for ' + parsername + ' is missing!' )
6081 try :
61- parsermanifest = json .loads ( open ( os .path .realpath (BASE_DIR + '/../parsers' ) + '/' + parsername + '/manifest.json' ).read () )
82+ parsermanifest = json .loads (open ( os .path .realpath (BASE_DIR + '/../parsers' ) + '/' + parsername + '/manifest.json' ).read ())
6283 except :
6384 raise RuntimeError ('Parser API Error: Parser manifest for ' + parsername + ' has corrupted format!' )
6485
6586 if (not 'enabled' in parsermanifest or not parsermanifest ['enabled' ]) and not self .settings ['debug_regime' ]:
6687 continue
6788
68- All_parsers [parsername ] = importlib .import_module ('tilde.parsers.' + parsername + '.' + parsername ) # all imported modules will be stored here
89+ All_parsers [parsername ] = importlib .import_module ('tilde.parsers.' + parsername + '.' + parsername ) # all imported modules will be here
6990
7091 # replace modules by classes and check *fingerprints* method
7192 for parser , module in All_parsers .items ():
@@ -101,7 +122,7 @@ def __init__(self, settings=settings):
101122 raise RuntimeError ('Module API Error: no appdata tag for ' + appname + '!' )
102123 if 'onprocess' in appmanifest :
103124 try :
104- app = __import__ ('tilde.apps.' + appname + '.' + appname , fromlist = [appname .capitalize ()]) # this means: from foo import Foo
125+ app = __import__ ('tilde.apps.' + appname + '.' + appname , fromlist = [appname .capitalize ()]) # from foo import Foo
105126 except ImportError :
106127 raise RuntimeError ('Module API Error: module ' + appname + ' is invalid or not found!' )
107128 self .Apps [appname ] = {
@@ -285,7 +306,7 @@ def _parse(self, parsable, parser_name):
285306 error = "routine %s parser error in %s: %s" % ( parser_name , parsable , e )
286307 except :
287308 exc_type , exc_value , exc_tb = sys .exc_info ()
288- error = "unexpected %s parser error in %s:\n %s" % ( parser_name , parsable , "" .join (traceback .format_exception ( exc_type , exc_value , exc_tb )) )
309+ error = "unexpected %s parser error in %s:\n %s" % (parser_name , parsable , "" .join (traceback .format_exception ( exc_type , exc_value , exc_tb )))
289310 yield None , error
290311
291312 def parse (self , parsable ):
@@ -549,7 +570,7 @@ def postprocess(self, calc, with_module=None, dry_run=None):
549570 AppInstance = appclass ['appmodule' ](calc )
550571 except :
551572 exc_type , exc_value , exc_tb = sys .exc_info ()
552- errmsg = "Fatal error in %s module:\n %s" % ( appname , " " .join (traceback .format_exception ( exc_type , exc_value , exc_tb )) )
573+ errmsg = "Fatal error in %s module:\n %s" % (appname , " " .join (traceback .format_exception ( exc_type , exc_value , exc_tb )))
553574 calc .apps [appname ]['error' ] = errmsg
554575 calc .warning ( errmsg )
555576 else :
@@ -601,9 +622,15 @@ def save(self, calc, session):
601622 # re-orientate eigenvectors
602623 for i in range (0 , len (calc .phonons ['ph_eigvecs' ][bzpoint ])):
603624 for j in range (0 , len (calc .phonons ['ph_eigvecs' ][bzpoint ][i ])// 3 ):
604- eigv = array ([calc .phonons ['ph_eigvecs' ][bzpoint ][i ][j * 3 ], calc .phonons ['ph_eigvecs' ][bzpoint ][i ][j * 3 + 1 ], calc .phonons ['ph_eigvecs' ][bzpoint ][i ][j * 3 + 2 ]])
625+ eigv = array ([
626+ calc .phonons ['ph_eigvecs' ][bzpoint ][i ][j * 3 ],
627+ calc .phonons ['ph_eigvecs' ][bzpoint ][i ][j * 3 + 1 ],
628+ calc .phonons ['ph_eigvecs' ][bzpoint ][i ][j * 3 + 2 ]
629+ ])
605630 R = dot ( eigv , calc .structures [- 1 ].cell ).tolist ()
606- calc .phonons ['ph_eigvecs' ][bzpoint ][i ][j * 3 ], calc .phonons ['ph_eigvecs' ][bzpoint ][i ][j * 3 + 1 ], calc .phonons ['ph_eigvecs' ][bzpoint ][i ][j * 3 + 2 ] = [round (x , 3 ) for x in R ]
631+ calc .phonons ['ph_eigvecs' ][bzpoint ][i ][j * 3 ], \
632+ calc .phonons ['ph_eigvecs' ][bzpoint ][i ][j * 3 + 1 ], \
633+ calc .phonons ['ph_eigvecs' ][bzpoint ][i ][j * 3 + 2 ] = [round (x , 3 ) for x in R ]
607634
608635 try : irreps = calc .phonons ['irreps' ][bzpoint ]
609636 except KeyError :
@@ -612,7 +639,7 @@ def save(self, calc, session):
612639 empty .append ('' )
613640 irreps = empty
614641
615- phonons_json .append ({ 'bzpoint' :bzpoint , 'freqs' :frqset , 'irreps' :irreps , 'ph_eigvecs' :calc .phonons ['ph_eigvecs' ][bzpoint ] })
642+ phonons_json .append ({'bzpoint' :bzpoint , 'freqs' :frqset , 'irreps' :irreps , 'ph_eigvecs' :calc .phonons ['ph_eigvecs' ][bzpoint ]})
616643 if bzpoint == '0 0 0' :
617644 phonons_json [- 1 ]['ir_active' ] = calc .phonons ['ir_active' ]
618645 phonons_json [- 1 ]['raman_active' ] = calc .phonons ['raman_active' ]
@@ -641,8 +668,15 @@ def save(self, calc, session):
641668
642669 # construct ORM for other props
643670 calc .related_files = list (map (virtualize_path , calc .related_files ))
644- ormcalc .meta_data = model .Metadata (location = calc .info ['location' ], finished = calc .info ['finished' ], raw_input = calc .info ['input' ], modeling_time = calc .info ['duration' ], chemical_formula = html_formula (calc .info ['standard' ]), download_size = calc .download_size , filenames = json .dumps (calc .related_files ))
645-
671+ ormcalc .meta_data = model .Metadata (
672+ location = calc .info ['location' ],
673+ finished = calc .info ['finished' ],
674+ raw_input = calc .info ['input' ],
675+ modeling_time = calc .info ['duration' ],
676+ chemical_formula = html_formula (calc .info ['standard' ]),
677+ download_size = calc .download_size ,
678+ filenames = json .dumps (calc .related_files )
679+ )
646680 codefamily = model .Codefamily .as_unique (session , content = calc .info ['framework' ])
647681 codeversion = model .Codeversion .as_unique (session , content = calc .info ['prog' ])
648682
@@ -651,17 +685,30 @@ def save(self, calc, session):
651685
652686 pot = model .Pottype .as_unique (session , name = calc .info ['H' ])
653687 pot .instances .append (ormcalc )
654- ormcalc .recipinteg = model .Recipinteg (kgrid = calc .info ['k' ], kshift = calc .info ['kshift' ], smearing = calc .info ['smear' ], smeartype = calc .info ['smeartype' ])
688+ ormcalc .recipinteg = model .Recipinteg (
689+ kgrid = calc .info ['k' ],
690+ kshift = calc .info ['kshift' ],
691+ smearing = calc .info ['smear' ],
692+ smeartype = calc .info ['smeartype' ]
693+ )
655694 ormcalc .basis = model .Basis (
656695 kind = calc .info ['ansatz' ],
657- content = _json .dumps (calc .electrons ['basis_set' ]) if calc .electrons ['basis_set' ] else None # NB. ujson fails on NaN
696+ content = _json .dumps (calc .electrons ['basis_set' ]) if calc .electrons ['basis_set' ] else None # NB. ujson fails here on NaN
658697 )
659698 ormcalc .energy = model .Energy (convergence = json .dumps (calc .convergence ), total = calc .info ['energy' ])
660699
661700 ormcalc .spacegroup = model .Spacegroup (n = calc .info ['ng' ])
662- ormcalc .struct_ratios = model .Struct_ratios (chemical_formula = calc .info ['standard' ], formula_units = calc .info ['expanded' ], nelem = calc .info ['nelem' ], dimensions = calc .info ['dims' ])
701+ ormcalc .struct_ratios = model .Struct_ratios (
702+ chemical_formula = calc .info ['standard' ],
703+ formula_units = calc .info ['expanded' ],
704+ nelem = calc .info ['nelem' ],
705+ dimensions = calc .info ['dims' ]
706+ )
663707 if len (calc .tresholds ) > 1 :
664- ormcalc .struct_optimisation = model .Struct_optimisation (tresholds = json .dumps (calc .tresholds ), ncycles = json .dumps (calc .ncycles ))
708+ ormcalc .struct_optimisation = model .Struct_optimisation (
709+ tresholds = _json .dumps (calc .tresholds ), # NB. ujson fails here on NaN
710+ ncycles = json .dumps (calc .ncycles )
711+ )
665712
666713 for n , ase_repr in enumerate (calc .structures ):
667714 is_final = True if n == len (calc .structures )- 1 else False
@@ -678,7 +725,7 @@ def save(self, calc, session):
678725 charges = ase_repr .get_array ('charges' ) if 'charges' in ase_repr .arrays else [None for j in range (len (ase_repr ))]
679726 magmoms = ase_repr .get_array ('magmoms' ) if 'magmoms' in ase_repr .arrays else [None for j in range (len (ase_repr ))]
680727 for n , i in enumerate (ase_repr ):
681- struct .atoms .append ( model .Atom ( number = chemical_symbols .index (i .symbol ), x = i .x , y = i .y , z = i .z , charge = charges [n ], magmom = magmoms [n ] ) )
728+ struct .atoms .append (model .Atom (number = chemical_symbols .index (i .symbol ), x = i .x , y = i .y , z = i .z , charge = charges [n ], magmom = magmoms [n ]) )
682729
683730 ormcalc .structures .append (struct )
684731 # TODO Forces
@@ -773,7 +820,10 @@ def purge(self, session, checksum):
773820
774821 # for all types of entries
775822 if len (C .references ):
776- left_references = [ int (i [0 ]) for i in session .query (model .Reference .reference_id ).join (model .metadata_references , model .Reference .reference_id == model .metadata_references .c .reference_id ).filter (model .metadata_references .c .checksum == checksum ).all () ]
823+ left_references = [ int (i [0 ]) for i in session .query (model .Reference .reference_id ).join (
824+ model .metadata_references ,
825+ model .Reference .reference_id == model .metadata_references .c .reference_id
826+ ).filter (model .metadata_references .c .checksum == checksum ).all () ]
777827 session .execute ( model .delete ( model .metadata_references ).where ( model .metadata_references .c .checksum == checksum ) )
778828
779829 # remove the whole citation?
@@ -804,8 +854,15 @@ def merge(self, session, checksums, title):
804854
805855 cur_depth = 0
806856
807- for nested_depth , grid_item , download_size in session .query (model .Calculation .nested_depth , model .Grid .info , model .Metadata .download_size ).filter (model .Calculation .checksum == model .Grid .checksum , model .Grid .checksum == model .Metadata .checksum , model .Calculation .checksum .in_ (checksums )).all ():
808-
857+ for nested_depth , grid_item , download_size in session .query (
858+ model .Calculation .nested_depth ,
859+ model .Grid .info ,
860+ model .Metadata .download_size
861+ ).filter (
862+ model .Calculation .checksum == model .Grid .checksum ,
863+ model .Grid .checksum == model .Metadata .checksum ,
864+ model .Calculation .checksum .in_ (checksums )
865+ ).all ():
809866 if nested_depth > cur_depth : cur_depth = nested_depth
810867
811868 grid_item = json .loads (grid_item )
@@ -881,8 +938,15 @@ def augment(self, session, parent, addendum):
881938 parent_grid = session .query (model .Grid ).get (parent )
882939 info_obj = json .loads (parent_grid .info )
883940
884- for nested_depth , grid_item , download_size in session .query (model .Calculation .nested_depth , model .Grid .info , model .Metadata .download_size ).filter (model .Calculation .checksum == model .Grid .checksum , model .Grid .checksum == model .Metadata .checksum , model .Calculation .checksum .in_ (filtered_addendum )).all ():
885-
941+ for nested_depth , grid_item , download_size in session .query (
942+ model .Calculation .nested_depth ,
943+ model .Grid .info ,
944+ model .Metadata .download_size
945+ ).filter (
946+ model .Calculation .checksum == model .Grid .checksum ,
947+ model .Grid .checksum == model .Metadata .checksum ,
948+ model .Calculation .checksum .in_ (filtered_addendum )
949+ ).all ():
886950 if nested_depth >= parent_calc .nested_depth :
887951 parent_calc .nested_depth = nested_depth + 1
888952
0 commit comments