def __init__(self, r, d, symmetry_agreement, status): assert r.den() == 1 self.r = r order = r.order() self.r_info = sgtbx.rot_mx_info(r) type = self.r_info.type() axis = self.r_info.ev() self.symmetry_agreement = symmetry_agreement self.status = status # compute intrinsic and location part of d, using p, which is # the order times the projector onto r's invariant space p = mat.sqr(r.accumulate().as_double()) t_i_num = (p*d).as_int() t_l = d - t_i_num/order t_i = sgtbx.tr_vec(sg_t_den//order*t_i_num, tr_den=sg_t_den) # compute the origin corresponding to t_l by solving # (1 - r) o = t_l one_minus_r = -mat.sqr(self.r.minus_unit_mx().num()) one_minus_r_row_echelon = one_minus_r.as_flex_int_matrix() q = mat.identity(3).as_flex_int_matrix() rank = scitbx.math.row_echelon_form_t(one_minus_r_row_echelon, q) qd = flex.double(mat.sqr(q)*t_l)[:rank] o = flex.double((0,0,0)) scitbx.math.row_echelon_back_substitution_float( one_minus_r_row_echelon, qd, o) # construct object state self.t_i, self.raw_origin = t_i, mat.col(o) self.origin = None self.one_minus_r = one_minus_r
def find_space_group(self): decorated_symmetry_pool = [] denominator = 12**3 for i, (r, d) in enumerate(self.cross_correlation_peaks()): t = sgtbx.tr_vec((d*denominator).as_int(), tr_den=denominator) cb_op = sgtbx.change_of_basis_op(sgtbx.rt_mx(r, t)) phi_sym = self.f_in_p1.symmetry_agreement_factor( cb_op, assert_is_similar_symmetry=False) if phi_sym < self.phi_sym_acceptance_cutoff: status = possible_symmetry.accepted elif phi_sym < self.phi_sym_rejection_cutoff: status = possible_symmetry.unsure else: status = possible_symmetry.rejected decorated_symmetry_pool.append( (-status, i, possible_symmetry(r, d, phi_sym, status))) decorated_symmetry_pool.sort() self.symmetry_pool = [ item[-1] for item in decorated_symmetry_pool ] self.origin = mat.mutable_zeros(3) for symm in self.symmetry_pool: if symm.status != symm.accepted: continue symm.set_components_of_global_origin(self.origin) if self.origin.elems.count(0) == 0: break for symm in self.symmetry_pool: if symm.status != symm.accepted: continue symm.change_origin(self.origin) self.space_group.expand_smx(symm.rt)
def list_all_axes(space_group_symbol=None, space_group_info=None): assert space_group_symbol is None or space_group_info is None shift_range = 1 # XXX Works for the 230 reference settings; it is not # XXX clear to me (rwgk) what value is needed in general. if (space_group_symbol is not None): space_group_info = sgtbx.space_group_info(symbol=space_group_symbol) space_group_info.show_summary() print print "Rotation type, Axis direction, Intrinsic part, Origin shift" axes_dict = {} for s in space_group_info.group(): r = s.r() t = s.t() shift = [0,0,0] for shift[0] in xrange(-shift_range,shift_range+1): for shift[1] in xrange(-shift_range,shift_range+1): for shift[2] in xrange(-shift_range,shift_range+1): ts = t.plus(sgtbx.tr_vec(shift, 1)).new_denominator(t.den()) ss = sgtbx.rt_mx(r, ts) axes_dict[rt_mx_analysis(ss)] = 0 axes_list = axes_dict.keys() axes_list.sort() for a in axes_list: print a print
def find_centring_translations(self): for d in self.centring_translation_peak_sites(): t = [ scitbx.math.continued_fraction.from_real(x, 1e-2).as_rational() for x in d ] if t.count(0) > 1: continue unique_denominators = dict([(r.denominator(), 1) for r in t if r.numerator() != 0]).keys() assert len(unique_denominators) in (0, 1) if len(unique_denominators) == 1: den = unique_denominators[0] num = [r.numerator() for r in t] tr_vec = sgtbx.tr_vec(num, den) try: tr_vec = tr_vec.new_denominator(sg_t_den) except RuntimeError, e: if (not str(e).endswith( "Unsuitable value for rational translation vector." )): raise raise RuntimeError( "Sorry not implemented: handling of translation vector %s" % str(tuple(t))) self.space_group.expand_ltr(tr_vec)
def convert(file_object): """ Examplify the direct use of the tool from shelx.lexer In practice, one is strongly encouraged to make use of the tools from shelx.parsers: that is to say, for the task handled here, crystal_symmetry_parser (the code to follow just parrots the implementation of crystal_symmetry_parser). """ space_group = None for command, line in shelx.command_stream(file=file_object): cmd, args = command[0], command[-1] if cmd == "LATT": assert space_group is None assert len(args) == 1 space_group = sgtbx.space_group() n = int(args[0]) if n > 0: space_group.expand_inv(sgtbx.tr_vec((0, 0, 0))) z = "*PIRFABC"[abs(n)] space_group.expand_conventional_centring_type(z) elif cmd == "SYMM": assert space_group is not None assert len(args) == 1 s = sgtbx.rt_mx(args[0]) space_group.expand_smx(s) elif cmd == "SFAC": return sgtbx.space_group_info(group=space_group)
def find_space_group(self): decorated_symmetry_pool = [] denominator = 12**3 for i, (r, d) in enumerate(self.cross_correlation_peaks()): t = sgtbx.tr_vec((d * denominator).as_int(), tr_den=denominator) cb_op = sgtbx.change_of_basis_op(sgtbx.rt_mx(r, t)) phi_sym = self.f_in_p1.symmetry_agreement_factor( cb_op, assert_is_similar_symmetry=False) if phi_sym < self.phi_sym_acceptance_cutoff: status = possible_symmetry.accepted elif phi_sym < self.phi_sym_rejection_cutoff: status = possible_symmetry.unsure else: status = possible_symmetry.rejected decorated_symmetry_pool.append( (-status, i, possible_symmetry(r, d, phi_sym, status))) decorated_symmetry_pool.sort() self.symmetry_pool = [item[-1] for item in decorated_symmetry_pool] self.origin = mat.mutable_zeros(3) for symm in self.symmetry_pool: if symm.status != symm.accepted: continue symm.set_components_of_global_origin(self.origin) if self.origin.elems.count(0) == 0: break for symm in self.symmetry_pool: if symm.status != symm.accepted: continue symm.change_origin(self.origin) self.space_group.expand_smx(symm.rt)
def get_all_axes(space_group_symbol=None, space_group_info=None, extension=0): assert space_group_symbol is None or space_group_info is None shift_range = 1 # RWGK Works for the 230 reference settings; it is not # RWGK clear to me (rwgk) what value is needed in general. if (space_group_symbol is not None): space_group_info = sgtbx.space_group_info(symbol=space_group_symbol) #space_group_info.show_summary() axes_dict = {} for smx in space_group_info.group(): r = smx.r() t = smx.t() shift = [0, 0, 0] for shift[0] in range(-shift_range, shift_range + 1): for shift[1] in range(-shift_range, shift_range + 1): for shift[2] in range(-shift_range, shift_range + 1): ts = t.plus(sgtbx.tr_vec(shift, 1)).new_denominator(t.den()) m = sgtbx.rt_mx(r, ts) #print m rtmxanal = rlc_RTMxAnalysis(m) #print r, t, shift, ts, m if rtmxanal: #print rtmxanal axes_dict[rtmxanal] = 0 axes_list = axes_dict.keys() axes_list.sort() # reject nonenantiomorphic space groups if len(axes_list) > 0 and not re.compile("[A-z]").search( space_group_symbol[1:]): try: sgtbx.space_group_info(space_group_symbol).show_summary(), #print len(axes_list), space_group_symbol except: print space_group, space_group_symbol print sys.exit(1) axes = [] for a in axes_list: if len(a) == 3 and len(a[1]) == 3 and len(a[2]) == 3: tmp_dict = {} print "%4s %7.4f %7.4f %7.4f %7.4f %7.4f %7.4f " % ( a[0], a[1][0], a[1][1], a[1][2], a[2][0], a[2][1], a[2][2]) tmp_dict['symb'] = a[0] start_array = N.asarray(a[1]) end_array = N.asarray(a[2]) start_vec = start_array - (end_array - start_array) * extension end_vec = end_array + (end_array - start_array) * extension tmp_dict['start'] = start_vec tmp_dict['end'] = end_vec #rlc# tmp_dict['start'] = a[1] #rlc# tmp_dict['end'] = a[2] axes.append(tmp_dict) else: print a else: return None return axes
def list_all_axes(space_group_symbol=None, space_group_info=None): assert space_group_symbol is None or space_group_info is None shift_range = 1 # XXX Works for the 230 reference settings; it is not # XXX clear to me (rwgk) what value is needed in general. if (space_group_symbol is not None): space_group_info = sgtbx.space_group_info(symbol=space_group_symbol) space_group_info.show_summary() print() print("Rotation type, Axis direction, Intrinsic part, Origin shift") axes_dict = {} for s in space_group_info.group(): r = s.r() t = s.t() shift = [0,0,0] for shift[0] in range(-shift_range,shift_range+1): for shift[1] in range(-shift_range,shift_range+1): for shift[2] in range(-shift_range,shift_range+1): ts = t.plus(sgtbx.tr_vec(shift, 1)).new_denominator(t.den()) ss = sgtbx.rt_mx(r, ts) axes_dict[rt_mx_analysis(ss)] = 0 axes_list = list(axes_dict.keys()) axes_list.sort() for a in axes_list: print(a) print()
def __init__(self, file_name, header_only=False): self.file_name = os.path.normpath(file_name) f = open(file_name) line = f.readline() assert line[5] == " " n_sym_ops_from_file = int(line[:5].strip()) assert n_sym_ops_from_file > 0 self.space_group_symbol = line[6:].strip() self.space_group_from_ops = sgtbx.space_group() for i in xrange(n_sym_ops_from_file): line = f.readline().rstrip() assert len(line) == 27 r = sgtbx.rot_mx([int(line[j*3:(j+1)*3]) for j in xrange(9)], 1) line = f.readline().rstrip() assert len(line) == 9 t = sgtbx.tr_vec([int(line[j*3:(j+1)*3]) for j in xrange(3)], 12) self.space_group_from_ops.expand_smx(sgtbx.rt_mx(r, t)) f.close() if (header_only): self.original_indices = None return all_arrays = scalepack_ext.no_merge_original_index_arrays( file_name, n_sym_ops_from_file*2+1) self.original_indices = all_arrays.original_indices() self.unique_indices = all_arrays.unique_indices() self.batch_numbers = all_arrays.batch_numbers() self.centric_tags = all_arrays.centric_tags() self.spindle_flags = all_arrays.spindle_flags() self.asymmetric_unit_indices = all_arrays.asymmetric_unit_indices() self.i_obs = all_arrays.i_obs() self.sigmas = all_arrays.sigmas()
def possible_point_group_generators(self): lattice_group = lattice_symmetry.group(self.f_in_p1.unit_cell(), max_delta=1) lattice_group.expand_inv(sgtbx.tr_vec((0, 0, 0))) rot_parts = set() decorated_rot_parts = [] for op in lattice_group: r = op.r() if r.is_unit_mx(): continue if op.inverse() in rot_parts: continue r_info = sgtbx.rot_mx_info(r) if r_info.type() < -2: continue rot_parts.add(op) decorated_rot_parts.append(( r_info.type() == -1, # inversion shall come first, list(r_info.ev()).count( 0), # axes // to unit cell shall come first # note Python 2.5- compatibility r_info.type() == -2, # mirrors preferred. r.order(), # higher order preferred op)) decorated_rot_parts.sort() decorated_rot_parts.reverse() for item in decorated_rot_parts: yield item[-1]
def __init__(self, file_name, header_only=False): self.file_name = os.path.normpath(file_name) f = open(file_name) line = f.readline() assert line[5] == " " n_sym_ops_from_file = int(line[:5].strip()) assert n_sym_ops_from_file > 0 self.space_group_symbol = line[6:].strip() self.space_group_from_ops = sgtbx.space_group() for i in range(n_sym_ops_from_file): line = f.readline().rstrip() assert len(line) == 27 r = sgtbx.rot_mx([int(line[j*3:(j+1)*3]) for j in range(9)], 1) line = f.readline().rstrip() assert len(line) == 9 t = sgtbx.tr_vec([int(line[j*3:(j+1)*3]) for j in range(3)], 12) self.space_group_from_ops.expand_smx(sgtbx.rt_mx(r, t)) f.close() if (header_only): self.original_indices = None return all_arrays = scalepack_ext.no_merge_original_index_arrays( file_name, n_sym_ops_from_file*2+1) self.original_indices = all_arrays.original_indices() self.unique_indices = all_arrays.unique_indices() self.batch_numbers = all_arrays.batch_numbers() self.centric_tags = all_arrays.centric_tags() self.spindle_flags = all_arrays.spindle_flags() self.asymmetric_unit_indices = all_arrays.asymmetric_unit_indices() self.i_obs = all_arrays.i_obs() self.sigmas = all_arrays.sigmas()
def __init__(self, r, d, symmetry_agreement, status): assert r.den() == 1 self.r = r order = r.order() self.r_info = sgtbx.rot_mx_info(r) type = self.r_info.type() axis = self.r_info.ev() self.symmetry_agreement = symmetry_agreement self.status = status # compute intrinsic and location part of d, using p, which is # the order times the projector onto r's invariant space p = mat.sqr(r.accumulate().as_double()) t_i_num = (p * d).as_int() t_l = d - t_i_num / order t_i = sgtbx.tr_vec(sg_t_den // order * t_i_num, tr_den=sg_t_den) # compute the origin corresponding to t_l by solving # (1 - r) o = t_l one_minus_r = -mat.sqr(self.r.minus_unit_mx().num()) one_minus_r_row_echelon = one_minus_r.as_flex_int_matrix() q = mat.identity(3).as_flex_int_matrix() rank = scitbx.math.row_echelon_form_t(one_minus_r_row_echelon, q) qd = flex.double(mat.sqr(q) * t_l)[:rank] o = flex.double((0, 0, 0)) scitbx.math.row_echelon_back_substitution_float( one_minus_r_row_echelon, qd, o) # construct object state self.t_i, self.raw_origin = t_i, mat.col(o) self.origin = None self.one_minus_r = one_minus_r
def convert(file_object): """ Examplify the direct use of the tool from shelx.lexer In practice, one is strongly encouraged to make use of the tools from shelx.parsers: that is to say, for the task handled here, crystal_symmetry_parser (the code to follow just parrots the implementation of crystal_symmetry_parser). """ space_group = None for command, line in shelx.command_stream(file=file_object): cmd, args = command[0], command[-1] if cmd == "LATT": assert space_group is None assert len(args) == 1 space_group = sgtbx.space_group() n = int(args[0]) if n > 0: space_group.expand_inv(sgtbx.tr_vec((0,0,0))) z = "*PIRFABC"[abs(n)] space_group.expand_conventional_centring_type(z) elif cmd == "SYMM": assert space_group is not None assert len(args) == 1 s = sgtbx.rt_mx(args[0]) space_group.expand_smx(s) elif cmd == "SFAC": return sgtbx.space_group_info(group=space_group)
def change_origin(self, origin): o = self.raw_origin - origin t_l = self.one_minus_r*o t_l = sgtbx.tr_vec((sg_t_den*t_l).as_int(), tr_den=sg_t_den) self.rt = sgtbx.rt_mx(self.r, self.t_i.plus(t_l).new_denominator(sg_t_den)) tr_info = sgtbx.translation_part_info(self.rt) self.origin = tr_info.origin_shift() self.t_i = tr_info.intrinsic_part()
def get_all_axes(space_group_symbol=None, space_group_info=None, extension=0): assert space_group_symbol is None or space_group_info is None shift_range = 1 # RWGK Works for the 230 reference settings; it is not # RWGK clear to me (rwgk) what value is needed in general. if (space_group_symbol is not None): space_group_info = sgtbx.space_group_info(symbol=space_group_symbol) #space_group_info.show_summary() axes_dict = {} for smx in space_group_info.group(): r = smx.r() t = smx.t() shift = [0,0,0] for shift[0] in range(-shift_range,shift_range+1): for shift[1] in range(-shift_range,shift_range+1): for shift[2] in range(-shift_range,shift_range+1): ts = t.plus(sgtbx.tr_vec(shift, 1)).new_denominator(t.den()) m = sgtbx.rt_mx(r, ts) #print m rtmxanal = rlc_RTMxAnalysis(m) #print r, t, shift, ts, m if rtmxanal: #print rtmxanal axes_dict[rtmxanal] = 0 axes_list = axes_dict.keys() axes_list.sort() # reject nonenantiomorphic space groups if len(axes_list) > 0 and not re.compile("[A-z]").search(space_group_symbol[1:]): try: sgtbx.space_group_info(space_group_symbol).show_summary(), #print len(axes_list), space_group_symbol except: print space_group, space_group_symbol print sys.exit(1) axes = [] for a in axes_list: if len(a) == 3 and len(a[1]) == 3 and len(a[2]) == 3: tmp_dict = {} print "%4s %7.4f %7.4f %7.4f %7.4f %7.4f %7.4f " % (a[0],a[1][0],a[1][1],a[1][2],a[2][0],a[2][1],a[2][2]) tmp_dict['symb'] = a[0] start_array = N.asarray(a[1]) end_array = N.asarray(a[2]) start_vec = start_array - (end_array - start_array)*extension end_vec = end_array + (end_array - start_array)*extension tmp_dict['start'] = start_vec tmp_dict['end'] = end_vec #rlc# tmp_dict['start'] = a[1] #rlc# tmp_dict['end'] = a[2] axes.append(tmp_dict) else: print a else: return None return axes
def __init__(self, lf): self.symbol = None l = lf.next() print l.strip() if (lf.eof): return no, number, symbol, m = l.split() assert no == "NO." number = int(number) assert int(float(m)) == float(m) m = int(float(m)) space_group = sgtbx.space_group() if (m < 0): space_group.expand_inv(sgtbx.tr_vec((0, 0, 0))) space_group.expand_conventional_centring_type(symbol[0]) t_den = space_group.t_den() matrices = [] for i in xrange(abs(m)): l = lf.next() assert not lf.eof flds = l.split() assert len(flds) == 12 r = [int(e) for e in flds[1:4] + flds[5:8] + flds[9:12]] t = [ int(round(float(e) * t_den)) for e in (flds[0], flds[4], flds[8]) ] try: s = sgtbx.rt_mx(sgtbx.rot_mx(r), sgtbx.tr_vec(t)) except RuntimeError, e: print e print l else: try: matrices.append(s) space_group.expand_smx(s) except RuntimeError, e: print e print l print s
def __init__(self, input, n_bins, lattice_symmetry_max_delta, completeness_as_non_anomalous=None): self.completeness_as_non_anomalous = completeness_as_non_anomalous self.input = input.eliminate_sys_absent(integral_only=True, log=sys.stdout) self.lattice_symmetry_max_delta = lattice_symmetry_max_delta if (not self.input.is_unique_set_under_symmetry()): print("Merging symmetry-equivalent reflections:") merged = self.input.merge_equivalents() merged.show_summary(prefix=" ") print() self.input = merged.array() del merged if (input.info() is not None): self.input.set_info(input.info().customized_copy(merged=True)) else: self.input.set_info(miller.array_info(merged=True)) self.input.show_comprehensive_summary() print() self.input.setup_binner(n_bins=n_bins) self.resolution_range = self.input.resolution_range() self.change_of_basis_op_to_minimum_cell \ = self.input.change_of_basis_op_to_minimum_cell() self.observations = self.input.change_basis( cb_op=self.change_of_basis_op_to_minimum_cell) \ .expand_to_p1() \ .map_to_asu() if (self.input.anomalous_flag()): self.anom_diffs = abs(self.input.anomalous_differences()).change_basis( cb_op=self.change_of_basis_op_to_minimum_cell) \ .expand_to_p1() \ .map_to_asu() else: self.anom_diffs = None self.minimum_cell_symmetry = crystal.symmetry.change_basis( self.input, cb_op=self.change_of_basis_op_to_minimum_cell) self.intensity_symmetry = \ self.minimum_cell_symmetry.reflection_intensity_symmetry( anomalous_flag=self.input.anomalous_flag()) self.lattice_group = sgtbx.lattice_symmetry.group( self.minimum_cell_symmetry.unit_cell(), max_delta=self.lattice_symmetry_max_delta) self.lattice_group.expand_inv(sgtbx.tr_vec((0, 0, 0))) self.lattice_group.make_tidy() self.lattice_symmetry = crystal.symmetry( unit_cell=self.minimum_cell_symmetry.unit_cell(), space_group_info=sgtbx.space_group_info(group=self.lattice_group), assert_is_compatible_unit_cell=False)
def __init__(self, lf): self.symbol = None l = lf.next() print l.strip() if (lf.eof): return no, number, symbol, m = l.split() assert no == "NO." number = int(number) assert int(float(m)) == float(m) m = int(float(m)) space_group = sgtbx.space_group() if (m < 0): space_group.expand_inv(sgtbx.tr_vec((0,0,0))) space_group.expand_conventional_centring_type(symbol[0]) t_den = space_group.t_den() matrices = [] for i in xrange(abs(m)): l = lf.next() assert not lf.eof flds = l.split() assert len(flds) == 12 r = [int(e) for e in flds[1:4] + flds[5:8] + flds[9:12]] t = [int(round(float(e)*t_den)) for e in (flds[0],flds[4],flds[8])] try: s = sgtbx.rt_mx(sgtbx.rot_mx(r), sgtbx.tr_vec(t)) except RuntimeError, e: print e print l else: try: matrices.append(s) space_group.expand_smx(s) except RuntimeError, e: print e print l print s
def __init__(self, input, n_bins, lattice_symmetry_max_delta, completeness_as_non_anomalous=None): self.completeness_as_non_anomalous = completeness_as_non_anomalous self.input = input.eliminate_sys_absent(integral_only=True, log=sys.stdout) self.lattice_symmetry_max_delta = lattice_symmetry_max_delta if not self.input.is_unique_set_under_symmetry(): print "Merging symmetry-equivalent reflections:" merged = self.input.merge_equivalents() merged.show_summary(prefix=" ") print self.input = merged.array() del merged if input.info() is not None: self.input.set_info(input.info().customized_copy(merged=True)) else: self.input.set_info(miller.array_info(merged=True)) self.input.show_comprehensive_summary() print self.input.setup_binner(n_bins=n_bins) self.resolution_range = self.input.resolution_range() self.change_of_basis_op_to_minimum_cell = self.input.change_of_basis_op_to_minimum_cell() self.observations = ( self.input.change_basis(cb_op=self.change_of_basis_op_to_minimum_cell).expand_to_p1().map_to_asu() ) if self.input.anomalous_flag(): self.anom_diffs = ( abs(self.input.anomalous_differences()) .change_basis(cb_op=self.change_of_basis_op_to_minimum_cell) .expand_to_p1() .map_to_asu() ) else: self.anom_diffs = None self.minimum_cell_symmetry = crystal.symmetry.change_basis( self.input, cb_op=self.change_of_basis_op_to_minimum_cell ) self.intensity_symmetry = self.minimum_cell_symmetry.reflection_intensity_symmetry( anomalous_flag=self.input.anomalous_flag() ) self.lattice_group = sgtbx.lattice_symmetry.group( self.minimum_cell_symmetry.unit_cell(), max_delta=self.lattice_symmetry_max_delta ) self.lattice_group.expand_inv(sgtbx.tr_vec((0, 0, 0))) self.lattice_group.make_tidy() self.lattice_symmetry = crystal.symmetry( unit_cell=self.minimum_cell_symmetry.unit_cell(), space_group_info=sgtbx.space_group_info(group=self.lattice_group), assert_is_compatible_unit_cell=False, )
def compatible_symmetries(point_group): """ Primitive setting assumed """ for op in point_group: r = op.r() order = r.order() if r.info().type() == 1: continue yield op invariants = [ matrix.col(u) for u in r.info().basis_of_invariant() ] if len(invariants) == 2: t1, t2 = invariants invariants.extend((t1 + t2, t1 - t2)) translations = [] for t in invariants: t = sgtbx.tr_vec(t, order).mod_short() if not t.is_zero() and t not in translations: translations.append(t) for t in translations: yield sgtbx.rt_mx(r, t.new_denominator(sgtbx.sg_t_den))
def compatible_symmetries(point_group): """ Primitive setting assumed """ for op in point_group: r = op.r() order = r.order() if r.info().type() == 1: continue yield op invariants = [matrix.col(u) for u in r.info().basis_of_invariant()] if len(invariants) == 2: t1, t2 = invariants invariants.extend((t1 + t2, t1 - t2)) translations = [] for t in invariants: t = sgtbx.tr_vec(t, order).mod_short() if not t.is_zero() and t not in translations: translations.append(t) for t in translations: yield sgtbx.rt_mx(r, t.new_denominator(sgtbx.sg_t_den))
def find_centring_translations(self): for d in self.centring_translation_peak_sites(): t = [ scitbx.math.continued_fraction.from_real(x, 1e-2).as_rational() for x in d ] if t.count(0) > 1: continue unique_denominators = dict( [ (r.denominator(), 1) for r in t if r.numerator() != 0 ]).keys() assert len(unique_denominators) in (0, 1) if len(unique_denominators) == 1: den = unique_denominators[0] num = [ r.numerator() for r in t ] tr_vec = sgtbx.tr_vec(num, den) try: tr_vec = tr_vec.new_denominator(sg_t_den) except RuntimeError, e: if (not str(e).endswith( "Unsuitable value for rational translation vector.")): raise raise RuntimeError( "Sorry not implemented: handling of translation vector %s" % str(tuple(t))) self.space_group.expand_ltr(tr_vec)
def exercise_change_of_basis_between_arbitrary_space_groups(): from random import randint from scitbx import matrix as mat g = sgtbx.space_group_info('hall: P 2') h = sgtbx.space_group_info('hall: P 2c') assert g.change_of_basis_op_to(h) is None g = sgtbx.space_group_info('hall: C 2c 2 (x+y,x-y,z)') h = g.change_basis(sgtbx.change_of_basis_op(sgtbx.rt_mx('-y,x,z'))) cb_op = g.change_of_basis_op_to(h) assert cb_op.as_xyz() == 'x,y,z+1/4' assert g.change_basis(cb_op).group() == h.group() g = sgtbx.space_group_info('hall: I 4 2 3') z2p_op = g.change_of_basis_op_to_primitive_setting() h = g.change_basis(z2p_op) cb_op = g.change_of_basis_op_to(h) assert cb_op.c() == z2p_op.c(), (cb_op.as_xyz(), z2p_op.as_xyz()) for i in xrange(1, 231): s = sgtbx.space_group_symbols(space_group_number=i) g = sgtbx.space_group_info(group=sgtbx.space_group(s, t_den=24)) o = tuple([ randint(0, 23) for j in xrange(3) ]) cb_op = sgtbx.change_of_basis_op(sgtbx.rt_mx(sgtbx.tr_vec(o, 24))) h = g.change_basis(cb_op) cb_op_1 = g.change_of_basis_op_to(h) assert cb_op_1.c().r().is_unit_mx() delta = (mat.col(cb_op_1.c().t().as_double()) - mat.col(cb_op.c().t().as_double())) assert h.is_allowed_origin_shift(delta, tolerance=1e-12) z2p_op = g.change_of_basis_op_to_primitive_setting() h = g.change_basis(z2p_op) cb_op = g.change_of_basis_op_to(h) h1 = g.change_basis(cb_op) assert (h.as_reference_setting().group() == h1.as_reference_setting().group())
def exercise_change_of_basis_between_arbitrary_space_groups(): from random import randint from scitbx import matrix as mat g = sgtbx.space_group_info('hall: P 2') h = sgtbx.space_group_info('hall: P 2c') assert g.change_of_basis_op_to(h) is None g = sgtbx.space_group_info('hall: C 2c 2 (x+y,x-y,z)') h = g.change_basis(sgtbx.change_of_basis_op(sgtbx.rt_mx('-y,x,z'))) cb_op = g.change_of_basis_op_to(h) assert cb_op.as_xyz() == 'x,y,z+1/4' assert g.change_basis(cb_op).group() == h.group() g = sgtbx.space_group_info('hall: I 4 2 3') z2p_op = g.change_of_basis_op_to_primitive_setting() h = g.change_basis(z2p_op) cb_op = g.change_of_basis_op_to(h) assert cb_op.c() == z2p_op.c(), (cb_op.as_xyz(), z2p_op.as_xyz()) for i in range(1, 231): s = sgtbx.space_group_symbols(space_group_number=i) g = sgtbx.space_group_info(group=sgtbx.space_group(s, t_den=24)) o = tuple([randint(0, 23) for j in range(3)]) cb_op = sgtbx.change_of_basis_op(sgtbx.rt_mx(sgtbx.tr_vec(o, 24))) h = g.change_basis(cb_op) cb_op_1 = g.change_of_basis_op_to(h) assert cb_op_1.c().r().is_unit_mx() delta = (mat.col(cb_op_1.c().t().as_double()) - mat.col(cb_op.c().t().as_double())) assert h.is_allowed_origin_shift(delta, tolerance=1e-12) z2p_op = g.change_of_basis_op_to_primitive_setting() h = g.change_basis(z2p_op) cb_op = g.change_of_basis_op_to(h) h1 = g.change_basis(cb_op) assert (h.as_reference_setting().group() == h1.as_reference_setting().group())
def filtered_commands(self): """ Yields those command in self.command_stream that this parser is not concerned with. On the contrary, LATT, SYMM are swallowed (CELL is yielded because it carries the wavelength too). """ unit_cell = None unit_cell_param_sigmas = None space_group = sgtbx.space_group() for command, line in self.command_stream: cmd, args = command[0], command[-1] if cmd == 'CELL': assert unit_cell is None unit_cell = uctbx.unit_cell(args[1:]) yield command, line elif cmd == 'ZERR': assert unit_cell_param_sigmas is None unit_cell_param_sigmas = args[1:] yield command, line elif cmd == 'LATT': assert len(args) == 1 n = int(args[0]) if n > 0: space_group.expand_inv(sgtbx.tr_vec((0, 0, 0))) z = "*PIRFABC"[abs(n)] space_group.expand_conventional_centring_type(z) elif cmd == 'SYMM': assert len(args) == 1 s = sgtbx.rt_mx(args[0]) space_group.expand_smx(s) else: if cmd == 'SFAC': assert unit_cell is not None self.builder.make_crystal_symmetry(unit_cell=unit_cell, space_group=space_group) self.builder.set_unit_cell_parameter_sigmas( unit_cell_param_sigmas) yield command, line
def possible_point_group_generators(self): lattice_group = lattice_symmetry.group(self.f_in_p1.unit_cell(), max_delta=1) lattice_group.expand_inv(sgtbx.tr_vec((0,0,0))) rot_parts = set() decorated_rot_parts = [] for op in lattice_group: r = op.r() if r.is_unit_mx(): continue if op.inverse() in rot_parts: continue r_info = sgtbx.rot_mx_info(r) if r_info.type() < -2: continue rot_parts.add(op) decorated_rot_parts.append( (r_info.type() == -1, # inversion shall come first, list(r_info.ev()).count(0), # axes // to unit cell shall come first # note Python 2.5- compatibility r_info.type() == -2, # mirrors preferred. r.order(), # higher order preferred op)) decorated_rot_parts.sort() decorated_rot_parts.reverse() for item in decorated_rot_parts: yield item[-1]
def filtered_commands(self): """ Yields those command in self.command_stream that this parser is not concerned with. On the contrary, LATT, SYMM are swallowed (CELL is yielded because it carries the wavelength too). """ unit_cell = None unit_cell_param_sigmas = None space_group = sgtbx.space_group() for command, line in self.command_stream: cmd, args = command[0], command[-1] if cmd == 'CELL': assert unit_cell is None unit_cell = uctbx.unit_cell(args[1:]) yield command, line elif cmd == 'ZERR': assert unit_cell_param_sigmas is None unit_cell_param_sigmas = args[1:] yield command, line elif cmd == 'LATT': assert len(args) == 1 n = int(args[0]) if n > 0: space_group.expand_inv(sgtbx.tr_vec((0,0,0))) z = "*PIRFABC"[abs(n)] space_group.expand_conventional_centring_type(z) elif cmd == 'SYMM': assert len(args) == 1 s = sgtbx.rt_mx(args[0]) space_group.expand_smx(s) else: if cmd == 'SFAC': assert unit_cell is not None self.builder.make_crystal_symmetry(unit_cell=unit_cell, space_group=space_group) self.builder.set_unit_cell_parameter_sigmas(unit_cell_param_sigmas) yield command, line
def derive_result_group_list(self,group_of_interest): # Get list of sub-spacegroups subgrs = subgroups.subgroups(group_of_interest).groups_parent_setting() # Order sub-groups sort_values = flex.double() for group in subgrs: order_z = group.order_z() space_group_number = sgtbx.space_group_type(group, False).number() assert 1 <= space_group_number <= 230 sort_values.append(order_z*1000+space_group_number) perm = flex.sort_permutation(sort_values, True) for i_subgr in perm: acentric_subgroup = subgrs[i_subgr] acentric_supergroup = metric_supergroup(acentric_subgroup) # Add centre of inversion to acentric lattice symmetry centric_group = sgtbx.space_group(acentric_subgroup) centric_group.expand_inv(sgtbx.tr_vec((0,0,0))) # Make symmetry object: unit-cell + space-group # The unit cell is potentially modified to be exactly compatible # with the space group symmetry. subsym = crystal.symmetry( unit_cell=self.minimum_symmetry.unit_cell(), space_group=centric_group, assert_is_compatible_unit_cell=False) supersym = crystal.symmetry( unit_cell=self.minimum_symmetry.unit_cell(), space_group=acentric_supergroup, assert_is_compatible_unit_cell=False) # Convert subgroup to reference setting cb_op_minimum_ref = subsym.space_group_info().type().cb_op() ref_subsym = subsym.change_basis(cb_op_minimum_ref) # Ignore unwanted groups if (self.bravais_types_only and not str(ref_subsym.space_group_info()) in bravais_types.centric): continue # Choose best setting for monoclinic and orthorhombic systems cb_op_best_cell = self.change_of_basis_op_to_best_cell(ref_subsym) best_subsym = ref_subsym.change_basis(cb_op_best_cell) # Total basis transformation cb_op_best_cell = change_of_basis_op(str(cb_op_best_cell),stop_chars='',r_den=144,t_den=144) cb_op_minimum_ref=change_of_basis_op(str(cb_op_minimum_ref),stop_chars='',r_den=144,t_den=144) self.cb_op_inp_minimum=change_of_basis_op(str(self.cb_op_inp_minimum),stop_chars='',r_den=144,t_den=144) cb_op_inp_best = cb_op_best_cell * cb_op_minimum_ref * self.cb_op_inp_minimum # Use identity change-of-basis operator if possible if (best_subsym.unit_cell().is_similar_to(self.input_symmetry.unit_cell())): cb_op_corr = cb_op_inp_best.inverse() try: best_subsym_corr = best_subsym.change_basis(cb_op_corr) except RuntimeError, e: if (str(e).find("Unsuitable value for rational rotation matrix.") < 0): raise else: if (best_subsym_corr.space_group() == best_subsym.space_group()): cb_op_inp_best = cb_op_corr * cb_op_inp_best self.result_groups.append({'subsym':subsym, 'supersym':supersym, 'ref_subsym':ref_subsym, 'best_subsym':best_subsym, 'cb_op_inp_best':cb_op_inp_best, 'max_angular_difference': find_max_delta( reduced_cell=self.minimum_symmetry.unit_cell(), space_group=acentric_supergroup) })
def exercise(space_group_info, fixed_random_seed=True, shifted_origin=None, elements=None, d_min=0.8, grid_resolution_factor=1/3., verbose=False, **kwds): if elements is None: n_C = 5 n_O = 1 n_N = 1 elements = ["C"]*n_C + ["O"]*n_O + ["N"]*n_N if verbose: print elements target_space_group_type = space_group_info.type() hall = sgtbx.space_group_symbols( target_space_group_type.lookup_symbol()).hall() print hall if fixed_random_seed: random.seed(1) flex.set_random_seed(1) # Generate a random structure in real space, # compute its structure factors, # that we will try to recover the symmetry of target_structure = random_structure.xray_structure( space_group_info=space_group_info, elements=elements, use_u_iso=True, random_u_iso=True, random_u_iso_scale=0.04, use_u_aniso=False, ) if shifted_origin is None: shifted_origin = flex.random_double(3) shifted_origin = mat.col(shifted_origin) if verbose: print "new origin = (%.3f, %.3f, %.3f)" % shifted_origin.elems print target_structure_in_p1 = target_structure\ .expand_to_p1().apply_shift(shifted_origin) target_f_in_p1 = miller.build_set( crystal_symmetry=target_structure_in_p1, anomalous_flag=False, d_min=d_min ).structure_factors_from_scatterers( xray_structure=target_structure_in_p1, algorithm="direct").f_calc() # Recover space group? sf_symm = symmetry_search.structure_factor_symmetry(target_f_in_p1) if verbose: print sf_symm solution_hall, target_hall = [ sgi.as_reference_setting().type().hall_symbol() for sgi in (sf_symm.space_group_info, target_structure.space_group_info()) ] assert solution_hall == target_hall, (solution_hall, target_hall) # Shift maximises goodness of symmetry? gos, solution_f = sf_symm.symmetrised_structure_factors() if space_group_info.type().hall_symbol() != ' P 1': assert gos.correlation > 0.99 assert gos.gradient == (0, 0, 0) gos_away_from_max = sf_symm.symmetrised_structure_factors( delta=mat.col((0.1, 0.1, 0.1)))[0] assert gos_away_from_max.correlation < 0.9, gos_away_from_max.correlation # Recovered origin """The sequence of transform read: ----->target structure ^ V ^ V (1, shifted_origin=sigma) ^ V ^ shifted target ^ V ^ V sf_symm.cb_op_to_primitive = (P, 0) ^ V ^ shifted target in primitive cell = shifted solution in primitive cell ^ V ^ V (1, -sf_symm.origin=-s) ^ V ^ solution in primitive cell ^ V ^ V solution_to_target_cb_op = (Q, q) ^ V ^------------ The total transfrom from the target structure back to it reads (QP, q') with q' = (Q,q)(-s + P sigma) = (Q,q)delta_o with delta_o = sf_symm.cb_op_to_primitive(shifted_origin) - sf_symm.origin (Q, q') must leave the target structure space group invariant. Most of the time Q is the unit matrix and the test boils down to check whether delta is an allowed origin shift after changing to the input cell but it does not hurt to do the more general test all the time. """ solution_to_target_cb_op = ( target_structure.space_group_info() .change_of_basis_op_to_reference_setting().inverse() * sf_symm.space_group_info .change_of_basis_op_to_reference_setting()) if verbose: print print "solution -> target: %s" % solution_to_target_cb_op.as_xyz() delta_o = (mat.col(sf_symm.cb_op_to_primitive(shifted_origin)) - sf_symm.origin) delta = mat.col(solution_to_target_cb_op(delta_o)) stabilising_cb_op = sgtbx.change_of_basis_op(sgtbx.rt_mx( (solution_to_target_cb_op*sf_symm.cb_op_to_primitive).c().r(), sgtbx.tr_vec((delta*72).as_int()*2, tr_den=144))) # guarding against rounding errors on some platforms (e.g. FC8) # meaning that (delta*144).as_int() would not work. target_sg = target_structure.space_group() assert target_sg == target_sg.change_basis(stabilising_cb_op)
def exercise_unmerged(space_group_info): import random from cctbx import sgtbx # shuffle the space_group = sgtbx.space_group("P 1", no_expand=True) perm = list(range(len(space_group_info.group()))) random.shuffle(perm) for i in perm: space_group.expand_smx(space_group_info.group()[i]) unit_cell = space_group_info.any_compatible_unit_cell(volume=1000) for cb_op in ( None, space_group.info().change_of_basis_op_to_primitive_setting(), unit_cell.change_of_basis_op_to_niggli_cell(), ): miller_set = crystal.symmetry(unit_cell=unit_cell, space_group=space_group).build_miller_set( d_min=1, anomalous_flag=True ) miller_set = miller_set.expand_to_p1().customized_copy(space_group_info=miller_set.space_group_info()) if cb_op is not None: miller_set = miller_set.change_basis(cb_op) m = mtz.object() m.set_title("This is a title") m.set_space_group_info(miller_set.space_group_info()) x = m.add_crystal("XTAL", "CCTBX", miller_set.unit_cell().parameters()) d = x.add_dataset("TEST", 1) indices = miller_set.indices() original_indices = indices.deep_copy() # map the miller indices to one hemisphere (i.e. just I+) miller.map_to_asu(m.space_group().type(), False, indices) h, k, l = [i.iround() for i in indices.as_vec3_double().parts()] m.adjust_column_array_sizes(len(h)) m.set_n_reflections(len(h)) # assign H, K, L d.add_column("H", "H").set_values(h.as_double().as_float()) d.add_column("K", "H").set_values(k.as_double().as_float()) d.add_column("L", "H").set_values(l.as_double().as_float()) d.add_column("M_ISYM", "Y").set_values(flex.float(len(indices))) m.replace_original_index_miller_indices(original_indices) assert (m.extract_original_index_miller_indices() == original_indices).count(False) == 0 # check the indices in the mtz file are actually in the asu extracted_indices = m.extract_miller_indices() miller.map_to_asu(m.space_group().type(), False, extracted_indices) assert (extracted_indices == m.extract_miller_indices()).count(False) == 0 # test change_basis_in_place if appropriate for current space group import cctbx.sgtbx.cosets cb_op_to_niggli_cell = miller_set.change_of_basis_op_to_niggli_cell() minimum_cell_symmetry = crystal.symmetry.change_basis(miller_set.crystal_symmetry(), cb_op=cb_op_to_niggli_cell) lattice_group = sgtbx.lattice_symmetry.group(minimum_cell_symmetry.unit_cell(), max_delta=3.0) lattice_group.expand_inv(sgtbx.tr_vec((0, 0, 0))) lattice_group.make_tidy() cosets = sgtbx.cosets.left_decomposition_point_groups_only( g=lattice_group, h=minimum_cell_symmetry.reflection_intensity_symmetry(anomalous_flag=True) .space_group() .build_derived_acentric_group() .make_tidy(), ) possible_twin_laws = cosets.best_partition_representatives( cb_op=cb_op_to_niggli_cell.inverse(), omit_first_partition=True, omit_negative_determinants=True ) for twin_law in possible_twin_laws: cb_op = sgtbx.change_of_basis_op(twin_law.as_xyz()) # print cb_op.as_hkl() # forward direction m.change_basis_in_place(cb_op) assert (m.extract_original_index_miller_indices() == cb_op.apply(original_indices)).count(False) == 0 ## check the indices in the mtz file are actually in the asu # extracted_indices = m.extract_miller_indices() # miller.map_to_asu(m.space_group().type(), False, extracted_indices) # assert (extracted_indices == m.extract_miller_indices()).count(False) == 0 # and back again m.change_basis_in_place(cb_op.inverse()) assert (m.extract_original_index_miller_indices() == original_indices).count(False) == 0
def __init__(self, lf): self.symbol = None l = next(lf) print(l.strip()) if (lf.eof): return no, number, symbol, m = l.split() assert no == "NO." number = int(number) assert int(float(m)) == float(m) m = int(float(m)) space_group = sgtbx.space_group() if (m < 0): space_group.expand_inv(sgtbx.tr_vec((0, 0, 0))) space_group.expand_conventional_centring_type(symbol[0]) t_den = space_group.t_den() matrices = [] for i in range(abs(m)): l = next(lf) assert not lf.eof flds = l.split() assert len(flds) == 12 r = [int(e) for e in flds[1:4] + flds[5:8] + flds[9:12]] t = [ int(round(float(e) * t_den)) for e in (flds[0], flds[4], flds[8]) ] try: s = sgtbx.rt_mx(sgtbx.rot_mx(r), sgtbx.tr_vec(t)) except RuntimeError as e: print(e) print(l) else: try: matrices.append(s) space_group.expand_smx(s) except RuntimeError as e: print(e) print(l) print(s) space_group_info = sgtbx.space_group_info(group=space_group) if (space_group_info.type().number() != number): print("Space group number mismatch:") print(" from file:", number) print(" operations:", space_group_info.type().number()) for s in matrices: space_group = sgtbx.space_group_info(symbol=number).group() order_z = space_group.order_z() space_group.expand_smx(s) if (space_group.order_z() != order_z): print(" misfit:", s) space_group = sgtbx.space_group_info(symbol=number).group() for i_smx in range(space_group.n_smx()): OK = False for i_inv in range(space_group.f_inv()): for i_ltr in range(space_group.n_ltr()): sg = space_group(i_ltr, i_inv, i_smx).mod_positive() for sm in matrices: sm = sm.mod_positive() if (sm == sg): OK = True break if (OK): break if (OK): break if (not OK): print(" missing:", sg) self.number = number self.symbol = symbol self.space_group_info = space_group_info
try: from crys3d.qttbx.xray_structure_viewer import display except IOError: def display(*args, **kwds): pass # then use it #display(xray_structure=xs) # Let's look at symmetries info = xs.space_group_info() info.show_summary() print "Hall: %s" % info.type().hall_symbol() # List of all symmetries print "Symmetries:" for rt in info.group(): print rt.as_xyz() # The mathematical object representing the group g = info.group() print "Inversion at origin:%s" % ('no', 'yes')[g.is_origin_centric()] # Let's triple the cell from cctbx import sgtbx g.expand_ltr(sgtbx.tr_vec((1,0,1),3).new_denominator(g.t_den())) g.expand_ltr(sgtbx.tr_vec((2,0,2),3).new_denominator(g.t_den())) tripled_info = sgtbx.space_group_info(group=g) tripled_info.show_summary() print tripled_info.type().hall_symbol() # Let's change the space group of the structure now xs.as_cif_simple(open('03srv209x3.cif', 'w'))
def exercise_space_group_info(): i = sgtbx.space_group_info("P 1") assert i.type().number() == 1 i = sgtbx.space_group_info("P -1") assert i.type().number() == 2 i = sgtbx.space_group_info("P 2", "I", space_group_t_den=24) assert str(i) == "P 1 1 2" assert i.group().t_den() == 24 i = sgtbx.space_group_info("P32 (a,b,3c)", space_group_t_den=36) assert str(i) == "P 32 (a,b,3*c)" assert i.group().t_den() == 36 i = sgtbx.space_group_info("P 2", "I") assert str(i) == "P 1 1 2" i = sgtbx.space_group_info("P 2", "a") assert str(i) == "P 1 2 1" assert i.group() == i.type().group() assert i.reciprocal_space_asu().reference_as_string() \ == "k>=0 and (l>0 or (l==0 and h>=0))" assert str(i.brick()) == "0<=x<=1/2; 0<=y<1; 0<=z<1" assert i.wyckoff_table().space_group_type().group() == i.type().group() assert len(i.structure_seminvariants().vectors_and_moduli()) == 3 assert i.number_of_continuous_allowed_origin_shifts() == 1 for sg_number in (1, 3, 15, 75, 143, 195): assert approx_equal( sgtbx.space_group_info(sg_number).any_compatible_unit_cell( 100).volume(), 100) s = pickle.dumps(i) j = pickle.loads(s) assert str(i) == str(j) i = sgtbx.space_group_info("B 2", "i") assert not i.is_reference_setting() assert str(i.change_of_basis_op_to_reference_setting().c()) == "-x,z,y" assert str(i.reference_setting()) == "C 1 2 1" assert str(i.as_reference_setting()) == "C 1 2 1" assert str(i.primitive_setting()) == "C 1 2 1 (-x+y,z,x+y)" asu = i.direct_space_asu() assert len(asu.cuts) == 6 assert sgtbx.space_group(asu.hall_symbol) == i.group() j = i.primitive_setting() asu = j.direct_space_asu() assert len(asu.cuts) == 6 assert sgtbx.space_group(asu.hall_symbol) == j.group() i = sgtbx.space_group_info(number=19) assert [ str(sgtbx.space_group_info(group=group)) for group in i.reflection_intensity_equivalent_groups() ] == [ "P 2 2 2", "P 2 2 21", "P 21 2 2", "P 2 21 2", "P 21 21 2", "P 2 21 21", "P 21 2 21", "P 21 21 21" ] assert len(i.reflection_intensity_equivalent_groups(anomalous_flag=False)) \ == 127 # i = sgtbx.space_group_info(symbol="C 1 2 1") assert str(i.change_of_basis_op_to_reference_setting().c()) == "x,y,z" assert approx_equal( i.subtract_continuous_allowed_origin_shifts( translation_frac=[1, 2, 3]), [1, 0, 3]) i = sgtbx.space_group_info(symbol="B 2 1 1") assert str(i.change_of_basis_op_to_reference_setting().c()) == "z,x,y" assert approx_equal( i.subtract_continuous_allowed_origin_shifts( translation_frac=[1, 2, 3]), [0, 2, 3]) # for space_group_symbol, addl_smx, uhm in [ ("P 21 21 21", "x+1/2,y+1/2,z", "C 2 2 21 (a-1/4,b,c)"), ("C 1 2 1", "x,y+1/2,z", "P 1 2 1 (2*a,2*b,c)") ]: for f in range(1, 12 + 1): sg_t_den = sgtbx.sg_t_den * f cb_r_den = sgtbx.cb_r_den * f cb_t_den = sgtbx.cb_t_den * f # sg_i = sgtbx.space_group_info(symbol=space_group_symbol) t = sg_i.type() assert sg_i.type(tidy_cb_op=True) is t assert sg_i.type(tidy_cb_op=False) is not t if (f != 1): t = sg_i.type() c = t.cb_op().c() assert c.r().den() == sgtbx.cb_r_den assert c.t().den() == sgtbx.cb_t_den for t_den in [cb_t_den, None]: if (t_den is not None): tt = sg_i.type(t_den=t_den) assert tt is not t else: assert sg_i.type(t_den=t_den) is tt c = tt.cb_op().c() assert c.r().den() == sgtbx.cb_r_den assert c.t().den() == cb_t_den for r_den in [cb_r_den, None]: if (r_den is not None): tr = sg_i.type(r_den=r_den) assert tr is not tt else: sg_i.type(r_den=r_den) is tr c = tr.cb_op().c() assert c.r().den() == cb_r_den assert c.t().den() == cb_t_den # sg_i = sgtbx.space_group_info(symbol=space_group_symbol, space_group_t_den=sg_t_den) sgx = sgtbx.space_group(sg_i.group()) rt_mx = sgtbx.rt_mx(addl_smx) rt_mx = rt_mx.new_denominators(sgx.r_den(), sgx.t_den()) sgx.expand_smx(rt_mx) sgx_i = sgx.info() assert str(sgx_i) == uhm t = sgx_i.type() c = t.cb_op().c() assert c.r().den() == cb_r_den assert c.t().den() == cb_t_den for r_den, t_den in [(None, None), (cb_r_den, None), (None, cb_t_den), (cb_r_den, cb_t_den)]: assert sgx_i.type(r_den=r_den, t_den=t_den) is t assert sgx_i.type(tidy_cb_op=False, r_den=r_den, t_den=t_den) is not t for i, op in enumerate(sgx_i.group()): assert sgx_i.cif_symmetry_code(op) == "%i" % (i + 1) assert sgx_i.cif_symmetry_code(op, full_code=True, sep=" ") == "%i 555" % (i + 1) tr = [random.randint(-4, 4) for j in range(3)] rt_mx = sgtbx.rt_mx( op.r(), op.t().plus( sgtbx.tr_vec(tr, tr_den=1).new_denominator(op.t().den()))) assert sgx_i.cif_symmetry_code(rt_mx, full_code=True) \ == "%i_%i%i%i" %(i+1, 5+tr[0], 5+tr[1], 5+tr[2])
def rt_plus_unit_shifts(rt, unit_shifts): return sgtbx.rt_mx(rt.r(), rt.t().plus(sgtbx.tr_vec(unit_shifts, 1)))
def exercise_unmerged(space_group_info): import random from cctbx import sgtbx # shuffle the space_group = sgtbx.space_group('P 1', no_expand=True) perm = list(range(len(space_group_info.group()))) random.shuffle(perm) for i in perm: space_group.expand_smx(space_group_info.group()[i]) unit_cell = space_group_info.any_compatible_unit_cell(volume=1000) for cb_op in (None, space_group.info().change_of_basis_op_to_primitive_setting(), unit_cell.change_of_basis_op_to_niggli_cell()): miller_set = crystal.symmetry( unit_cell=unit_cell, space_group=space_group).build_miller_set(d_min=1, anomalous_flag=True) miller_set = miller_set.expand_to_p1().customized_copy( space_group_info=miller_set.space_group_info()) if cb_op is not None: miller_set = miller_set.change_basis(cb_op) m = mtz.object() m.set_title('This is a title') m.set_space_group_info(miller_set.space_group_info()) x = m.add_crystal('XTAL', 'CCTBX', miller_set.unit_cell().parameters()) d = x.add_dataset('TEST', 1) indices = miller_set.indices() original_indices = indices.deep_copy() # map the miller indices to one hemisphere (i.e. just I+) miller.map_to_asu(m.space_group().type(), False, indices) h, k, l = [i.iround() for i in indices.as_vec3_double().parts()] m.adjust_column_array_sizes(len(h)) m.set_n_reflections(len(h)) # assign H, K, L d.add_column('H', 'H').set_values(h.as_double().as_float()) d.add_column('K', 'H').set_values(k.as_double().as_float()) d.add_column('L', 'H').set_values(l.as_double().as_float()) d.add_column('M_ISYM', 'Y').set_values(flex.float(len(indices))) m.replace_original_index_miller_indices(original_indices) assert (m.extract_original_index_miller_indices() == original_indices ).count(False) == 0 # check the indices in the mtz file are actually in the asu extracted_indices = m.extract_miller_indices() miller.map_to_asu(m.space_group().type(), False, extracted_indices) assert ( extracted_indices == m.extract_miller_indices()).count(False) == 0 # test change_basis_in_place if appropriate for current space group import cctbx.sgtbx.cosets cb_op_to_niggli_cell \ = miller_set.change_of_basis_op_to_niggli_cell() minimum_cell_symmetry = crystal.symmetry.change_basis( miller_set.crystal_symmetry(), cb_op=cb_op_to_niggli_cell) lattice_group = sgtbx.lattice_symmetry.group( minimum_cell_symmetry.unit_cell(), max_delta=3.0) lattice_group.expand_inv(sgtbx.tr_vec((0, 0, 0))) lattice_group.make_tidy() cosets = sgtbx.cosets.left_decomposition_point_groups_only( g=lattice_group, h=minimum_cell_symmetry.reflection_intensity_symmetry( anomalous_flag=True).space_group( ).build_derived_acentric_group().make_tidy()) possible_twin_laws = cosets.best_partition_representatives( cb_op=cb_op_to_niggli_cell.inverse(), omit_first_partition=True, omit_negative_determinants=True) for twin_law in possible_twin_laws: cb_op = sgtbx.change_of_basis_op(twin_law.as_xyz()) #print cb_op.as_hkl() # forward direction m.change_basis_in_place(cb_op) assert (m.extract_original_index_miller_indices() == cb_op.apply( original_indices)).count(False) == 0 ## check the indices in the mtz file are actually in the asu #extracted_indices = m.extract_miller_indices() #miller.map_to_asu(m.space_group().type(), False, extracted_indices) #assert (extracted_indices == m.extract_miller_indices()).count(False) == 0 # and back again m.change_basis_in_place(cb_op.inverse()) assert (m.extract_original_index_miller_indices() == original_indices).count(False) == 0
def derive_result_group_list(self, group_of_interest): # Get list of sub-spacegroups subgrs = subgroups.subgroups(group_of_interest).groups_parent_setting() # Order sub-groups sort_values = flex.double() for group in subgrs: order_z = group.order_z() space_group_number = sgtbx.space_group_type(group, False).number() assert 1 <= space_group_number <= 230 sort_values.append(order_z * 1000 + space_group_number) perm = flex.sort_permutation(sort_values, True) for i_subgr in perm: acentric_subgroup = subgrs[i_subgr] acentric_supergroup = metric_supergroup(acentric_subgroup) # Add centre of inversion to acentric lattice symmetry centric_group = sgtbx.space_group(acentric_subgroup) centric_group.expand_inv(sgtbx.tr_vec((0, 0, 0))) # Make symmetry object: unit-cell + space-group # The unit cell is potentially modified to be exactly compatible # with the space group symmetry. subsym = crystal.symmetry( unit_cell=self.minimum_symmetry.unit_cell(), space_group=centric_group, assert_is_compatible_unit_cell=False) supersym = crystal.symmetry( unit_cell=self.minimum_symmetry.unit_cell(), space_group=acentric_supergroup, assert_is_compatible_unit_cell=False) # Convert subgroup to reference setting cb_op_minimum_ref = subsym.space_group_info().type().cb_op() ref_subsym = subsym.change_basis(cb_op_minimum_ref) # Ignore unwanted groups if (self.bravais_types_only and not str( ref_subsym.space_group_info()) in bravais_types.centric): continue # Choose best setting for monoclinic and orthorhombic systems cb_op_best_cell = self.change_of_basis_op_to_best_cell(ref_subsym) best_subsym = ref_subsym.change_basis(cb_op_best_cell) # Total basis transformation cb_op_best_cell = change_of_basis_op(str(cb_op_best_cell), stop_chars='', r_den=144, t_den=144) cb_op_minimum_ref = change_of_basis_op(str(cb_op_minimum_ref), stop_chars='', r_den=144, t_den=144) self.cb_op_inp_minimum = change_of_basis_op(str( self.cb_op_inp_minimum), stop_chars='', r_den=144, t_den=144) cb_op_inp_best = cb_op_best_cell * cb_op_minimum_ref * self.cb_op_inp_minimum # Use identity change-of-basis operator if possible if (best_subsym.unit_cell().is_similar_to( self.input_symmetry.unit_cell())): cb_op_corr = cb_op_inp_best.inverse() try: best_subsym_corr = best_subsym.change_basis(cb_op_corr) except RuntimeError, e: if (str(e).find( "Unsuitable value for rational rotation matrix.") < 0): raise else: if (best_subsym_corr.space_group() == best_subsym.space_group()): cb_op_inp_best = cb_op_corr * cb_op_inp_best self.result_groups.append({ 'subsym': subsym, 'supersym': supersym, 'ref_subsym': ref_subsym, 'best_subsym': best_subsym, 'cb_op_inp_best': cb_op_inp_best, 'max_angular_difference': find_max_delta(reduced_cell=self.minimum_symmetry.unit_cell(), space_group=acentric_supergroup) })
def exercise(space_group_info, anomalous_flag, use_u_aniso, n_elements=3, d_min=3., verbose=0): structure_z = random_structure.xray_structure( space_group_info, elements=("Se", ) * n_elements, volume_per_atom=200, random_f_prime_d_min=1.0, random_f_double_prime=anomalous_flag, random_u_iso=True, use_u_aniso=use_u_aniso, random_occupancy=True) check_weight_without_occupancy(structure_z) f_z = structure_z.structure_factors(anomalous_flag=anomalous_flag, d_min=d_min, algorithm="direct").f_calc() f_abs_z = abs(f_z) f_rad_z = f_z.phases() f_deg_z = f_z.phases(deg=True) hl_z = generate_random_hl(miller_set=f_z) hl_z_rad = hl_z.phase_integrals() if (0 or verbose): structure_z.show_summary().show_scatterers() print("n_special_positions:", \ structure_z.special_position_indices().size()) z2p_op = structure_z.space_group().z2p_op() z2p_op = sgtbx.change_of_basis_op(z2p_op.c() + sgtbx.tr_vec( (2, -1, 3), 12).new_denominator(z2p_op.c().t().den())) for change_hand in [False, True]: if (change_hand): z2p_op = z2p_op * sgtbx.change_of_basis_op("-x,-y,-z") structure_p = structure_z.change_basis(z2p_op) check_weight_without_occupancy(structure_p) check_site_symmetry_table(structure_z, z2p_op, structure_p) if (0 or verbose): structure_p.show_summary().show_scatterers() print("n_special_positions:", \ structure_p.special_position_indices().size()) assert tuple(structure_p.special_position_indices()) \ == tuple(structure_z.special_position_indices()) structure_pz = structure_p.change_basis(z2p_op.inverse()) check_weight_without_occupancy(structure_pz) check_site_symmetry_table(structure_p, z2p_op.inverse(), structure_pz) assert structure_pz.unit_cell().is_similar_to(structure_z.unit_cell()) assert structure_pz.space_group() == structure_z.space_group() f_pz = f_z.structure_factors_from_scatterers( xray_structure=structure_pz, algorithm="direct").f_calc() f_abs_pz = abs(f_pz) f_rad_pz = f_pz.phases() f_deg_pz = f_pz.phases(deg=True) c = flex.linear_correlation(f_abs_z.data(), f_abs_pz.data()) assert c.is_well_defined() if (0 or verbose): print("correlation:", c.coefficient()) assert c.coefficient() > 0.999 f_p_cb = f_z.change_basis(z2p_op) f_abs_p_cb = f_abs_z.change_basis(z2p_op) f_rad_p_cb = f_rad_z.change_basis(z2p_op, deg=False) f_deg_p_cb = f_deg_z.change_basis(z2p_op, deg=True) hl_p_cb = hl_z.change_basis(z2p_op) hl_p_cb_rad = hl_p_cb.phase_integrals() assert approx_equal( hl_z_rad.change_basis(z2p_op).data(), hl_p_cb_rad.data()) assert f_abs_p_cb.indices().all_eq(f_p_cb.indices()) if (not change_hand): o = flex.order(f_abs_p_cb.indices(), f_abs_z.indices()) else: o = flex.order(-f_abs_p_cb.indices(), f_abs_z.indices()) if (f_abs_z.space_group().n_ltr() == 1): assert o == 0 else: assert o != 0 f_pz = f_p_cb.change_basis(z2p_op.inverse()) f_abs_pz = f_abs_p_cb.change_basis(z2p_op.inverse()) f_rad_pz = f_rad_p_cb.change_basis(z2p_op.inverse(), deg=False) f_deg_pz = f_deg_p_cb.change_basis(z2p_op.inverse(), deg=True) hl_pz = hl_p_cb.change_basis(z2p_op.inverse()) hl_pz_rad = hl_pz.phase_integrals() assert approx_equal(hl_z_rad.data(), hl_pz_rad.data()) for i, o in zip(hl_z.data(), hl_pz.data()): assert approx_equal(i, o) assert approx_equal(flex.max(flex.abs(f_pz.data() - f_z.data())), 0) assert flex.order(f_abs_pz.indices(), f_abs_z.indices()) == 0 assert f_abs_pz.indices().all_eq(f_pz.indices()) assert approx_equal( flex.max( scitbx.math.phase_error(phi1=f_rad_pz.data(), phi2=f_rad_z.data())), 0) assert approx_equal( flex.max( scitbx.math.phase_error(phi1=f_deg_pz.data(), phi2=f_deg_z.data(), deg=True)), 0) assert approx_equal(f_deg_pz.data(), f_rad_pz.data() * (180 / math.pi)) f_p_sf = f_p_cb.structure_factors_from_scatterers( xray_structure=structure_p, algorithm="direct").f_calc() det = abs(z2p_op.c().r().determinant()) assert approx_equal( flex.max(flex.abs(f_p_sf.data() * complex(det) - f_p_cb.data())), 0) f_abs_p_sf = abs(f_p_sf) f_rad_p_sf = f_p_sf.phases() f_deg_p_sf = f_p_sf.phases(deg=True) assert approx_equal( flex.max( scitbx.math.phase_error(phi1=f_rad_p_sf.data(), phi2=f_rad_p_cb.data())), 0) assert approx_equal( flex.max( scitbx.math.phase_error(phi1=f_deg_p_sf.data(), phi2=f_deg_p_cb.data(), deg=True)), 0) c = flex.linear_correlation(f_abs_p_sf.data(), f_abs_p_cb.data()) assert c.is_well_defined() if (0 or verbose): print("correlation:", c.coefficient()) assert c.coefficient() > 0.999
def exercise( space_group_info, anomalous_flag, use_u_aniso, n_elements=3, d_min=3., verbose=0): structure_z = random_structure.xray_structure( space_group_info, elements=("Se",)*n_elements, volume_per_atom=200, random_f_prime_d_min=1.0, random_f_double_prime=anomalous_flag, random_u_iso=True, use_u_aniso=use_u_aniso, random_occupancy=True) check_weight_without_occupancy(structure_z) f_z = structure_z.structure_factors( anomalous_flag=anomalous_flag, d_min=d_min, algorithm="direct").f_calc() f_abs_z = abs(f_z) f_rad_z = f_z.phases() f_deg_z = f_z.phases(deg=True) hl_z = generate_random_hl(miller_set=f_z) hl_z_rad = hl_z.phase_integrals() if (0 or verbose): structure_z.show_summary().show_scatterers() print "n_special_positions:", \ structure_z.special_position_indices().size() z2p_op = structure_z.space_group().z2p_op() z2p_op = sgtbx.change_of_basis_op( z2p_op.c() + sgtbx.tr_vec((2,-1,3), 12).new_denominator(z2p_op.c().t().den())) for change_hand in [False, True]: if (change_hand): z2p_op = z2p_op * sgtbx.change_of_basis_op("-x,-y,-z") structure_p = structure_z.change_basis(z2p_op) check_weight_without_occupancy(structure_p) check_site_symmetry_table(structure_z, z2p_op, structure_p) if (0 or verbose): structure_p.show_summary().show_scatterers() print "n_special_positions:", \ structure_p.special_position_indices().size() assert tuple(structure_p.special_position_indices()) \ == tuple(structure_z.special_position_indices()) structure_pz = structure_p.change_basis(z2p_op.inverse()) check_weight_without_occupancy(structure_pz) check_site_symmetry_table(structure_p, z2p_op.inverse(), structure_pz) assert structure_pz.unit_cell().is_similar_to(structure_z.unit_cell()) assert structure_pz.space_group() == structure_z.space_group() f_pz = f_z.structure_factors_from_scatterers( xray_structure=structure_pz, algorithm="direct").f_calc() f_abs_pz = abs(f_pz) f_rad_pz = f_pz.phases() f_deg_pz = f_pz.phases(deg=True) c = flex.linear_correlation(f_abs_z.data(), f_abs_pz.data()) assert c.is_well_defined() if (0 or verbose): print "correlation:", c.coefficient() assert c.coefficient() > 0.999 f_p_cb = f_z.change_basis(z2p_op) f_abs_p_cb = f_abs_z.change_basis(z2p_op) f_rad_p_cb = f_rad_z.change_basis(z2p_op, deg=False) f_deg_p_cb = f_deg_z.change_basis(z2p_op, deg=True) hl_p_cb = hl_z.change_basis(z2p_op) hl_p_cb_rad = hl_p_cb.phase_integrals() assert approx_equal( hl_z_rad.change_basis(z2p_op).data(), hl_p_cb_rad.data()) assert f_abs_p_cb.indices().all_eq(f_p_cb.indices()) if (not change_hand): o = flex.order(f_abs_p_cb.indices(), f_abs_z.indices()) else: o = flex.order(-f_abs_p_cb.indices(), f_abs_z.indices()) if (f_abs_z.space_group().n_ltr() == 1): assert o == 0 else: assert o != 0 f_pz = f_p_cb.change_basis(z2p_op.inverse()) f_abs_pz = f_abs_p_cb.change_basis(z2p_op.inverse()) f_rad_pz = f_rad_p_cb.change_basis(z2p_op.inverse(), deg=False) f_deg_pz = f_deg_p_cb.change_basis(z2p_op.inverse(), deg=True) hl_pz = hl_p_cb.change_basis(z2p_op.inverse()) hl_pz_rad = hl_pz.phase_integrals() assert approx_equal(hl_z_rad.data(), hl_pz_rad.data()) for i,o in zip(hl_z.data(), hl_pz.data()): assert approx_equal(i, o) assert approx_equal( flex.max(flex.abs(f_pz.data() - f_z.data())), 0) assert flex.order(f_abs_pz.indices(), f_abs_z.indices()) == 0 assert f_abs_pz.indices().all_eq(f_pz.indices()) assert approx_equal(flex.max(scitbx.math.phase_error( phi1=f_rad_pz.data(), phi2=f_rad_z.data())), 0) assert approx_equal(flex.max(scitbx.math.phase_error( phi1=f_deg_pz.data(), phi2=f_deg_z.data(), deg=True)), 0) assert approx_equal(f_deg_pz.data(), f_rad_pz.data()*(180/math.pi)) f_p_sf = f_p_cb.structure_factors_from_scatterers( xray_structure=structure_p, algorithm="direct").f_calc() det = abs(z2p_op.c().r().determinant()) assert approx_equal( flex.max(flex.abs(f_p_sf.data()*complex(det) - f_p_cb.data())), 0) f_abs_p_sf = abs(f_p_sf) f_rad_p_sf = f_p_sf.phases() f_deg_p_sf = f_p_sf.phases(deg=True) assert approx_equal(flex.max(scitbx.math.phase_error( phi1=f_rad_p_sf.data(), phi2=f_rad_p_cb.data())), 0) assert approx_equal(flex.max(scitbx.math.phase_error( phi1=f_deg_p_sf.data(), phi2=f_deg_p_cb.data(), deg=True)), 0) c = flex.linear_correlation(f_abs_p_sf.data(), f_abs_p_cb.data()) assert c.is_well_defined() if (0 or verbose): print "correlation:", c.coefficient() assert c.coefficient() > 0.999
def exercise(space_group_info, fixed_random_seed=True, shifted_origin=None, elements=None, d_min=0.8, grid_resolution_factor=1/3., verbose=False, **kwds): if elements is None: n_C = 5 n_O = 1 n_N = 1 elements = ["C"]*n_C + ["O"]*n_O + ["N"]*n_N if verbose: print(elements) target_space_group_type = space_group_info.type() hall = sgtbx.space_group_symbols( target_space_group_type.lookup_symbol()).hall() print(hall) if fixed_random_seed: random.seed(1) flex.set_random_seed(1) # Generate a random structure in real space, # compute its structure factors, # that we will try to recover the symmetry of target_structure = random_structure.xray_structure( space_group_info=space_group_info, elements=elements, use_u_iso=True, random_u_iso=True, random_u_iso_scale=0.04, use_u_aniso=False, ) if shifted_origin is None: shifted_origin = flex.random_double(3) shifted_origin = mat.col(shifted_origin) if verbose: print("new origin = (%.3f, %.3f, %.3f)" % shifted_origin.elems) print() target_structure_in_p1 = target_structure\ .expand_to_p1().apply_shift(shifted_origin) target_f_in_p1 = miller.build_set( crystal_symmetry=target_structure_in_p1, anomalous_flag=False, d_min=d_min ).structure_factors_from_scatterers( xray_structure=target_structure_in_p1, algorithm="direct").f_calc() # Recover space group? sf_symm = symmetry_search.structure_factor_symmetry(target_f_in_p1) if verbose: print(sf_symm) solution_hall, target_hall = [ sgi.as_reference_setting().type().hall_symbol() for sgi in (sf_symm.space_group_info, target_structure.space_group_info()) ] assert solution_hall == target_hall, (solution_hall, target_hall) # Shift maximises goodness of symmetry? gos, solution_f = sf_symm.symmetrised_structure_factors() if space_group_info.type().hall_symbol() != ' P 1': assert gos.correlation > 0.99 assert gos.gradient == (0, 0, 0) gos_away_from_max = sf_symm.symmetrised_structure_factors( delta=mat.col((0.1, 0.1, 0.1)))[0] assert gos_away_from_max.correlation < 0.9, gos_away_from_max.correlation # Recovered origin """The sequence of transform read: ----->target structure ^ V ^ V (1, shifted_origin=sigma) ^ V ^ shifted target ^ V ^ V sf_symm.cb_op_to_primitive = (P, 0) ^ V ^ shifted target in primitive cell = shifted solution in primitive cell ^ V ^ V (1, -sf_symm.origin=-s) ^ V ^ solution in primitive cell ^ V ^ V solution_to_target_cb_op = (Q, q) ^ V ^------------ The total transfrom from the target structure back to it reads (QP, q') with q' = (Q,q)(-s + P sigma) = (Q,q)delta_o with delta_o = sf_symm.cb_op_to_primitive(shifted_origin) - sf_symm.origin (Q, q') must leave the target structure space group invariant. Most of the time Q is the unit matrix and the test boils down to check whether delta is an allowed origin shift after changing to the input cell but it does not hurt to do the more general test all the time. """ solution_to_target_cb_op = ( target_structure.space_group_info() .change_of_basis_op_to_reference_setting().inverse() * sf_symm.space_group_info .change_of_basis_op_to_reference_setting()) if verbose: print() print("solution -> target: %s" % solution_to_target_cb_op.as_xyz()) delta_o = (mat.col(sf_symm.cb_op_to_primitive(shifted_origin)) - sf_symm.origin) delta = mat.col(solution_to_target_cb_op(delta_o)) stabilising_cb_op = sgtbx.change_of_basis_op(sgtbx.rt_mx( (solution_to_target_cb_op*sf_symm.cb_op_to_primitive).c().r(), sgtbx.tr_vec((delta*72).as_int()*2, tr_den=144))) # guarding against rounding errors on some platforms (e.g. FC8) # meaning that (delta*144).as_int() would not work. target_sg = target_structure.space_group() assert target_sg == target_sg.change_basis(stabilising_cb_op)
def exercise_space_group_info(): i = sgtbx.space_group_info("P 1") assert i.type().number() == 1 i = sgtbx.space_group_info("P -1") assert i.type().number() == 2 i = sgtbx.space_group_info("P 2", "I", space_group_t_den=24) assert str(i) == "P 1 1 2" assert i.group().t_den() == 24 i = sgtbx.space_group_info("P32 (a,b,3c)", space_group_t_den=36) assert str(i) == "P 32 (a,b,3*c)" assert i.group().t_den() == 36 i = sgtbx.space_group_info("P 2", "I") assert str(i) == "P 1 1 2" i = sgtbx.space_group_info("P 2", "a") assert str(i) == "P 1 2 1" assert i.group() == i.type().group() assert i.reciprocal_space_asu().reference_as_string() \ == "k>=0 and (l>0 or (l==0 and h>=0))" assert str(i.brick()) == "0<=x<=1/2; 0<=y<1; 0<=z<1" assert i.wyckoff_table().space_group_type().group() == i.type().group() assert len(i.structure_seminvariants().vectors_and_moduli()) == 3 assert i.number_of_continuous_allowed_origin_shifts() == 1 for sg_number in (1,3,15,75,143,195): assert approx_equal( sgtbx.space_group_info(sg_number).any_compatible_unit_cell(100).volume(), 100) s = pickle.dumps(i) j = pickle.loads(s) assert str(i) == str(j) i = sgtbx.space_group_info("B 2", "i") assert not i.is_reference_setting() assert str(i.change_of_basis_op_to_reference_setting().c()) == "-x,z,y" assert str(i.reference_setting()) == "C 1 2 1" assert str(i.as_reference_setting()) == "C 1 2 1" assert str(i.primitive_setting()) == "C 1 2 1 (-x+y,z,x+y)" asu = i.direct_space_asu() assert len(asu.cuts) == 6 assert sgtbx.space_group(asu.hall_symbol) == i.group() j = i.primitive_setting() asu = j.direct_space_asu() assert len(asu.cuts) == 6 assert sgtbx.space_group(asu.hall_symbol) == j.group() i = sgtbx.space_group_info(number=19) assert [str(sgtbx.space_group_info(group=group)) for group in i.reflection_intensity_equivalent_groups()] == [ "P 2 2 2", "P 2 2 21", "P 21 2 2", "P 2 21 2", "P 21 21 2", "P 2 21 21", "P 21 2 21", "P 21 21 21"] assert len(i.reflection_intensity_equivalent_groups(anomalous_flag=False)) \ == 127 # i = sgtbx.space_group_info(symbol="C 1 2 1") assert str(i.change_of_basis_op_to_reference_setting().c()) == "x,y,z" assert approx_equal( i.subtract_continuous_allowed_origin_shifts(translation_frac=[1,2,3]), [1,0,3]) i = sgtbx.space_group_info(symbol="B 2 1 1") assert str(i.change_of_basis_op_to_reference_setting().c()) == "z,x,y" assert approx_equal( i.subtract_continuous_allowed_origin_shifts(translation_frac=[1,2,3]), [0,2,3]) # for space_group_symbol, addl_smx, uhm in [ ("P 21 21 21", "x+1/2,y+1/2,z", "C 2 2 21 (a-1/4,b,c)"), ("C 1 2 1", "x,y+1/2,z", "P 1 2 1 (2*a,2*b,c)")]: for f in xrange(1,12+1): sg_t_den = sgtbx.sg_t_den * f cb_r_den = sgtbx.cb_r_den * f cb_t_den = sgtbx.cb_t_den * f # sg_i = sgtbx.space_group_info(symbol=space_group_symbol) t = sg_i.type() assert sg_i.type(tidy_cb_op=True) is t assert sg_i.type(tidy_cb_op=False) is not t if (f != 1): t = sg_i.type() c = t.cb_op().c() assert c.r().den() == sgtbx.cb_r_den assert c.t().den() == sgtbx.cb_t_den for t_den in [cb_t_den, None]: if (t_den is not None): tt = sg_i.type(t_den=t_den) assert tt is not t else: assert sg_i.type(t_den=t_den) is tt c = tt.cb_op().c() assert c.r().den() == sgtbx.cb_r_den assert c.t().den() == cb_t_den for r_den in [cb_r_den, None]: if (r_den is not None): tr = sg_i.type(r_den=r_den) assert tr is not tt else: sg_i.type(r_den=r_den) is tr c = tr.cb_op().c() assert c.r().den() == cb_r_den assert c.t().den() == cb_t_den # sg_i = sgtbx.space_group_info( symbol=space_group_symbol, space_group_t_den=sg_t_den) sgx = sgtbx.space_group(sg_i.group()) rt_mx = sgtbx.rt_mx(addl_smx) rt_mx = rt_mx.new_denominators(sgx.r_den(), sgx.t_den()) sgx.expand_smx(rt_mx) sgx_i = sgx.info() assert str(sgx_i) == uhm t = sgx_i.type() c = t.cb_op().c() assert c.r().den() == cb_r_den assert c.t().den() == cb_t_den for r_den,t_den in [(None, None), (cb_r_den, None), (None, cb_t_den), (cb_r_den, cb_t_den)]: assert sgx_i.type(r_den=r_den, t_den=t_den) is t assert sgx_i.type(tidy_cb_op=False, r_den=r_den, t_den=t_den) is not t for i, op in enumerate(sgx_i.group()): assert sgx_i.cif_symmetry_code(op) == "%i" %(i+1) assert sgx_i.cif_symmetry_code( op, full_code=True, sep=" ") == "%i 555" %(i+1) tr = [random.randint(-4, 4) for j in range(3)] rt_mx = sgtbx.rt_mx(op.r(), op.t().plus( sgtbx.tr_vec(tr, tr_den=1).new_denominator(op.t().den()))) assert sgx_i.cif_symmetry_code(rt_mx, full_code=True) \ == "%i_%i%i%i" %(i+1, 5+tr[0], 5+tr[1], 5+tr[2])