def __init__(self, millarr, mprint=sys.stdout.write): from iotbx.gui_tools.reflections import get_array_description data = millarr.data() if (isinstance(data, flex.int)): data = [e for e in data if e != display.inanval] if millarr.is_complex_array(): data = flex.abs(millarr.data()) data = [e for e in data if not math.isnan(e)] self.maxdata = max(data) self.mindata = min(data) self.maxsigmas = self.minsigmas = None if millarr.sigmas() is not None: data = millarr.sigmas() data = [e for e in data if not math.isnan(e)] self.maxsigmas = max(data) self.minsigmas = min(data) self.minmaxdata = (roundoff(self.mindata), roundoff(self.maxdata)) self.minmaxsigs = (roundoff(self.minsigmas), roundoff(self.maxsigmas)) self.labels = self.desc = "" #import code, traceback; code.interact(local=locals(), banner="".join( traceback.format_stack(limit=10) ) ) if millarr.info(): self.labels = millarr.info().label_string() self.desc = get_array_description(millarr) self.span = ("?", "?") dmin = 0.0 dmax = 0.0 try: self.span = (millarr.index_span().min(), millarr.index_span().max()) dmin = millarr.d_max_min()[1] dmax = millarr.d_max_min()[0] except Exception, e: mprint(to_str(e))
def __init__(self, millarr): from iotbx.gui_tools.reflections import get_array_description data = millarr.data() if (isinstance(data, flex.int)): data = [e for e in data if e!= display.inanval] if millarr.is_complex_array(): data = flex.abs(millarr.data()) self.maxdata =max( data ) self.mindata =min( data ) self.maxsigmas = self.minsigmas = display.nanval if millarr.sigmas() is not None: data = millarr.sigmas() self.maxsigmas =max( data ) self.minsigmas =min( data ) self.minmaxstr = "MinMaxValues:[%s; %s], MinMaxSigmaValues:[%s; %s]" \ %(roundoff(self.mindata), roundoff(self.maxdata), \ roundoff(self.minsigmas), roundoff(self.maxsigmas)) else: self.minmaxstr = "MinMaxValues:[%s; %s]" %(roundoff(self.mindata), roundoff(self.maxdata)) self.labels = self.desc = "" if millarr.info(): self.labels = millarr.info().label_string() self.desc = get_array_description(millarr) self.span = "HKLs: %s to %s" % \ ( millarr.index_span().min(), millarr.index_span().max()) self.infostr = "%s (%s), %s %s, %s, d_min: %s" % \ (self.labels, self.desc, millarr.size(), self.span, self.minmaxstr, roundoff(millarr.d_min()))
class ArrayInfo: def __init__(self, millarr, mprint=sys.stdout.write): from iotbx.gui_tools.reflections import get_array_description data = millarr.data() if (isinstance(data, flex.int)): data = [e for e in data if e != display.inanval] if millarr.is_complex_array(): data = flex.abs(millarr.data()) data = [e for e in data if not math.isnan(e)] self.maxdata = max(data) self.mindata = min(data) self.maxsigmas = self.minsigmas = None if millarr.sigmas() is not None: data = millarr.sigmas() data = [e for e in data if not math.isnan(e)] self.maxsigmas = max(data) self.minsigmas = min(data) self.minmaxdata = (roundoff(self.mindata), roundoff(self.maxdata)) self.minmaxsigs = (roundoff(self.minsigmas), roundoff(self.maxsigmas)) self.labels = self.desc = "" #import code, traceback; code.interact(local=locals(), banner="".join( traceback.format_stack(limit=10) ) ) if millarr.info(): self.labels = millarr.info().label_string() self.desc = get_array_description(millarr) self.span = ("?", "?") dmin = 0.0 dmax = 0.0 try: self.span = (millarr.index_span().min(), millarr.index_span().max()) dmin = millarr.d_max_min()[1] dmax = millarr.d_max_min()[0] except Exception, e: mprint(to_str(e)) issymunique = millarr.is_unique_set_under_symmetry() self.infotpl = (self.labels, self.desc, millarr.indices().size(), self.span, self.minmaxdata, self.minmaxsigs, (roundoff(dmin), roundoff(dmax)), issymunique) self.infostr = "%s (%s), %s HKLs: %s, MinMax: %s, MinMaxSigs: %s, d_minmax: %s, SymUnique: %d" % self.infotpl
def tabulate_arrays(self, datalabels): if len(self.origarrays) == 0: # if not an mtz file then split columns # SupersetMillerArrays may not be necessary if file formats except for cif and mtz can't store multiple data columns #self.viewer.SupersetMillerArrays() self.origarrays["HKLs"] = self.viewer.proc_arrays[0].indices() for arr in self.viewer.proc_arrays: if arr.is_complex_array(): ampls, phases = self.viewer.Complex2AmplitudesPhases(arr.data()) cmplxlst = [ "%.4f + %.4f * i"%(e.real, e.imag) if not cmath.isnan(e) else display.nanval for e in arr.data() ] self.origarrays[arr.info().label_string()] = cmplxlst self.origarrays[arr.info().labels[0]] = list(ampls) self.origarrays[arr.info().labels[-1]] = list(phases) elif arr.is_hendrickson_lattman_array(): A,B,C,D = arr.data().as_abcd() HLlst = [ "%.4f, %.4f, %.4f, %.4f"%(e[0], e[1], e[2], e[3]) for e in arr.data() ] self.origarrays[arr.info().label_string()] = HLlst self.origarrays[arr.info().labels[0]] = list(A) self.origarrays[arr.info().labels[1]] = list(B) self.origarrays[arr.info().labels[2]] = list(C) self.origarrays[arr.info().labels[3]] = list(D) elif arr.sigmas() is not None: labels = arr.info().labels # Labels could be something like ['I(+)', 'SIGI(+)', 'I(-)', 'SIGI(-)']. # So group datalabels and sigmalabels separately assuming that sigma column contain the three letters "sig" datalabel = ",".join([ e for e in labels if "sig" not in e.lower()]) sigmalabel = ",".join([ e for e in labels if "sig" in e.lower()]) self.origarrays[datalabel] = list(arr.data()) self.origarrays[sigmalabel] = list(arr.sigmas()) elif arr.is_integer_array(): list_with_nans = [ e if not e==display.inanval else display.nanval for e in arr.data() ] if self.viewer.array_infotpls[id][0] == 'FreeR_flag': # want True or False back list_with_nans = [ 1==e if not cmath.isnan(e) else display.nanval for e in list_with_nans ] self.origarrays[arr.info().label_string()] = list_with_nans else: self.origarrays[arr.info().label_string()] = list(arr.data()) labels = eval(datalabels) indices = self.origarrays["HKLs"] dres = self.procarrays[0].unit_cell().d( indices) dreslst = [("d_res", roundoff(list(dres)),3)] hkls = list(indices) hkllst = [ ("H", [e[0] for e in hkls] ), ("K", [e[1] for e in hkls] ), ("L", [e[2] for e in hkls] )] datalst = [] for label in labels: datalst.append( (label, list(self.origarrays[label]))) self.idx_data = hkllst + dreslst + datalst self.mprint("Sending table data...", verbose=0) mydict = { "tabulate_miller_array": self.idx_data } self.params.tabulate_miller_array_ids = "[]" # to allow reopening a closed window again self.SendInfoToGUI(mydict)
def list_vectors(self): self.viewer.all_vectors = self.viewer.rotation_operators[:] if self.tncsvec is not None: uc = self.viewer.miller_array.unit_cell() # TNCS vector is specified in realspace fractional coordinates. Convert it to cartesian cartvec = list( self.tncsvec * matrix.sqr(uc.orthogonalization_matrix()) ) ln = len(self.viewer.all_vectors) self.viewer.all_vectors.append( (ln, "TNCS", 0, cartvec, "", "", str(roundoff(self.tncsvec, 5)) ) ) self.viewer.all_vectors = self.viewer.all_vectors + self.uservectors for (opnr, label, order, cartvec, hkl_op, hkl, abc) in self.viewer.all_vectors: # avoid onMessage-DrawVector in HKLJavaScripts.js misinterpreting the commas in strings like "-x,z+y,-y" name = label + hkl_op.replace(",", "_") self.viewer.RemovePrimitives(name) self.SendInfoToGUI( { "all_vectors": self.viewer.all_vectors } ) return self.viewer.all_vectors
def add_user_vector(self): uc = self.viewer.miller_array.unit_cell() ln = len(self.viewer.all_vectors) label = self.params.viewer.user_label order = 0 try: hklvec = "" abcvec = "" hklop = "" if self.params.viewer.add_user_vector_hkl not in [None, "", "()"]: hklvec = eval(self.params.viewer.add_user_vector_hkl.replace(" ","")) # convert into cartesian space cartvec = list( self.viewer.scene.renderscale*(hklvec * matrix.sqr(uc.fractionalization_matrix()).transpose()) ) elif self.params.viewer.add_user_vector_abc not in [None, "", "()"]: abcvec = eval(self.params.viewer.add_user_vector_abc.replace(" ","")) # convert into cartesian space cartvec = list(abcvec * matrix.sqr(uc.orthogonalization_matrix())) elif self.params.viewer.add_user_vector_hkl_op not in [None, ""]: hklop = self.params.viewer.add_user_vector_hkl_op.replace(" ","") rt = sgtbx.rt_mx(symbol=hklop, r_den=12, t_den=144) rt.r().as_double() self.viewer.symops.append( rt ) # (cartvec, a, label, order) = self.viewer.GetVectorAndAngleFromRotationMx( rt.r() ) if label: label = "%s-fold_%s" %(str(int(roundoff(2*math.pi/a, 0))), self.params.viewer.user_label) self.mprint("Rotation axis, %s, added" %label) if (self.params.viewer.add_user_vector_hkl in [None, "", "()"] \ and self.params.viewer.add_user_vector_abc in [None, "", "()"] \ and self.params.viewer.add_user_vector_hkl_op) in [None, ""]: self.mprint("No vector was specified") self.uservectors.append( (ln, label, order, cartvec, hklop, str(hklvec), str(abcvec) )) self.list_vectors() except Exception as e: raise Sorry( str(e)) self.params.viewer.add_user_vector_hkl_op = "" self.params.viewer.add_user_vector_hkl = "" self.params.viewer.add_user_vector_abc = ""
def __init__(self, millarr, wrap_labels=0): from cctbx.miller import display2 from cctbx.array_family import flex from scitbx import graphics_utils from libtbx.math_utils import roundoff import math nan = float("nan") self.wrap_labels = wrap_labels if millarr.space_group() is None: self.spginf = "?" else: self.spginf = millarr.space_group_info().symbol_and_number() if millarr.unit_cell() is None: self.ucell = (nan, nan, nan, nan, nan, nan) else: self.ucell = millarr.unit_cell().parameters() self.ucellinf = "({:.6g}Å, {:.6g}Å, {:.6g}Å, {:.6g}°, {:.6g}°, {:.6g}°)".format( *self.ucell) data = millarr.deep_copy().data() self.maxdata = self.mindata = self.maxsigmas = self.minsigmas = nan self.minmaxdata = (nan, nan) self.minmaxsigs = (nan, nan) self.data_sigdata_max = nan self.data_sigdata = nan self.desc = "" self.arrsize = data.size() if not isinstance(data, flex.std_string): if isinstance(data, flex.hendrickson_lattman): data = graphics_utils.NoNansHL(data) # estimate minmax values of HL coefficients as a simple sum if self.arrsize: self.maxdata = max( [e[0] + e[1] + e[2] + e[3] for e in data]) self.mindata = min( [e[0] + e[1] + e[2] + e[3] for e in data]) self.arrsize = len([ 42 for e in millarr.data() if not math.isnan(e[0] + e[1] + e[2] + e[3]) ]) elif isinstance(data, flex.vec3_double) or isinstance( data, flex.vec2_double): # XDS produces 2D or 3D arrays in some of its files if self.arrsize: self.maxdata = max([max(e) for e in data]) self.mindata = min([min(e) for e in data]) else: # Get a list of bools with True whenever there is a nan selection = ~graphics_utils.IsNans( flex.abs(millarr.data()).as_double()) # count elements that are not nan values self.arrsize = millarr.data().select(selection).size() if (isinstance(data, flex.int)): data = flex.double( [e for e in data if e != display2.inanval]) if millarr.is_complex_array(): data = flex.abs(data) i = 0 while math.isnan(data[i]): i += 1 # go on until we find a data[i] that isn't NaN data = graphics_utils.NoNansArray( data, data[i]) # assuming data[0] isn't NaN self.maxdata = flex.max(data) self.mindata = flex.min(data) if millarr.sigmas() is not None: data = millarr.sigmas().deep_copy() i = 0 while math.isnan(data[i]): i += 1 # go on until we find a data[i] that isn't NaN data = graphics_utils.NoNansArray(data, data[i]) self.maxsigmas = flex.max(data) self.minsigmas = flex.min(data) # Inspired by Diederichs doi:10.1107/S0907444910014836 I/SigI_asymptotic data_over_sigdata = millarr.data() / millarr.sigmas() self.data_sigdata = flex.sum(data_over_sigdata) / len( data_over_sigdata) self.data_sigdata_max = flex.max(data_over_sigdata) self.minmaxdata = (self.mindata, self.maxdata) self.minmaxsigs = (self.minsigmas, self.maxsigmas) self.labels = self.desc = self.wavelength = "" if millarr.info(): self.labels = millarr.info().labels self.desc = get_array_description(millarr) self.wavelength = "{:.6g}".format( millarr.info().wavelength) if millarr.info( ).wavelength is not None else float("nan") self.span = "(?,?,?), (?,?,?)" self.dmin = nan self.dmax = nan if millarr.unit_cell() is not None: self.span = str(millarr.index_span().min()) + ", " + str( millarr.index_span().max()) self.dmin = millarr.d_max_min()[1] self.dmax = millarr.d_max_min()[0] self.dminmax = roundoff((self.dmin, self.dmax)) self.issymunique = "?" self.isanomalous = "?" self.n_sys_abs = 0 self.n_bijvoet = self.n_singletons = 0 self.ano_mean_diff = nan self.ano_completeness = nan self.data_compl_infty = nan self.data_completeness = nan self.n_centric = nan # computations below done as in cctbx.miller.set.show_comprehensive_summary() if self.spginf != "?": self.issymunique = millarr.is_unique_set_under_symmetry() self.isanomalous = millarr.anomalous_flag() sys_absent_flags = millarr.sys_absent_flags().data() self.n_sys_abs = sys_absent_flags.count(True) if (self.n_sys_abs != 0): millarr = millarr.select(selection=~sys_absent_flags) self.n_centric = millarr.centric_flags().data().count(True) if not math.isnan(self.ucell[0]): if (self.spginf != "?" and millarr.indices().size() > 0 and self.issymunique): millarr.setup_binner(n_bins=1) completeness_d_max_d_min = millarr.completeness( use_binning=True) binner = completeness_d_max_d_min.binner assert binner.counts_given()[0] == 0 assert binner.counts_given()[2] == 0 n_obs = binner.counts_given()[1] n_complete = binner.counts_complete()[1] if (n_complete != 0 and self.dmax != self.dmin): self.data_completeness = n_obs / n_complete n_complete += binner.counts_complete()[0] if (n_complete != 0): self.data_compl_infty = n_obs / n_complete if (self.isanomalous) and (millarr.is_xray_intensity_array() or millarr.is_xray_amplitude_array()): self.ano_completeness = millarr.anomalous_completeness() if (self.spginf != "?" and self.isanomalous and self.issymunique): asu, matches = millarr.match_bijvoet_mates() self.n_bijvoet = matches.pairs().size() self.n_singletons = matches.n_singles() - self.n_centric if millarr.is_real_array(): self.ano_mean_diff = millarr.anomalous_signal() # break long label into list of shorter strings self.labelstr = ",".join(self.labels) if self.wrap_labels > 0: tlabels = textwrap.wrap(self.labelstr, width=self.wrap_labels) nlabl = len(tlabels) self.labelsformat = "{0[0]:>%d} " % (1 + self.wrap_labels) if len(tlabels) > 1: for i in range((len(tlabels) - 1)): self.labelsformat += "\n{0[%d]:>%d} " % ( i + 1, self.wrap_labels + 1) blanks = self.wrap_labels - 5 else: self.labelsformat = "{:>16} " if len(self.labelstr) > 15: self.labelsformat = "{}\n " blanks = 10 self.info_format_dict = { # the keys here must be verbatim copies of names of phil attributes in arrayinfo_phil_str below "labels": (" %s" % self.caption_dict["labels"][0] + " " * blanks, self.labelstr, "{}", self.labelsformat), "description": (" %s " % self.caption_dict["description"][0], self.desc, "{}", "{:>16} "), "wavelength": (" %s " % self.caption_dict["wavelength"][0], self.wavelength, "{}", "{:>8} "), "n_reflections": (" %s " % self.caption_dict["n_reflections"][0], self.arrsize, "{}", "{:>8} "), "span": (" " * 15 + self.caption_dict["span"][0] + " " * 14, self.span, "{}", "{:>32} "), "minmax_data": (" %s " % self.caption_dict["minmax_data"][0], self.minmaxdata, "{0[0]:.6}, {0[1]:.6}", "{0[0]:>11.5}, {0[1]:>11.5}"), "minmax_sigmas": (" %s " % self.caption_dict["minmax_sigmas"][0], self.minmaxsigs, "{0[0]:.6}, {0[1]:.6}", "{0[0]:>11.5}, {0[1]:>11.5}"), "data_sigdata": (" %s" % self.caption_dict["data_sigdata"][0], self.data_sigdata, "{:.4g}", "{:>9.4g} "), "data_sigdata_max": ("%s" % self.caption_dict["data_sigdata_max"][0], self.data_sigdata_max, "{:.4g}", "{:>11.4g} "), "d_minmax": (" %s " % self.caption_dict["d_minmax"][0], self.dminmax, "{0[0]:.6}, {0[1]:.6}", "{0[0]:>8.5}, {0[1]:>8.5}"), "unit_cell": (" %s " % self.caption_dict["unit_cell"][0], self.ucell, "{0[0]:>7.5g},{0[1]:>7.5g},{0[2]:>7.5g},{0[3]:>7.5g},{0[4]:>7.5g},{0[5]:>7.5g}", "{0[0]:>7.5g},{0[1]:>7.5g},{0[2]:>7.5g},{0[3]:>7.5g},{0[4]:>7.5g},{0[5]:>7.5g} " ), "space_group": (" %s " % self.caption_dict["space_group"][0], self.spginf, "{}", "{:>19} "), "n_centrics": ("%s" % self.caption_dict["n_centrics"][0], self.n_centric, "{}", "{:>8} "), "n_sys_abs": ("%s" % self.caption_dict["n_sys_abs"][0], self.n_sys_abs, "{}", "{:>9} "), "data_completeness": ("%s" % self.caption_dict["data_completeness"][0], self.data_completeness, "{:.5g}", "{:>10.5g} "), "data_compl_infty": ("%s" % self.caption_dict["data_compl_infty"][0], self.data_compl_infty, "{:.5g}", "{:>9.5g} "), "is_anomalous": ("%s" % self.caption_dict["is_anomalous"][0], str(self.isanomalous), "{}", "{:>8} "), "is_symmetry_unique": ("%s" % self.caption_dict["is_symmetry_unique"][0], str(self.issymunique), "{}", "{:>8} "), "ano_completeness": ("%s" % self.caption_dict["ano_completeness"][0], self.ano_completeness, "{:.5g}", "{:>11.5g} "), "ano_mean_diff": ("%s" % self.caption_dict["ano_mean_diff"][0], self.ano_mean_diff, "{:.5g}", "{:>8.5g} "), "n_bijvoet": ("%s" % self.caption_dict["n_bijvoet"][0], self.n_bijvoet, "{}", "{:>8} "), "n_singletons": ("%s" % self.caption_dict["n_singletons"][0], self.n_singletons, "{}", "{:>10} "), }
def DrawNGLJavaScript(self): if self.miller_array is None: self.mprint("A miller array must be selected for drawing") return self.mprint("Composing NGL JavaScript...") h_axis = self.scene.axes[0] k_axis = self.scene.axes[1] l_axis = self.scene.axes[2] nrefls = self.scene.points.size() Hstararrowstart = roundoff( [-h_axis[0] * 100, -h_axis[1] * 100, -h_axis[2] * 100]) Hstararrowend = roundoff( [h_axis[0] * 100, h_axis[1] * 100, h_axis[2] * 100]) Hstararrowtxt = roundoff( [h_axis[0] * 102, h_axis[1] * 102, h_axis[2] * 102]) Kstararrowstart = roundoff( [-k_axis[0] * 100, -k_axis[1] * 100, -k_axis[2] * 100]) Kstararrowend = roundoff( [k_axis[0] * 100, k_axis[1] * 100, k_axis[2] * 100]) Kstararrowtxt = roundoff( [k_axis[0] * 102, k_axis[1] * 102, k_axis[2] * 102]) Lstararrowstart = roundoff( [-l_axis[0] * 100, -l_axis[1] * 100, -l_axis[2] * 100]) Lstararrowend = roundoff( [l_axis[0] * 100, l_axis[1] * 100, l_axis[2] * 100]) Lstararrowtxt = roundoff( [l_axis[0] * 102, l_axis[1] * 102, l_axis[2] * 102]) # make arrow font size roughly proportional to radius of highest resolution shell fontsize = str(1.0 + roundoff( math.pow(max(self.miller_array.index_span().max()), 1.0 / 3.0))) arrowstr = """ // xyz arrows shape.addSphere( [0,0,0] , [ 1, 1, 1 ], 0.3, 'Origo'); //blue-x shape.addArrow( %s, %s , [ 0, 0, 1 ], 0.1); //green-y shape.addArrow( %s, %s , [ 0, 1, 0 ], 0.1); //red-z shape.addArrow( %s, %s , [ 1, 0, 0 ], 0.1); shape.addText( %s, [ 0, 0, 1 ], %s, 'h'); shape.addText( %s, [ 0, 1, 0 ], %s, 'k'); shape.addText( %s, [ 1, 0, 0 ], %s, 'l'); """ % (str(Hstararrowstart), str(Hstararrowend), str(Kstararrowstart), str(Kstararrowend), str(Lstararrowstart), str(Lstararrowend), Hstararrowtxt, fontsize, Kstararrowtxt, fontsize, Lstararrowtxt, fontsize) # Make colour gradient array used for drawing a bar of colours next to associated values on the rendered html mincolourscalar = self.othermindata[self.icolourcol] maxcolourscalar = self.othermaxdata[self.icolourcol] if self.settings.sigma_color: mincolourscalar = self.otherminsigmas[self.icolourcol] maxcolourscalar = self.othermaxsigmas[self.icolourcol] span = maxcolourscalar - mincolourscalar ln = 60 incr = span / ln colourgradarrays = [] val = mincolourscalar colourscalararray = flex.double() colourscalararray.append(val) for j, sc in enumerate(range(ln)): val += incr colourscalararray.append(val) if self.otherscenes[self.icolourcol].miller_array.is_complex_array(): # When displaying phases from map coefficients together with fom values # compute colour map chart as a function of fom and phase values (x,y axis) incr = 360.0 / ln val = 0.0 colourscalararray = flex.double() colourscalararray.append(val) for j in enumerate(range(ln)): val += incr colourscalararray.append(val) fomarrays = [] if self.otherscenes[self.icolourcol].isUsingFOMs(): fomln = 50 fom = 1.0 fomdecr = 1.0 / (fomln - 1.0) # make fomln fom arrays of size len(colourscalararray) when calling colour_by_phi_FOM for j in range(fomln): fomarrays.append(flex.double(len(colourscalararray), fom)) fom -= fomdecr for j in range(fomln): colourgradarrays.append( graphics_utils.colour_by_phi_FOM( colourscalararray * (math.pi / 180.0), fomarrays[j]) * 255.0) else: fomln = 1 fomarrays = [1.0] colourgradarrays.append( graphics_utils.colour_by_phi_FOM(colourscalararray * (math.pi / 180.0)) * 255.0) else: fomln = 1 fomarrays = [1.0] colourgradarrays.append( graphics_utils.color_by_property( properties=flex.double(colourscalararray), selection=flex.bool(len(colourscalararray), True), color_all=False, gradient_type=self.settings.color_scheme) * 255.0) colors = self.otherscenes[self.icolourcol].colors radii = self.otherscenes[self.iradiicol].radii points = self.scene.points hkls = self.scene.indices dres = self.scene.dres colstr = self.scene.miller_array.info().label_string() data = self.scene.data colourlabel = self.otherscenes[self.icolourcol].colourlabel fomlabel = self.otherscenes[self.icolourcol].fomlabel #import code, traceback; code.interact(local=locals(), banner="".join( traceback.format_stack(limit=10) ) ) assert (colors.size() == radii.size() == nrefls) colours = [] positions = [] radii2 = [] spbufttips = [] self.workingbinvals = [] if not self.binarray == "Resolution": ibinarray = int(self.binarray) self.workingbinvals = [ self.othermindata[ibinarray] - 0.1, self.othermaxdata[ibinarray] + 0.1 ] self.workingbinvals.extend(self.binvals) self.workingbinvals.sort() if self.workingbinvals[0] < 0.0: self.workingbinvals.append(0.0) self.workingbinvals.sort() bindata = self.otherscenes[ibinarray].data if self.otherscenes[ibinarray].work_array.is_complex_array(): bindata = self.otherscenes[ibinarray].ampl else: self.workingbinvals = self.binvals colstr = "dres" bindata = 1.0 / dres self.nbin = len(self.workingbinvals) for ibin in range(self.nbin): colours.append([]) # colours and positions are 3 x size of data() positions.append([]) radii2.append([]) spbufttips.append([]) def data2bin(d): for ibin, binval in enumerate(self.workingbinvals): if (ibin + 1) == self.nbin: return ibin if d > binval and d <= self.workingbinvals[ibin + 1]: return ibin #import code, traceback; code.interact(local=locals(), banner="".join( traceback.format_stack(limit=10) ) ) raise Sorry("Should never get here") #import code, traceback; code.interact(local=locals(), banner="".join( traceback.format_stack(limit=10) ) ) for i, hklstars in enumerate(points): # bin currently displayed data according to the values of another miller array ibin = data2bin(bindata[i]) spbufttip = 'H,K,L: %s, %s, %s' % (hkls[i][0], hkls[i][1], hkls[i][2]) spbufttip += '\ndres: %s ' % str(roundoff(dres[i])) spbufttip += '\' + AA + \'' for j, otherscene in enumerate(self.otherscenes): ocolstr = self.proc_arrays[j].info().label_string() odata = otherscene.data od = "" if self.proc_arrays[j].is_complex_array(): if not math.isnan(otherscene.foms[i]): od = str(roundoff(otherscene.ampl[i])) + ", " + str(roundoff(otherscene.phases[i]) ) + \ "\' + DGR + \'" + ", " + str(roundoff(otherscene.foms[i]) ) else: od = str(roundoff(otherscene.ampl[i])) + ", " + str(roundoff(otherscene.phases[i]) ) + \ "\' + DGR + \'" elif self.proc_arrays[j].sigmas() is not None: od = str(roundoff(odata[i])) + ", " + str( roundoff(otherscene.sigmas[i])) else: od = str(roundoff(odata[i])) if not (math.isnan(abs(odata[i])) or odata[i] == display.inanval): spbufttip += "\n%s: %s" % (ocolstr, od) positions[ibin].extend(roundoff(list(hklstars))) colours[ibin].extend(roundoff(list(colors[i]), 2)) radii2[ibin].append(roundoff(radii[i], 2)) spbufttips[ibin].append(spbufttip) spherebufferstr = """ ttips = new Array(%d) positions = new Array(%d) colours = new Array(%d) radii = new Array(%d) spherebufs = new Array(%d) """ % (self.nbin, self.nbin, self.nbin, self.nbin, self.nbin) negativeradiistr = "" cntbin = 0 self.binstrs = [] for ibin in range(self.nbin): mstr = "" nreflsinbin = len(radii2[ibin]) if (ibin + 1) < self.nbin and nreflsinbin > 0: bin1 = self.workingbinvals[ibin] bin2 = self.workingbinvals[ibin + 1] if colstr == "dres": bin1 = 1.0 / self.workingbinvals[ibin] bin2 = 1.0 / self.workingbinvals[ibin + 1] mstr= "bin:%d, %d reflections with %s in ]%2.2f; %2.2f]" %(cntbin, nreflsinbin, \ colstr, bin1, bin2) self.binstrs.append(mstr) self.mprint(mstr, verbose=True) spherebufferstr += """ // %s ttips[%d] = %s positions[%d] = new Float32Array( %s ) colours[%d] = new Float32Array( %s ) radii[%d] = new Float32Array( %s ) spherebufs[%d] = new NGL.SphereBuffer({ position: positions[%d], color: colours[%d], radius: radii[%d], picking: ttips[%d], }) //}, { disableImpostor: true }) // if true allows wireframe spheres but does not allow resizing spheres shape.addBuffer(spherebufs[%d]) """ %(mstr, cntbin, str(spbufttips[ibin]).replace('\"', '\''), \ cntbin, str(positions[ibin]), cntbin, str(colours[ibin]), \ cntbin, str(radii2[ibin]), cntbin, cntbin, cntbin, cntbin, cntbin, cntbin ) if self.workingbinvals[ibin] < 0.0: negativeradiistr += "spherebufs[%d].setParameters({metalness: 1})\n" % cntbin cntbin += 1 spherebufferstr += """ // create tooltip element and add to the viewer canvas tooltip = document.createElement("div"); Object.assign(tooltip.style, { display: "none", position: "absolute", zIndex: 10, pointerEvents: "none", backgroundColor: "rgba(255, 255, 255, 0.75)", color: "black", padding: "0.1em", fontFamily: "sans-serif" }); stage.viewer.container.appendChild(tooltip); // listen to `hovered` signal to move tooltip around and change its text stage.signals.hovered.add(function (pickingProxy) { if (pickingProxy && (Object.prototype.toString.call(pickingProxy.picker) === '[object Array]' )){ var sphere = pickingProxy.sphere; var cp = pickingProxy.canvasPosition; tooltip.innerText = pickingProxy.picker[pickingProxy.pid]; tooltip.style.bottom = cp.y + 7 + "px"; tooltip.style.left = cp.x + 8 + "px"; tooltip.style.fontSize = "smaller"; tooltip.style.display = "block"; }else{ tooltip.style.display = "none"; } }); stage.signals.clicked.add(function (pickingProxy) { if (pickingProxy && (Object.prototype.toString.call(pickingProxy.picker) === '[object Array]' )){ var innerText = pickingProxy.picker[pickingProxy.pid]; mysocket.send( innerText); } }); """ colourgradstrs = "colourgradvalarray = new Array(%s)\n" % fomln # if displaying phases from map coefficients together with fom values then for g, colourgradarray in enumerate(colourgradarrays): self.colourgradientvalues = [] for j, e in enumerate(colourgradarray): self.colourgradientvalues.append([colourscalararray[j], e]) self.colourgradientvalues = roundoff(self.colourgradientvalues) fom = fomarrays[g] colourgradstr = [] for j, val in enumerate(self.colourgradientvalues): vstr = "" alpha = 1.0 gradval = "rgba(%s, %s, %s, %s)" % (val[1][0], val[1][1], val[1][2], alpha) if j % 10 == 0 or j == len(self.colourgradientvalues) - 1: vstr = str(roundoff(val[0], 2)) colourgradstr.append([vstr, gradval]) colourgradstrs += " colourgradvalarray[%s] = %s\n" % ( g, str(colourgradstr)) #negativeradiistr = "" #for ibin in range(self.nbin): # if self.workingbinvals[ibin] < 0.0: # negativeradiistr += "spherebufs[%d].setParameters({metalness: 1})\n" %ibin self.NGLscriptstr = """ // Microsoft Edge users follow instructions on // https://stackoverflow.com/questions/31772564/websocket-to-localhost-not-working-on-microsoft-edge // to enable websocket connection var pagename = location.pathname.substring(1); var mysocket = new WebSocket('ws://127.0.0.1:7894/'); mysocket.onopen = function (e) { mysocket.send('%s now connected via websocket to ' + pagename + '\\n'); }; mysocket.onclose = function (e) { mysocket.send('%s now disconnecting from websocket ' + pagename + '\\n'); }; // Log errors to debugger of your browser mysocket.onerror = function (error) { console.log('WebSocket Error ' + error); }; window.addEventListener( 'resize', function( event ){ stage.handleResize(); }, false ); var stage; var shape; var shapeComp; var repr; var AA = String.fromCharCode(197); // short for angstrom var DGR = String.fromCharCode(176); // short for degree symbol function createElement (name, properties, style) { // utility function used in for loop over colourgradvalarray var el = document.createElement(name) Object.assign(el, properties) Object.assign(el.style, style) Object.assign(el.style, { display: "block", position: "absolute", color: "black", fontFamily: "sans-serif", fontSize: "smaller", } ) return el } function addElement (el) { // utility function used in for loop over colourgradvalarray Object.assign(el.style, { position: "absolute", zIndex: 10 }) stage.viewer.container.appendChild(el) } function addDivBox(txt, t, l, w, h, bgcolour='rgba(255.0, 255.0, 255.0, 0.0)') { divbox = createElement("div", { innerText: txt }, { backgroundColor: bgcolour, color: 'rgba(0.0, 0.0, 0.0, 1.0)', top: t.toString() + "px", left: l.toString() + "px", width: w.toString() + "px", height: h.toString() + "px", } ); addElement(divbox) } var hklscene = function () { shape = new NGL.Shape('shape'); stage = new NGL.Stage('viewport', { backgroundColor: "grey", tooltip:false, fogNear: 100, fogFar: 100 }); stage.setParameters( { cameraType: "%s" } ); %s %s shapeComp = stage.addComponentFromObject(shape); repr = shapeComp.addRepresentation('buffer'); shapeComp.autoView(); repr.update() // if some radii are negative draw them with wireframe %s //colourgradvalarrays %s var ih = 3; var topr = 35 var topr2 = 10 var lp = 10 var wp = 40 var lp2 = lp + wp var gl = 3 var wp2 = gl var fomlabelheight = 25 if (colourgradvalarray.length === 1) { wp2 = 15 fomlabelheight = 0 } var wp3 = wp + colourgradvalarray.length * wp2 + 2 totalheight = ih*colourgradvalarray[0].length + 35 + fomlabelheight // make a white box on top of which boxes with transparent background are placed // containing the colour values at regular intervals as well as label legend of // the displayed miller array addDivBox("", topr2, lp, wp3, totalheight, 'rgba(255.0, 255.0, 255.0, 1.0)'); // print label of the miller array used for colouring addDivBox("%s", topr2, lp, wp, 20); if (colourgradvalarray.length > 1) { // print FOM label, 1, 0.5 and 0.0 values below colour chart fomtop = topr2 + totalheight - 18 fomlp = lp + wp fomwp = wp3 fomtop2 = fomtop - 13 // print the 1 number addDivBox("1", fomtop2, fomlp, fomwp, 20) // print the 0.5 number leftp = fomlp + 0.48 * gl * colourgradvalarray.length addDivBox("0.5", fomtop2, leftp, fomwp, 20) // print the FOM label addDivBox("%s", fomtop, leftp, fomwp, 20); // print the 0 number leftp = fomlp + 0.96 * gl * colourgradvalarray.length addDivBox("0", fomtop2, leftp, fomwp, 20) } for (j = 0; j < colourgradvalarray[0].length; j++) { rgbcol = colourgradvalarray[0][j][1]; val = colourgradvalarray[0][j][0] topv = j*ih + topr toptxt = topv - 5 // print value of miller array if present in colourgradvalarray[0][j][0] addDivBox(val, toptxt, lp, wp, ih); } // draw the colour gradient for (g = 0; g < colourgradvalarray.length; g++) { leftp = g*gl + lp + wp // if FOM values are supplied draw colour gradients with decreasing // saturation values as stored in the colourgradvalarray[g] arrays for (j = 0; j < colourgradvalarray[g].length; j++) { rgbcol = colourgradvalarray[g][j][1]; val = colourgradvalarray[g][j][0] topv = j*ih + topr addDivBox("", topv, leftp, wp2, ih, rgbcol); } } } document.addEventListener('DOMContentLoaded', function() { hklscene() }, false ); mysocket.onmessage = function (e) { //alert('Server: ' + e.data); var c var alpha var si mysocket.send('got ' + e.data ); // tell server what it sent us try { val = e.data.split(",") if (val[0] === "alpha") { ibin = parseInt(val[1]) alpha = parseFloat(val[2]) spherebufs[ibin].setParameters({opacity: alpha}) stage.viewer.requestRender() } if (val[0] === "colour") { ibin = parseInt(val[1]) si = parseInt(val[2]) colours[ibin][3*si] = parseFloat(val[3]) colours[ibin][3*si+1] = parseFloat(val[4]) colours[ibin][3*si+2] = parseFloat(val[5]) spherebufs[ibin].setAttributes({ color: colours[ibin] }) stage.viewer.requestRender() } if (val[0] === "Redraw") { stage.viewer.requestRender() } if (val[0] === "ReOrient") { mysocket.send( 'Reorienting ' + pagename ); sm = new Float32Array(16); for (j=0; j<16; j++) sm[j] = parseFloat(val[j + 2]) // first 2 are "ReOrient", "NGL\\n" var m = new NGL.Matrix4(); m.fromArray(sm); stage.viewerControls.orient(m); stage.viewer.requestRender(); } if (val[0] === "Reload") { // refresh browser with the javascript file cvorient = stage.viewerControls.getOrientation().elements msg = String(cvorient) mysocket.send('Current vieworientation:\\n, ' + msg ); mysocket.send( 'Refreshing ' + pagename ); window.location.reload(true); } if (val[0] === "Testing") { // test something new mysocket.send( 'Testing something new ' + pagename ); var newradii = radii[0].map(function(element) { return element*1.5; }); spherebufs[0].setAttributes({ radius: newradii }) stage.viewer.requestRender() } } catch(err) { mysocket.send('error: ' + err ); } }; """ % (self.__module__, self.__module__, self.cameratype, arrowstr, spherebufferstr, \ negativeradiistr, colourgradstrs, colourlabel, fomlabel) if self.jscriptfname: with open(self.jscriptfname, "w") as f: f.write(self.NGLscriptstr) self.ReloadNGL()