m).Fexp2)")
# convert axes in formula
metadata.setdefault("fit_slope", 1/wp.fit_slope)
metadata.setdefault("fit_y_intercept", -wp.fit_y_intercept/wp.fit_slope)
metadata.setdefault("<|E^2-1|>", wp.mean_e_sq_minus_1)
metadata.setdefault("%|E| > 2", wp.percent_e_sq_gt_2)
self.metadata = metadata
self.data.setdefault('dataset1', Dataset(wp.y,wp.x,metadata=metadata))
def make_gradient_box(self, size = (320, 35)):
boxWidth = size[0]
boxHeight = size[1]*0.4
boxTopOffset = self.imY * 0.035
colour = self.pageColour
im = Image.new('RGB', size, colour)
draw = ImageDraw.Draw(im)
#target_left = (0,0,255)
#target_right = (0,255,0)
middle = boxWidth/2
box = (0,boxTopOffset,boxWidth-1,boxTopOffset+boxHeight-1)
draw.rectangle(box, fill=self.fillColour, outline=self.outlineColour)
margin_left = int((boxWidth/4))
margin_right = int((boxWidth/4)*3)
scale = float((0.968-0.736)/(boxWidth - (margin_right - margin_left)))
metadata = self.data['dataset1'].metadata()
value = float(metadata.get("<|E^2-1|>", 0))
begin = (0.736 - margin_left * scale)
end = (0.968 + margin_left * scale)
self.wilson_grad_begin = begin
self.wilson_grad_end = end
if value < (0.736 - 0.736*0.2):
max1 = 128.0
c1 = (255.0, 0 , 0)
max2 = 128.0
c2 = (0, 0, 0)
elif (0.736 - 0.736*0.1) < value < (0.736 + 0.736*0.1):
max1 = 128.0
c1 = (0, 255.0 , 0)
max2 = 128.0
c2 = (0, 0, 0)
elif (0.736 + 0.736*0.1) <= value <= (0.968 - 0.968*0.1):
max1 = 128.0
c1 = (255.0, 0, 0)
max2 = 128.0
c2 = (255.0, 0, 0)
elif (0.968 - 0.968*0.1) < value < (0.968 + 0.968*0.1):
max1 = 128.0
c1 = (0, 0, 0)
max2 = 128.0
c2 = (0, 255.0, 0)
elif value > (0.968 + 0.968*0.1):
max1 = 128.0
c1 = (0, 0, 0)
max2 = 128.0
c2 = (255.0, 0, 0)
else:
max1 = 128.0
c1 = (255.0, 0, 0)
max2 = 128.0
c2 = (255.0, 0, 0)
for i in range(boxWidth-2):
i += 1
if i == margin_left:
txt = "acentric"
txt = OV.TranslatePhrase(txt)
wX, wY = IT.textsize(draw, txt, font_size=self.font_size_tiny)
top_left = (i - int(wX / 2), 0)
IT.write_text_to_draw(draw, txt, top_left=top_left, font_size=self.font_size_tiny, font_colour=self.gui_html_highlight_colour)
txt = "0.736"
wX, wY = get_text_size(draw, txt, font=self.font_tiny)
draw.text((i - int(wX / 2), boxTopOffset + boxHeight), "%s" % txt, font=self.font_tiny, fill=self.titleColour)
if i == (margin_right):
txt = "centric"
txt = OV.TranslatePhrase(txt)
wX, wY = get_text_size(draw, txt, font=self.font_tiny)
top_left = (i-int(wX/2), 0)
IT.write_text_to_draw(draw, txt, top_left=top_left, font_size=self.font_size_tiny, font_colour=self.gui_html_highlight_colour)
txt = "0.968"
wX, wY = get_text_size(draw, txt, font=self.font_small)
draw.text((i - int(wX / 2), boxTopOffset + boxHeight), "%s" % txt, font=self.font_tiny, fill=self.titleColour)
top = int(boxTopOffset+1)
bottom = int(boxTopOffset+boxHeight-2)
if i < margin_left:
step = (max1)/margin_left
col = max1+step*(margin_left - i)
col = int(col)
fill = self.grad_fill(max1, c1, col)
draw.line(((i, top),(i, bottom)), fill=fill)
elif i == margin_left:
draw.line(((i, top),(i, bottom)), fill=self.outlineColour)
elif i < middle:
step = (max1)/(middle-margin_left)
col = max1+step*(i - margin_left)
col = int(col)
fill = self.grad_fill(max1, c1, col)
draw.line(((i, top),(i, bottom)), fill=fill)
elif i == middle:
draw.line(((i, top),(i, bottom)), fill=self.outlineColour)
elif i > middle and i < (margin_right):
step = (max2)/(margin_right-middle)
col = max2+step*(margin_right - i)
col = int(col)
fill = self.grad_fill(max2, c2, col)
draw.line(((i, top),(i, bottom)), fill=fill)
elif i == (margin_right):
draw.line(((i, top),(i, bottom)), fill=self.outlineColour)
else:
step = ((max2)/(boxWidth-margin_right))
col = max2+step*(i - margin_right)
col = int(col)
fill = self.grad_fill(max2, c2, col)
draw.line(((i, top),(i, bottom)), fill=fill)
val = int((value - begin) / scale)
txt = chr(8226)
wX, wY = get_text_size(draw, txt, font=self.font_bold_normal)
draw.ellipse(((val-int(wX/2), boxTopOffset+3),(val+int(wX/2), boxTopOffset+boxHeight-3)), fill=(255,235,10))
draw.text((val-int(wX/2), boxTopOffset-self.imY*0.001), "%s" %txt, font=self.font_bold_normal, fill="#ff0000")
image_location = "%s.png" %("grad")
OlexVFS.save_image_to_olex(im, image_location, 1)
return im
def grad_fill(self, max, c1, col):
fill = []
for c in c1:
if not c:
c = col
fill.append(int(col))
else:
fill.append(int(c))
fill = tuple(fill)
return fill
class ChargeFlippingPlot(PrgAnalysis):
def __init__(self):
program = ExternalPrgParameters.defineExternalPrograms()[0].programs["olex2.solve"]
method = program.methods["Charge Flipping"]
self.item = "Charge Flipping"
PrgAnalysis.__init__(self, program, method)
def run_charge_flipping_graph(self, flipping, solving, previous_state):
top = self.graph_top
marker_width = 5
title = self.graphInfo.get('Title', "")
width = self.params.size_x
height = self.graph_bottom - self.graph_top
if solving.state is solving.guessing_delta:
if previous_state is not solving.guessing_delta:
txt = "%s" %self.attempt
wX, wY = IT.textsize(self.draw, txt, font_size=self.font_size_large, font_name = "DefaultFont Bold")
x = self.counter + marker_width + 5
top_left = (x, self.graph_bottom -wY -3)
IT.write_text_to_draw(self.draw, txt, top_left=top_left, font_size=self.font_size_large, font_name = "DefaultFont Bold", font_colour=self.light_grey)
self.attempt += 1
if self.counter != 0:
self.counter += 1
self.draw.line(((self.counter + marker_width, self.graph_top),(self.counter + marker_width, self.graphY+self.graph_top - 2)), width=1, fill=(230, 230, 230))
return
elif solving.state is solving.solving:
cc = flipping.c_tot_over_c_flip()
R1 = flipping.r1_factor()
self.counter+=marker_width
if self.counter > width - 10:
self.make_empty_graph()
self.draw = ImageDraw.Draw(self.im)
self.counter = self.bSides
txt = "...continued"
wX, wY = IT.textsize(self.draw, txt, font_size=self.font_size_normal)
x = width - wX - self.bSides - 3
top_left = (x, 20)
IT.write_text_to_draw(self.draw, txt, top_left=top_left, font_size=self.font_size_normal, font_colour=self.light_grey)
x = self.counter
## Draw CC
txt = "cc=%.3f" %cc
if cc > 1: cc = 1
ccR = int(255*cc)
ccG = int(255*(1.3-cc))
ccB = 0
cc = int(height*(1-cc) + top)
box = (x,cc,x+marker_width,cc+marker_width)
self.draw.rectangle(box, fill=(ccR, ccG, ccB), outline=(int(ccR/2), int(ccG/2), 0))
## Draw R1
txt += ", R1=%.3f" %R1
rR = int(255*R1*2)
rG = int(255*(1.3-R1*2))
rB = 0
R1 = height*(1-R1) + top
box = (x,R1,x+marker_width,R1+2)
self.draw.rectangle(box, fill=(rR, rG, rB), outline=(int(rR/2), int(rG/2), 0))
font_name = "DefaultFont"
font_size = 10
font = IT.registerFontInstance(font_name, font_size)
legend_top = height + 20
legend_top = self.graph_bottom + 1
m_offset = 5
## Wipe the legend area
box = (0,legend_top,width,legend_top + 20)
self.draw.rectangle(box, fill=self.fillColour)
## Draw CC Legend
box = (10,legend_top +m_offset,10+marker_width, legend_top+marker_width + m_offset)
self.draw.rectangle(box, fill=(ccR, ccG, ccB), outline=(int(ccR/2), int(ccG/2), 0))
tt = "CC"
top_left = (10+marker_width+3, legend_top)
IT.write_text_to_draw(self.draw, txt, top_left=top_left, font_size=self.font_size_normal, font_colour=self.light_grey)
## Draw R1 Legend
box = (40,legend_top + m_offset + 1,40+marker_width,legend_top + m_offset + 3)
self.draw.rectangle(box, fill=(rR, rG, rB), outline=(int(rR/2), int(rG/2), 0))
tt = "R1"
self.draw.text((40+marker_width+3, legend_top), "%s" %tt, font=self.font_large, fill="#888888")
## Draw Current Numbers
wX, wY = get_text_size(self.draw, txt, font=self.font_large)
x = width - wX - self.bSides
self.draw.text((x, legend_top), "%s" %txt, font=self.font_large, fill="#888888")
self.update_image()
class CumulativeIntensityDistribution(Analysis):
def __init__(self):
Analysis.__init__(self)
self.item = "cumulative"
self.graphInfo["Title"] = OV.TranslatePhrase("Cumulative Intensity Distribution")
self.graphInfo["pop_html"] = self.item
self.graphInfo["pop_name"] = self.item
self.graphInfo["TopRightTitle"] = self.TopRightTitle
self.auto_axes = False
self.make_cumulative_intensity_distribution()
self.popout()
if self.params.cumulative_intensity.output_csv_file:
self.output_data_as_csv()
def make_cumulative_intensity_distribution(self):
acentric = "1-exp(-x)"
centric = "sqrt(erf(0.5*x))"
twinned_acentric = "1-(1+2*x)*exp(-2*x)" # E. Stanley, J.Appl.Cryst (1972). 5, 191
locals = {'erf':erf}
self.cctbx_cumulative_intensity_distribution()
self.make_empty_graph(axis_x = True)
self.plot_function(centric, locals=locals)
self.plot_function(acentric, locals=locals)
self.plot_function(twinned_acentric, locals=locals)
self.metadata['equations'] = [{'eq':acentric, 'name':'acentric'},
{'eq':centric, 'name':'centric'},
{'eq':twinned_acentric, 'name':"twinned acentric"},
]
key = self.draw_key(({'type': 'function',
'number': 1,
#'label': OV.TranslatePhrase('Centric')},
'label': 'Centric'},
{'type':'function',
'number': 2,
#'label': OV.TranslatePhrase('Acentric')},
'label': 'Acentric'},
{'type': 'function',
'number': 3,
#'label': OV.TranslatePhrase('Twinned Acentric')}
'label': 'Twinned Acentric'}
))
self.im.paste(key,
(int(self.graph_right-(key.size[0]+40)),
int(self.graph_bottom-(key.size[1]+40)))
)
self.draw_pairs(no_negatives=True)
def cctbx_cumulative_intensity_distribution(self, verbose=False):
from reflection_statistics import OlexCctbxGraphs
xy_plot = OlexCctbxGraphs(
'cumulative',
n_bins=self.params.cumulative_intensity.n_bins).xy_plot
metadata = {}
metadata.setdefault("y_label", xy_plot.yLegend)
metadata.setdefault("x_label", xy_plot.xLegend)
metadata.setdefault("name", 'Cumulative')
metadata['marker'] = {'size':12}
self.metadata = metadata
self.data.setdefault('dataset1', Dataset(xy_plot.x, xy_plot.y,metadata=metadata))
if verbose:
self.data['dataset1'].show_summary()
class CompletenessPlot(Analysis):
def __init__(self):
Analysis.__init__(self)
self.item = "completeness"
self.graphInfo["Title"] = OV.TranslatePhrase("Completeness Plot")
self.graphInfo["pop_html"] = self.item
self.graphInfo["pop_name"] = self.item
self.graphInfo["TopRightTitle"] = self.TopRightTitle
self.reverse_x = self.params.completeness.resolution_as in ('d_spacing', 'd_star_sq')
self.auto_axes = False
if self.params.completeness.resolution_as == "d_spacing":
self.use_log=10
self.auto_axes=True
else:
self.use_log=0
self.cctbx_completeness_statistics()
self.draw_pairs(reverse_x=self.reverse_x)
self.draw_fitlines()
self.popout()
if self.params.completeness.output_csv_file:
self.output_data_as_csv()
def draw_fitlines(self):
# ALL LAUE Info
deg = u"\u00B0"
completeness_info_text = HOS_instance.completeness_info_text
resolution_as = self.params.completeness.resolution_as
ttheta_full = round(completeness_info_text["Laue Full"]["2Theta"],2)
compl_full = round(completeness_info_text["Laue Full"]["completeness"],2)
ttheta_max = round(completeness_info_text["Laue Max"]["2Theta"],2)
compl_max = round(completeness_info_text["Laue Max"]["completeness"],2)
if resolution_as != "two_theta":
from cctbx import uctbx
from cctbx_olex_adapter import OlexCctbxAdapter
temp = OlexCctbxAdapter()
if resolution_as == "d_spacing":
res_max = uctbx.two_theta_as_d(ttheta_max,temp.wavelength,deg=True)
res_full = uctbx.two_theta_as_d(ttheta_full,temp.wavelength,deg=True)
elif resolution_as == "d_star_sq":
res_max = uctbx.two_theta_as_d_star_sq(ttheta_max,temp.wavelength,deg=True)
res_full = uctbx.two_theta_as_d_star_sq(ttheta_full,temp.wavelength,deg=True)
elif resolution_as == "stol":
res_max = uctbx.d_star_sq_as_stol(uctbx.two_theta_as_d_star_sq(ttheta_max,temp.wavelength,deg=True))
res_full = uctbx.d_star_sq_as_stol(uctbx.two_theta_as_d_star_sq(ttheta_full,temp.wavelength,deg=True))
elif resolution_as == "stol_sq":
res_max = uctbx.d_star_sq_as_stol_sq(uctbx.two_theta_as_d_star_sq(ttheta_max,temp.wavelength,deg=True))
res_full = uctbx.d_star_sq_as_stol_sq(uctbx.two_theta_as_d_star_sq(ttheta_full,temp.wavelength,deg=True))
text_full = "Full %s | Laue: %s%%" %(round(res_full,2), compl_full)
text_max = "Max %s | Laue: %s%%" %(round(res_max,2), compl_max)
else:
res_full = ttheta_full
res_max = ttheta_max
text_full = "Full %s%s | Laue: %s%%" %(ttheta_full, deg, compl_full)
text_max = "Max %s%s | Laue: %s%%" %(ttheta_max, deg, compl_max)
if not HOS_instance.hkl_stats['IsCentrosymmetric']:
compl_full_point = round(completeness_info_text["Point Full"]["completeness"],2)
text_full += ", Point: %s%%" %(compl_full_point)
compl_max_point = round(completeness_info_text["Point Max"]["completeness"],2)
text_max += ", Point: %s%%" %(compl_max_point)
try:
self.draw_fit_line(slope=0, y_intercept=0, x_intercept=res_max, write_equation=False, write_text=text_max, rotate_text="top_lineright")
self.draw_fit_line(slope=0, y_intercept=0, x_intercept=res_full, write_equation=False, write_text=text_full, rotate_text="bottom_lineleft")
except:
pass
def cctbx_completeness_statistics(self):
from reflection_statistics import OlexCctbxGraphs
params = self.params.completeness
self.make_empty_graph(axis_x = True)
xy_plot = OlexCctbxGraphs(
'completeness',
reflections_per_bin=params.reflections_per_bin,
bin_range_as=params.resolution_as, non_anomalous=True).xy_plot
metadata = {}
metadata.setdefault("y_label", OV.TranslatePhrase("Shell Completeness"))
metadata.setdefault("x_label", params.resolution_as)
metadata.setdefault("name", 'Completeness')
self.metadata = metadata
x = [xy_plot.x[i] for i in range(len(xy_plot.y)) if xy_plot.y[i] is not None]
y = [xy_plot.y[i]*100 for i in range(len(xy_plot.y)) if xy_plot.y[i] is not None]
self.data.setdefault('dataset1', Dataset(x, y, metadata=metadata))
if not olex_core.SGInfo()['Centrosymmetric']:
xy_plot = OlexCctbxGraphs(
'completeness',
reflections_per_bin=params.reflections_per_bin,
bin_range_as=params.resolution_as, non_anomalous=False).xy_plot
x = [xy_plot.x[i] for i in range(len(xy_plot.y)) if xy_plot.y[i] is not None]
y = [xy_plot.y[i]*100 for i in range(len(xy_plot.y)) if xy_plot.y[i] is not None]
self.data.setdefault('dataset2', Dataset(x, y, metadata=metadata))
key = self.draw_key(({'type': 'marker',
'number': 1,
'label': OV.TranslatePhrase('Laue')},
{'type':'marker',
'number': 2,
'label': OV.TranslatePhrase('Point group')},
))
self.im.paste(key,
(int(self.graph_left + 10),
int(self.graph_bottom-(key.size[1]+20)))
)
class SystematicAbsencesPlot(Analysis):
def __init__(self):
Analysis.__init__(self)
self.item = "sys_absences"
self.graphInfo["Title"] = OV.TranslatePhrase("Systematic Absences Intensity Distribution")
self.graphInfo["pop_html"] = self.item
self.graphInfo["pop_name"] = self.item
self.graphInfo["TopRightTitle"] = self.TopRightTitle
self.auto_axes = True
self.cctbx_systematic_absences_plot()
self.popout()
if self.have_data:
if self.params.systematic_absences.output_csv_file:
self.output_data_as_csv()
def cctbx_systematic_absences_plot(self):
from reflection_statistics import OlexCctbxGraphs
xy_plot = OlexCctbxGraphs('sys_absent').xy_plot
metadata = {}
metadata.setdefault("y_label", xy_plot.yLegend)
metadata.setdefault("x_label", xy_plot.xLegend)
metadata.setdefault("name", 'Systematic Absences')
self.metadata = metadata
if xy_plot.x is None:
self.have_data = False
self.draw_origin = True
self.make_empty_graph(axis_x = True)
print("No systematic absences present")
return None
self.have_data = True
self.data.setdefault('dataset1', Dataset(xy_plot.x, xy_plot.y, indices=xy_plot.indices, metadata=metadata))
self.draw_origin = True
self.make_empty_graph(axis_x = True)
self.draw_pairs(marker_size_factor = 1/1.5)
class bijvoet_differences_scatter_plot(Analysis):
def __init__(self):
Analysis.__init__(self)
self.item = "bijvoet_differences_scatter"
self.graphInfo["pop_html"] = self.item
self.graphInfo["pop_name"] = self.item
self.graphInfo["TopRightTitle"] = self.TopRightTitle
self.auto_axes = True
import reflection_statistics
use_students_t = self.params.bijvoet_differences_scatter_plot.use_students_t
xy_plot = reflection_statistics.bijvoet_differences_scatter_plot(
use_students_t=use_students_t).xy_plot_info()
if xy_plot is None:
self.have_data = False
return
self.graphInfo["Title"] = OV.TranslatePhrase(xy_plot.title)
metadata = {}
metadata.setdefault("fit_slope", xy_plot.fit_slope)
metadata.setdefault("fit_y_intercept", xy_plot.fit_y_intercept)
metadata.setdefault("y_label", xy_plot.yLegend)
metadata.setdefault("x_label", xy_plot.xLegend)
metadata.setdefault("R", xy_plot.R)
metadata.setdefault("name", 'Bijvoet Differences')
self.metadata = metadata
self.have_data = True
self.data.setdefault(
'dataset1', Dataset(xy_plot.x, xy_plot.y, sigmas=xy_plot.sigmas,
indices=xy_plot.indices, metadata=metadata))
self.draw_origin = True
self.make_empty_graph(axis_x = True)
self.draw_pairs(marker_size_factor = 1/1.5)
if self.have_data:
self.popout()
if self.params.bijvoet_differences_scatter_plot.output_csv_file:
self.output_data_as_csv()
class bijvoet_differences_NPP(Analysis):
def __init__(self):
Analysis.__init__(self)
self.item = "bijvoet_differences_NPP"
self.graphInfo["pop_html"] = self.item
self.graphInfo["pop_name"] = self.item
self.graphInfo["TopRightTitle"] = self.TopRightTitle
self.auto_axes = True
import reflection_statistics
params = self.params.bijvoet_differences_probability_plot
use_students_t = params.use_students_t
use_fcf = params.source == "fcf"
xy_plot = reflection_statistics.bijvoet_differences_NPP(
use_students_t=use_students_t, use_fcf=use_fcf).xy_plot_info()
if xy_plot is None:
self.have_data = False
return
self.graphInfo["Title"] = OV.TranslatePhrase(xy_plot.title)
metadata = {}
metadata.setdefault("fit_slope", xy_plot.fit_slope)
metadata.setdefault("fit_y_intercept", xy_plot.fit_y_intercept)
metadata.setdefault("y_label", xy_plot.yLegend)
metadata.setdefault("x_label", xy_plot.xLegend)
metadata.setdefault("R", xy_plot.R)
self.metadata = metadata
self.have_data = True
self.data.setdefault('dataset1', Dataset(xy_plot.x, xy_plot.y, indices=xy_plot.indices, metadata=metadata))
self.draw_origin = True
self.make_empty_graph(axis_x = True)
self.draw_pairs(marker_size_factor = 1/1.5)
if self.have_data:
self.popout()
if self.params.bijvoet_differences_probability_plot.output_csv_file:
self.output_data_as_csv()
class Normal_probability_plot(Analysis):
def __init__(self):
Analysis.__init__(self)
self.item = "Normal_probability_plot"
self.graphInfo["Title"] = OV.TranslatePhrase("Normal Probability Plot")
self.graphInfo["pop_html"] = self.item
self.graphInfo["pop_name"] = self.item
self.graphInfo["TopRightTitle"] = self.TopRightTitle
self.auto_axes = True
self.draw_origin = True
self.make_normal_probability_plot()
self.popout()
if self.params.normal_probability.output_csv_file in (True, 'true', 'True'):
self.output_data_as_csv()
def make_normal_probability_plot(self):
from reflection_statistics import normal_probability_plot
xy_plot = normal_probability_plot().xy_plot_info()
self.metadata.setdefault("y_label", xy_plot.yLegend)
self.metadata.setdefault("x_label", xy_plot.xLegend)
metadata = {}
metadata.setdefault("fit_slope", xy_plot.fit_slope)
metadata.setdefault("fit_y_intercept", xy_plot.fit_y_intercept)
metadata.setdefault("R", xy_plot.R)
amplitudes = [elem[1] for elem in list(xy_plot.amplitudes_array)]
metadata['amplitudes'] = amplitudes
data = Dataset(
xy_plot.x, xy_plot.y, indices=xy_plot.indices, metadata=metadata)
self.data.setdefault('dataset1', data)
self.make_empty_graph(axis_x = True)
self.draw_pairs()
class Fractal_Dimension(Analysis):
def __init__(self):
Analysis.__init__(self)
self.item = "Fractal_Dimension_Plot"
self.graphInfo["Title"] = OV.TranslatePhrase("Fractal Dimension Plot")
self.graphInfo["pop_html"] = self.item
self.graphInfo["pop_name"] = self.item
self.graphInfo["TopRightTitle"] = self.TopRightTitle
self.auto_axes = True
self.max_y = 3.05
self.min_y = 0.00
self.min_x = -1.0
self.max_x = 1.0
self.delta_x = 0.1
self.delta_y = 0.5
self.params.n_divisions = 10
self.draw_origin = True
self.make_fractal_dimension_plot()
self.popout()
def make_fractal_dimension_plot(self):
from reflection_statistics import fractal_dimension
xy_plot = fractal_dimension(parent=self, resolution=0.1, stepsize=0.01).xy_plot_info()
self.metadata.setdefault("y_label", xy_plot.yLegend)
self.metadata.setdefault("x_label", xy_plot.xLegend)
data = Dataset(xy_plot.x, xy_plot.y)
self.data.setdefault('dataset1', data)
self.make_empty_graph(axis_x = True)
self.ax_marker_length = int(self.imX * 0.006)
self.get_division_spacings_and_scale()
for dataset in list(self.data.values()):
self.draw_data_points(dataset.xy_pairs(), sigmas=dataset.sigmas, indices=dataset.indices, hrefs=dataset.hrefs, targets=dataset.targets)
self.draw_x_axis()
self.draw_y_axis()
self.draw_info("e_gross: %8.2f e-\ne_net: %10.2f e-" % (xy_plot.e_gross, xy_plot.e_net), font_size=self.font_size_small)
class MuPlot(Analysis):
def __init__(self):
Analysis.__init__(self)
self.item = "Mu_Plot"
self.graphInfo["Title"] = OV.TranslatePhrase("Mu Plot")
self.graphInfo["pop_html"] = self.item
self.graphInfo["pop_name"] = self.item
self.graphInfo["TopRightTitle"] = self.TopRightTitle
self.common_wl = [2.2911, 1.5419, 1.3923, 1.3414, 0.71073, 0.5609, 0.5136]
self.common_wl_name = ["Cr", "Cu Ka", "Cu Kb", "Ga", "Mo", "Ag", "In"]
self.scale = 4
self.auto_axes = True
self.min_x = 0.1
self.max_x = 2.5
self.delta_x = 0.1
self.params.n_divisions = 10
self.reverse_x = True
self.extend_x = False
self.draw_origin = True
self.make_mu_plot()
self.popout()
def make_mu_plot(self):
import numpy as np
from brennan import brennan
from cctbx.array_family import flex
br = brennan()
steps = 250
self.x = flex.double(steps)
for i, v in enumerate(np.linspace(self.min_x, self.max_x, steps)):
self.x[i] = v
self.metadata.setdefault("x_label", IT.get_unicode_characters("Wavelength (Angstrom)"))
self.metadata.setdefault("y_label", "Mu (Kbarns)")
import olexex
rm = olexex.OlexRefinementModel()
elements = list(rm.get_unique_types(use_charges=True))
elements.sort()
atoms = rm.atoms()
refined_disp = []
for a in atoms:
if 'disp' in a:
fp, fdp = a['disp']
refined_disp.append((a['label'], fp, fdp, a['type']))
keys = []
self.make_empty_graph(axis_x=True)
self.ax_marker_length = int(self.imX * 0.006)
wavelength = float(olx.xf.exptl.Radiation())
refined_data = {}
colours = []
colours_mark = []
for n, e in enumerate(elements):
y = flex.double(steps)
problem = False
for i, v in enumerate(np.linspace(self.min_x, self.max_x, steps)):
try:
y[i] = br.get_mu_at_angstrom(v, e) / 1000
except:
print(f"Error getting Value for {e}; No Conoversion to ยต possible!")
problem = True
break
if problem == True:
continue
data = Dataset(self.x, y)
self.data.setdefault(e, data)
col = IT.decimalColorToRGB(int(olx.GetMaterial("{}.Sphere".format(e)).split(";")[1]))
colours.append(col)
keys.append({'type': 'function',
'number': n + 1,
'label': e,
'colour': col})
for n, ref in enumerate(refined_disp):
x = flex.double(1)
x[0] = wavelength
y = flex.double(1)
y[0] = br.convert_fdp_to_mu(wavelength, ref[2], ref[3]) / 1000
data = Dataset(x, y)
refined_data.setdefault(ref[0], data)
col = IT.decimalColorToRGB(int(olx.GetMaterial("{}.Sphere".format(ref[3])).split(";")[1]))
for k in keys:
if k.get('colour') == col and k.get('type') == 'marker':
temp1, temp2, temp3 = col
temp1 = min(255, temp1 + 5)
temp2 = min(255, temp2 + 5)
temp3 = min(255, temp3 + 5)
col = (temp1, temp2, temp3)
del temp1, temp2, temp3
colours_mark.append(col)
keys.append({'type': 'marker',
'number': n + 1,
'label': ref[0],
'colour': col})
self.get_division_spacings_and_scale()
self.draw_x_axis()
self.draw_y_axis()
for i, wl in enumerate(self.common_wl):
self.draw_fit_line(slope=0,
y_intercept=0,
x_intercept=wl,
write_equation=False,
write_text=self.common_wl_name[i],
rotate_text="top_linemiddle",
width = 1)
key = self.draw_key(tuple(keys))
self.im.paste(key,
(int(self.graph_right - (key.size[0] + 10)),
int(self.graph_top + 10 * self.scale))
)
for i,data in enumerate(self.data.values()):
self.plot_data_points(data.xy_pairs(), colour=colours[i], width = 2)
for i,data in enumerate(refined_data.values()):
self.draw_data_points(data.xy_pairs(), colour=colours_mark[i], force_draw=True)
OV.registerFunction(MuPlot)
class AnomDispPlot(Analysis):
def __init__(self):
Analysis.__init__(self)
self.item = "AnomDispPlot"
self.graphInfo["Title"] = OV.TranslatePhrase("Anomalous Dispersion Plot")
self.graphInfo["pop_html"] = self.item
self.graphInfo["pop_name"] = self.item
self.graphInfo["TopRightTitle"] = self.TopRightTitle
self.scale = 4
self.auto_axes = True
self.min_x = 0.2
self.max_x = 2.5
self.delta_x = 0.1
self.params.n_divisions = 10
self.reverse_x = True
self.extend_x = False
self.common_wl = [2.2911, 1.5419, 1.3923, 1.3414, 0.71073, 0.5609, 0.5136]
self.common_wl_name = ["Cr", "Cu Ka", "Cu Kb", "Ga", "Mo", "Ag", "In"]
self.draw_origin = True
self.make_anom_plot()
self.popout()
def make_anom_plot(self):
import numpy as np
from brennan import brennan
from cctbx.array_family import flex
br = brennan()
steps = 250
self.x = flex.double(steps)
for i, v in enumerate(np.linspace(self.min_x, self.max_x, steps)):
self.x[i] = v
self.metadata.setdefault("x_label", IT.get_unicode_characters("Wavelength (Angstrom)"))
self.metadata.setdefault("y_label", "f' / f'' (electrons)")
import olexex
rm = olexex.OlexRefinementModel()
elements = list(rm.get_unique_types(use_charges=True))
elements.sort()
atoms = rm.atoms()
refined_disp = []
for a in atoms:
if 'disp' in a:
fp, fdp = a['disp']
refined_disp.append((a['label'], fp, fdp, a['type']))
keys = []
self.make_empty_graph(axis_x=True)
self.ax_marker_length = int(self.imX * 0.006)
wavelength = float(olx.xf.exptl.Radiation())
refined_data = {}
data2 = {}
min_y = 0
max_y = 0
colours = []
colours_mark = []
for n, e in enumerate(elements):
y = flex.double(steps)
y2 = flex.double(steps)
t = br.table(e)
for i, v in enumerate(np.linspace(self.min_x, self.max_x, steps)):
try:
r = t.at_angstrom(v)
y[i] = r.fp()
y2[i] = r.fdp()
except:
print(f"Error getting Value for {e}; Switching to Sasaki; Carefull with interpreting the Plot for {e}!")
from cctbx.eltbx import sasaki
tables = sasaki
t = tables.table(e)
r = t.at_angstrom(v)
y[i] = r.fp()
y2[i] = r.fdp()
min_y = min(min_y, y[i])
max_y = max(max_y, y2[i])
data = Dataset(self.x, y)
data_ = Dataset(self.x, y2)
col = IT.decimalColorToRGB(int(olx.GetMaterial("{}.Sphere".format(e)).split(";")[1]))
colours.append(col)
self.data.setdefault(e + "fp", data)
data2.setdefault(e + "fdp", data_)
keys.append({'type': 'function',
'number': n + 1,
'label': e,
'colour': col})
self.min_y = min_y * 1.1
self.max_y = max_y * 1.1
for n, ref in enumerate(refined_disp):
x = flex.double(2)
x[0] = wavelength
x[1] = x[0]
y = flex.double(2)
y[0] = ref[1]
y[1] = ref[2]
data = Dataset(x, y)
refined_data.setdefault(ref[0], data)
col = IT.decimalColorToRGB(int(olx.GetMaterial("{}.Sphere".format(ref[3])).split(";")[1]))
for k in keys:
if k.get('colour') == col and k.get('type') == 'marker':
temp1, temp2, temp3 = col
temp1 = min(255, temp1 + 5)
temp2 = min(255, temp2 + 5)
temp3 = min(255, temp3 + 5)
col = (temp1, temp2, temp3)
del temp1, temp2, temp3
colours_mark.append(col)
keys.append({'type': 'marker',
'number': n + 1,
'label': ref[0],
'colour': col})
self.get_division_spacings_and_scale()
self.draw_x_axis()
self.draw_y_axis()
for i, wl in enumerate(self.common_wl):
self.draw_fit_line(slope=0,
y_intercept=0,
x_intercept=wl,
write_equation=False,
write_text=self.common_wl_name[i],
rotate_text="top_linemiddle",
width = 1)
key = self.draw_key(tuple(keys))
self.im.paste(key,
(int(self.graph_right - (key.size[0] + 10)),
int(self.graph_top + 10 * self.scale))
)
for i, data in enumerate(self.data.values()):
self.plot_data_points(data.xy_pairs(), width=2, colour=colours[i])
self.function_counter = 0
for i,data in enumerate(data2.values()):
self.plot_data_points(data.xy_pairs(), width=2, colour=colours[i])
for i,data in enumerate(refined_data.values()):
self.draw_data_points(data.xy_pairs(), colour=colours_mark[i], force_draw=True)
OV.registerFunction(AnomDispPlot)
class Fobs_Fcalc_plot(Analysis):
def __init__(self, batch_number=None):
Analysis.__init__(self)
self.item = "Fobs_Fcalc"
self.graphInfo["Title"] = OV.TranslatePhrase("Fobs vs Fcalc")
self.graphInfo["pop_html"] = self.item
self.graphInfo["pop_name"] = self.item
self.graphInfo["TopRightTitle"] = self.TopRightTitle
self.auto_axes = False
try:
batch_number = int(batch_number)
except (ValueError, TypeError):
self.batch_number = None
else:
self.batch_number = batch_number
try:
self.make_f_obs_f_calc_plot()
except AssertionError as e:
if str(e) == "model.scatterers().size() > 0":
print("You need some scatterers to do this!")
return
else:
raise
self.popout()
if self.params.fobs_fcalc.output_csv_file:
self.output_data_as_csv()
def make_f_obs_f_calc_plot(self):
from reflection_statistics import f_obs_vs_f_calc
xy_plot = f_obs_vs_f_calc(batch_number=self.batch_number).xy_plot
self.metadata['shapes'] = []
self.metadata.setdefault("y_label", xy_plot.yLegend)
self.metadata.setdefault("x_label", xy_plot.xLegend)
equal_line = {'type':'line',
'xy':('0','0','%(max_x)s','%(max_x)s'),
'line': {
'color': 'rgb(100, 100, 100)',
'width': 1,
'dash':'dashdot'
}
}
self.metadata["shapes"].append(equal_line)
## Included Data
metadata = {}
# metadata.setdefault("fit_slope", xy_plot.fit_slope)
# metadata.setdefault("fit_y_intercept", xy_plot.fit_y_intercept)
metadata["name"] = "Included Data"
data = Dataset(
xy_plot.f_calc, xy_plot.f_obs, indices=xy_plot.indices, metadata=metadata)
self.data.setdefault('dataset1', data)
## Omitted Data
metadata = {}
metadata["name"] = "Omitted Data"
if xy_plot.f_obs_omitted and xy_plot.f_obs_omitted.size():
data_omitted = Dataset(
xy_plot.f_calc_omitted, xy_plot.f_obs_omitted, indices=xy_plot.indices_omitted, metadata=metadata)
self.data.setdefault('dataset2', data_omitted)
self.make_empty_graph(axis_x = True, square=False)
self.plot_function("x", n_points=100)
self.draw_pairs()
key = self.draw_key(({'type': 'marker',
'number': 1,
'label': OV.TranslatePhrase('Filtered Data')},
{'type':'marker',
'number': 2,
'label': OV.TranslatePhrase('Omitted (cut) Data')},
{'type':'marker',
'number': 3,
'label': OV.TranslatePhrase('Omitted (hkl) Data')}
))
self.im.paste(key,
(int(self.graph_right - (key.size[0] + 40)),
int(self.graph_bottom - (key.size[1] + 40)))
)
class Iobs_Icalc_plot(Analysis):
def __init__(self, batch_number=None):
Analysis.__init__(self)
self.item = "Iobs_Icalc"
self.graphInfo["Title"] = OV.TranslatePhrase("Iobs vs Icalc")
self.graphInfo["pop_html"] = self.item
self.graphInfo["pop_name"] = self.item
self.graphInfo["TopRightTitle"] = self.TopRightTitle
self.auto_axes = False
try:
batch_number = int(batch_number)
except (ValueError, TypeError):
self.batch_number = None
else:
self.batch_number = batch_number
try:
self.make_I_obs_I_calc_plot()
except AssertionError as e:
if str(e) == "model.scatterers().size() > 0":
print("You need some scatterers to do this!")
return
else:
raise
self.popout()
if self.params.iobs_icalc.output_csv_file:
self.output_data_as_csv()
def make_I_obs_I_calc_plot(self):
from reflection_statistics import I_obs_vs_I_calc
xy_plot = I_obs_vs_I_calc(batch_number=self.batch_number).xy_plot
self.metadata['shapes'] = []
self.metadata.setdefault("y_label", xy_plot.yLegend)
self.metadata.setdefault("x_label", xy_plot.xLegend)
equal_line = {'type':'line',
'xy':('0','0','%(max_x)s','%(max_x)s'),
'line': {
'color': 'rgb(100, 100, 100)',
'width': 1,
'dash':'dashdot'
}
}
self.metadata["shapes"].append(equal_line)
## Included Data
metadata = {}
# metadata.setdefault("fit_slope", xy_plot.fit_slope)
# metadata.setdefault("fit_y_intercept", xy_plot.fit_y_intercept)
metadata["name"] = "Included Data"
data = Dataset(
xy_plot.I_calc, xy_plot.I_obs, indices=xy_plot.indices, metadata=metadata)
self.data.setdefault('dataset1', data)
## Omitted Data
metadata = {}
metadata["name"] = "Omitted Data"
if xy_plot.I_obs_omitted and xy_plot.I_obs_omitted.size():
data_omitted = Dataset(
xy_plot.I_calc_omitted, xy_plot.I_obs_omitted, indices=xy_plot.indices_omitted, metadata=metadata)
self.data.setdefault('dataset2', data_omitted)
self.make_empty_graph(axis_x = True, square=False)
self.plot_function("x", n_points=100)
self.draw_pairs()
key = self.draw_key(({'type': 'marker',
'number': 1,
'label': OV.TranslatePhrase('Filtered Data')},
{'type':'marker',
'number': 2,
'label': OV.TranslatePhrase('Omitted (cut) Data')},
{'type':'marker',
'number': 3,
'label': OV.TranslatePhrase('Omitted (hkl) Data')}
))
self.im.paste(key,
(int(self.graph_right-(key.size[0]+40)),
int(self.graph_bottom-(key.size[1]+40)))
)
class Fobs_over_Fcalc_plot(Analysis):
def __init__(self):
Analysis.__init__(self)
self.item = "Fobs_over_Fcalc"
self.graphInfo["Title"] = OV.TranslatePhrase("Fobs/Fcalc vs resolution")
self.graphInfo["pop_html"] = self.item
self.graphInfo["pop_name"] = self.item
self.graphInfo["TopRightTitle"] = self.TopRightTitle
self.auto_axes = False
self.max_y = 1.05
try:
self.make_plot()
except AssertionError as e:
if str(e) == "model.scatterers().size() > 0":
print("You need some scatterers to do this!")
return
else:
raise AssertionError(e)
self.popout()
if self.params.fobs_over_fcalc.output_csv_file:
self.output_data_as_csv()
def make_plot(self):
from reflection_statistics import f_obs_over_f_calc
params = self.params.fobs_over_fcalc
xy_plot = f_obs_over_f_calc(
binning=params.binning,
n_bins=params.n_bins,
resolution_as=params.resolution_as).xy_plot
self.metadata.setdefault("y_label", xy_plot.yLegend)
self.metadata.setdefault("x_label", xy_plot.xLegend)
metadata = {}
if not params.binning:
indices = xy_plot.indices
else:
indices = None
data = Dataset(
xy_plot.resolution, xy_plot.f_obs_over_f_calc,
indices=indices, metadata=metadata)
reverse_x = params.resolution_as in ('d_spacing', 'd_star_sq')
self.data.setdefault('dataset1', data)
self.make_empty_graph(axis_x=True)
#self.plot_function("1")
self.draw_fit_line(slope=0, y_intercept=1, write_equation=False)
self.draw_pairs(reverse_x=reverse_x)
class scale_factor_vs_resolution_plot(Analysis):
def __init__(self):
Analysis.__init__(self)
self.item = "scale_factor_vs_resolution"
self.graphInfo["Title"] = OV.TranslatePhrase("Scale factor vs resolution")
self.graphInfo["pop_html"] = self.item
self.graphInfo["pop_name"] = self.item
self.graphInfo["TopRightTitle"] = self.TopRightTitle
self.auto_axes = False
self.max_y = 1.05
try:
self.make_plot()
except AssertionError as e:
if str(e) == "model.scatterers().size() > 0":
print("You need some scatterers to do this!")
return
else:
raise AssertionError(e)
self.popout()
if self.params.scale_factor_vs_resolution.output_csv_file:
self.output_data_as_csv()
def make_plot(self):
from reflection_statistics import scale_factor_vs_resolution
params = self.params.scale_factor_vs_resolution
xy_plot = scale_factor_vs_resolution(
params.n_bins, params.resolution_as).xy_plot_info()
self.metadata.setdefault("y_label", xy_plot.yLegend)
self.metadata.setdefault("x_label", xy_plot.xLegend)
metadata = {}
data = Dataset(
xy_plot.x, xy_plot.y, metadata=metadata)
self.data.setdefault('dataset1', data)
self.make_empty_graph(axis_x=True)
self.draw_fit_line(slope=0, y_intercept=1, write_equation=False)
reverse_x = params.resolution_as in ('d_spacing', 'd_star_sq')
self.draw_pairs(reverse_x=reverse_x)
class item_vs_resolution_plot(Analysis):
def __init__(self, item):
Analysis.__init__(self)
self.item = item
params = getattr(self.params, self.item)
self.graphInfo["Title"] = params.title
self.graphInfo["pop_html"] = self.item
self.graphInfo["pop_name"] = self.item
self.graphInfo["TopRightTitle"] = self.TopRightTitle
self.auto_axes = False
#self.max_y = 1.05
try:
res = self.make_plot()
except AssertionError as e:
if str(e) == "model.scatterers().size() > 0":
print("You need some scatterers to do this!")
return
else:
raise
if not res:
return None
self.popout()
if OV.GetParam('user.diagnostics.save_file'):
res = self.im.save(OV.ModelSrc() + "_" + self.item + ".png",'PNG')
self.output_data_as_csv()
def make_plot(self):
y_factor = 1
if "r1" in self.item:
y_factor = 100
from reflection_statistics import item_vs_resolution
params = getattr(self.params, self.item)
if params.resolution_as == "d_spacing":
self.use_log=10
self.auto_axes=True
try:
xy_plot = item_vs_resolution(item=self.item, n_bins=params.n_bins, resolution_as=params.resolution_as).xy_plot_info()
except Exception as err:
print(err)
return
if not xy_plot:
return None
while None in xy_plot.y:
params.n_bins -= 1
xy_plot = item_vs_resolution(item=self.item, n_bins=params.n_bins, resolution_as=params.resolution_as).xy_plot_info()
self.metadata.setdefault("y_label", xy_plot.yLegend)
self.metadata.setdefault("x_label", xy_plot.xLegend)
self.metadata.setdefault("shapes",[])
cutoff_line = {'type':'line',
'xy':('%(min_x)s','2','%(max_x)s','2'),
'line': {
'color': 'rgb(255, 100, 100)',
'width': 1,
'dash':'dashdot'
}
}
IUCr_limit= {'type':'line',
'xy':('50', '%(min_y)s', '50', '%(max_y)s'),
'line': {
'color': 'rgb(100, 100, 100)',
'width': 1,
'dash':'dashdot'
}
}
self.metadata["shapes"].append(cutoff_line)
self.metadata["shapes"].append(IUCr_limit)
metadata = self.metadata
data = Dataset(
xy_plot.x, [y*y_factor for y in xy_plot.y], metadata=metadata)
self.data.setdefault('dataset1', data)
self.make_empty_graph(axis_x=True)
alpha = IT.get_unicode_characters("alpha")
beta = IT.get_unicode_characters("beta")
iucr = 0
rad_name = "?"
radi= olx.xf.exptl.Radiation()
if radi.startswith('1.54'): # Cu alpha radiation
iucr = 135.58
rad_name = "CuK" + alpha
elif radi.startswith('1.39'): # Cu beta radiation
iucr = 113.16
rad_name = "CuK" + beta
elif radi.startswith('1.34'): # Ga alpha radiation
iucr = 112.88
rad_name = "GaK" + alpha
elif radi.startswith('0.71'): # Mo radiation
iucr = 50.74
rad_name = "MoK" + alpha
elif radi.startswith('0.56'): # Ag radiation
iucr = 39.02
rad_name = "AgK" + alpha
else:
iucr = 0.84
rad_name = str(radi) + (IT.get_unicode_characters("Angstrom"))
from cctbx import uctbx
if params.resolution_as == "d_spacing":
if iucr != 0.84:
iucr = uctbx.two_theta_as_d(iucr,float(olx.xf.exptl.Radiation()),deg=True)
elif params.resolution_as == "d_star_sq":
if iucr != 0.84:
iucr = uctbx.two_theta_as_d_star_sq(iucr,float(olx.xf.exptl.Radiation()),deg=True)
else:
iucr = uctbx.d_as_d_star_sq(iucr)
elif params.resolution_as == "stol":
if iucr != 0.84:
iucr = uctbx.d_star_sq_as_stol(uctbx.two_theta_as_d_star_sq(iucr,float(olx.xf.exptl.Radiation()),deg=True))
else:
iucr = uctbx.d_star_sq_as_stol(uctbx.d_as_d_star_sq(iucr))
elif params.resolution_as == "stol_sq":
if iucr != 0.84:
iucr = uctbx.d_star_sq_as_stol_sq(uctbx.two_theta_as_d_star_sq(iucr,float(olx.xf.exptl.Radiation()),deg=True))
else:
iucr = uctbx.d_star_sq_as_stol_sq(uctbx.d_as_d_star_sq(iucr))
elif params.resolution_as == "two_theta":
if iucr == 0.84:
iucr = uctbx.d_star_sq_as_two_theta(uctbx.d_as_d_star_sq(iucr),float(olx.xf.exptl.Radiation()),deg=True)
reverse_x = params.resolution_as in ('d_spacing', 'd_star_sq')
plot_reflection_count = False
scale = None
max_y = None
if self.item == "i_over_sigma_vs_resolution" or self.item == "rmerge_vs_resolution":
plot_reflection_count = True
item_save = self.item
try:
xy_plot2 = item_vs_resolution(item="refln_vs_resolution", n_bins=params.n_bins, resolution_as=params.resolution_as).xy_plot_info()
except Exception as err:
print(err)
return
if not xy_plot2:
return None
while None in xy_plot2.y:
params.n_bins -= 1
xy_plot2 = item_vs_resolution(item="refln_vs_resolution", n_bins=params.n_bins, resolution_as=params.resolution_as).xy_plot_info()
self.item = item_save #BECAUSE THIS IS SOMEHOW BEYOND ME!
metadata2 = dict(metadata)
max_y1 = max(xy_plot.y)
min_y1 = min(xy_plot.y)
max_y = max(xy_plot2.y)
scale = (max_y1)/max(xy_plot2.y)
metadata2["y_label"] = xy_plot2.yLegend
data2 = Dataset(xy_plot2.x, [y*scale for y in xy_plot2.y], metadata=metadata2)
self.data.setdefault('dataset2', data2)
self.ax_marker_length = int(self.imX * 0.006)
self.reverse_x = reverse_x
self.get_division_spacings_and_scale()
for dataset in list(self.data.values()):
if dataset.metadata().get("fit_slope") and dataset.metadata().get("fit_slope"):
slope = float(dataset.metadata().get("fit_slope"))
y_intercept = float(dataset.metadata().get("fit_y_intercept"))
self.draw_fit_line(slope, y_intercept, R=dataset.metadata().get("R", None))
if dataset.metadata().get('y_label') == "I/sigma":
self.draw_data_points(
dataset.xy_pairs(), sigmas=dataset.sigmas, indices=dataset.indices,
hrefs=dataset.hrefs, targets=dataset.targets, lt=3)
self.draw_fit_line(slope=0, y_intercept=3, write_equation=False, write_text="3 sigma line (noise below, data above)", reverse_x=reverse_x)
self.draw_fit_line(slope=0, y_intercept=0, x_intercept=iucr, write_equation=False, write_text="Min IUCr resolution for %s" %rad_name, rotate_text="top_lineleft", reverse_x=reverse_x)
elif dataset.metadata().get('y_label') == "R_merge /%":
self.draw_data_points(
dataset.xy_pairs(), sigmas=dataset.sigmas, indices=dataset.indices,
hrefs=dataset.hrefs, targets=dataset.targets, gt=0.15)
self.draw_fit_line(slope=0, y_intercept=0.15, write_equation=False, write_text="15 %% line (troublesome data above, good data below)", reverse_x=reverse_x)
self.draw_fit_line(slope=0, y_intercept=0, x_intercept=iucr, write_equation=False, write_text="Min IUCr resolution for %s" %rad_name, rotate_text="top_lineleft", reverse_x=reverse_x)
elif dataset.metadata().get('y_label') == "CC 1/2":
self.draw_data_points(
dataset.xy_pairs(), sigmas=dataset.sigmas, indices=dataset.indices,
hrefs=dataset.hrefs, targets=dataset.targets, lt=0.95)
self.draw_fit_line(slope=0, y_intercept=0.95, write_equation=False, write_text="Recommendation line (noise below, data above)", reverse_x=reverse_x)
self.draw_fit_line(slope=0, y_intercept=0, x_intercept=iucr, write_equation=False, write_text="Min IUCr resolution for %s" %rad_name, rotate_text="top_lineleft", reverse_x=reverse_x)
else:
if plot_reflection_count:
self.draw_data_points(
dataset.xy_pairs(), sigmas=dataset.sigmas, indices=dataset.indices,
hrefs=dataset.hrefs, targets=dataset.targets, scale=1/scale)
else:
self.draw_data_points(
dataset.xy_pairs(), sigmas=dataset.sigmas, indices=dataset.indices,
hrefs=dataset.hrefs, targets=dataset.targets)
self.draw_x_axis()
if list(self.data.values())[0].metadata().get('y_label') == "R_merge /%":
self.draw_y_axis(percent=True)
else:
self.draw_y_axis()
if plot_reflection_count:
self.draw_y_axis_2(0,max_y,"Nr. uniq. Refln.")
#self.draw_legend("test")
#self.draw_pairs(reverse_x=reverse_x, lt=3)
return True
class X_Y_plot(Analysis):
def __init__(self):
Analysis.__init__(self)
self.item = "X_Y_plot"
self.series = []
print("Good things will come to those who wait")
def run(self):
self.graphInfo.update(self.metadata)
self.make_empty_graph(axis_x = True)
i = 1
for item in self.series:
self.data.setdefault('dataset%s'%i,Dataset(x=item[0],
y=item[1],
hrefs=item[2],
targets=item[3],
metadata=item[4],
))
i += 1
self.draw_pairs()
self.graphInfo.setdefault("pop_html", 'acgraph.htm')
self.graphInfo.setdefault("pop_name", 'acgraph')
self.popout()
class HistoryGraph(Analysis):
def __init__(self, history_tree):
Analysis.__init__(self)
self.params = OV.Params().user.graphs.program_analysis
self.i_bar = 0
self.tree = history_tree
self.item = "history"
self.green = OV.GetParam('gui.green').rgb[1]
self.red = OV.GetParam('gui.red').rgb[0]
self.blue = 0
self.make_graph()
def make_graph(self):
global PreviousHistoryNode
bars = []
node = self.tree.active_child_node
while node is not None:
R1 = node.R1
href = "spy.revert_history(%s)>>html.Update>>if html.IsPopup(history-tree) then spy.popout_history_tree()" %(node.name)
target = '%s (%s)' %(node.program, node.method)
if node.is_solution:
R1 = 1
else:
if R1 == 'n/a': R1 = 0.99
try:
target += ' - %.2f%%' %(node.R1 * 100)
except (ValueError, TypeError):
pass
if node is self.tree.active_node:
self.i_active_node = len(bars)
bars.append((R1,href,target))
node = node.active_child_node
n_bars = len(bars)
#width = int(olx.html.ClientWidth('self')) - OV.GetParam('gui.htmlpanelwidth_margin_adjust')
width = IT.skin_width_table - int(OV.GetParam('gui.html.table_firstcol_width')/2)
size = (width, 100)
self.params.size_x, self.params.size_y = size
self.make_empty_graph(draw_title=False)
y_scale_factor = self.params.y_scale_factor
if len(bars) > 0:
x = []
y = []
hrefs = []
targets = []
for i, bar in enumerate(bars):
x.append(i+1)
y.append(bar[0]) # R factor
hrefs.append(bar[1])
targets.append(bar[2])
data = Dataset(x, y, hrefs=hrefs, targets=targets)
self.draw_history_bars(dataset=data, y_scale_factor=y_scale_factor,
colour_function=self.get_bar_colours,
draw_bar_labels=False)
def get_bar_colours(self, bar_height):
factor = self.params.y_scale_factor
if bar_height == factor:
fill = (139, 0, 204)
else:
fill = (int(self.red*bar_height), int(self.green*(1.3-bar_height)), self.blue)
self.i_bar += 1
return fill
class Dataset(object):
def __init__(self, x=None, y=None, indices=None, sigmas=None,
hrefs=None, targets=None, metadata={}):
if x is None: x = []
if y is None: y = []
self.x = x
self.y = y
self.sigmas = sigmas
self.hrefs = hrefs
self.targets = targets
self.indices = indices
self._metadata = metadata
def xy_pairs(self):
return list(zip(self.x,self.y))
def metadata(self):
return self._metadata
def show_summary(self):
print(''.join("%f, %f\n" %(x,y) for x,y in self.xy_pairs()))
def add_pair(self, x, y):
self.x.append(x)
self.y.append(y)
Analysis_instance = Analysis()
OV.registerMacro(Analysis_instance.run_Analysis,
'n_bins-Number of bins (for histograms only!)&;method-olex or cctbx')
OV.registerFunction(WilsonPlot)
OV.registerFunction(CumulativeIntensityDistribution)
OV.registerFunction(CompletenessPlot)
OV.registerFunction(SystematicAbsencesPlot)
OV.registerFunction(Fobs_Fcalc_plot)
OV.registerFunction(Iobs_Icalc_plot)
OV.registerFunction(Fobs_over_Fcalc_plot)
OV.registerFunction(Normal_probability_plot)
OV.registerFunction(item_vs_resolution_plot)
OV.registerFunction(scale_factor_vs_resolution_plot)
OV.registerFunction(X_Y_plot)
OV.registerFunction(bijvoet_differences_scatter_plot)
OV.registerFunction(bijvoet_differences_NPP)
def array_scalar_multiplication(array, multiplier):
return [i * multiplier for i in array]
def makeReflectionGraphOptions(graph, name):
guiParams = OV.GuiParams()
### This is assuming that there are no more than FOUR option controls:
width = int(OV.GetParam('gui.htmlpanelwidth') - OV.GetParam('gui.htmlpanelwidth_margin_adjust'))/4
value = graph.short_caption
options_gui = []
i = 1
for obj in graph.active_objects():
i += 1
data_type = obj.type.phil_type
caption = obj.caption
value = obj.extract()
# obj_name = name.upper() + "_" + object.caption.upper().replace(" ","_").replace("%","").replace("-","_")
obj_name = name.upper()
if data_type == "int":
ctrl_name = 'SPIN_%s' %(obj_name)
d = {'ctrl_name':ctrl_name,
'value':value,
'max':'30',
'width':'%s' %width,
'label':'%s ' %caption,
'onchange':"spy.SetParam('user.graphs.reflections.%s.%s',html.GetValue('%s'))" %(
graph.name, obj.name,ctrl_name),
}
options_gui.append(htmlTools.make_spin_input(d))
elif data_type in ("str", "float"):
ctrl_name = 'TEXT_%s' %(obj_name)
d = {'ctrl_name':ctrl_name,
'value':value,
'width':'%s' %width,
'label':'%s ' %caption,
'onchange':"spy.SetParam('user.graphs.reflections.%s.%s',html.GetValue('%s'))" %(
graph.name, obj.name,ctrl_name),
'readonly':'readonly',
}
options_gui.append(htmlTools.make_input_text_box(d))
elif data_type == "bool":
ctrl_name = 'TICK_%s' %(obj_name)
d = {'ctrl_name': ctrl_name,
'value': '%s ' % caption,
'checked': '%s' % value,
'oncheck': "spy.SetParam('user.graphs.reflections.%s.%s','True')" % (
graph.name, obj.name),
'onuncheck': "spy.SetParam('user.graphs.reflections.%s.%s','False')" % (
graph.name, obj.name),
'width': '%s' % width,
'bgcolor': '%s' % guiParams.html.table_bg_colour,
}
options_gui.append(htmlTools.make_tick_box_input(d))
elif data_type == "choice":
items_l = []
ctrl_name = 'COMBO_%s' % (obj_name)
for thing in obj.words:
items_l.append(thing.value.lstrip('*'))
items = ";".join(items_l)
d = {'ctrl_name':ctrl_name,
'label':'%s ' %caption,
'items':items,
'value':obj.extract(),
'onchange':"spy.SetParam('user.graphs.reflections.%s.%s',html.GetValue('%s'))>>spy.make_reflection_graph(html.GetValue('SET_REFLECTION_STATISTICS'))" %(
graph.name, obj.name,ctrl_name),
'width':'%s' %width,
}
options_gui.append(htmlTools.make_combo_text_box(d))
options_gui = '\n%s | \n' %'\n'.join(options_gui)
colspan = i
return options_gui, colspan
def makeReflectionGraphGui():
global GuiGraphChooserComboExists
guiParams = OV.GuiParams()
value = False
gui_d = {}
gui_d.setdefault('colspan', '1')
gui_d.setdefault('options_gui', "")
gui_d.setdefault('make_graph_button', "")
gui_d.setdefault('graph_chooser', "")
if GuiGraphChooserComboExists:
try:
value = OV.GetValue('SET_REFLECTION_STATISTICS')
except:
value = None
if not value:
GuiGraphChooserComboExists = True
help_name = None
name = None
else:
name = value.lower().replace(" ", "_").replace("-", "_").replace("/","_over_")
graph = olx.phil_handler.get_scope_by_name('user.graphs.reflections.%s' %name)
if not graph:
value = "no phil"
help_name = None
else:
gui_d['options_gui'], gui_d['colspan'] = makeReflectionGraphOptions(graph, name)
help_name = graph.help
onclick = 'spy.make_reflection_graph\(%s)' %name
d = {'name':'BUTTON_MAKE_REFLECTION_GRAPH',
'bgcolor':guiParams.html.input_bg_colour,
'onclick': onclick,
'width':'30',
'value':'Go',
'valign':'top',
}
#gui_d['make_graph_button'] = htmlTools.make_input_button(d)
gui_d['make_graph_button'] = "$spy.MakeHoverButton('button_small-go@MakeGraphs','%s')" %onclick
gui_d['help'] = htmlTools.make_table_first_col(
help_name=help_name, popout=False)
d = {'ctrl_name': 'SET_REFLECTION_STATISTICS',
'items': "-- %Please Select% --;"
+ "Wilson Plot;"
+ "Cumulative Intensity;"
+ "Systematic Absences;"
+ "Fobs-Fcalc;"
+ "Iobs-Icalc;"
+ "I/sigma vs resolution;"
+ "cc_half_vs_resolution;"
+ "Rmerge vs resolution;"
+ "Fobs over Fcalc;"
+ "Completeness%;"
+ "Normal Probability;"
+ "Fractal Dimension;"
+ "Scale factor vs resolution;"
+ "R1 factor vs resolution;"
+ "Bijvoet Differences %Probability Plot%;"
+ "Bijvoet Differences %Scatter Plot%",
'height': guiParams.html.combo_height,
'bgcolor': guiParams.html.input_bg_colour,
'value': value,
'onchange': "spy.make_reflection_graph(html.GetValue('SET_REFLECTION_STATISTICS'))>>html.Update",
'manage': 'manage',
'readonly': 'readonly',
'width': '$math.eval(html.clientwidth(self)-140)',
'readonly': 'readonly',
}
gui_d['graph_chooser']=htmlTools.make_combo_text_box(d)
gui_d['row_table_off'] = htmlTools.include_block('gui/blocks/row_table_off.htm')
gui_d['row_table_on'] = htmlTools.include_block('gui/blocks/row_table_on.htm')
gui_d['tool-first-column'] = htmlTools.include_block('gui/blocks/tool-first-column.htm')
gui_d['bgcolor'] = guiParams.html.table_firstcol_colour
txt = '''
|
%(graph_chooser)s
|
%(make_graph_button)s
|
''' % gui_d
if gui_d['options_gui'] != '':
txt += r'''
%(row_table_off)s
%(tool-first-column)s
%(row_table_on)s
%(options_gui)s
''' % gui_d
txt = OV.Translate(txt)
return txt
OV.registerFunction(makeReflectionGraphGui)
def make_reflection_graph(name):
name = name.lower().replace(" ", "_").replace("-", "_")
if name == "gui_fobs_fcalc":
name = "iobs_icalc" if OV.IsEDRefinement() else "fobs_fcalc"
run_d = {'wilson_plot': WilsonPlot,
'cumulative_intensity': CumulativeIntensityDistribution,
'systematic_absences': SystematicAbsencesPlot,
'fobs_fcalc': Fobs_Fcalc_plot,
'iobs_icalc': Iobs_Icalc_plot,
'fobs_over_fcalc': Fobs_over_Fcalc_plot,
'completeness': CompletenessPlot,
'normal_probability': Normal_probability_plot,
'fractal_dimension': Fractal_Dimension,
'r1_factor_vs_resolution': (item_vs_resolution_plot, "r1_factor_vs_resolution"),
'i/sigma_vs_resolution': (item_vs_resolution_plot, "i_over_sigma_vs_resolution"),
'i_over_sigma_vs_resolution': (item_vs_resolution_plot, "i_over_sigma_vs_resolution"),
'cc_half_vs_resolution': (item_vs_resolution_plot, "cc_half_vs_resolution"),
'rmerge_vs_resolution': (item_vs_resolution_plot, "rmerge_vs_resolution"),
'scale_factor_vs_resolution': scale_factor_vs_resolution_plot,
'bijvoet_differences_probability_plot': bijvoet_differences_NPP,
'bijvoet_differences_scatter_plot': bijvoet_differences_scatter_plot,
}
func = run_d.get(name)
arg = None
if type(func) is tuple:
fun = func[0]
arg = func[1]
fun(arg)
else:
if func:
try:
func()
except Exception as e:
print(e)
if OV.IsDebugging():
sys.stderr.formatExceptionInfo()
OV.registerFunction(make_reflection_graph)
class HealthOfStructure():
def __init__(self):
self.hkl_stats = {}
self.grade_1_colour = OV.GetParam('gui.skin.diagnostics.colour_grade1').hexadecimal
self.grade_2_colour = OV.GetParam('gui.skin.diagnostics.colour_grade2').hexadecimal
self.grade_3_colour = OV.GetParam('gui.skin.diagnostics.colour_grade3').hexadecimal
self.grade_4_colour = OV.GetParam('gui.skin.diagnostics.colour_grade4').hexadecimal
self.available_width = int(OV.GetParam('gui.htmlpanelwidth'))
self.stats = None
self.scale = OV.GetParam('gui.internal_scale')
self.scope = "hkl"
self.supplied_cif = False
self.deg = u"\u00B0"
self.im_cache = {}
self.isED = False
self.default_phil_handler = olx.phil_handler
self.ED_phil_handler = None
_ = ['Completeness', 'MeanIOverSigma','Rint']
_ += ['_refine_ls_shift/su_max', '_refine_diff_density_max',
'_refine_diff_density_min', '_refine_ls_goodness_of_fit_ref',
'_refine_ls_abs_structure_Flack']
for item in _:
self.im_cache.setdefault(item,{})
def get_HOS_d(self):
try:
if self.initialise_HOS():
return self.summarise_HOS()
except Exception as err:
print(err)
return None
def set_ED_phil(self):
if OV.IsEDData():
self.ED = True
if not self.ED_phil_handler:
ACED_path = os.path.join(OV.BaseDir(), 'util', 'pyUtil', 'ACEDd', 'ACED.phil')
if not os.path.exists(ACED_path):
ACED_path = os.path.join(OV.BaseDir(), 'util', 'pyUtil', 'ACED', 'ACED.phil')
phil_file = ACED_path
if os.path.exists(phil_file):
ACED_phil = open(phil_file, 'r').read()
olx.phil_handler.merge_phil(phil_string=ACED_phil)
self.ED_phil_handler = olx.phil_handler
else:
olx.phil_handler = self.ED_phil_handler
else:
self.isED = False
if olx.phil_handler != self.default_phil_handler:
olx.phil_handler = self.default_phil_handler
def make_HOS(self, force=False, supplied_cif=False):
#self.set_ED_phil()
force = OV.get_bool_from_any(force)
self.width = int(IT.skin_width*0.98)
self.supplied_cif = supplied_cif
self.scopes = OV.GetParam('user.diagnostics.scopes')
self.scope = OV.GetParam('snum.current_process_diagnostics')
if timing:
import time
t1 = time.time()
res = self.initialise_HOS(force=force)
self.hos_text = ""
if res[0]:
if OV.GetParam('user.diagnostics.pin_scopes'):
for scope in self.scopes:
self.scope = scope
self.summarise_HOS()
self.make_HOS_html()
else:
self.summarise_HOS()
self.make_HOS_html()
OV.write_to_olex("hos.htm",self.hos_text)
elif res[1]:
OV.write_to_olex("hos.htm", "")
OV.write_to_olex("reflection-stats-summary.htm" , "n/a")
self.stats = None
if timing:
print("HOS took %.4f seconds" %(time.time() - t1))
def get_info_from_hkl_stats(self):
#hkl_src = olx.HKLSrc() cannot rely purely on HklSrc as the file might have data (as CIF does)
if 'Rsigma' not in self.hkl_stats:
return
try:
self.hkl_stats['MeanIOverSigma'] = 1/self.hkl_stats['Rsigma'] if self.hkl_stats['Rsigma'] else 0
self.theta_max = math.asin(self.radiation/(2*self.hkl_stats['MinD']))*180/math.pi
if olx.IsFileType("ires") == 'true':
try:
od_theta = OV.get_cif_item('_reflns_odcompleteness_theta')
if od_theta:
self.theta_full = float(od_theta)
else:
self.theta_full = float(olx.Ins("ACTA"))/2
if self.theta_max < self.theta_full:
self.theta_full = self.theta_max
except:
pass
# adjust to the dataset theta max if needed
if self.theta_max < self.theta_full:
self.theta_full = self. theta_max
for x in (('full', self.theta_full), ('max', self.theta_max)):
self.hkl_stats['Completeness_laue_%s' %x[0]] = float(olx.xf.rm.Completeness(x[1]*2,True))
self.hkl_stats['Completeness_point_%s' %x[0]] = float(olx.xf.rm.Completeness(x[1]*2,False))
except Exception as err:
print("Could not get info from hkl_stats: %s" %err)
def get_info_from_cif(self):
from cctbx import uctbx
try:
wl = float(olx.Cif('_diffrn_radiation_wavelength'))
l = (('Completeness_laue_%s','_diffrn_measured_fraction_theta_%s'),
('Completeness_laue_%s','_diffrn_reflns_laue_measured_fraction_%s'),
('Completeness_point_%s','_diffrn_reflns_point_group_measured_fraction_%s'),
)
for x in ('full', 'max'):
for alias,cif_item in l:
alias = alias%x
_ = olx.Cif(cif_item%x)
if _ == "n/a":
self.hkl_stats.setdefault(alias, 0)
else:
self.hkl_stats.setdefault(alias, float(_))
theta_max = olx.Cif('_diffrn_reflns_theta_max')
if theta_max == "n/a":
theta_max = olx.Cif('_diffrn_reflns_Laue_measured_fraction_max')
if theta_max != "n/a":
self.theta_max = float(theta_max)
self.hkl_stats['MinD'] = uctbx.two_theta_as_d(2 * self.theta_max ,wl, True)
else:
self.hkl_stats['MinD'] = 0
theta_full = olx.Cif('_diffrn_reflns_theta_full')
if theta_full == "n/a":
theta_full = olx.Cif('_diffrn_reflns_Laue_measured_fraction_full')
if theta_full != "n/a":
self.theta_full = float(theta_full)
##The following items can have alternate/deprecated identifiers
l = ['_diffrn_reflns_av_unetI/netI', '_diffrn_reflns_av_sigmaI/netI']
self.hkl_stats[''] = 0
for item in l:
_ = olx.Cif(item)
if _ != "n/a":
self.hkl_stats['MeanIOverSigma'] = 1/float(_)
break
else:
self.hkl_stats['MeanIOverSigma'] = 0
break
l = ['_diffrn_reflns_av_R_equivalents',]
self.hkl_stats['Rint'] = 0
for item in l:
_ = olx.Cif(item)
# ? is for HKLF 5
if _ != "n/a" and _ != '?':
self.hkl_stats['Rint'] = float(_)
else:
self.hkl_stats['Rint'] = 1
except Exception as err:
print("Could not get info from CIF: %s" %err)
def initialise_HOS(self, force=False):
""" Returns (bool, bool) the first boolean specifies if the initialisation
was successful, and the second - if the HOS has to be reset
"""
if olx.IsFileLoaded() != 'true':
return (False, True)
self.is_CIF = (olx.IsFileType('cif') == 'true')
try:
self.radiation = float(olx.xf.exptl.Radiation())
self.theta_full = math.asin(self.radiation*0.6)*180/math.pi
self.theta_max = 0
self.hkl_stats = olex_core.GetHklStat()
if self.hkl_stats['DataCount'] == 0:
self.hkl_stats = {}
self.hkl_stats['IsCentrosymmetric'] = olex_core.SGInfo()['Centrosymmetric']
self.resolution_type = OV.get_diag('hkl.Completeness.resolution')
self.resolution_display = OV.get_diag('hkl.Completeness.resolution_display')
if self.is_CIF:
self.get_info_from_cif()
else:
self.get_info_from_hkl_stats()
completnesses = []
self.completeness_info_text = {}
for x in ('full', 'max'):
completnesses.append(self.hkl_stats.get('Completeness_point_%s' %x, 0.0)*100)
completnesses.append(self.hkl_stats.get('Completeness_laue_%s' %x, 0.0)*100)
ttheta = IT.get_unicode_characters(u"2\u0398")
try:
min_d = "%.4f" %self.hkl_stats['MinD']
except:
min_d = 0
self.completeness_info_text['Point Full'] = {'2Theta': self.theta_full*2, 'completeness': completnesses[0] }
self.completeness_info_text['Laue Full'] = {'2Theta': self.theta_full*2, 'completeness': completnesses[1] }
self.completeness_info_text['Point Max'] = {'2Theta': self.theta_max*2, 'd_min': min_d, 'completeness': completnesses[2] }
self.completeness_info_text['Laue Max'] = {'2Theta': self.theta_max*2, 'd_min': min_d, 'completeness': completnesses[3] }
l = ["- Laue Group Completeness to %s=%.1f: %.1f%%%%" %(ttheta, self.theta_full*2, completnesses[1])]
if self.theta_full != self.theta_max:
l.append("Laue Group Completeness to %s=%.1f: %.1f%%%%" %(ttheta, self.theta_max*2, completnesses[3]))
if not self.hkl_stats['IsCentrosymmetric']:
l.append("Point Group Completeness to %s=%.1f: %.1f%%%%" %(ttheta, self.theta_full*2, completnesses[0]))
if self.theta_full != self.theta_max:
l.append("Point Group Completeness to %s=%.1f: %.1f%%%%" %(ttheta, self.theta_max*2, completnesses[2]))
target = "
- ".join(l)
OV.SetParam('snum.refinement.completeness.target', target)
try:
multi = self.hkl_stats['TotalReflections']/self.hkl_stats['UniqueReflections']
self.hkl_stats.setdefault('multiplicity', multi)
target = ["Internal R factors. Click to see the graph", "-- Multiplicity = %.2f" %multi]
target = "
- ".join(target)
OV.SetParam('snum.refinement.Rint.target', target)
except:
pass
except Exception as err:
print(err)
return (False, True)
if self.scope == "refinement":
return (True, True)
else:
self.scope = "hkl"
if force:
return (True, None)
try:
min_d = "%.4f" %self.hkl_stats['MinD']
if OV.GetParam('snum.hkl.d_min') == float(min_d):
if bool(olx.fs.Exists('MinD')):
return (False, False)
else:
OV.SetParam('snum.hkl.d_min',min_d)
if not self.hkl_stats:
return (False, True)
except:
return (False, True)
return (True, None)
def get_cctbx_reflection_statistics_html(self):
from reflection_statistics import OlexCctbxReflectionStats
self.stats = OlexCctbxReflectionStats()
value = self.stats.cctbx_stats.observations.completeness()
return value
def summarise_HOS(self):
d = {}
txt = ""
l = ['Completeness', 'MeanIOverSigma','Rint']
for item in self.hkl_stats:
value = self.hkl_stats[item]
if type(value) == tuple and len(value) > 0 and type(value[0]) == float:
value = tuple([round(x,4) for x in value])
else:
try:
fv = float(value)
iv = int(value)
if fv != iv:
value = "%.4f" %fv
except:
pass
d.setdefault(item, value)
txt += "
%s | %s |
" %(item, value)
OV.write_to_olex("reflection-stats-summary.htm" , txt)
if olx.HKLSrc():
t = time.ctime(os.path.getmtime(olx.HKLSrc()))
else:
t = "No Reflections"
OV.write_to_olex("reflection-date.htm" , t)
return d
def is_in_cache(self, var, val):
global cache
if var in cache:
if cache[var]['val'] == val:
return True
else:
cache[var]['val'] = val
return False
else:
cache.setdefault(var,{'val':val, 'img':None})
return False
def make_HOS_html(self):
if self.scope == None:
self.scope = 'hkl'
# is_CIF = (olx.IsFileType('cif') == 'true')
if self.scope == "refinement":
if self.is_CIF:
l = ['_refine_ls_shift/su_max', '_refine_diff_density_max',
'_refine_diff_density_min', '_refine_ls_goodness_of_fit_ref',
'_refine_ls_abs_structure_Flack']
if olx.Cif('_refine_ls_abs_structure_Flack') == "n/a":
l.remove("_refine_ls_abs_structure_Flack")
else:
l = ['max_shift_over_esd', 'max_peak', 'max_hole', 'goof','hooft_str']
if not OV.GetParam('snum.refinement.hooft_str'):
l.remove("hooft_str")
else:
self.scope = "hkl"
## If there is no CIF information and no hkl file, we don't have stats, but still have {'IsCentrosymmetric} as a single item
if not self.hkl_stats or len(self.hkl_stats) == 1:
return
l = ['MinD', 'MeanIOverSigma','Rint','Completeness']
txt = ""
counter = 0
for item in l:
counter += 1
if self.scope == "hkl":
if self.supplied_cif and item == "Rint":
value = self.supplied_cif.get('_diffrn_reflns_av_R_equivalents',0)
try:
value = float(value)
except:
pass
elif item in self.hkl_stats:
value = float(self.hkl_stats[item])
else:
value=None
if type(value) == tuple and len(value) > 0:
value = value[0]
elif self.scope == "refinement":
if item == "hooft_str":
hooft_src = "Flack"
if item == 'hooft_str':
try:
value = OV.get_cif_item('_refine_ls_abs_structure_Flack')
value = olx.Cif('_refine_ls_abs_structure_Flack')
_ = olx.Cif('_refine_ls_abs_structure_details')
if "parsons" in _.lower():
hooft_src = "Parsons"
elif "hooft" in _.lower():
hooft_src = "Hooft"
OV.SetParam('user.diagnostics.%s.%s.display' %(self.scope,item), hooft_src)
except:
value = OV.GetParam('snum.refinement.%s' %item)
if self.is_CIF:
try:
value = float(olx.Cif(item))
except:
value = olx.Cif(item)
item = item.replace('/', '_over_')
else:
value = OV.GetParam('snum.refinement.%s' %item)
if item == "_refine_ls_goodness_of_fit_ref":
item = 'goof'
elif item == "_refine_diff_density_max":
item = 'max_peak'
elif item == "_refine_diff_density_min":
item = 'max_hole'
elif item == "_refine_ls_shift_over_su_max":
item = 'max_shift_over_esd'
elif item == "_refine_ls_abs_structure_Flack":
item = 'hooft_str'
display = OV.get_diag('%s.%s.display' %(self.scope,item))
if item == "MinD":
_ = olx.xf.exptl.Radiation()
if _.startswith("1.54"):
_ = "CuKalpha"
elif _.startswith("0.71"):
_ = "MoKalpha"
elif _.startswith("1.34"):
_ = "GaKalpha"
elif _.startswith("0.56"):
_ = "AgKalpha"
elif _.startswith("1.39"):
_ = "Cubeta"
display += " (%s)" % (IT.get_unicode_characters(_))
value_format = OV.get_diag('%s.%s.value_format' %(self.scope,item))
href = OV.get_diag('%s.%s.href' %(self.scope,item))
raw_val = value
bg_colour = None
flack_esd_f = 0
if item == "hooft_str":
if "(" not in str(value):
value = str(value) + "()"
flack_val = value.split("(")[0]
flack_esd = value.split("(")[1].strip(")")
if len(flack_val.strip("-")) == 1:
if len(flack_esd) == 1:
flack_esd_f = float("%s" %flack_esd)
if len(flack_val.strip("-")) == 3:
if len(flack_esd) == 1:
flack_esd_f = float("0.%s" %flack_esd)
elif len(flack_esd) == 2:
flack_esd_f = float("%s.%s" %(flack_esd[0],flack_esd[1]))
elif len(flack_val.strip("-")) == 4:
if len(flack_esd) == 1:
flack_esd_f = float("0.0%s" %flack_esd)
elif len(flack_esd) == 2:
flack_esd_f = float("0.%s" %flack_esd)
elif len(flack_val.strip("-")) == 5:
if len(flack_esd) == 1:
flack_esd_f = float("0.00%s" %flack_esd)
elif len(flack_esd) == 2:
flack_esd_f = float("0.0%s" %flack_esd)
bg_esd = self.get_bg_colour('flack_esd', flack_esd_f)
if len(flack_esd) == 1:
_ = 0.75
else:
_ = 0.63
if len(flack_esd) == 0:
bg_val = "#000000"
bg_esd = "#000000"
else:
bg_val = self.get_bg_colour('flack_val', flack_val)
bg_colour = (bg_val,_,bg_esd)
if not bg_colour:
bg_colour = self.get_bg_colour(item, raw_val)
if type(value) == tuple:
if len(value) > 0:
value = value[0]
else:
value = None
if value == None:
value = "n/a"
bg_colour = "#000000"
else:
try:
if "%" in value_format:
value_format = value_format.replace('%','f%%')
value = value * 100
#raw_val = value
except:
pass
if item == 'Rint':
if raw_val == 0:
value = "Merged!"
bg_colour = "#000000"
elif raw_val == -1:
value = "MERG 0"
bg_colour = "#000000"
else:
value_format = "%." + value_format
value = value_format %value
else:
try:
value_format = "%." + value_format
value = value_format %value
except:
pass
## Check for NULL values
have_null = False
null_values = [0, "0.0", "0.00", "n/a"]
if raw_val in null_values:
have_null = True
if item == 'Rint':
if raw_val == 1:
have_null = True
if item == 'max_shift_over_esd':
if raw_val == '0' or raw_val == 0:
have_null = False
if have_null:
bg_colour = "#555555"
value = "n/a"
##========================
use_image = True
if use_image:
if timing:
t = time.time()
if counter == 1:
self.image_position = "first"
elif counter == len(l):
self.image_position = "last"
else:
self.image_position = "middle"
txt += self.make_hos_images(item=item, colour=bg_colour, display=display, value_raw=raw_val, value_display=value, n=len(l))
if timing:
print(".. hos image took %.3f s (%s) " %((time.time() - t),item))
else:
ref_open = ''
ref_close = ''
if href:
dollar = ""
if "()" in href:
dollar = "$"
ref_open = "" %(dollar, href)
ref_close = ""
txt += '''
%s: %s%s%s
|
'''%(bg_colour, 100/len(l), display, ref_open, value, ref_close)
txt += "
"
if self.scope == "hkl" and 'Completeness' in self.hkl_stats:
completeness = self.hkl_stats['Completeness']
if type(completeness) == tuple and len(completeness) > 1:
txt = """%s |
Twin component completeness (in P1): %s |
""" %(
txt, ", ".join(["%.2f%%%%" %(x*100) for x in completeness]))
self.hos_text += txt
OV.SetParam('snum.hkl.hkl_stat_file', OV.HKLSrc())
def make_hos_images(self, item='test', colour='#ff0000', display='Display', value_display='10%', value_raw='0.1', n=1):
width = self.width
scale = self.scale
font_name = "DefaultFont"
font_size = round(OV.GetParam('gui.timage.hos.font_size'))
value_display_extra = ""
targetWidth = round(width/n)
targetHeight = round(OV.GetParam('gui.timage.hos.height'))
href = OV.get_diag('%s.%s.href' %(self.scope,item))
if item == "Completeness":
target = OV.GetParam('snum.refinement.%s.target' %item.lower())
elif item == "Rint":
target = ["Internal R factors. Click to see the graph", " Multiplicity = %.2f" %self.hkl_stats.get('multiplicity', 0.0)]
target = "
- ".join(target)
OV.SetParam('snum.refinement.Rint.target', target)
else:
target = OV.get_diag('%s.%s.target' %(self.scope,item))
txt = ""
ref_open = ''
ref_close = ''
if href:
if href == "atom":
href = "sel %s" %OV.GetParam('snum.refinement.%s_atom' %item)
if item != 'max_hole':
ref_open = '' %(target, href)
ref_close = ""
txt += '''
%s%s | ''' %(ref_open, item, ref_close)
cache_entry = "%s_%s_%s" %(item, value_raw, targetWidth)
cache_image = self.im_cache.get(cache_entry,None)
cache_entry_large = "%s_large_%s_%s" %(item, value_raw, targetWidth)
cache_image_large = self.im_cache.get(cache_entry_large,None)
if cache_image and cache_image_large:
if debug:
print("HOS from Cache: %s" %cache_entry)
im = IT.resize_image(cache_image, (targetWidth, targetHeight), name=cache_entry)
OlexVFS.save_image_to_olex(im, item, 0)
return txt
boxWidth = int(targetWidth * scale)
boxHeight = int(targetHeight * scale)
bgcolour= OV.GetParam('gui.html.table_firstcol_colour').hexadecimal
im = Image.new('RGBA', (boxWidth,boxHeight), (0,0,0,0))
draw = ImageDraw.Draw(im)
if value_raw != "n/a":
try:
value_raw = float(value_raw)
except:
value_raw = 0
od_value = None
theoretical_val = value_raw
if type(colour) == tuple:
fill = colour[0]
second_colour = colour[2]
second_colour_begin = colour[1]
else:
fill = colour
second_colour = colour
second_colour_begin = colour
box = (0,0,boxWidth,boxHeight)
draw.rectangle(box, fill=fill)
top = OV.get_diag('hkl.%s.top' %item)
if item == "hooft_str":
x = boxWidth * second_colour_begin
box = (x,0,boxWidth,boxHeight)
fill = second_colour
draw.rectangle(box, fill=fill)
value_display = value_display.replace("0.",".")
if item == "Completeness":
laue_name = 'Completeness_laue_full'
point_name = 'Completeness_point_full'
if round(self.theta_full*100) != round(self.theta_max*100):
if self.resolution_type == 'full':
if round(self.hkl_stats['Completeness_laue_max']*100) !=\
round(self.hkl_stats[laue_name]*100):
value_display_extra = "%.0f%% to %.1f%s" %(
self.hkl_stats['Completeness_laue_max']*100, self.theta_max*2, self.deg)
else:
laue_name = 'Completeness_laue_max'
point_name = 'Completeness_point_max'
if round(self.hkl_stats['Completeness_laue_full']*100) !=\
round(self.hkl_stats[laue_name]*100):
value_display_extra = "%.0f%% to %.1f%s" %(
self.hkl_stats['Completeness_laue_full']*100, self.theta_full*2, self.deg)
value_display = "%.1f" %(self.hkl_stats[laue_name]*100)
value_display = value_display.replace("100.0", "100")
value_display_extra = value_display_extra.replace("100.0", "100")
if self.resolution_type == "full":
label = "Full"
if not self.is_CIF and OV.get_cif_item('_reflns_odcompleteness_theta', None):
label = "CAP"
display = "%s %.1f%s" %(label, self.theta_full*2, self.deg)
else:
label = "Max"
display = "%s %.1f%s" %(label, self.theta_max*2, self.deg)
display = IT.get_unicode_characters(display)
value_display_extra = IT.get_unicode_characters(value_display_extra)
# Laue bar
laue = self.hkl_stats[laue_name]
laue_col = self.get_bg_colour(item, laue)
fill = laue_col
_ = int(boxWidth * (1-laue))
if _ == 0 and theoretical_val < 0.99:
_ = 1
if _ != 0:
right = int(laue * boxWidth)
box = (0,0,right,boxHeight)
draw.rectangle(box, fill=laue_col)
## Point group bar
point = self.hkl_stats[point_name]
_ = int(boxWidth * (1-point))
if _ == 0 and theoretical_val < 0.95:
_ = 1
if _ != 0:
x = boxWidth - _
box = (0,int(boxHeight/2),x,boxHeight)
point_col = self.get_bg_colour(item, point)
draw.rectangle(box, fill=point_col)
if item == "MeanIOverSigma":
display = IT.get_unicode_characters("I/sigma(I)")
elif item == "Rint":
display = "Rint"
display = IT.get_unicode_characters(display)
if boxWidth < 80 * scale:
font_size = 14
font_size_s = 8
x = 2
y_s = 1 * scale #top gap for the small writing
y = 1 * scale
else:
#font_size = 18
#font_size_s = 11
x = 2
y = int(boxHeight/45 * scale)
y_s = 0 * scale
font = IT.registerFontInstance("DefaultFont", int(font_size * scale))
font_l = IT.registerFontInstance("DefaultFont", int(font_size * 1.3 * scale))
font_s = IT.registerFontInstance("DefaultFont", int(font_size * 0.65 * scale))
## ADD THE Key
if self.is_CIF:
fill = IT.adjust_colour(fill, luminosity=0.85)
draw.text((int(boxWidth*0.3), -int(font_size * 0.3)), ".cif", font=font_l, fill=fill)
if item == "Rint":
try:
multi = self.hkl_stats.get('multiplicity', None)
if multi:
value_display_extra = "m=%.2f" %(multi)
except:
pass
if item == "MinD":
# fill = self.get_bg_colour(item, value_raw)
# fill = '#555555'
value_display_extra = "2Theta=%.1f%s" %(self.theta_max*2,self.deg)
value_display_extra = IT.get_unicode_characters(value_display_extra)
fill = '#ffffff'
else:
fill = '#ffffff'
draw.text((x, y_s), OV.correct_rendered_text(display), font=font_s, fill=fill)
## ADD THE ACTUAL VALUE
y += 1
dx,dy, offset = IT.getTxtWidthAndHeight(value_display, font_name=font_name, font_size=int(font_size * scale))
x = boxWidth - dx - 7 #right inside margin
draw.text((x, y), OV.correct_rendered_text(value_display), font=font, fill=fill)
if value_display_extra:
draw.text((0, y + 3 + dy/2), OV.correct_rendered_text(value_display_extra), font=font_s, fill="#ffffff")
#if self.is_CIF:
#fill = IT.adjust_colour(fill, luminosity=1.9)
#draw.text((int(x/2 - dx/2), y + 3 + dy/2), "CIF", font=font_s, fill="#ffffff")
##draw.text((2, boxHeight - 2*8), "CIF", font=font_l, fill=fill)
_ = im.copy()
_ = IT.add_whitespace(im, 'right', 4*scale, "#ffffff")
_ = IT.add_whitespace(im, 'left', 4*scale, "#ffffff")
OlexVFS.save_image_to_olex(_, "%s_large" %item, 0)
#if self.image_position != "last":
#im = IT.add_whitespace(im, 'right', 4, bgcolour)
im = IT.add_whitespace(im, side='bottom', weight=2*scale, colour=bgcolour)
self.im_cache[cache_entry] = im
im = IT.resize_image(im, ((targetWidth),(targetHeight+2)), name=cache_entry)
OlexVFS.save_image_to_olex(im, item, 0)
return txt
def get_bg_colour(self, item, val):
return gui.tools.get_diagnostics_colour(self.scope, item, val)
HOS_instance = HealthOfStructure()
OV.registerFunction(HOS_instance.make_HOS)
def title_replace(title):
title = title.replace("sigma", "σ")
title = title.replace("two_theta", "2Θ / °")
title = title.replace("d_spacing", "d-spacing / Å")
title = title.replace("Fobs", "Fobs")
title = title.replace("Fobs", "Fcalc")
title = title.replace(" vs ", " vs")
title = title.replace("_", "-")
return title