def __init__(SMG, goniometer): from scitbx.array_family import flex import math SMG.goniometer = goniometer coords = flex.vec3_double() axis = flex.size_t() # FACE A: Sample holder # Defined as semi-circle of radius r(A) = 10 mm (centred on PHI axis) # with rectangle of size a(A) = 12.8 mm (x 20 mm) offsetA = 33.0 # semi-circle for phi=-90 ... +90 radiusA = 10.0 phi = flex.double_range(-90, 100, step=10) * math.pi / 180 x = flex.double(phi.size(), -offsetA) y = radiusA * flex.cos(phi) z = radiusA * flex.sin(phi) # corners of square sqdA = 12.8 # square depth nsteps = 10 for i in range(nsteps + 1): for sign in (+1, -1): x.append(-offsetA) y.append(i * -sqdA / nsteps) z.append(sign * radiusA) x.append(-offsetA) y.append(-sqdA) z.append(0) SMG.faceA = flex.vec3_double(x, y, z) # FACE B: Lower arm sx = -28.50 sy = -4.90 sz = 8.50 mx = -13.80 my = -26.00 nx = -27.50 ny = -29.50 px = -65.50 py = -29.50 SMG.faceB = flex.vec3_double( ((sx, sy, sz), (mx, my, 0), (nx, ny, 0), (px, py, 0))) # FACE E: Rim of sample holder # Defined as circle of radius r(E) = 6 mm (centred on PHI axis) at an # offset o(E) = 19 mm offsetE = 19.0 radiusE = 6.0 phi = flex.double_range(0, 360, step=15) * math.pi / 180 x = flex.double(phi.size(), -offsetE) y = radiusE * flex.cos(phi) z = radiusE * flex.sin(phi) SMG.faceE = flex.vec3_double(x, y, z)
def __init__(self, goniometer): # FACE A: Sample holder # Defined as semi-circle of radius r(A) = 10 mm (centred on PHI axis) # with rectangle of size a(A) = 12.8 mm (x 20 mm) offsetA = 33.0 # semi-circle for phi=-90 ... +90 radiusA = 10.0 phi = flex.double_range(-90, 100, step=10) * math.pi / 180 x = flex.double(phi.size(), -offsetA) y = radiusA * flex.cos(phi) z = radiusA * flex.sin(phi) # corners of square sqdA = 12.8 # square depth nsteps = 10 for i in range(nsteps + 1): for sign in (+1, -1): x.append(-offsetA) y.append(i * -sqdA / nsteps) z.append(sign * radiusA) x.append(-offsetA) y.append(-sqdA) z.append(0) self.faceA = flex.vec3_double(-x, -y, z) # FACE B: Lower arm sx = -28.50 sy = -4.90 sz = 8.50 mx = -13.80 my = -26.00 nx = -27.50 ny = -29.50 px = -65.50 py = -29.50 self.faceB = flex.vec3_double( ((-sx, -sy, sz), (-mx, -my, 0), (-nx, -ny, 0), (-px, -py, 0)) ) # FACE E: Rim of sample holder # Defined as circle of radius r(E) = 6 mm (centred on PHI axis) at an # offset o(E) = 19 mm offsetE = 19.0 radiusE = 6.0 phi = flex.double_range(0, 360, step=15) * math.pi / 180 x = flex.double(phi.size(), -offsetE) y = radiusE * flex.cos(phi) z = radiusE * flex.sin(phi) self.faceE = flex.vec3_double(-x, -y, z) extrema_at_datum = self.faceA.deep_copy() extrema_at_datum.extend(self.faceE) super().__init__( goniometer, extrema_at_datum, flex.size_t(extrema_at_datum.size(), 1) )
def __init__(self, goniometer): from scitbx.array_family import flex import math self.goniometer = goniometer coords = flex.vec3_double() axis = flex.size_t() # FACE A: Sample holder # Defined as semi-circle of radius r(A) = 10 mm (centred on PHI axis) # with rectangle of size a(A) = 12.8 mm (x 20 mm) offsetA = 33.0 radiusA = 10.0 sqdA = 12.8 # square depth phi = flex.double_range(-90, 100, step=10) * math.pi / 180 x = flex.double(phi.size(), -offsetA) y = radiusA * flex.cos(phi) z = radiusA * flex.sin(phi) x.extend(flex.double(5, -offsetA)) y.extend(flex.double((-sqdA / 2, -sqdA, -sqdA, -sqdA, -sqdA / 2))) z.extend(flex.double((radiusA, radiusA, 0, -radiusA, -radiusA))) self.faceA = flex.vec3_double(x, y, z) # FACE B: Lower arm sx = -28.50 sy = -4.90 sz = 8.50 mx = -13.80 my = -26.00 nx = -27.50 ny = -29.50 px = -65.50 py = -29.50 self.faceB = flex.vec3_double( ((sx, sy, sz), (mx, my, 0), (nx, ny, 0), (px, py, 0))) # FACE E: Rim of sample holder # Defined as circle of radius r(E) = 6 mm (centred on PHI axis) at an # offset o(E) = 19 mm offsetE = 19.0 radiusE = 6.0 phi = flex.double_range(0, 360, step=15) * math.pi / 180 x = flex.double(phi.size(), -offsetE) y = radiusE * flex.cos(phi) z = radiusE * flex.sin(phi) self.faceE = flex.vec3_double(x, y, z)
def __init__(self, goniometer): from scitbx.array_family import flex import math self.goniometer = goniometer coords = flex.vec3_double() axis = flex.size_t() # FACE A: Sample holder # Defined as semi-circle of radius r(A) = 10 mm (centred on PHI axis) # with rectangle of size a(A) = 12.8 mm (x 20 mm) offsetA = 33.0 radiusA = 10.0 sqdA = 12.8 # square depth phi = flex.double_range(-90, 100, step=10) * math.pi/180 x = flex.double(phi.size(), -offsetA) y = radiusA * flex.cos(phi) z = radiusA * flex.sin(phi) x.extend(flex.double(5, -offsetA)) y.extend(flex.double((-sqdA/2, -sqdA, -sqdA, -sqdA, -sqdA/2))) z.extend(flex.double((radiusA, radiusA, 0, -radiusA, -radiusA))) self.faceA = flex.vec3_double(x, y, z) # FACE B: Lower arm sx = -28.50 sy = -4.90 sz = 8.50 mx = -13.80 my = -26.00 nx = -27.50 ny = -29.50 px = -65.50 py = -29.50 self.faceB = flex.vec3_double(((sx,sy,sz),(mx,my,0),(nx,ny,0),(px,py,0))) # FACE E: Rim of sample holder # Defined as circle of radius r(E) = 6 mm (centred on PHI axis) at an # offset o(E) = 19 mm offsetE = 19.0 radiusE = 6.0 phi = flex.double_range(0, 360, step=15) * math.pi/180 x = flex.double(phi.size(), -offsetE) y = radiusE * flex.cos(phi) z = radiusE * flex.sin(phi) self.faceE = flex.vec3_double(x, y, z)
def _construct_shadow_masker(goniometer): if request.param == "cpp": return GoniometerMaskerFactory.mini_kappa(goniometer) # Simple model of cone around goniometer phi axis # Exact values don't matter, only the ratio of height/radius height = 50 # mm radius = 20 # mm steps_per_degree = 1 theta = ( flex.double(range(360 * steps_per_degree)) * math.pi / 180 * 1 / steps_per_degree ) y = radius * flex.cos(-theta) z = radius * flex.sin(-theta) x = flex.double(theta.size(), height) coords = flex.vec3_double(zip(x, y, z)) coords.insert(0, (0, 0, 0)) return PyGoniometerShadowMasker(goniometer, coords, flex.size_t(len(coords), 0))
def parts(self,fpp): dano_summation = None Ddanocalc_Dp = [] for j,idx in enumerate(self.scatterer_idx): bool_array = self.xray_structure.by_index_selection([idx]) xrs_atom = self.xray_structure.select(bool_array) #xrs_atom.show_scatterers() f_calc_atom = self.f_calc.structure_factors_from_scatterers( xray_structure=xrs_atom, algorithm=algorithm).f_calc() adata = f_calc_atom.data().parts()[0] bdata = f_calc_atom.data().parts()[1] product_factor = bdata * flex.cos(self.phases.data()) - adata * flex.sin(self.phases.data()) # correspnds to -b cos(alpha) + a sin(alpha) #print list(xrs_atom.scattering_types()) #xrs_atom.scattering_type_registry().show_summary() #xrs_atom.scattering_type_registry().show() f_zero = xrs_atom.scattering_type_registry().sum_of_scattering_factors_at_diffraction_angle_0() #print f_zero Ddanocalc_Dp.append((-2./f_zero)*product_factor) term = (-2.*fpp[j]/f_zero)*product_factor if dano_summation is None: dano_summation = term else: dano_summation += term return dano_summation,Ddanocalc_Dp """
def parts(self, fpp): dano_summation = None Ddanocalc_Dp = [] for j, idx in enumerate(self.scatterer_idx): bool_array = self.xray_structure.by_index_selection([idx]) xrs_atom = self.xray_structure.select(bool_array) #xrs_atom.show_scatterers() f_calc_atom = self.f_calc.structure_factors_from_scatterers( xray_structure=xrs_atom, algorithm=algorithm).f_calc() adata = f_calc_atom.data().parts()[0] bdata = f_calc_atom.data().parts()[1] product_factor = bdata * flex.cos( self.phases.data()) - adata * flex.sin(self.phases.data()) # correspnds to -b cos(alpha) + a sin(alpha) #print list(xrs_atom.scattering_types()) #xrs_atom.scattering_type_registry().show_summary() #xrs_atom.scattering_type_registry().show() f_zero = xrs_atom.scattering_type_registry( ).sum_of_scattering_factors_at_diffraction_angle_0() #print f_zero Ddanocalc_Dp.append((-2. / f_zero) * product_factor) term = (-2. * fpp[j] / f_zero) * product_factor if dano_summation is None: dano_summation = term else: dano_summation += term return dano_summation, Ddanocalc_Dp """
def get_goniometer_shadow_masker(self, goniometer=None): if goniometer is None: goniometer = self.get_goniometer() from dials.util.masking import GoniometerShadowMaskGenerator from scitbx.array_family import flex import math # Simple model of cone around goniometer phi axis # Exact values don't matter, only the ratio of height/radius height = 10 # mm cone_opening_angle = 2 * 38 * math.pi / 180 radius_height_ratio = math.tan(1 / 2 * cone_opening_angle) radius = radius_height_ratio * height # print 2 * math.atan(radius/height) * 180 / math.pi steps_per_degree = 1 theta = (flex.double([range(360 * steps_per_degree)]) * math.pi / 180 * 1 / steps_per_degree) x = radius * flex.cos(theta) # x z = radius * flex.sin(theta) # y y = flex.double(theta.size(), height) # z coords = flex.vec3_double(zip(x, y, z)) coords.extend(flex.vec3_double(zip(x, -y, z))) coords.insert(0, (0, 0, 0)) if goniometer is None: goniometer = self.get_goniometer() return GoniometerShadowMaskGenerator(goniometer, coords, flex.size_t(len(coords), 0))
def circ_len (t, deg=True) : assert (len(t) > 0) from scitbx.array_family import flex if (deg) : t = math.pi * (t/180) sx = flex.sum(flex.cos(t)) / len(t) sy = flex.sum(flex.sin(t)) / len(t) return math.sqrt(sx**2 + sy**2)
def circ_len(t, deg=True): assert (len(t) > 0) from scitbx.array_family import flex if (deg): t = math.pi * (t / 180) sx = flex.sum(flex.cos(t)) / len(t) sy = flex.sum(flex.sin(t)) / len(t) return math.sqrt(sx**2 + sy**2)
def circ_mean(t, deg=True): assert (len(t) > 0) from scitbx.array_family import flex if (deg): t = math.pi * (t / 180) sx = flex.sum(flex.cos(t)) / len(t) sy = flex.sum(flex.sin(t)) / len(t) return math.degrees(math.atan2(sy, sx))
def circ_mean (t, deg=True) : assert (len(t) > 0) from scitbx.array_family import flex if (deg) : t = math.pi * (t/180) sx = flex.sum(flex.cos(t)) / len(t) sy = flex.sum(flex.sin(t)) / len(t) return math.degrees(math.atan2(sy, sx))
def compute_functional_and_gradients(self, vector): assert len(vector) == 3 two_pi_S_dot_v = 2 * math.pi * self.reciprocal_lattice_points.dot(vector) f = -flex.sum(flex.cos(two_pi_S_dot_v)) sin_part = flex.sin(two_pi_S_dot_v) g = flex.double( [flex.sum(2 * math.pi * self._xyz_parts[i] * sin_part) for i in range(3)] ) return f, g
def chebyshev_nodes(n, low=-1, high=1, include_limits=False): x = flex.double(range(n)) + 1 x = (2.0 * x - 1.0) / n x = x * math.pi / 2.0 x = -flex.cos(x) if include_limits: span = (flex.max(x) - flex.min(x)) / 2.0 x = x / span x = 0.5 * (low + high) + 0.5 * (high - low) * x if include_limits: x[0] = low x[n - 1] = high return x
def chebyshev_nodes(n, low=-1, high=1, include_limits=False): x = flex.double(range(n)) + 1 x = (2.0 * x - 1.0) / n x = x * math.pi / 2.0 x = -flex.cos(x) if include_limits: span = (flex.max(x) - flex.min(x)) / 2.0 x = x / span x = 0.5 * (low + high) + 0.5 * (high - low) * x if include_limits: x[0] = low x[n - 1] = high return (x)
def get_goniometer_shadow_masker(self, goniometer=None): if goniometer is None: goniometer = self.get_goniometer() assert goniometer is not None # avoid a module-level import from the DIALS namespace that kills LABELIT from dials.util.masking import GoniometerShadowMaskGenerator if goniometer.get_names()[1] == "GON_CHI": # SmarGon from dxtbx.format.SmarGonShadowMask import SmarGonShadowMaskGenerator return SmarGonShadowMaskGenerator(goniometer) elif goniometer.get_names()[1] == "GON_KAPPA": # mini Kappa from dials.util.masking import GoniometerShadowMaskGenerator from scitbx.array_family import flex # Simple model of cone around goniometer phi axis # Exact values don't matter, only the ratio of height/radius height = 50 # mm radius = 20 # mm steps_per_degree = 1 theta = ( flex.double([range(360 * steps_per_degree)]) * math.pi / 180 * 1 / steps_per_degree ) y = radius * flex.cos(theta) # x z = radius * flex.sin(theta) # y x = flex.double(theta.size(), height) # z coords = flex.vec3_double(zip(x, y, z)) coords.insert(0, (0, 0, 0)) return GoniometerShadowMaskGenerator( goniometer, coords, flex.size_t(len(coords), 0) ) else: raise RuntimeError( "Don't understand this goniometer: %s" % list(goniometer.get_names()) )
def fit_data(p): fls = fourier_legendre_series() fls.read_polynomials(p.fls_data) cos_sq = p.q*p.wavelength/(4.0*math.pi) cos_sq = cos_sq*cos_sq sin_sq = 1.0 - cos_sq fit_x = cos_sq + sin_sq*flex.cos(p.x) fit_ac = p.ac.deep_copy() fit_x, fit_ac = zip(*sorted(zip(fit_x,fit_ac))) fit_x = flex.double(fit_x) fit_ac = flex.double(fit_ac) fit_c = fls.compute_coefficients(p.fit_order,fit_ac,fit_x) fit_c = set_odd_coefficients_to_zero(fit_c) fit_v = fls.compute_coefficient_variances(p.fit_order,p.v,fit_x) fit_v = set_odd_coefficients_to_zero(fit_v) if (p.minimize): nz_c = flex.double() for k in xrange(0,len(fit_c),2): if (fit_c[k] < 0.0): fit_c[k] = -fit_c[k] nz_c.append(fit_c[k]) m = lbfgs_optimizer(fit_ac,flex.sqrt(p.v),nz_c,fit_x,fls) nz_v = m.estimate_asymptotic_variance(m.x) assert(nz_c.size() == nz_v.size()) count = 0 for k in xrange(0,len(fit_c),2): fit_c[k] = m.x[count] fit_v[k] = nz_v[count] count += 1 f_min = 1.0 f_max = 1.0 if (p.standardize): # standardize fitted curve to have a min of 1.0 and max of 2.0 old_f = fls.compute_function(fit_c,fit_x) # assume f is positive f_min = flex.min(old_f) f_max = flex.max(flex.fabs(old_f / f_min - 1.0)) scales = (f_min,f_max) return fit_c, fit_v, scales
def diamond_anvil_cell(goniometer, cone_opening_angle): radius_height_ratio = math.tan(1 / 2 * cone_opening_angle) height = 10 # mm radius = radius_height_ratio * height steps_per_degree = 1 theta = (flex.double([list(range(360 * steps_per_degree))]) * math.pi / 180 * 1 / steps_per_degree) x = radius * flex.cos(theta) # x z = radius * flex.sin(theta) # y y = flex.double(theta.size(), height) # z coords = flex.vec3_double(zip(x, y, z)) coords.extend(flex.vec3_double(zip(x, -y, z))) coords.insert(0, (0, 0, 0)) return GoniometerShadowMasker(goniometer, coords, flex.size_t(len(coords), 0), True)
def tst_sphere(): bli = intensity.block_integrator(50.0, 0.1, 1.0, 0.001) q = flex.double(range(1, 300)) / 1000.0 bli.setup_arrays(q) r = flex.double(range(500)) / 500.0 r = r pr = 6.0 * r * r * (2 - 3.0 * r + r * r * r) r = r * 50 #for rr, pp in zip(r,pr): # print rr, pp iii = bli.get_intensity(pr) iii = iii / 25.0 jjj = (flex.sin(25.0 * q) - 25.0 * q * flex.cos(q * 25.0)) / (1e-12 + q * q * q * 25 * 25 * 25) jjj = jjj * jjj jjj = jjj / jjj[0] for q, i, j in zip(q, iii, jjj): assert (abs(i - j) < 1e-2)
def get_goniometer_shadow_masker(self, goniometer=None): from dials.util.masking import GoniometerShadowMaskGenerator from scitbx.array_family import flex import math # Simple model of cone around goniometer phi axis # Exact values don't matter, only the ratio of height/radius height = 50 # mm radius = 20 # mm steps_per_degree = 1 theta = flex.double([range(360*steps_per_degree)]) * math.pi/180 * 1/steps_per_degree y = radius * flex.cos(theta) # x z = radius * flex.sin(theta) # y x = flex.double(theta.size(), height) # z coords = flex.vec3_double(zip(x, y, z)) coords.insert(0, (0,0,0)) if goniometer is None: goniometer = self.get_goniometer() return GoniometerShadowMaskGenerator( goniometer, coords, flex.size_t(len(coords), 0))
def get_goniometer_shadow_masker(self, goniometer=None): from dials.util.masking import GoniometerShadowMaskGenerator from scitbx.array_family import flex import math # Simple model of cone around goniometer phi axis # Exact values don't matter, only the ratio of height/radius height = 50 # mm radius = 20 # mm steps_per_degree = 1 theta = flex.double([range(360*steps_per_degree)]) * math.pi/180 * 1/steps_per_degree y = radius * flex.cos(theta) # x z = radius * flex.sin(theta) # y x = flex.double(theta.size(), height) # z coords = flex.vec3_double(zip(x, y, z)) coords.insert(0, (0,0,0)) if goniometer is None: goniometer = self.get_goniometer() return GoniometerShadowMaskGenerator( goniometer, coords, flex.size_t(len(coords), 0))
def mini_kappa(goniometer, cone_opening_angle=43.60281897270362): """Construct a GoniometerShadowMasker for a mini-kappa goniometer. This is modelled a simple cone with the opening angle specified by `cone_opening_angle`. Args: goniometer (`dxtbx.model.Goniometer`): The goniometer instance. cone_opening_angle (float): The opening angle of the cone (in degrees). Returns: `dxtbx.masking.GoniometerShadowMasker` """ assert isinstance(goniometer, MultiAxisGoniometer) assert len(goniometer.get_axes()) == 3 # Simple model of cone around goniometer phi axis # Exact values don't matter, only the ratio of height/radius height = 50 # mm radius_height_ratio = math.tan(1 / 2 * cone_opening_angle * math.pi / 180) radius = radius_height_ratio * height steps_per_degree = 1 theta = (flex.double(range(360 * steps_per_degree)) * math.pi / 180 * 1 / steps_per_degree) y = radius * flex.cos(-theta) # x z = radius * flex.sin(-theta) # y x = flex.double(theta.size(), height) # z coords = flex.vec3_double(zip(x, y, z)) coords.insert(0, (0, 0, 0)) return GoniometerShadowMasker(goniometer, coords, flex.size_t(len(coords), 0))
# check fit for last file # q, x, ac for the last file will exist from the end of earlier loop over files # result[file_index][q_index][0 = coefficients, 1 = variances, 2 = scales] fls = fourier_legendre_series() fls.read_polynomials(p.fls_data) q_count = 0 for q_i in ring_indices: f = open(output_directory + 'f_' + str(q_i).zfill(2) + '.dat', 'w') f2 = open(output_directory + 'e_' + str(q_i).zfill(2) + '.dat', 'w') cos_sq = float(q[q_i].split()[-1]) * p.wavelength / (4.0 * math.pi) cos_sq = cos_sq * cos_sq sin_sq = 1.0 - cos_sq ac_new = fls.compute_function(result[-1][q_count][0], cos_sq + sin_sq * flex.cos(x[q_i])) if (p.standardize): ac[q_i] = ac[q_i] / result[-1][q_count][2][0] - 1.0 ac[q_i] = 1.0 / result[-1][q_count][2][1] * ac[q_i] + 1.0 ac_new = ac_new / result[-1][q_count][2][0] - 1.0 ac_new = 1.0 / result[-1][q_count][2][1] * ac_new + 1.0 ac_error = 100.0 * flex.fabs(ac_new - ac[q_i]) / ac_new # write output for i in xrange(x[q_i].size()): f.write('%f %e\n' % (x[q_i][i], ac[q_i][i])) f.write('&\n') for i in xrange(x[q_i].size()): f.write('%f %e\n' % (x[q_i][i], ac_new[i]))
def get_goniometer_shadow_masker(self, goniometer=None): from dials.util.masking import GoniometerShadowMaskGenerator from scitbx.array_family import flex import math coords = flex.vec3_double(( (0,0,0), )) alpha = flex.double_range(0, 190, step=10) * math.pi / 180 r = flex.double(alpha.size(), 40) x = flex.double(r.size(), 107.61) y = -r*flex.sin(alpha) z = -r*flex.cos(alpha) coords.extend(flex.vec3_double(x, y, z)) coords.extend(flex.vec3_double(( # fixed (107.49, 7.84, 39.49), (107.39, 15.69, 38.97), (107.27, 23.53, 38.46), (107.16, 31.37, 37.94), (101.76, 33.99, 36.25), (96.37, 36.63, 34.56), (90.98, 39.25, 33.00), (85.58, 41.88, 31.18), (80.89, 47.06, 31.00), (76.55, 51.51, 31.03), (72.90, 55.04, 31.18), (66.86, 60.46, 31.67), (62.10, 64.41, 32.25), ))) alpha = flex.double_range(180, 370, step=10) * math.pi / 180 r = flex.double(alpha.size(), 33) x = (flex.sqrt(flex.pow2(r * flex.sin(alpha)) + 89.02**2) * flex.cos((50 * math.pi/180) - flex.atan(r/89.02 * flex.sin(alpha)))) y = (flex.sqrt(flex.pow2(r * flex.sin(alpha)) + 89.02**2) * flex.sin((50 * math.pi/180) - flex.atan(r/89.02 * flex.sin(alpha)))) z = -r*flex.cos(alpha) coords.extend(flex.vec3_double(x, y, z)) coords.extend(flex.vec3_double(( # fixed (62.10, 64.41, -32.25), (66.86, 60.46, -31.67), (72.90, 55.04, -31.18), (76.55, 51.51, -31.03), (80.89, 47.06, -31.00), (85.58, 41.88, -31.18), (90.98, 39.25, -33.00), (96.37, 36.63, -34.56), (101.76, 33.99, -36.25), (107.16, 31.37, -37.94), (107.27, 23.53, -38.46), (107.39, 15.69, -38.97), (107.49, 7.84, -39.49), (107.61, 0.00, -40.00) ))) # I23 end station coordinate system: # X-axis: positive direction is facing away from the storage ring (from # sample towards goniometer) # Y-axis: positive direction is vertically up # Z-axis: positive direction is in the direction of the beam (from # sample towards detector) # K-axis (kappa): at an angle of +50 degrees from the X-axis # K & phi rotation axes: clockwise rotation is positive (right hand # thumb rule) # Omega-axis: along the X-axis; clockwise rotation is positive # End station x-axis is parallel to ImgCIF x-axis # End station z-axis points in opposite direction to ImgCIF definition # (ImgCIF: The Z-axis is derived from the source axis which goes from # the sample to the source) # Consequently end station y-axis (to complete set following right hand # rule) points in opposite direction to ImgCIF y-axis. # Kappa arm aligned with -y in ImgCIF convention from rstbx.cftbx.coordinate_frame_helpers import align_reference_frame from scitbx import matrix R = align_reference_frame(matrix.col((1,0,0)), matrix.col((1,0,0)), matrix.col((0,1,0)), matrix.col((0,-1,0))) coords = R.elems * coords if goniometer is None: goniometer = self.get_goniometer() return GoniometerShadowMaskGenerator( goniometer, coords, flex.size_t(len(coords), 1))
def t_variate(a=1.0,mu=0.0,sigma=1.0,N=100): "T-variate via Baley's one-liner" U1 = flex.random_double(size=N) U2 = flex.random_double(size=N) return ( flex.sqrt(a*(flex.pow(U1,-2.0/a)-1.0)) *flex.cos(2.0*math.pi*U2)*sigma+mu )
def normal_variate(mu=0.0, sigma=1.0, N=100): "Normal variate via Box-Muller transform" U1 = flex.random_double(size=N) U2 = flex.random_double(size=N) return flex.sqrt(-2.0 * flex.log(U1)) * flex.cos( 2.0 * math.pi * U2) * sigma + mu
def t_variate(a=1.0, mu=0.0, sigma=1.0, N=100): "T-variate via Baley's one-liner" U1 = flex.random_double(size=N) U2 = flex.random_double(size=N) return (flex.sqrt(a * (flex.pow(U1, -2.0 / a) - 1.0)) * flex.cos(2.0 * math.pi * U2) * sigma + mu)
def normal_variate(mu=0.0,sigma=1.0,N=100): "Normal variate via Box-Muller transform" U1 = flex.random_double(size=N) U2 = flex.random_double(size=N) return flex.sqrt(-2.0*flex.log(U1))*flex.cos(2.0*math.pi*U2)*sigma+mu
def sphere_data(q, d_max): r=d_max/2.0 a = r*r*r*( flex.sin(q*r)-q*r*flex.cos(q*r) )/( r*r*r*q*q*q ) return a*a
def compute_functional(vector): two_pi_S_dot_v = 2 * math.pi * reciprocal_lattice_points.dot(vector) return flex.sum(flex.cos(two_pi_S_dot_v))
def target(self, vector): tmp = vector.deep_copy() result = (flex.sum(flex.cos(tmp * 10)) + self.n + 1) * flex.sum( (tmp) * (tmp)) return result
def compute_functional(vector, reciprocal_lattice_points): two_pi_S_dot_v = 2 * math.pi * reciprocal_lattice_points.dot(vector) cosines = flex.cos(two_pi_S_dot_v) return flex.sum(flex.cos(two_pi_S_dot_v))
def get_goniometer_shadow_masker(self, goniometer=None): from dials.util.masking import GoniometerShadowMaskGenerator from scitbx.array_family import flex import math coords = flex.vec3_double(((0, 0, 0), )) alpha = flex.double_range(0, 190, step=10) * math.pi / 180 r = flex.double(alpha.size(), 40) x = flex.double(r.size(), 107.61) y = -r * flex.sin(alpha) z = -r * flex.cos(alpha) coords.extend(flex.vec3_double(x, y, z)) coords.extend( flex.vec3_double(( # fixed (107.49, 7.84, 39.49), (107.39, 15.69, 38.97), (107.27, 23.53, 38.46), (107.16, 31.37, 37.94), (101.76, 33.99, 36.25), (96.37, 36.63, 34.56), (90.98, 39.25, 33.00), (85.58, 41.88, 31.18), (80.89, 47.06, 31.00), (76.55, 51.51, 31.03), (72.90, 55.04, 31.18), (66.86, 60.46, 31.67), (62.10, 64.41, 32.25), ))) alpha = flex.double_range(180, 370, step=10) * math.pi / 180 r = flex.double(alpha.size(), 33) x = (flex.sqrt(flex.pow2(r * flex.sin(alpha)) + 89.02**2) * flex.cos((50 * math.pi / 180) - flex.atan(r / 89.02 * flex.sin(alpha)))) y = (flex.sqrt(flex.pow2(r * flex.sin(alpha)) + 89.02**2) * flex.sin((50 * math.pi / 180) - flex.atan(r / 89.02 * flex.sin(alpha)))) z = -r * flex.cos(alpha) coords.extend(flex.vec3_double(x, y, z)) coords.extend( flex.vec3_double(( # fixed (62.10, 64.41, -32.25), (66.86, 60.46, -31.67), (72.90, 55.04, -31.18), (76.55, 51.51, -31.03), (80.89, 47.06, -31.00), (85.58, 41.88, -31.18), (90.98, 39.25, -33.00), (96.37, 36.63, -34.56), (101.76, 33.99, -36.25), (107.16, 31.37, -37.94), (107.27, 23.53, -38.46), (107.39, 15.69, -38.97), (107.49, 7.84, -39.49), (107.61, 0.00, -40.00)))) # I23 end station coordinate system: # X-axis: positive direction is facing away from the storage ring (from # sample towards goniometer) # Y-axis: positive direction is vertically up # Z-axis: positive direction is in the direction of the beam (from # sample towards detector) # K-axis (kappa): at an angle of +50 degrees from the X-axis # K & phi rotation axes: clockwise rotation is positive (right hand # thumb rule) # Omega-axis: along the X-axis; clockwise rotation is positive # End station x-axis is parallel to ImgCIF x-axis # End station z-axis points in opposite direction to ImgCIF definition # (ImgCIF: The Z-axis is derived from the source axis which goes from # the sample to the source) # Consequently end station y-axis (to complete set following right hand # rule) points in opposite direction to ImgCIF y-axis. # Kappa arm aligned with -y in ImgCIF convention from rstbx.cftbx.coordinate_frame_helpers import align_reference_frame from scitbx import matrix R = align_reference_frame(matrix.col((1, 0, 0)), matrix.col((1, 0, 0)), matrix.col((0, 1, 0)), matrix.col( (0, -1, 0))) coords = R.elems * coords if goniometer is None: goniometer = self.get_goniometer() return GoniometerShadowMaskGenerator(goniometer, coords, flex.size_t(len(coords), 1))
def get_goniometer_shadow_masker(self, goniometer=None): if goniometer is None: goniometer = self.get_goniometer() assert goniometer is not None #avoid a module-level import from the DIALS namespace that kills LABELIT from dials.util.masking import GoniometerShadowMaskGenerator if goniometer.get_names()[1] == 'GON_CHI': # SmarGon class SmarGonShadowMaskGenerator(GoniometerShadowMaskGenerator): def __init__(SMG, goniometer): from scitbx.array_family import flex import math SMG.goniometer = goniometer coords = flex.vec3_double() axis = flex.size_t() # FACE A: Sample holder # Defined as semi-circle of radius r(A) = 10 mm (centred on PHI axis) # with rectangle of size a(A) = 12.8 mm (x 20 mm) offsetA = 33.0 # semi-circle for phi=-90 ... +90 radiusA = 10.0 phi = flex.double_range(-90, 100, step=10) * math.pi / 180 x = flex.double(phi.size(), -offsetA) y = radiusA * flex.cos(phi) z = radiusA * flex.sin(phi) # corners of square sqdA = 12.8 # square depth nsteps = 10 for i in range(nsteps + 1): for sign in (+1, -1): x.append(-offsetA) y.append(i * -sqdA / nsteps) z.append(sign * radiusA) x.append(-offsetA) y.append(-sqdA) z.append(0) SMG.faceA = flex.vec3_double(x, y, z) # FACE B: Lower arm sx = -28.50 sy = -4.90 sz = 8.50 mx = -13.80 my = -26.00 nx = -27.50 ny = -29.50 px = -65.50 py = -29.50 SMG.faceB = flex.vec3_double( ((sx, sy, sz), (mx, my, 0), (nx, ny, 0), (px, py, 0))) # FACE E: Rim of sample holder # Defined as circle of radius r(E) = 6 mm (centred on PHI axis) at an # offset o(E) = 19 mm offsetE = 19.0 radiusE = 6.0 phi = flex.double_range(0, 360, step=15) * math.pi / 180 x = flex.double(phi.size(), -offsetE) y = radiusE * flex.cos(phi) z = radiusE * flex.sin(phi) SMG.faceE = flex.vec3_double(x, y, z) def extrema_at_scan_angle(SMG, scan_angle): from scitbx.array_family import flex # Align end station coordinate system with ImgCIF coordinate system from rstbx.cftbx.coordinate_frame_helpers import align_reference_frame from scitbx import matrix R = align_reference_frame(matrix.col((-1, 0, 0)), matrix.col((1, 0, 0)), matrix.col((0, -1, 0)), matrix.col((0, 1, 0))) faceA = R.elems * SMG.faceA faceE = R.elems * SMG.faceE axes = SMG.goniometer.get_axes() angles = SMG.goniometer.get_angles() scan_axis = SMG.goniometer.get_scan_axis() angles[scan_axis] = scan_angle extrema = flex.vec3_double() for coords in (faceA, faceE): coords = coords.deep_copy() for i, axis in enumerate(axes): if i == 0: continue # shadow doesn't change with phi setting sel = flex.bool(len(coords), True) rotation = matrix.col( axis).axis_and_angle_as_r3_rotation_matrix( angles[i], deg=True) coords.set_selected( sel, rotation.elems * coords.select(sel)) extrema.extend(coords) s = matrix.col(SMG.faceB[0]) mx, my, _ = SMG.faceB[1] nx, ny, _ = SMG.faceB[2] px, py, _ = SMG.faceB[3] Rchi = (R.inverse() * matrix.col(axes[1]) ).axis_and_angle_as_r3_rotation_matrix(angles[1], deg=True) sk = Rchi * s sxk, syk, szk = sk.elems coords = flex.vec3_double(( (sxk, syk, 0), (sxk, syk, szk), (sxk + mx / 2, syk + my / 2, szk), (sxk + mx, syk + my, szk), (sxk + (mx + nx) / 2, syk + (my + ny) / 2, szk), (sxk + nx, syk + ny, szk), (sxk + (nx + px) / 2, syk + (ny + py) / 2, szk), (sxk + px, syk + py, szk), (sxk + px, syk + py, 0), (sxk + px, syk + py, -szk), (sxk + (nx + px) / 2, syk + (ny + py) / 2, -szk), (sxk + nx, syk + ny, -szk), (sxk + (mx + nx) / 2, syk + (my + ny) / 2, -szk), (sxk + mx, syk + my, -szk), (sxk + mx / 2, syk + my / 2, -szk), (sxk, syk, -szk), )) coords = R.elems * coords Romega = matrix.col( axes[2]).axis_and_angle_as_r3_rotation_matrix( angles[2], deg=True) coords = Romega.elems * coords extrema.extend(coords) return extrema #------------------ finished defining SmarGonShadowMaskGenerator return SmarGonShadowMaskGenerator(goniometer) elif goniometer.get_names()[1] == 'GON_KAPPA': # mini Kappa from dials.util.masking import GoniometerShadowMaskGenerator from scitbx.array_family import flex import math # Simple model of cone around goniometer phi axis # Exact values don't matter, only the ratio of height/radius height = 50 # mm radius = 20 # mm steps_per_degree = 1 theta = flex.double([range(360 * steps_per_degree) ]) * math.pi / 180 * 1 / steps_per_degree y = radius * flex.cos(theta) # x z = radius * flex.sin(theta) # y x = flex.double(theta.size(), height) # z coords = flex.vec3_double(zip(x, y, z)) coords.insert(0, (0, 0, 0)) if goniometer is None: goniometer = self.get_goniometer() return GoniometerShadowMaskGenerator(goniometer, coords, flex.size_t(len(coords), 0)) else: raise RuntimeError("Don't understand this goniometer: %s" % list(goniometer.get_names()))
def compute_functional(self, vector): two_pi_S_dot_v = 2 * math.pi * self.reciprocal_lattice_points.dot(vector) return -flex.sum(flex.cos(two_pi_S_dot_v))
def compute_functional(vector): two_pi_S_dot_v = 2 * math.pi * reciprocal_lattice_vectors.dot( vector) return flex.sum(flex.cos(two_pi_S_dot_v))
def target(self, vector): tmp = vector.deep_copy() result = (flex.sum(flex.cos(tmp*10))+self.n+1)*flex.sum( (tmp)*(tmp) ) return result