import sys, os
import hashlib
import os.path
import shutil
import FileSystem as FS
from ArgumentParser import ArgumentParser
try:
import olx
import olex
except:
pass
import variableFunctions
from olexFunctions import OV
import time
import zlib
tree = None
timing = False #bool(OV.GetParam('gui.timing'))
class HistoryFiles(object):
def from_list(self, files):
self.hkl = None
self.dyn = None
self.res = None
self.cif_od = None
self.files = []
for f in files:
if not os.path.exists(f):
continue
ext = os.path.splitext(f)[1]
if ext ==".hkl":
self.hkl = f
elif ext == ".cif_od":
self.cif_od = f
elif ext == ".cif_cap":
self.dyn = f
elif ext == ".res" or ext == ".ins":
self.res = f
else:
raise Exception("Undefined file found in the list!")
self.files.append(f)
def __init__(self, hkl_name, res_name):
data_base = os.path.splitext(hkl_name)[0]
self.from_list([hkl_name, res_name,
data_base + "_dyn.cif_cap",
data_base + ".cif_od"])
class History(ArgumentParser):
def __init__(self):
super(History, self).__init__()
def _getItems(self):
self.solve = False
self.basedir = OV.BaseDir()
self.filefull = OV.FileFull()
self.filepath = OV.FilePath()
self.filename = OV.ModelSrc()
if os.path.exists(self.filefull):
self.strdir = OV.StrDir()
else:
self.strdir = None
self.datadir = OV.DataDir()
self.history_filepath = os.path.join(self.strdir,self.filename) + ".hist6"
self.rename = OV.FindValue('rename')
self.his_file = None
OV.registerFunction(self.make_graph,False,'History')
def create_history(self, solution=False, label=None):
self._getItems()
self.solve = solution
global tree
if not tree:
tree = HistoryTree()
# don't attempt to make a history if a cif is loaded
if os.path.splitext(self.filefull)[-1].lower() == '.cif' or OV.IsClientMode():
return
files = HistoryFiles(OV.HKLSrc(), self.filefull)
if self.solve or not tree.children:
tree.add_top_level_node(files, is_solution=True, label=label)
if not self.solve:
tree.add_node(files)
self.his_file = tree.active_node.name
OV.SetParam('snum.history.current_node', tree.active_node.name)
if timing:
t = time.time()
if timing:
print(time.time() - t)
self.saveHistory()
return tree.active_node.name
def rename_history(self, name, label=None):
if label is None: return
label = label.strip()
if not label: return
node = tree._full_index.get(name)
assert node is not None
node.label = label
def describe_node(self, node_id):
try:
node = tree._full_index.get(node_id)
assert node is not None
if node.is_root:
return node_id
if node.is_solution:
return "%s-%s" %(node.program, node.method)
else:
import olex_core
import phil_interface
from phil_interface import phil_handler
name = ""
res = decompressFile(node.res).decode("utf-8")
st = res.index("")
end = res.index("")
edr = src = None
if st >= 0 and end >=0:
params = res[st+14:end].replace("REM", "").replace("\n", "").replace("\r", "").strip()
src = olex_core.GetStoredParams(params).get('Generic', None)
if src:
edr = OV.GetHeaderParam("ED.refinement.method", "Kinematic", src=src) != "Kinematic" and\
node.program.startswith("olex2.refine")
phil = None
try:
phil = phil_handler(master_phil=phil_interface.parse(
file_name=os.path.join(olx.BaseDir(), "params.phil")),
parse=phil_interface.parse)
phil.adopt_phil(phil_file=os.path.join(olx.BaseDir(), "util", "pyUtil", "NoSpherA2", "NoSpherA2.phil"))
phil.update(phil_string=zlib.decompress(node.phil).decode("utf-8"))
olx.phil_handler.rebuild_index()
except:
phil = None
if OV.IsDebugging():
sys.stdout.formatExceptionInfo()
if phil:
nsf = phil.get_validated_param("snum.NoSpherA2.use_aspherical")
if (edr or nsf) and src: #only olex2.refine
name = "Dyn-" + OV.GetACI().EDI.get_method_name(src=src)
else:
rp = phil.get_validated_param("snum.refinement.program")
name += rp
if phil.get_validated_param("snum.refinement.use_solvent_mask"):
name += "-mask"
if nsf:
name += "-NSF"
else:
if node.is_solution:
name = node.program
else:
sn = node.solution_node
name = "%s-%s" %(sn.program, node.program)
if not node.is_solution:
name += "-R-%.2f(%.2f)" %(node.R1*100, node.wR2*100)
return name
except:
if OV.IsDebugging():
sys.stdout.formatExceptionInfo()
return node_id
def create_archive(self, name, node_id):
import zipfile
if node_id:
node = tree._full_index.get(node_id)
assert node is not None
filename = OV.FileName()
with zipfile.ZipFile(name, 'w') as zout:
res = decompressFile(node.res).decode("utf-8").split("\n")
OV.update_HklSrc(res, filename+".hkl")
zout.writestr(filename+".res", "\n".join(res), zipfile.ZIP_DEFLATED)
zout.writestr(filename+".hkl", decompressFile(tree.getHklData(node)), zipfile.ZIP_DEFLATED)
try:
if node.dyn is not None:
zout.writestr(filename+"_dyn_.cif_cap", decompressFile(tree.getDynData(node)), zipfile.ZIP_DEFLATED)
except AttributeError:
pass
try:
if node.cif_od is not None:
zout.writestr(filename+".cif_od", decompressFile(tree.getCifODData(node)), zipfile.ZIP_DEFLATED)
except AttributeError:
pass
try:
if node.phil:
zout.writestr("olex2/"+filename+".phil", zlib.decompress(node.phil), zipfile.ZIP_DEFLATED)
except AttributeError:
pass
if node.lst is not None:
zout.writestr(filename+".lst", decompressFile(node.lst), zipfile.ZIP_DEFLATED)
else:
file_exts = [".cif", ".fcf", ".cif_od", "_dyn_.cif_cap", ".lst", ".log", ".tsc", ".tscb"]
filename = OV.FileName()
filepath = OV.FilePath()
ffilename = os.path.join(filepath, filename)
with zipfile.ZipFile(name, 'w') as zout:
res_fn = ffilename + ".res"
if os.path.exists(res_fn):
res = [l.rstrip('\r\n') for l in open(res_fn, "r").readlines()]
OV.update_HklSrc(res, filename+".hkl")
zout.writestr(filename+".res", '\n'.join(res), zipfile.ZIP_DEFLATED)
try:
zout.writestr("olex2/"+filename+".phil", get_snum_data(), zipfile.ZIP_DEFLATED)
except:
pass
metacif = os.path.join(filepath, "olex2", filename) + ".metacif"
if os.path.exists(metacif):
zout.write(metacif, "olex2/"+filename+".metacif", zipfile.ZIP_DEFLATED)
hklSrc = OV.HKLSrc()
if os.path.exists(hklSrc):
zout.write(hklSrc, filename + ".hkl", zipfile.ZIP_DEFLATED)
for e in file_exts:
fn = ffilename + e
if os.path.exists(fn):
zout.write(fn, filename + e, zipfile.ZIP_DEFLATED)
def revert_to_original(self):
node = tree._full_index.get(OV.FileName())
self.revert_history(node.children[0].name)
def revert_history(self, node_index):
node = tree._full_index.get(node_index)
assert node is not None
if node.is_root:
return
tree.active_node = node
node.set_params()
filepath = OV.FilePath()
filename = OV.FileName()
resFile = os.path.join(filepath, filename + ".res")
resFileData = decompressFile(node.res)
with open(resFile, 'wb') as wFile:
wFile.write(resFileData)
lstFile = os.path.join(filepath, filename + ".lst")
if node.lst is not None:
lstFileData = decompressFile(node.lst)
with open(lstFile, 'wb') as wFile:
wFile.write(lstFileData)
else:
## remove lst file if no lst file was saved in history
if os.path.exists(lstFile):
os.remove(lstFile)
try:
if node.phil:
phil = zlib.decompress(node.phil) #.decode("utf-8")
phil_fn = os.path.join(OV.StrDir(), OV.ModelSrc()) + ".phil"
with open(phil_fn, "wb") as out:
out.write(phil)
except AttributeError:
node.phil = None
except:
print("Failed to revert SNUM PHIL")
original_sg = olex.f("sg()")
olex.m("reap '%s' -no_save=true" %resFile)
hklSrc = OV.HKLSrc()
if not tree.isTheSameHklDigest(node, hklSrc):
olx.Echo("Current HKL does not match the one from history - updating!", m='warning')
hklFileData = decompressFile(tree.getHklData(node))
with open(hklSrc, 'wb') as wFile:
wFile.write(hklFileData)
try:
if node.dyn is not None:
dynFile = os.path.splitext(hklSrc)[0] + "_dyn_.cif_cap"
dynFileData = decompressFile(tree.getDynData(node))
with open(dynFile, 'wb') as wFile:
wFile.write(dynFileData)
except AttributeError:
node.dyn = None
try:
if node.cif_od is not None:
cif_odFile = os.path.splitext(hklSrc)[0] + ".cif_od"
if not os.path.exists(cif_odFile) and not tree.isTheSameCifODDigest(node, cif_odFile):
cif_odFileData = decompressFile(tree.getCifODData(node))
with open(cif_odFile, 'wb') as wFile:
wFile.write(cif_odFileData)
except AttributeError:
node.cif_od = None
olx.File() ## needed to make new .ins file
if OV.HasGUI() and original_sg != olex.f("sg()"):
olex.m("spy.run_skin sNumTitle")
def saveHistory(self):
if tree == None: # cif is loaded or no history
return
if timing:
t = time.time()
self._getItems()
if self.strdir:
variableFunctions.Pickle(tree,self.history_filepath + ".tmp")
if os.path.exists(self.history_filepath):
os.remove(self.history_filepath)
os.rename(self.history_filepath + ".tmp", self.history_filepath)
if timing:
print("saveHistory took %4fs" %(time.time() - t))
def loadHistory(self):
if timing:
t = time.time()
self._getItems()
global tree
if os.path.exists(self.history_filepath):
history_path = self.history_filepath
else: # older versions
history_path = os.path.join(self.strdir,self.filename) + ".hist5"
if not os.path.exists(history_path):
history_path = os.path.join(self.strdir,self.filename) + ".hist"
if os.path.exists(history_path):
tree = variableFunctions.unPickle(history_path)
if tree is None:
# Not sure why this ever happens though...
self._createNewHistory()
try:
historyName = tree.name
except AttributeError:
historyName = OV.ModelSrc()
tree.name = historyName
tree.upgrade()
if tree.active_node is None or tree.name != OV.ModelSrc():
self._createNewHistory()
if tree.active_node:
OV.SetParam('snum.history.current_node', tree.active_node.name)
else:
self._createNewHistory()
if timing:
print("loadHistory took %4fs" %(time.time() - t))
def _createNewHistory(self):
self.filename = OV.ModelSrc()
global tree
tree = HistoryTree()
tree.add_top_level_node(HistoryFiles(OV.HKLSrc(), OV.FileFull()),
is_solution=True)
tree.active_node.program = 'Unknown'
tree.active_node.method = 'Unknown'
def make_graph(self):
full_tree = not OV.GetParam('snum.history.condensed_tree')
OV.write_to_olex(
'history_tree.ind', ''.join(make_html_tree(tree, [], 0, full_tree)))
from Analysis import HistoryGraph
HistoryGraph(tree)
def _update_history_display(self):
pass
hist = History()
#OV.registerFunction(hist.delete_history)
OV.registerFunction(hist.rename_history)
OV.registerFunction(hist.revert_history)
OV.registerFunction(hist.create_history)
OV.registerFunction(hist.saveHistory)
OV.registerFunction(hist.loadHistory)
class Node(object):
is_root = False
link_table = []
_children = []
_active_child_node = None
_primary_parent_node = None
def __init__(self,
link_table=None,
name=None,
files: HistoryFiles=None,
label=None,
is_solution=False,
primary_parent_node=None,
history_leaf=None):
if link_table is None:
# XXX backwards compatibility 2010-12-12
# this should only happen if we are unpickling an old-style object of Node
return
self.link_table = link_table
self._children = []
self._active_child_node = None
self.name = name
self.label = label
self.primary_parent_node = primary_parent_node
self.is_solution = is_solution
self.R1 = None
self.wR2 = None
self.lst = None
self.res = None
self.hkl = None
self.dyn = None
self.cif_od = None
if files:
if files.hkl: self.hkl = digestPath(files.hkl)
if files.dyn: self.dyn = digestPath(files.dyn)
if files.cif_od: self.cif_od = digestPath(files.cif_od)
if history_leaf is None:
if files.res:
self.res = compressFile(files.res)
if self.is_solution:
self.program = OV.GetParam('snum.solution.program')
self.method = OV.GetParam('snum.solution.method')
else:
self.program = OV.GetParam('snum.refinement.program')
self.method = OV.GetParam('snum.refinement.method')
try:
self.R1 = float(OV.GetParam('snum.refinement.last_R1'))
self.wR2 = float(OV.GetParam('snum.refinement.last_wR2'))
except:
pass
try:
self.phil = zlib.compress(get_snum_data())
except:
self.phil = None
def get_node_index(self, node):
if node not in self.link_table:
self.link_table.append(node)
return len(self.link_table) -1
else:
return self.link_table.index(node)
@property
def active_child_node(self):
if self._active_child_node is None:
return None
return self.link_table[self._active_child_node]
@active_child_node.setter
def active_child_node(self, node):
self._active_child_node = self.get_node_index(node)
if self._active_child_node not in self._children:
self._children.append(self._active_child_node)
@property
def children(self):
return [self.link_table[i] for i in self._children]
@children.setter
def children(self, children):
for i, child in enumerate(children):
children[i] = self.get_node_index(child)
self._children = children
@property
def primary_parent_node(self):
if self._primary_parent_node is None:
return None
return self.link_table[self._primary_parent_node]
@primary_parent_node.setter
def primary_parent_node(self, node):
self._primary_parent_node = self.get_node_index(node)
@property
def solution_node(self):
nd = self
while nd and not nd.is_solution:
nd = nd.primary_parent_node
return nd
def _null(self):
for ch in self.children:
ch._null()
self._children = []
self._active_child_node = None
self._primary_parent_node = None
def _reindex(self, old_table, new_index):
self.link_table = new_index
children = self._children
self._children = []
for ch in children:
self._children.append(new_index.index(old_table[ch]))
if self._active_child_node is not None:
self._active_child_node = new_index.index(old_table[self._active_child_node])
if self._primary_parent_node is not None:
pn = old_table[self._primary_parent_node]
self._primary_parent_node = new_index.index(pn)
def set_params(self):
OV.SetParam('snum.refinement.last_R1',self.R1)
OV.SetParam('snum.refinement.last_wR2',self.wR2)
if self.is_solution:
OV.set_solution_program(OV.getCompatibleProgramName(self.program), self.method)
else:
if self.program != 'Unknown':
OV.set_refinement_program(OV.getCompatibleProgramName(self.program), self.method)
def __setstate__(self, state):
self.__dict__.update(state)
class HistoryTree(Node):
is_root = True
def __init__(self):
self._primary_parent_node = None
self.link_table = []
self._children = []
self._active_child_node = None
self._active_node = None
self.name = OV.ModelSrc()
self._full_index = {self.name: self}
# 2.1 - the HKL digest is only,
# 2.2 - the digest of actual reflections up to the end
# 2.3 - fixing the digests as the other would stop when sum hkl=0, not abs
# 2.4 - fixing so that 2.2-3 actually proceed to the end
# 2.5 - add dyn support, use cif_od register
# 2.6 - added snum phil
self.version = 2.6
self.hklFiles, self.dynFiles, self.cif_odFiles = {}, {}, {}
#maps simple digest of the file timestamp and path to full one
self.hklFilesMap, self.dynFilesMap, self.cif_odFilesMap = {}, {}, {}
self.label = "root"
self.next_sol_num = 1
def _updateData(self, node: Node, files: HistoryFiles):
if node.hkl is not None and node.hkl not in self.hklFiles:
full_md = self.hklFilesMap.get(node.hkl, None)
if full_md is None:
full_md = digestHKLFile(files.hkl)
self.hklFiles.setdefault(full_md, compressFile(files.hkl))
self.hklFilesMap[node.hkl] = full_md
if node.dyn is not None and node.dyn not in self.dynFiles:
full_md = self.dynFilesMap.get(node.dyn, None)
if full_md is None:
full_md = digestFile(files.dyn)
self.dynFiles.setdefault(full_md, compressFile(files.dyn))
self.dynFilesMap[node.dyn] = full_md
if node.cif_od is not None and node.cif_od not in self.cif_odFiles:
full_md = self.cif_odFilesMap.get(node.cif_od, None)
if full_md is None:
full_md = digestFile(files.cif_od)
self.cif_odFiles.setdefault(full_md, compressFile(files.cif_od))
self.cif_odFilesMap[node.cif_od] = full_md
def add_top_level_node(
self, files: HistoryFiles, is_solution=True, label=None):
if len(self.children) == 0:
saveOriginals(files)
if label is None:
label = 'Solution %s' %self.next_sol_num
self.next_sol_num += 1
name = hashlib.md5(time.asctime(time.localtime()).encode('utf-8')).hexdigest()
node = Node(self.link_table, name, files, label=label,
is_solution=is_solution, primary_parent_node=self)
self.children.append(node)
self.active_child_node = node
self.active_node = node
self._full_index.setdefault(name, node)
self._updateData(node, files)
return self.active_child_node.name
def add_node(self, files: HistoryFiles):
ref_name = hashlib.md5(time.asctime(time.localtime()).encode()).hexdigest()
node = Node(self.link_table, ref_name, files,
primary_parent_node=self.active_node)
self.active_node.active_child_node = node
self.active_node = node
self._full_index.setdefault(ref_name, node)
self._updateData(node, files)
@property
def active_node(self):
if self._active_node is None: return None
return self.link_table[self._active_node]
@active_node.setter
def active_node(self, node):
self._active_node = self.get_node_index(node)
OV.SetParam('snum.history.current_node', node.name)
while node._primary_parent_node is not None:
node.primary_parent_node.active_child_node = node
node = node.primary_parent_node
def find_solution_node_by_label(self, label):
for ndi in self._children:
if self.link_table[ndi].label == label:
return self.link_table[ndi]
return None
def del_node(self, child):
# store old index
old_table = [x for x in self.link_table]
if child._primary_parent_node is not None:
n_idx = self.link_table.index(child)
pn = child.primary_parent_node
pn._children.remove(n_idx)
if pn._active_child_node == n_idx:
pn._active_child_node = None
child._null()
new_lt = [self]
for n in self.link_table:
if n._primary_parent_node is not None:
new_lt.append(n)
self.link_table = new_lt
for n in self.link_table:
n._reindex(old_table, new_lt)
self._full_index = index_node(self, {})
def isTheSameHklDigest(self, node: Node, hklPath: str):
md5 = self.hklFilesMap.get(node.hkl, node.hkl)
return os.path.exists(hklPath) and digestHKLFile(hklPath) == md5
def isTheSameDynDigest(self, node: Node, dynPath: str):
md5 = self.dynFilesMap.get(node.dyn, node.dyn)
return os.path.exists(dynPath) and digestFile(dynPath) == md5
def isTheSameCifODDigest(self, node: Node, cif_odPath: str):
md5 = self.cif_odFilesMap.get(node.cif_od, node.cif_od)
return os.path.exists(cif_odPath) and digestFile(cif_odPath) == md5
def getHklData(self, node):
return self.hklFiles[self.hklFilesMap.get(node.hkl, node.hkl)]
def getDynData(self, node):
return self.dynFiles[self.dynFilesMap.get(node.dyn, node.dyn)]
def getCifODData(self, node):
return self.cif_odFiles[self.cif_odFilesMap.get(node.cif_od, node.cif_od)]
def delete_solution_node_by_label(self, label):
node = self.find_solution_node_by_label(label)
if not node:
return False
self._active_node = None
self.del_node(node)
if len(self._children) == 0:
self._active_node = None
else:
self._active_node = self._children[0]
self._full_index = index_node(self, {})
return True
def __setstate__(self, state):
Node.__setstate__(self, state)
def _build_cif_od_register_etc(self, node: Node, call_id=0):
"""For upgrade from 2.4->2.5 only"""
try:
node.dyn = None
if call_id > 0 and node.cif_od:
if len(node.cif_od) != 32: # already upgraded?
md = digestData(decompressFile(node.cif_od))
self.cif_odFiles.setdefault(md, node.cif_od)
node.cif_od = md
except AttributeError:
node.cif_od = None
call_id += 1
for c in node.children:
self._build_cif_od_register_etc(c, call_id=call_id)
def upgrade(self):
current_version = 2.6 # current version
if self.version == current_version:
return
start_time = time.time()
if self.version < 2.2:
new_index = {}
self.hklFilesMap = {}
for k,v in self.hklFiles.items():
if not isinstance(v, (bytes, bytearray)):
v = v.encode('latin1')
md = digestHKLData(decompressFile(v))
new_index.setdefault(md, v)
self.hklFilesMap[k] = md
self.hklFiles = new_index
elif self.version < 2.4:
new_index = {}
r_index = {}
# build reverse index
for k,v in self.hklFilesMap.items():
r_index.setdefault(v, list()).append(k)
for k,v in self.hklFiles.items():
if not isinstance(v, (bytes, bytearray)):
v = v.encode('latin1')
md = digestHKLData(decompressFile(v))
new_index.setdefault(md, v)
if k in r_index: # unbound HKL file?
for hkl_d in r_index[k]:
self.hklFilesMap[hkl_d] = md
self.hklFiles = new_index
if self.version < 2.5: # create cif_od register
self.dynFiles, self.cif_odFiles = {}, {}
self.dynFilesMap, self.cif_odFilesMap = {}, {}
self._build_cif_od_register_etc(self)
self.version = current_version
print("History has been upgraded in: %.2f ms" %((time.time() - start_time)*1000))
print("History contains %s HKL file(s), %s cif_od files and %s nodes" %(
len(self.hklFiles),len(self.cif_odFiles),len(self._full_index)))
def index_node(node, full_index):
if node.name not in full_index:
full_index.setdefault(node.name, node)
for child in node.children:
index_node(child, full_index)
return full_index
def delete_history(node_name):
node = tree._full_index.get(node_name)
if not node:
for nd in tree.link_table:
if nd.label == node_name:
node = nd
break
if not node:
print("Unknown branch: %s" %(node_name))
return
parent = node.primary_parent_node
tree.del_node(node)
if len(parent._children) == 0:
active_node = None
else:
active_node = parent.children[0]
while active_node.active_child_node is not None:
active_node = active_node.active_child_node
tree.active_node = active_node
tree._full_index = index_node(tree, {})
hist.revert_history(active_node.name)
def saveOriginals(originals: HistoryFiles):
backupFolder = os.path.join(OV.StrDir(), "originals")
if not os.path.exists(backupFolder):
os.mkdir(backupFolder)
duplicates = 0
for filePath in originals.files:
dest_base = os.path.join(backupFolder, os.path.basename(filePath))
dest_file = dest_base
src_stat = os.stat(filePath)
src_sha256 =None
#find unique backup name
inc = 1
do_copy = True
while os.path.exists(dest_file):
dest_stat = os.stat(dest_file)
if src_stat.st_size == dest_stat.st_size:
if src_stat.st_mtime == dest_stat.st_mtime:
do_copy = False
break
else: # fall back to digests
import hashlib
if src_sha256 is None:
src_sha256 = hashlib.sha256(open(filePath, 'rb').read()).hexdigest()
if src_sha256 == hashlib.sha256(open(dest_file, 'rb').read()).hexdigest():
do_copy = False
break
dest_file = "%s_%s" %(dest_base, inc)
inc += 1
duplicates += 1
if do_copy:
shutil.copy2(filePath, dest_file)
if duplicates > 0:
olx.Echo("%s Previous backups found!" %(duplicates), m="warning")
def compressFile(filePath):
return zlib.compress(open(filePath, "rb").read(), 9)
def decompressFile(fileData):
if not isinstance(fileData, (bytes, bytearray)):
fileData = fileData.encode('latin1')
return zlib.decompress(fileData)
def digestHKLData(fileData):
import io
md = hashlib.md5()
input = io.BytesIO(fileData)
l = input.readline()
while l:
try:
s = abs(int(l[0:4])) + abs(int(l[4:8])) + abs(int(l[8:12]))
if s == 0:
break
except:
break
md.update(l)
l = input.readline()
return md.hexdigest()
def digestHKLFile(filePath):
return digestHKLData(open(filePath, "rb").read())
def digestFile(filePath):
md = hashlib.md5()
md.update(open(filePath, "rb").read())
return md.hexdigest()
def digestData(fileData):
import io
md = hashlib.md5()
input = io.BytesIO(fileData)
md.update(input.read())
return md.hexdigest()
def digestPath(filePath):
return hashlib.md5(b'%f%s' %(os.path.getmtime(filePath),
filePath.encode('utf-8'))).hexdigest()
def get_snum_data():
try:
from io import StringIO
out = StringIO()
olx.phil_handler.save_param_file(
file_name=None, out_stream=out,
scope_name='snum', diff_only=True)
return out.getvalue().encode("utf-8")
except:
return None
def make_history_bars():
if olx.GetVar("update_history_bars", 'true') == 'false':
olx.UnsetVar("update_history_bars")
return
hist.make_graph()
OV.registerFunction(make_history_bars)
def get(where, what):
if tree:
if where == 'solution':
acn = tree.active_child_node
solution = True
else:
acn = tree.active_node
solution = False
if acn and acn.is_solution == solution:
if what == 'program':
if acn.program.lower().startswith('shelx'):
return acn.program.upper()
return acn.program
elif what == 'method':
return acn.method
return 'Unknown'
OV.registerFunction(get, namespace="history")
def popout_history_tree(width=800, height=500):
width = int(width)
height = int(height)
font_colour = OV.GetParam('gui.html.font_colour')
font_size = OV.GetParam('HtmlGuiFontSize')
html = """
""" %(font_colour, font_size, width, height)
htm_location = "popout-history-tree.htm"
pop_name = 'history-tree'
pop_str = "popup %s %s -b=stci -t='History Tree' -w=%s -h=%s -x=1 -y=50" %(
#pop_name, htm_location, int(width), int(height))
pop_name, htm_location, int(width*1.033), int(height*1.1))
OV.write_to_olex(htm_location, html)
olex.m(pop_str)
olx.html.SetBorders(pop_name,0)
olex.m(pop_str)
OV.registerFunction(popout_history_tree)
def make_html_tree(node, tree_text, indent_level, full_tree=False,
start_count=0, end_count=0):
indent = indent_level * '\t'
if node.is_root:
label = node.name
elif node.label is not None:
label = node.label
else:
label = '%s (%s)' %(node.program, node.method)
try:
label += ' - %.2f%%' %(node.R1 * 100)
except (ValueError, TypeError):
pass
if full_tree:
tree_text.append(indent + label + '\n' + indent + node.name + '\n')
indent_level += 1
elif (node.active_child_node is not None and
len(node.active_child_node.children) > 1 or
len(node.children) == 0):
if start_count != end_count:
label = "refinements %i - %i" %(start_count, end_count)
child = node
while (child.active_child_node is not None and
len(child.active_child_node.children) <=1):
child = child.active_child_node
tree_text.append(indent + label + '\n' + indent + child.name + '\n')
indent_level += 1
elif (node.is_root or
node.primary_parent_node.is_root or
len(node.children) > 1
#or node.program != node.primary_parent_node.program
# or
#len(node.primary_parent_node.children) > 1
):
start_count = end_count + 1
tree_text.append(indent + label + '\n' + indent + node.name + '\n')
indent_level += 1
end_count +=1
#tree_text.append(indent + label + '\n' + indent + node.name + '\n')
for node in node.children:
make_html_tree(
node, tree_text, indent_level, full_tree, start_count, end_count)
return tree_text
OV.registerFunction(delete_history, False, "history")