pyemaps 2.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pyemaps/COPYING +798 -0
- pyemaps/CifFile/CifFile_module.py +3117 -0
- pyemaps/CifFile/StarFile.py +2496 -0
- pyemaps/CifFile/TypeContentsParser.py +82 -0
- pyemaps/CifFile/YappsStarParser_1_0.py +289 -0
- pyemaps/CifFile/YappsStarParser_1_1.py +288 -0
- pyemaps/CifFile/YappsStarParser_2_0.py +369 -0
- pyemaps/CifFile/YappsStarParser_STAR2.py +382 -0
- pyemaps/CifFile/__init__.py +7 -0
- pyemaps/CifFile/drel/__init__.py +1 -0
- pyemaps/CifFile/drel/drel_ast_yacc.py +582 -0
- pyemaps/CifFile/drel/drel_lex.py +228 -0
- pyemaps/CifFile/drel/drel_runtime.py +126 -0
- pyemaps/CifFile/drel/parsetab.py +185 -0
- pyemaps/CifFile/drel/py_from_ast.py +628 -0
- pyemaps/CifFile/parsetab.py +185 -0
- pyemaps/CifFile/yapps3_compiled_rt.py +390 -0
- pyemaps/README.md +201 -0
- pyemaps/__config__.py +91 -0
- pyemaps/__init__.py +233 -0
- pyemaps/__main__.py +219 -0
- pyemaps/__version__.py +1 -0
- pyemaps/cdata/Aluminium.xtl +4 -0
- pyemaps/cdata/AluminiumOxide.xtl +5 -0
- pyemaps/cdata/Aluminium_FCC.xtl +4 -0
- pyemaps/cdata/BariumTitanate_180k.xtl +6 -0
- pyemaps/cdata/BariumTitanate_270k.xtl +7 -0
- pyemaps/cdata/BariumTitanate_Tetra.xtl +7 -0
- pyemaps/cdata/BiMnO3.xtl +27 -0
- pyemaps/cdata/Boron_Tetra.xtl +8 -0
- pyemaps/cdata/CadmiumSelenide_Hex.xtl +5 -0
- pyemaps/cdata/CadmiumSulfide_Cubic.xtl +5 -0
- pyemaps/cdata/CadmiumSulfide_Hex.xtl +5 -0
- pyemaps/cdata/Chromium_BCC.xtl +4 -0
- pyemaps/cdata/CoSb3_Skutterudite.xtl +5 -0
- pyemaps/cdata/CopperOxide.xtl +5 -0
- pyemaps/cdata/Copper_FCC.xtl +4 -0
- pyemaps/cdata/Cu2O_Cuprite.xtl +5 -0
- pyemaps/cdata/Diamond.xtl +4 -0
- pyemaps/cdata/ErbiumPyrogermanate.xtl +9 -0
- pyemaps/cdata/FePd_Tetra.xtl +5 -0
- pyemaps/cdata/FeS2_Pyrite.xtl +15 -0
- pyemaps/cdata/GalliumAntimonide.xtl +5 -0
- pyemaps/cdata/GalliumArsenide.xtl +5 -0
- pyemaps/cdata/GalliumNitride.xtl +5 -0
- pyemaps/cdata/Germanium.xtl +4 -0
- pyemaps/cdata/Gold_FCC.xtl +4 -0
- pyemaps/cdata/IndiumArsenide.xtl +5 -0
- pyemaps/cdata/LaMnO3.xtl +7 -0
- pyemaps/cdata/LeadZirconateTitanate.xtl +8 -0
- pyemaps/cdata/Li2MnO3.xtl +13 -0
- pyemaps/cdata/NaFeO2.xtl +6 -0
- pyemaps/cdata/Nb3Sn.xtl +5 -0
- pyemaps/cdata/Pentacene.xtl +39 -0
- pyemaps/cdata/Silicon.xtl +4 -0
- pyemaps/cdata/StrontiumTitanate.xtl +6 -0
- pyemaps/cdata/TelluriumDioxide.xtl +5 -0
- pyemaps/cdata/TinDioxide_RT.xtl +5 -0
- pyemaps/cdata/TitaniumDioxide_Anatase.xtl +5 -0
- pyemaps/cdata/TitaniumDioxide_Rutile.xtl +5 -0
- pyemaps/cdata/TungstenDiselenide.xtl +5 -0
- pyemaps/cdata/VanadiumDioxide_RT.xtl +6 -0
- pyemaps/cdata/ZincOxide.xtl +5 -0
- pyemaps/cdata/Zinc_HCP.xtl +4 -0
- pyemaps/cdata/ZirconiumNitride.xtl +5 -0
- pyemaps/cdata/limno2.xtl +6 -0
- pyemaps/crystals.py +1415 -0
- pyemaps/ddiffs.py +147 -0
- pyemaps/diffract/__init__.py +70 -0
- pyemaps/diffract/bloch_dec.py +779 -0
- pyemaps/diffract/csf_dec.py +242 -0
- pyemaps/diffract/dif_dec.py +519 -0
- pyemaps/diffract/dpgen_dec.py +175 -0
- pyemaps/diffract/mxtal_dec.py +201 -0
- pyemaps/diffract/powder_dec.py +137 -0
- pyemaps/diffract/stereo_dec.py +111 -0
- pyemaps/display.py +791 -0
- pyemaps/emcontrols.py +1017 -0
- pyemaps/errors.py +266 -0
- pyemaps/fileutils.py +1001 -0
- pyemaps/kdiffs.py +1221 -0
- pyemaps/license.txt +42 -0
- pyemaps/samples/adf.py +137 -0
- pyemaps/samples/al.img +0 -0
- pyemaps/samples/al_dpgen.py +57 -0
- pyemaps/samples/al_ediom.py +94 -0
- pyemaps/samples/convert_image.py +88 -0
- pyemaps/samples/dm_diff.py +225 -0
- pyemaps/samples/mask.im3 +0 -0
- pyemaps/samples/powder.py +51 -0
- pyemaps/samples/raw.img +0 -0
- pyemaps/samples/si_bloch.py +120 -0
- pyemaps/samples/si_constructor.py +51 -0
- pyemaps/samples/si_csf.py +59 -0
- pyemaps/samples/si_dif.py +134 -0
- pyemaps/samples/si_lacbed.py +59 -0
- pyemaps/samples/si_pyemaps.py +80 -0
- pyemaps/samples/si_scm.py +156 -0
- pyemaps/samples/si_stereo.py +116 -0
- pyemaps/scattering/__init__.py +26 -0
- pyemaps/scattering/sct_dec.py +31 -0
- pyemaps/spg/__init__.py +25 -0
- pyemaps/spg/spg_dec.py +60 -0
- pyemaps/stackimg.py +1031 -0
- pyemaps/xtal.py +222 -0
- pyemaps-2.0.0.dist-info/METADATA +231 -0
- pyemaps-2.0.0.dist-info/RECORD +112 -0
- pyemaps-2.0.0.dist-info/WHEEL +5 -0
- pyemaps-2.0.0.dist-info/entry_points.txt +2 -0
- pyemaps-2.0.0.dist-info/licenses/COPYING +798 -0
- pyemaps-2.0.0.dist-info/licenses/license.txt +42 -0
- pyemaps-2.0.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,628 @@
|
|
|
1
|
+
# To maximize python3/python2 compatibility
|
|
2
|
+
from __future__ import print_function
|
|
3
|
+
from __future__ import unicode_literals
|
|
4
|
+
from __future__ import division
|
|
5
|
+
from __future__ import absolute_import
|
|
6
|
+
|
|
7
|
+
# The unicode type does not exist in Python3 as the str type
|
|
8
|
+
# encompasses unicode. PyCIFRW tests for 'unicode' would fail
|
|
9
|
+
# Suggestions for a better approach welcome.
|
|
10
|
+
|
|
11
|
+
if isinstance(u"abc",str): #Python3
|
|
12
|
+
unicode = str
|
|
13
|
+
|
|
14
|
+
import re
|
|
15
|
+
from CifFile import CifError
|
|
16
|
+
pycifrw_func_table = { #how to use PyCIFRW CifFile objects
|
|
17
|
+
"data_access": "ciffile[%s]", # argument is dataname to be accessed
|
|
18
|
+
"optional_data_access":"emapsCifFile.get(%s,None)",
|
|
19
|
+
"element_no": "%s[%s]", # accessing a particular element of the result of data_access
|
|
20
|
+
"count_data": "len(%s)", # number of elements for result of data_access
|
|
21
|
+
"cat_names":"emapsCifFile.dictionary.names_in_cat(%s)", #names in category %s
|
|
22
|
+
"has_name":"emapsCifFile.has_key_or_alias(%s)",
|
|
23
|
+
"semantic_packet":"emapsCifFile.GetKeyedSemanticPacket(%s,%s)" #get a packet for key, value
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
def make_python_function(in_ast,func_name,targetname, special_ids=[{}],
|
|
27
|
+
func_table = pycifrw_func_table, cif_dic=None,cat_meth=False,
|
|
28
|
+
func_def = False, have_sn=True,loopable={},debug=None,depends=False):
|
|
29
|
+
"""Convert in_ast to python code"""
|
|
30
|
+
if debug is not None:
|
|
31
|
+
print("incoming AST:")
|
|
32
|
+
print(repr(in_ast))
|
|
33
|
+
func_text,withtable,dependencies,cur_row = start_traverse(in_ast,func_table,target_id=targetname,cat_meth=cat_meth,loopable=loopable,debug=debug,func=func_def,cif_dic=cif_dic)
|
|
34
|
+
if debug is not None:
|
|
35
|
+
print('Start========')
|
|
36
|
+
print(func_text)
|
|
37
|
+
print('End==========')
|
|
38
|
+
if func_def and not depends:
|
|
39
|
+
return func_text
|
|
40
|
+
elif func_def:
|
|
41
|
+
return func_text, None
|
|
42
|
+
# now indent the string
|
|
43
|
+
noindent = func_text.splitlines()
|
|
44
|
+
# get the minimum indent and remove empty lines
|
|
45
|
+
no_spaces = [re.match(r' *',a).end() for a in noindent if a] #drop empty lines
|
|
46
|
+
min_spaces = min(no_spaces)+4 # because we add 4 ourselves to everything
|
|
47
|
+
if len(withtable) > 0 or cur_row: # a loop method
|
|
48
|
+
d_vars = [a[1][0] for a in withtable.items()]
|
|
49
|
+
if cur_row:
|
|
50
|
+
d_vars = d_vars + ['__current_row']
|
|
51
|
+
dummy_vars = ",".join(d_vars)
|
|
52
|
+
actual_names = [k for k in withtable.keys()]
|
|
53
|
+
actual_names = [func_table["data_access"]% ("'"+a+"'") for a in actual_names]
|
|
54
|
+
# intercept optional values and replace with [] if None
|
|
55
|
+
optional_names = ["__option_w%d"%n for n,k in enumerate(withtable.keys()) if withtable[k][2]]
|
|
56
|
+
if cur_row:
|
|
57
|
+
actual_names+=['__row_id']
|
|
58
|
+
final_names = actual_names[:]
|
|
59
|
+
one_pack_names = [func_table["element_no"] % (a,"packet_no") for a in actual_names]
|
|
60
|
+
for n,k in enumerate(withtable.keys()):
|
|
61
|
+
if withtable[k][2]:
|
|
62
|
+
final_names[n]="__option_w%d"%n #pre-evaluated
|
|
63
|
+
one_pack_names[n] = "__option_w%d"%n
|
|
64
|
+
map_names = ",".join(final_names)
|
|
65
|
+
one_packet_each = ",".join(one_pack_names)
|
|
66
|
+
preamble = "def %s(ciffile,packet_no=-1):\n" % (func_name)
|
|
67
|
+
preamble +=" try:\n"
|
|
68
|
+
preamble +=" from itertools import repeat,imap\n" #note that imap might fail
|
|
69
|
+
preamble +=" except ImportError: #python3\n"
|
|
70
|
+
preamble +=" imap = map\n"
|
|
71
|
+
preamble +=" def drel_func(%s):\n" % dummy_vars
|
|
72
|
+
# for debugging
|
|
73
|
+
print_instruction = "'Function passed variables "+("{!r} "*len(d_vars))+"'.format("+dummy_vars+",)"
|
|
74
|
+
preamble +=" print(%s)\n" % print_instruction
|
|
75
|
+
# preamble +=" print('Globals inside looped drel_func:' + repr(globals())\n")
|
|
76
|
+
# the actual function gets inserted here
|
|
77
|
+
# Handle the optional names
|
|
78
|
+
end_body = "\n"
|
|
79
|
+
for n,one_opt in enumerate(withtable.keys()):
|
|
80
|
+
if withtable[one_opt][2]:
|
|
81
|
+
end_body += " try:\n"
|
|
82
|
+
end_body += " %s%d = %s\n" % ("__option_w",n,func_table["optional_data_access"]%("'"+one_opt+"'"))
|
|
83
|
+
end_body += " except KeyError:\n"
|
|
84
|
+
end_body += " %s%d = None\n" % ("__option_w",n)
|
|
85
|
+
end_body+= " if packet_no < 0: #map\n"
|
|
86
|
+
for one_opt in optional_names:
|
|
87
|
+
end_body += " if %s is None: %s = repeat(None)\n" % (one_opt,one_opt)
|
|
88
|
+
|
|
89
|
+
if cur_row and len(actual_names) > 1: #i.e. have real names from category
|
|
90
|
+
end_body +=" __row_id = range(%s)\n" % (func_table['count_data'] % ("'"+actual_names[0]+"'"))
|
|
91
|
+
elif cur_row and len(actual_names)==1: #so no actual names available
|
|
92
|
+
|
|
93
|
+
end_body += " cat_names = %s\n" % (func_table["cat_names"] % ("'"+getcatname(targetname)[0]+"'"))
|
|
94
|
+
end_body += " have_name = [a for a in cat_names if %s]\n" % (func_table["has_name"] % "a")
|
|
95
|
+
end_body += " if len(have_name)>0:\n"
|
|
96
|
+
end_body += " full_length = %s \n" % (func_table["count_data"] % (func_table["data_access"] % "have_name[0]"))
|
|
97
|
+
end_body += " __row_id = range(full_length)\n"
|
|
98
|
+
end_body += " else:\n"
|
|
99
|
+
end_body += " return []\n"
|
|
100
|
+
|
|
101
|
+
end_body+= " return list(imap(drel_func,%s))\n" % (map_names+",")
|
|
102
|
+
end_body+= " else:\n"
|
|
103
|
+
end_body+= " return drel_func(%s)\n" % one_packet_each
|
|
104
|
+
|
|
105
|
+
else:
|
|
106
|
+
preamble = "def %s(ciffile):\n" % func_name
|
|
107
|
+
#preamble +=" global StarList#from emapsCifFile.drel import drel_runtime\n"
|
|
108
|
+
end_body = ""
|
|
109
|
+
|
|
110
|
+
if cat_meth:
|
|
111
|
+
preamble += " "*8 + "__dreltarget = {}\n" # initialise
|
|
112
|
+
num_header = """
|
|
113
|
+
import math,cmath
|
|
114
|
+
try:
|
|
115
|
+
import numpy
|
|
116
|
+
except:
|
|
117
|
+
print("Can't import numerical python, this method may not work")
|
|
118
|
+
"""
|
|
119
|
+
preamble += num_header
|
|
120
|
+
indented = map(lambda a:" "*8 + a +"\n",noindent) #indent dREL body
|
|
121
|
+
postamble = ""
|
|
122
|
+
postamble += " "*8 + "return __dreltarget"
|
|
123
|
+
final = preamble + "".join(indented) + postamble + end_body
|
|
124
|
+
if not depends:
|
|
125
|
+
return final
|
|
126
|
+
else: return final, dependencies
|
|
127
|
+
|
|
128
|
+
def start_traverse(in_node,api_table,target_id=None,loopable={},cat_meth=False,debug=None, func=False,
|
|
129
|
+
cif_dic=None):
|
|
130
|
+
special_info = {"special_id":[{}],"target_id":target_id,"withtable":{},"sub_subject":"",
|
|
131
|
+
"depends":set(),"loopable_cats":loopable,"packet_vars":{},
|
|
132
|
+
"need_current_row":False,"rhs":None,"inif":False}
|
|
133
|
+
# create a virtual enclosing 'with' statement
|
|
134
|
+
if target_id is not None and not cat_meth and not func:
|
|
135
|
+
cat,name = getcatname(target_id)
|
|
136
|
+
special_info["special_id"][-1].update({"_"+cat:[cat,"",False]})
|
|
137
|
+
if cat in special_info["loopable_cats"].keys(): #
|
|
138
|
+
special_info["special_id"][-1]["_"+cat][1] = "looped_cat"
|
|
139
|
+
mathop_table = {"+":None, "-":None, "<":"<", "*":None, "/":None,
|
|
140
|
+
"&":"&", "|":"|",
|
|
141
|
+
">":">", "<=":"<=", ">=":">=", "!=":"!=",
|
|
142
|
+
"or":" or ", "and":" and ",
|
|
143
|
+
"==":"==", "in":" in ", "not in":" not in ",
|
|
144
|
+
"^":None,"**":"**"}
|
|
145
|
+
|
|
146
|
+
aug_assign_table = {"++=":"drel_runtime.aug_append",
|
|
147
|
+
"+=":"drel_runtime.aug_add",
|
|
148
|
+
"-=":"drel_runtime.aug_sub",
|
|
149
|
+
"--=":"drel_runtime.aug_remove"}
|
|
150
|
+
|
|
151
|
+
def traverse_ast(in_node,debug=debug):
|
|
152
|
+
if isinstance(in_node,(unicode,str)):
|
|
153
|
+
return in_node
|
|
154
|
+
if isinstance(in_node[0],list):
|
|
155
|
+
raise SyntaxError('First element of AST Node must be string: ' + repr(in_node))
|
|
156
|
+
node_type = in_node[0]
|
|
157
|
+
if debug == node_type:
|
|
158
|
+
print(node_type + ": " + repr(in_node))
|
|
159
|
+
if node_type == "ARGLIST":
|
|
160
|
+
pass
|
|
161
|
+
elif node_type == "BINARY":
|
|
162
|
+
return("%d" % int(in_node[1],base=2))
|
|
163
|
+
elif node_type == "FALSE":
|
|
164
|
+
return("False")
|
|
165
|
+
elif node_type == "REAL":
|
|
166
|
+
return(in_node[1])
|
|
167
|
+
elif node_type == "HEX":
|
|
168
|
+
return("%d" % int(in_node[1],base=16))
|
|
169
|
+
elif node_type == "INT":
|
|
170
|
+
return(in_node[1])
|
|
171
|
+
elif node_type == "IMAGINARY":
|
|
172
|
+
return(in_node[1])
|
|
173
|
+
elif node_type == "OCTAL":
|
|
174
|
+
return("%d" % int(in_node[1],base=8))
|
|
175
|
+
|
|
176
|
+
elif node_type == "ATOM":
|
|
177
|
+
if isinstance(in_node[1],(unicode,str)):
|
|
178
|
+
# pick up built-in literals
|
|
179
|
+
if in_node[1].lower() == 'twopi':
|
|
180
|
+
return "(2.0 * math.pi)"
|
|
181
|
+
if in_node[1].lower() == 'pi':
|
|
182
|
+
return "math.pi"
|
|
183
|
+
else:
|
|
184
|
+
return in_node[1]
|
|
185
|
+
else:
|
|
186
|
+
return traverse_ast(in_node[1])
|
|
187
|
+
elif node_type == "ITEM_TAG":
|
|
188
|
+
return in_node[1]
|
|
189
|
+
elif node_type == "LITERAL":
|
|
190
|
+
return in_node[1]
|
|
191
|
+
elif node_type == "LIST":
|
|
192
|
+
if len(in_node)==1: #empty list
|
|
193
|
+
return "StarList([])"
|
|
194
|
+
if special_info["rhs"] == True:
|
|
195
|
+
outstring = "StarList(["
|
|
196
|
+
else:
|
|
197
|
+
outstring = ""
|
|
198
|
+
for list_elem in in_node[1:]:
|
|
199
|
+
outstring = outstring + traverse_ast(list_elem) + ","
|
|
200
|
+
if special_info["rhs"] == True:
|
|
201
|
+
return outstring[:-1] + "])"
|
|
202
|
+
else:
|
|
203
|
+
return outstring[:-1]
|
|
204
|
+
elif node_type == "TABLE":
|
|
205
|
+
if len(in_node)==1:
|
|
206
|
+
return "StarTable({})"
|
|
207
|
+
else:
|
|
208
|
+
outstring = "{"
|
|
209
|
+
for table_elem in in_node[1:]:
|
|
210
|
+
outstring = outstring + traverse_ast(table_elem[0])+":"+traverse_ast(table_elem[1]) +","
|
|
211
|
+
return outstring[:-1] + "}"
|
|
212
|
+
elif node_type == "SUBSCRIPTION": # variable, single expression
|
|
213
|
+
newid = 0
|
|
214
|
+
if in_node[1][0] == "ATOM" and in_node[1][1][0] == "ITEM_TAG": #keyed lookup
|
|
215
|
+
print("Found category used as item tag: subscribing")
|
|
216
|
+
newid = [in_node[1][1][1][1:],False,False] #drop underscore and remember
|
|
217
|
+
else:
|
|
218
|
+
primary = traverse_ast(in_node[1])
|
|
219
|
+
# check to see if this is a special variable
|
|
220
|
+
for idtable in special_info["special_id"]:
|
|
221
|
+
newid = idtable.get(primary,0)
|
|
222
|
+
if newid: break
|
|
223
|
+
if primary in special_info["loopable_cats"].keys(): #loop category used
|
|
224
|
+
newid = [primary,False,False]
|
|
225
|
+
break
|
|
226
|
+
if newid:
|
|
227
|
+
#FIXME: the dataname may not be the <cat>.<obj> construction (eg pdCIF)
|
|
228
|
+
key_items = ["_"+newid[0]+"."+s for s in special_info["loopable_cats"][newid[0]][0]] #key name
|
|
229
|
+
special_info["depends"].update([k.lower() for k in key_items])
|
|
230
|
+
get_loop = api_table["semantic_packet"] % (traverse_ast(in_node[2]),"'"+newid[0]+"'")
|
|
231
|
+
special_info["sub_subject"] = newid[0] #in case of attribute reference following
|
|
232
|
+
print("Set sub_subject to %s" % special_info["sub_subject"])
|
|
233
|
+
return get_loop
|
|
234
|
+
else:
|
|
235
|
+
outstring = primary + "["
|
|
236
|
+
outstring = outstring + traverse_ast(in_node[2]) + "]"
|
|
237
|
+
return outstring
|
|
238
|
+
|
|
239
|
+
elif node_type == "ATTRIBUTE": # id/tag , att
|
|
240
|
+
outstring = ""
|
|
241
|
+
newid = 0
|
|
242
|
+
# check for special ids
|
|
243
|
+
primary = traverse_ast(in_node[1]) # this will set sub_subject if necessary
|
|
244
|
+
for idtable in special_info["special_id"]:
|
|
245
|
+
newid = idtable.get(primary,0)
|
|
246
|
+
if newid: break
|
|
247
|
+
if newid:
|
|
248
|
+
#catch our output name
|
|
249
|
+
true_name = cif_dic.get_name_by_cat_obj(newid[0].lower(),in_node[2].lower()).lower()
|
|
250
|
+
if true_name == special_info.get("target_id","").lower():
|
|
251
|
+
outstring = "__dreltarget"
|
|
252
|
+
special_info["have_drel_target"] = True
|
|
253
|
+
# if we are looping, we add a loop prefix. If we are withing an
|
|
254
|
+
# unlooped category, we put the full name back.
|
|
255
|
+
elif newid[2] or (not newid[2] and not newid[1]): # looping or simple with
|
|
256
|
+
outstring = api_table["data_access"] % ('"' +true_name +'"')
|
|
257
|
+
special_info["depends"].add(true_name)
|
|
258
|
+
if newid[1]: # a loop statement requires an index
|
|
259
|
+
outstring += "[" + newid[1]+ "]"
|
|
260
|
+
else: # a with statement; capture the name and create a dummy variable
|
|
261
|
+
if true_name not in special_info["withtable"]: #new
|
|
262
|
+
position = len(special_info["withtable"])
|
|
263
|
+
new_var = "__w%d" % position
|
|
264
|
+
isoptional = special_info["inif"]
|
|
265
|
+
special_info["withtable"][true_name] = (new_var,position,isoptional)
|
|
266
|
+
outstring += special_info["withtable"][true_name][0]
|
|
267
|
+
special_info["depends"].add(true_name)
|
|
268
|
+
elif in_node[1][0] == "ATOM" and primary[0] == "_": # a cat/obj name
|
|
269
|
+
fullname = cif_dic.get_name_by_cat_obj(primary,in_node[2]).lower()
|
|
270
|
+
# a simple cat.obj dataname from the dictionary
|
|
271
|
+
if special_info.get("target_id","").lower() == fullname:
|
|
272
|
+
outstring = "__dreltarget"
|
|
273
|
+
special_info["have_drel_target"] = True
|
|
274
|
+
else:
|
|
275
|
+
special_info["depends"].add(fullname)
|
|
276
|
+
outstring = api_table["data_access"] % ("'" + fullname + "'")
|
|
277
|
+
else: # default to Python attribute access
|
|
278
|
+
# check for packet variables
|
|
279
|
+
if primary in special_info["packet_vars"]:
|
|
280
|
+
real_cat = special_info["packet_vars"][primary]
|
|
281
|
+
fullname = cif_dic.get_name_by_cat_obj(real_cat,in_node[2])
|
|
282
|
+
special_info['depends'].add(fullname)
|
|
283
|
+
elif special_info["sub_subject"]:
|
|
284
|
+
fullname = cif_dic.get_name_by_cat_obj(special_info["sub_subject"],in_node[2])
|
|
285
|
+
special_info['depends'].add(fullname)
|
|
286
|
+
else: # not anything special
|
|
287
|
+
fullname = in_node[2]
|
|
288
|
+
outstring = "getattr(" + primary + ",'" + fullname + "')"
|
|
289
|
+
# sub_subject no longer relevant after attribute resolution
|
|
290
|
+
special_info['sub_subject'] = ""
|
|
291
|
+
return outstring
|
|
292
|
+
|
|
293
|
+
elif node_type == "FUNC_CALL":
|
|
294
|
+
if in_node[1] == "Current_Row": #not a function but a keyword really
|
|
295
|
+
outstring = "__current_row"
|
|
296
|
+
special_info["need_current_row"]=True
|
|
297
|
+
else:
|
|
298
|
+
func_name,every_arg_prefix,postfix = get_function_name(in_node[1])
|
|
299
|
+
outstring = func_name + "( "
|
|
300
|
+
if func_name == "list" and len(in_node[2])>1: #special case
|
|
301
|
+
outstring = outstring + "["
|
|
302
|
+
for argument in in_node[2]:
|
|
303
|
+
outstring = outstring + every_arg_prefix + traverse_ast(argument) + ","
|
|
304
|
+
if postfix == None: # signal for dictionary defined
|
|
305
|
+
outstring = outstring + "ciffile)"
|
|
306
|
+
else:
|
|
307
|
+
outstring = outstring[:-1]
|
|
308
|
+
if func_name == "list" and len(in_node[2])>1:
|
|
309
|
+
outstring = outstring + "]"
|
|
310
|
+
outstring = outstring + ")" + postfix
|
|
311
|
+
return outstring
|
|
312
|
+
|
|
313
|
+
elif node_type == "SLICE": # primary [[start,finish,step],[...]
|
|
314
|
+
outstring = traverse_ast(in_node[1]) + "["
|
|
315
|
+
slice_list = in_node[2]
|
|
316
|
+
for one_slice in slice_list:
|
|
317
|
+
if one_slice[0] == "EXPR": #not a slice as such
|
|
318
|
+
outstring += traverse_ast(one_slice)
|
|
319
|
+
elif len(one_slice) == 0:
|
|
320
|
+
outstring += ":"
|
|
321
|
+
elif len(one_slice) >0: # at least start
|
|
322
|
+
outstring += traverse_ast(one_slice[0]) + ":"
|
|
323
|
+
if len(one_slice) >1: #start,finish only
|
|
324
|
+
outstring += traverse_ast(one_slice[1])
|
|
325
|
+
if len(one_slice) == 3: #step as well
|
|
326
|
+
outstring += ":" + traverse_ast(one_slice[2])
|
|
327
|
+
outstring += ","
|
|
328
|
+
outstring = outstring[:-1] + "]"
|
|
329
|
+
return outstring
|
|
330
|
+
|
|
331
|
+
elif node_type == "MATHOP":
|
|
332
|
+
op = mathop_table[in_node[1]]
|
|
333
|
+
first_arg = traverse_ast(in_node[2])
|
|
334
|
+
second_arg = traverse_ast(in_node[3])
|
|
335
|
+
if op is not None: #simple operation
|
|
336
|
+
outstring = first_arg + op + second_arg
|
|
337
|
+
else:
|
|
338
|
+
outstring = fix_mathops(in_node[1],first_arg,second_arg)
|
|
339
|
+
return outstring
|
|
340
|
+
elif node_type == "SIGN":
|
|
341
|
+
outstring = "drel_runtime.drel_dot(" + in_node[1] + "1," + traverse_ast(in_node[2])+")"
|
|
342
|
+
return outstring
|
|
343
|
+
elif node_type == "UNARY":
|
|
344
|
+
outstring = in_node[1] + " " + traverse_ast(in_node[2])
|
|
345
|
+
return outstring
|
|
346
|
+
|
|
347
|
+
elif node_type == "IF_EXPR": #IF_EXPR test true_suite [ELSE IF_EXPR] false_suite
|
|
348
|
+
outstring = "if "
|
|
349
|
+
outstring = outstring + traverse_ast(in_node[1])
|
|
350
|
+
outstring = outstring + ":"
|
|
351
|
+
old_inif = special_info["inif"]
|
|
352
|
+
special_info["inif"] = True
|
|
353
|
+
true_bit = traverse_ast(in_node[2])
|
|
354
|
+
outstring = outstring + add_indent("\n"+true_bit) #indent
|
|
355
|
+
elseif = in_node[3]
|
|
356
|
+
if len(elseif)!=0:
|
|
357
|
+
for one_cond in elseif: #each entry is condition, suite
|
|
358
|
+
outstring += "\nelif " + traverse_ast(one_cond[0]) + ":"
|
|
359
|
+
outstring += add_indent("\n" + traverse_ast(one_cond[1]))
|
|
360
|
+
if len(in_node)>4:
|
|
361
|
+
outstring = outstring + "\nelse:"
|
|
362
|
+
false_bit = traverse_ast(in_node[4])
|
|
363
|
+
outstring = outstring + add_indent("\n"+false_bit) #indent
|
|
364
|
+
special_info["inif"] = old_inif
|
|
365
|
+
return outstring
|
|
366
|
+
|
|
367
|
+
# dREL for statements include the final value, whereas a python range will include
|
|
368
|
+
# everything up to the final number
|
|
369
|
+
elif node_type == "DO": #DO ID = start, finish, incr, suite
|
|
370
|
+
outstring = "for " + in_node[1] + " in range(" + traverse_ast(in_node[2]) + ","
|
|
371
|
+
finish = traverse_ast(in_node[3])
|
|
372
|
+
increment = traverse_ast(in_node[4])
|
|
373
|
+
outstring = outstring + finish + "+1" + "," + increment
|
|
374
|
+
outstring = outstring + "):"
|
|
375
|
+
suite = add_indent("\n"+traverse_ast(in_node[5]))
|
|
376
|
+
return outstring + suite
|
|
377
|
+
elif node_type == "FOR": # FOR target_list expression_list suite
|
|
378
|
+
outstring = "for "
|
|
379
|
+
for express in in_node[1]:
|
|
380
|
+
outstring = outstring + traverse_ast(express) + ","
|
|
381
|
+
outstring = outstring[:-1] + " in "
|
|
382
|
+
special_info["rhs"] = True
|
|
383
|
+
for target in in_node[2]:
|
|
384
|
+
outstring += "copy("+traverse_ast(target) + "),"
|
|
385
|
+
special_info["rhs"] = None
|
|
386
|
+
outstring = outstring[:-1] + ":" + add_indent("\n" + traverse_ast(in_node[3]))
|
|
387
|
+
return outstring
|
|
388
|
+
elif node_type == "REPEAT": #REPEAT suite
|
|
389
|
+
outstring = "while True:" + add_indent("\n" + traverse_ast(in_node[1]))
|
|
390
|
+
return outstring
|
|
391
|
+
elif node_type == "WITH": #new_id old_id suite
|
|
392
|
+
# each entry in special_id is [alias:[cat_name,loop variable, is_loop]]
|
|
393
|
+
alias_id = in_node[1]
|
|
394
|
+
cat_id = in_node[2]
|
|
395
|
+
is_already_there = [a for a in special_info['special_id'][-1].keys() if \
|
|
396
|
+
special_info['special_id'][-1][a][0] == cat_id]
|
|
397
|
+
if len(is_already_there)>0:
|
|
398
|
+
del special_info['special_id'][-1][is_already_there[0]]
|
|
399
|
+
print("Found explicit loop category alias: %s for %s" % (alias_id,cat_id) )
|
|
400
|
+
special_info['special_id'][-1].update({alias_id:[cat_id,"",False]})
|
|
401
|
+
if in_node[2] in special_info['loopable_cats'].keys(): #flag this
|
|
402
|
+
special_info['special_id'][-1][alias_id][1] = "looped_cat"
|
|
403
|
+
outstring = traverse_ast(in_node[3])
|
|
404
|
+
return outstring
|
|
405
|
+
|
|
406
|
+
elif node_type == "LOOP": #ALIAS CAT LOOPVAR COMP COMPVAR SUITE
|
|
407
|
+
alias_id = in_node[1]
|
|
408
|
+
cat_id = in_node[2]
|
|
409
|
+
var_info = [cat_id,"",False]
|
|
410
|
+
if cat_id not in special_info['loopable_cats'].keys():
|
|
411
|
+
message = "%s is not a loopable category (must be one of:\n%s)" % (cat_id,special_info['loopable_cats'].keys())
|
|
412
|
+
print(message)
|
|
413
|
+
raise CifError(message)
|
|
414
|
+
#loop over some index
|
|
415
|
+
loop_num = len(special_info['special_id'][-1])+1
|
|
416
|
+
if in_node[3] == "": # provide our own
|
|
417
|
+
loop_index = "__pi%d" % loop_num
|
|
418
|
+
else:
|
|
419
|
+
loop_index = in_node[3]
|
|
420
|
+
var_info[1] = loop_index
|
|
421
|
+
var_info[2] = True
|
|
422
|
+
special_info['special_id'][-1].update({alias_id:var_info})
|
|
423
|
+
# now emit some text: first to find the length of the category
|
|
424
|
+
# loopable cats contains a list of names defined for the category
|
|
425
|
+
# this might not be robust as we ignore alternative resolutions of the (cat,name) pair
|
|
426
|
+
catnames = set([a[1][0] for a in cif_dic.cat_obj_lookup_table.items() if a[0][0]==cat_id.lower()])
|
|
427
|
+
outstring = "__pyallitems = " + repr(catnames)
|
|
428
|
+
outstring += "\nprint('names in cat = %s' % repr(__pyallitems))"
|
|
429
|
+
outstring += "\n" + "__pycitems = [a for a in __pyallitems if %s]" % (api_table["has_name"] % "a")
|
|
430
|
+
outstring += "\nprint('names in cat -> %s' % repr(__pycitems))\n"
|
|
431
|
+
cat_key = cif_dic[cat_id]['_category_key.name'][0] #take official key
|
|
432
|
+
# If there is nothing in the category, provoke category creation by evaluating the key
|
|
433
|
+
outstring += "if len(__pycitems)==0:\n"
|
|
434
|
+
outstring += " __pydummy = %s\n" % (api_table["data_access"] % repr(cat_key))
|
|
435
|
+
outstring += " __pycitems = [a for a in __pyallitems if %s]\n" % (api_table["has_name"] % "a")
|
|
436
|
+
outstring += " print('After category creation, names in cat ->' + repr(__pycitems))\n"
|
|
437
|
+
special_info["depends"].add(cat_key) #add key as a dependency
|
|
438
|
+
if var_info[2] == True:
|
|
439
|
+
access_string = api_table["count_data"] % (api_table["data_access"] % "__pycitems[0]")
|
|
440
|
+
outstring += "\n" + "__loop_range%d = range(%s)" % (loop_num,access_string)
|
|
441
|
+
else:
|
|
442
|
+
outstring += "\n" + "__loop_range%d = [0]" % loop_num
|
|
443
|
+
#outstring +="\n" + "for __noloop in [0]:"
|
|
444
|
+
# deal with this comparison test
|
|
445
|
+
if in_node[4] != "":
|
|
446
|
+
outstring += "\n" + "__loop_range%d = [a for a in __loop_range%d if a %s %s]" % (loop_num,loop_num,in_node[4],in_node[5])
|
|
447
|
+
# now output the looping command
|
|
448
|
+
outstring += "\n" + "for %s in __loop_range%d:" % (loop_index,loop_num)
|
|
449
|
+
# now the actual body of the loop
|
|
450
|
+
loop_body = traverse_ast(in_node[6])
|
|
451
|
+
outstring = outstring + add_indent("\n"+loop_body)
|
|
452
|
+
return outstring
|
|
453
|
+
|
|
454
|
+
elif node_type == "FUNCTION": #FUNCTION ID ARGLIST SUITE
|
|
455
|
+
func_name = in_node[1]
|
|
456
|
+
outstring = "def %s (" % func_name
|
|
457
|
+
for one_arg in in_node[2]:
|
|
458
|
+
outstring += one_arg[0] + ","
|
|
459
|
+
outstring = outstring + "ciffile):"
|
|
460
|
+
# imports
|
|
461
|
+
#import_lines = "import numpy\nfrom emapsCifFile.drel import drel_runtime\n"
|
|
462
|
+
import_lines = ""
|
|
463
|
+
outstring = outstring + add_indent("\n" + import_lines + traverse_ast(in_node[3])+"\nreturn %s" % func_name)
|
|
464
|
+
return outstring
|
|
465
|
+
|
|
466
|
+
|
|
467
|
+
elif node_type == "STATEMENTS":
|
|
468
|
+
outstring = ""
|
|
469
|
+
for one_statement in in_node[1]:
|
|
470
|
+
# try:
|
|
471
|
+
next_bit = traverse_ast(one_statement)
|
|
472
|
+
if not isinstance(next_bit,(unicode,str)):
|
|
473
|
+
print("Unable to traverse AST for %s" % one_statement[0])
|
|
474
|
+
else:
|
|
475
|
+
outstring = outstring + next_bit + "\n"
|
|
476
|
+
# except SyntaxError as message:
|
|
477
|
+
# print("Failed, so far have \n " + outstring)
|
|
478
|
+
# outstring += "raise SyntaxError, %s" % message
|
|
479
|
+
# except:
|
|
480
|
+
# print("Failed, so far have \n " + outstring)
|
|
481
|
+
# outstring += "raise SyntaxError, %s" % `one_statement`
|
|
482
|
+
return outstring
|
|
483
|
+
elif node_type == "ASSIGN": #Target_list ,assigner, expression list
|
|
484
|
+
outstring = ""
|
|
485
|
+
lhs_values = []
|
|
486
|
+
special_info["rhs"] = False
|
|
487
|
+
for target_value in in_node[1]:
|
|
488
|
+
one_value = traverse_ast(target_value)
|
|
489
|
+
outstring = outstring + one_value +","
|
|
490
|
+
lhs_values.append(one_value)
|
|
491
|
+
lhs = outstring[:-1]
|
|
492
|
+
rhs = ""
|
|
493
|
+
special_info["rhs"] = True
|
|
494
|
+
for order,expression in enumerate(in_node[3]):
|
|
495
|
+
rhs += traverse_ast(expression)+","
|
|
496
|
+
if special_info["sub_subject"] != "": #a full packet
|
|
497
|
+
special_info["packet_vars"].update({lhs_values[order]:special_info["sub_subject"]})
|
|
498
|
+
special_info["sub_subject"] = ""
|
|
499
|
+
# we cannot expand a numpy array, hence the workaround here
|
|
500
|
+
#if in_node[2] == "++=":
|
|
501
|
+
# outstring = "_temp1 = %s;%s = %s(_temp1,%s)" % (lhs,lhs,aug_assign_table["++="],rhs[:-1])
|
|
502
|
+
if in_node[2] != "=":
|
|
503
|
+
outstring = "%s = %s(%s,%s)" % (lhs, aug_assign_table[in_node[2]],lhs,rhs[:-1])
|
|
504
|
+
else:
|
|
505
|
+
outstring = "%s = %s" % (lhs,rhs[:-1])
|
|
506
|
+
special_info["rhs"] = None
|
|
507
|
+
return outstring
|
|
508
|
+
elif node_type == "FANCY_ASSIGN": # [1] is cat name, [2] is list of objects
|
|
509
|
+
catname = in_node[1]
|
|
510
|
+
outstring = ""
|
|
511
|
+
special_info["rhs"] = True
|
|
512
|
+
for obj,value in in_node[2]:
|
|
513
|
+
real_id = cif_dic.get_name_by_cat_obj(catname, obj)
|
|
514
|
+
newvalue = traverse_ast(value)
|
|
515
|
+
outstring = outstring + "__dreltarget.update({'%s':__dreltarget.get('%s',[])+[%s]})\n" % (real_id,real_id,newvalue)
|
|
516
|
+
special_info["rhs"] = None
|
|
517
|
+
return outstring
|
|
518
|
+
|
|
519
|
+
elif node_type == "LIST":
|
|
520
|
+
outstring = "["
|
|
521
|
+
for one_element in in_node[1]:
|
|
522
|
+
outstring = outstring + traverse_ast(one_element) + ","
|
|
523
|
+
return outstring + "]"
|
|
524
|
+
elif node_type == "EXPR":
|
|
525
|
+
return traverse_ast(in_node[1])
|
|
526
|
+
# Expr list occurs only when a non-assignment statement appears as expr_stmt
|
|
527
|
+
elif node_type == "EXPRLIST":
|
|
528
|
+
outstring = ""
|
|
529
|
+
for one_expr in in_node[1]:
|
|
530
|
+
outstring += traverse_ast(one_expr) + "\n"
|
|
531
|
+
return outstring
|
|
532
|
+
elif node_type == "GROUP":
|
|
533
|
+
outstring = "("
|
|
534
|
+
for expression in in_node[1]:
|
|
535
|
+
outstring = outstring + traverse_ast(expression) + ","
|
|
536
|
+
return outstring[:-1] + ")"
|
|
537
|
+
elif node_type == "PRINT":
|
|
538
|
+
return 'print( ' + traverse_ast(in_node[1]) + ")"
|
|
539
|
+
elif node_type == "BREAK":
|
|
540
|
+
return 'break '
|
|
541
|
+
elif node_type == "NEXT":
|
|
542
|
+
return 'continue '
|
|
543
|
+
|
|
544
|
+
else:
|
|
545
|
+
return "Not found: %s" % repr(in_node)
|
|
546
|
+
result = traverse_ast(in_node)
|
|
547
|
+
# remove target id from dependencies
|
|
548
|
+
if special_info["target_id"] is not None:
|
|
549
|
+
special_info["depends"].discard(special_info["target_id"].lower())
|
|
550
|
+
if not special_info.get("have_drel_target",False):
|
|
551
|
+
print('WARNING: no assignment to __dreltarget in %s (this is OK for category methods)' % repr(target_id))
|
|
552
|
+
print(result)
|
|
553
|
+
return result,special_info["withtable"],special_info["depends"],special_info["need_current_row"]
|
|
554
|
+
|
|
555
|
+
def get_function_name(in_name):
|
|
556
|
+
"""Return the Python name of the dREL function, an argument prefix,
|
|
557
|
+
and anything to be appended to the end"""
|
|
558
|
+
builtins = {"table":"dict",
|
|
559
|
+
"list":"list",
|
|
560
|
+
"array":"numpy.array",
|
|
561
|
+
"len":"len",
|
|
562
|
+
"abs":"abs",
|
|
563
|
+
"magn":"abs",
|
|
564
|
+
"atoi":"int",
|
|
565
|
+
"float":"float",
|
|
566
|
+
"str":"str",
|
|
567
|
+
"array":"numpy.array",
|
|
568
|
+
"norm":"numpy.linalg.norm",
|
|
569
|
+
"sqrt":"math.sqrt",
|
|
570
|
+
"exp":"math.exp",
|
|
571
|
+
"complex":"complex",
|
|
572
|
+
"max":"max",
|
|
573
|
+
"min":"min",
|
|
574
|
+
"strip":"drel_runtime.drel_strip",
|
|
575
|
+
"int":"drel_runtime.drel_int",
|
|
576
|
+
"eigen":"drel_runtime.drel_eigen",
|
|
577
|
+
"hash":"hash" #dREL extension
|
|
578
|
+
}
|
|
579
|
+
test_name = in_name.lower()
|
|
580
|
+
target_name = builtins.get(test_name,None)
|
|
581
|
+
if target_name is not None:
|
|
582
|
+
return target_name,"",""
|
|
583
|
+
if test_name in ['sind','cosd','tand']:
|
|
584
|
+
return "math."+test_name[:-1],"math.radians(",")"
|
|
585
|
+
if test_name in ['acosd','asind','atand','atan2d']:
|
|
586
|
+
return "math.degrees(math."+test_name[:-1],"",")"
|
|
587
|
+
if test_name == "mod":
|
|
588
|
+
return "divmod","","[1]"
|
|
589
|
+
if test_name == "upper":
|
|
590
|
+
return "","",".upper()"
|
|
591
|
+
if test_name == "transpose":
|
|
592
|
+
return "","",".T"
|
|
593
|
+
if test_name == 'expimag':
|
|
594
|
+
return "cmath.exp","1j*(",")"
|
|
595
|
+
if test_name in ['real','imag']:
|
|
596
|
+
return "","","." + test_name
|
|
597
|
+
if test_name == 'matrix':
|
|
598
|
+
return "numpy.matrix","",".astype('float64')"
|
|
599
|
+
if test_name == 'sort':
|
|
600
|
+
return "","",".sort()"
|
|
601
|
+
return in_name,"",None #dictionary defined
|
|
602
|
+
|
|
603
|
+
def fix_mathops(op,first_arg,second_arg):
|
|
604
|
+
"""Return a string that will carry out the requested operation"""
|
|
605
|
+
if op == "^":
|
|
606
|
+
return "numpy.cross(%s,%s)" % (first_arg,second_arg)
|
|
607
|
+
elif op == "*": #could be matrix multiplication
|
|
608
|
+
return "drel_runtime.drel_dot(%s,%s)" % (first_arg,second_arg)
|
|
609
|
+
elif op == "+":
|
|
610
|
+
return "drel_runtime.drel_add(%s,%s)" % (first_arg, second_arg)
|
|
611
|
+
elif op == "-":
|
|
612
|
+
return "numpy.subtract(%s,%s)" % (first_arg, second_arg)
|
|
613
|
+
# beware integer division on this one...
|
|
614
|
+
elif op == "/":
|
|
615
|
+
return "numpy.true_divide(%s,%s)" % (first_arg, second_arg)
|
|
616
|
+
|
|
617
|
+
def add_indent(text,n=4):
|
|
618
|
+
"""Indent text by n spaces"""
|
|
619
|
+
return re.sub("\n","\n"+4*" ",text)
|
|
620
|
+
|
|
621
|
+
def getcatname(dataname):
|
|
622
|
+
"""Return cat,name pair from dataname"""
|
|
623
|
+
try:
|
|
624
|
+
cat,name = dataname.split(".")
|
|
625
|
+
except ValueError: #no period in name
|
|
626
|
+
return cat,None
|
|
627
|
+
return cat[1:],name
|
|
628
|
+
|