def add_hydrogen_to(self, reparametrisation, bond_length, pivot_site, pivot_neighbour_sites, pivot_site_param, pivot_neighbour_site_params, pivot_neighbour_substituent_site_params, hydrogens, **kwds): if len(pivot_neighbour_site_params) != 1: raise InvalidConstraint(_.bad_connectivity_msg % (self.__class__.__name__, pivot_site_param.scatterers[0].label)) if not len(pivot_neighbour_substituent_site_params): raise InvalidConstraint(need_at_least_one_substituent_msg % (self.__class__.__name__, pivot_site_param.scatterers[0].label)) if self.stagger_on is None: if len(pivot_neighbour_substituent_site_params) == 1: stagger_on = pivot_neighbour_substituent_site_params[0] else: # staggered with respect to the shortest # pivot_neighbour - pivot_neighbour_substituent bond # # If the two bond lengths are similar, then the hydrogen could have a # tendancy to flip between the positions. If this is the case, a # staggered hydrogen constraint is probably unsuitable, and a freely # rotatable constraint could be used. # uc = reparametrisation.structure.unit_cell() x_s = col(pivot_neighbour_sites[0]) d_s = sorted((uc.distance(s.value, x_s), i) for i, s in enumerate( pivot_neighbour_substituent_site_params)) stagger_on = pivot_neighbour_substituent_site_params[d_s[0][1]] else: for p in pivot_neighbour_substituent_site_params: if p.index == self.stagger_on: stagger_on = p break # The stagger_on atom must be one of the pivot_neighbour_substituents. # If we reach here, this is not the case so an error is raised. raise InvalidConstraint(_.bad_connectivity_msg % (self.__class__.__name__, pivot_site_param.scatterers[0].label)) for j, ops in reparametrisation.pair_sym_table[self.pivot].items(): for k, ops in reparametrisation.pair_sym_table[self.pivot].items(): if j == k: continue reparametrisation.fixed_angles.setdefault((j, self.pivot, k), tetrahedral_angle) return reparametrisation.add( getattr(_, self.__class__.__name__), pivot=pivot_site_param, pivot_neighbour=pivot_neighbour_site_params[0], length=bond_length, stagger_on=stagger_on, hydrogen=hydrogens)
def __init__(self, groups, angles=(0,0,0), fix_xyz=True, fix_u=True): """ fix_xyz and fix_u are to be used for debugging purposes only: if the coordinates are not fixed, then the refined angles should be stored externally and passed to this object """ if len(groups) < 2: raise InvalidConstraint("at least two atom sets are expected") l = len(groups[0]) for g in groups[1:]: if len(g) != l: raise InvalidConstraint("atoms sets differ in size") self.groups = groups self.fix_xyz = fix_xyz self.fix_u = fix_u self.angles = angles
def add_hydrogen_to(self, reparametrisation, bond_length, pivot_site, pivot_neighbour_sites, pivot_site_param, pivot_neighbour_site_params, hydrogens, **kwds): if len(pivot_neighbour_site_params) != 1: raise InvalidConstraint(_.bad_connectivity_msg % (self.__class__.__name__, pivot_site_param.scatterers[0].label)) azimuth = reparametrisation.add(_.independent_scalar_parameter, value=0, variable=self.rotating) uc = reparametrisation.structure.unit_cell() for j, ops in reparametrisation.pair_sym_table[self.pivot].items(): for k, ops in reparametrisation.pair_sym_table[self.pivot].items(): if j == k: continue reparametrisation.fixed_angles.setdefault((j, self.pivot, k), tetrahedral_angle) return reparametrisation.add( getattr(_, self.__class__.__name__), pivot=pivot_site_param, pivot_neighbour=pivot_neighbour_site_params[0], length=bond_length, azimuth=azimuth, e_zero_azimuth=uc.orthogonalize( col(hydrogens[0].site) - col(pivot_site)), hydrogen=hydrogens)
def __init__(self, center, ind_sequence, sizeable, rotatable): if len(ind_sequence) == 0: raise InvalidConstraint("at least one atom is expected") self.pivot = center self.indices = ind_sequence self.sizeable = sizeable self.rotatable = rotatable
def add_to(self, reparametrisation): scatterers = reparametrisation.structure.scatterers() src_uses_u = scatterers[self.indices[0]].flags.use_u_aniso() for i in range(1, len(self.indices)): if scatterers[self.indices[i]].flags.use_u_aniso() != src_uses_u: raise InvalidConstraint( "mixing isotropic and anisotropic atoms is not allowed for shared ADP" ) u_c = reparametrisation.add_new_thermal_displacement_parameter( self.indices[0]) for i in range(1, len(self.indices)): if src_uses_u: param = reparametrisation.add( _.shared_u_star, reference=u_c, scatterer=scatterers[self.indices[i]]) else: param = reparametrisation.add( _.shared_u_iso, reference=u_c, scatterer=scatterers[self.indices[i]]) reparametrisation.shared_Us[self.indices[i]] = u_c reparametrisation.asu_scatterer_parameters[ self.indices[i]].u = param self.value = u_c
def ideal_bond_length(self, pivot, temperature): pivot_element = pivot.scattering_type d = self.room_temperature_bond_length.get(pivot_element) if d is None: raise InvalidConstraint( "Invalid %s constraint involving %s:" " ideal bond length not defined to atom type %s" % (self.__class__.__name__, pivot.label, pivot_element)) if temperature is not None: if temperature < -70: d += 0.02 elif temperature < -20: d += 0.01 return d
def add_hydrogen_to(self, reparametrisation, bond_length, pivot_site, pivot_neighbour_sites, pivot_site_param, pivot_neighbour_site_params, hydrogens, **kwds): if len(pivot_neighbour_site_params) != 4 and\ len(pivot_neighbour_site_params) != 5: raise InvalidConstraint(_.bad_connectivity_msg % (self.__class__.__name__, pivot_site_param.scatterers[0].label)) return reparametrisation.add( _.polyhedral_bh_site, pivot=pivot_site_param, pivot_neighbours=pivot_neighbour_site_params, length=bond_length, hydrogen=hydrogens[0])
def add_hydrogen_to(self, reparametrisation, bond_length, pivot_site, pivot_neighbour_sites, pivot_site_param, pivot_neighbour_site_params, hydrogens, **kwds): if len(pivot_neighbour_site_params) != 3: raise InvalidConstraint(_.bad_connectivity_msg % (self.__class__.__name__, pivot_site_param.scatterers[0].label)) return reparametrisation.add( _.tertiary_xh_site, pivot=pivot_site_param, pivot_neighbour_0=pivot_neighbour_site_params[0], pivot_neighbour_1=pivot_neighbour_site_params[1], pivot_neighbour_2=pivot_neighbour_site_params[2], length=bond_length, hydrogen=hydrogens[0])
def add_hydrogen_to(self, reparametrisation, bond_length, pivot_site, pivot_neighbour_sites, pivot_site_param, pivot_neighbour_site_params, hydrogens, **kwds): if len(pivot_neighbour_site_params) != 1: raise InvalidConstraint(_.bad_connectivity_msg % (self.__class__.__name__, pivot_site_param.scatterers[0].label)) for j, ops in reparametrisation.pair_sym_table[self.pivot].items(): for k, ops in reparametrisation.pair_sym_table[self.pivot].items(): if j == k: continue reparametrisation.fixed_angles.setdefault((j, self.pivot, k), 180.0) return reparametrisation.add( _.terminal_linear_ch_site, pivot=pivot_site_param, pivot_neighbour=pivot_neighbour_site_params[0], length=bond_length, hydrogen=hydrogens[0])
def add_hydrogen_to(self, reparametrisation, bond_length, pivot_site, pivot_neighbour_sites, pivot_site_param, pivot_neighbour_site_params, hydrogens, **kwds): # e.g. Carbon atoms in Cyclopentadienyl complexes will have # 3 pivot neighbours if len(pivot_neighbour_site_params) not in (2, 3): raise InvalidConstraint(_.bad_connectivity_msg % (self.__class__.__name__, pivot_site_param.scatterers[0].label)) uc = reparametrisation.structure.unit_cell() x_s = col(pivot_site) d_s = sorted((uc.distance(s, x_s), i) for i, s in enumerate(pivot_neighbour_sites)) return reparametrisation.add( _.secondary_planar_xh_site, pivot=pivot_site_param, pivot_neighbour_0=pivot_neighbour_site_params[d_s[0][1]], pivot_neighbour_1=pivot_neighbour_site_params[d_s[1][1]], length=bond_length, hydrogen=hydrogens[0])
def add_hydrogen_to(self, reparametrisation, bond_length, pivot_site, pivot_neighbour_sites, pivot_site_param, pivot_neighbour_site_params, hydrogens, **kwds): if len(pivot_neighbour_site_params) != 2: raise InvalidConstraint(_.bad_connectivity_msg % (self.__class__.__name__, pivot_site_param.scatterers[0].label)) x_h = [col(h.site) for h in hydrogens] x_p = col(pivot_site) uc = reparametrisation.structure.unit_cell() theta = col(uc.orthogonalize(x_h[0] - x_p)).angle( col(uc.orthogonalize(x_h[1] - x_p))) angle_param = None if self.flapping: angle_param = reparametrisation.add(_.independent_scalar_parameter, value=theta, variable=True) else: if self.angle is not None: angle_param = reparametrisation.add( _.independent_scalar_parameter, value=self.angle, variable=False) else: angle_param = reparametrisation.add( _.angle_parameter, left=pivot_neighbour_site_params[0], center=pivot_site_param, right=pivot_neighbour_site_params[1], value=theta) return reparametrisation.add( _.secondary_xh2_sites, pivot=pivot_site_param, pivot_neighbour_0=pivot_neighbour_site_params[0], pivot_neighbour_1=pivot_neighbour_site_params[1], length=bond_length, h_c_h_angle=angle_param, hydrogen_0=hydrogens[0], hydrogen_1=hydrogens[1])
def add_to(self, reparametrisation): scatterers = reparametrisation.structure.scatterers() if not scatterers[self.ind_ref].flags.use_u_aniso() or\ not scatterers[self.ind_atom].flags.use_u_aniso(): raise InvalidConstraint( "only anisotropic atoms are allowed for shared rotated ADP") u_c = reparametrisation.add_new_thermal_displacement_parameter( self.ind_ref) angle = reparametrisation.add(_.independent_scalar_parameter, value=self.angle_value * pi / 180, variable=self.refine_angle) param = reparametrisation.add( _.shared_rotated_u_star, scatterer=scatterers[self.ind_atom], reference=u_c, direction=reparametrisation.find_direction(self.direction), angle=angle) reparametrisation.shared_Us[self.ind_atom] = u_c reparametrisation.asu_scatterer_parameters[self.ind_atom].u = param self.value = u_c self.angle = angle
def __init__(self, var_refs, var_minus_one_refs): if (len(var_refs) + len(var_minus_one_refs)) == 0: raise InvalidConstraint("at least one atom is expected") self.as_var = var_refs self.as_one_minus_var = var_minus_one_refs
def add_to(self, reparametrisation): if not self.fix_u and not self.fix_xyz: return scatterers = reparametrisation.structure.scatterers() ref_sites = [] ref_u_isos = [] ref_u_stars = [] ref_adps = [] src_crds = [] inv_src_crds = [] uc = reparametrisation.structure.unit_cell() for i in self.groups[0]: src_crds.append(uc.orthogonalize(scatterers[i].site)) if self.fix_xyz: ref_sites.append(reparametrisation.add_new_site_parameter(i)) if self.fix_u: if scatterers[i].flags.use_u_iso(): ref_u_isos.append( reparametrisation.add_new_thermal_displacement_parameter(i)) else: ref_u_stars.append( reparametrisation.add_new_thermal_displacement_parameter(i)) for g in self.groups[1:]: if len(g) != len(self.groups[0]): raise InvalidConstraint("Group size mismatch") g_scatterers = [] g_u_iso_scatterers =[] g_u_star_scatterers = [] crds = [] for idx, i in enumerate(g): if scatterers[i].flags.use_u_iso() !=\ scatterers[self.groups[0][idx]].flags.use_u_iso(): raise InvalidConstraint("Mixing isotropic and anisotropic parameters") g_scatterers.append(scatterers[i]) crds.append(uc.orthogonalize(scatterers[i].site)) if scatterers[i].flags.use_u_iso(): g_u_iso_scatterers.append(scatterers[i]) else: g_u_star_scatterers.append(scatterers[i]) #need to map reference to target lsf = superpose.least_squares_fit( flex.vec3_double(crds), flex.vec3_double(src_crds)) #create a list of inverted coordinates if needed if len(inv_src_crds) == 0: for i in range(0, len(g)): inv_src_crds.append( 2*matrix.col(lsf.other_shift)-matrix.col(src_crds[i])) rm = lsf.r t = matrix.col(lsf.reference_shift)-matrix.col(lsf.other_shift) new_crd = lsf.other_sites_best_fit() d = 0 for i, c in enumerate(new_crd): d += matrix.col(matrix.col(c)-matrix.col(crds[i])).length_sq() lsf = superpose.least_squares_fit( flex.vec3_double(crds), flex.vec3_double(inv_src_crds)) new_crd = lsf.other_sites_best_fit() d_inv = 0 for i, c in enumerate(new_crd): d_inv += matrix.col(matrix.col(c)-matrix.col(crds[i])).length_sq() if d_inv < d: rm = -lsf.r if self.fix_xyz: shifts_and_angles =\ reparametrisation.add(_.independent_small_6_vector_parameter, value=(t[0],t[1],t[2],0,0,0), variable=True) if len(ref_u_stars) > 0: u_star_param = reparametrisation.add( _.same_group_u_star, scatterers=g_u_star_scatterers, u_stars=ref_u_stars, alignment_matrix=rm, shifts_and_angles=shifts_and_angles ) elif len(ref_u_stars) > 0: angles =\ reparametrisation.add(_.independent_small_3_vector_parameter, value=self.angles, variable=True) u_star_param = reparametrisation.add( _.same_group_u_star, scatterers=g_u_star_scatterers, u_stars=ref_u_stars, alignment_matrix=rm, angles=angles ) if self.fix_xyz: site_param = reparametrisation.add( _.same_group_xyz, scatterers=g_scatterers, sites=ref_sites, alignment_matrix=rm, shifts_and_angles=shifts_and_angles ) if len(ref_u_isos) > 0: u_iso_param = reparametrisation.add( _.same_group_u_iso, scatterers=g_u_iso_scatterers, u_isos=ref_u_isos ) site_proxy_index = 0 u_star_proxy_index = 0 u_iso_proxy_index = 0 for i in g: if self.fix_xyz: reparametrisation.asu_scatterer_parameters[i].site = site_param reparametrisation.add_new_same_group_site_proxy_parameter( site_param, site_proxy_index, i) site_proxy_index += 1 if self.fix_u: if scatterers[i].flags.use_u_iso(): reparametrisation.asu_scatterer_parameters[i].u = u_iso_param reparametrisation.shared_Us[i] = reparametrisation.add( _.same_group_u_iso_proxy, parent=u_iso_param, index=u_iso_proxy_index ) u_iso_proxy_index += 1 else: reparametrisation.asu_scatterer_parameters[i].u = u_star_param reparametrisation.shared_Us[i] = reparametrisation.add( _.same_group_u_star_proxy, parent=u_star_param, index=u_star_proxy_index ) u_star_proxy_index += 1
def __init__(self, ind_sequence): if len(ind_sequence) < 2: raise InvalidConstraint("at least two atoms are expected") self.indices = ind_sequence