def fixed_u_eq_adp_as_cif_loop(xray_structure, proxies): site_labels = xray_structure.scatterers().extract_labels() fmt = "%.4f" loop = model.loop(header=( "_restr_U_Ueq_atom_site_label_1", "_restr_U_Ueq_weight_param", "_restr_U_Ueq_target", "_restr_U_Ueq_diff" )) unit_cell = xray_structure.unit_cell() params = adp_restraints.adp_restraint_params( u_cart=xray_structure.scatterers().extract_u_cart(unit_cell), u_iso=xray_structure.scatterers().extract_u_iso(), use_u_aniso=xray_structure.use_u_aniso() ) for proxy in proxies: restraint = adp_restraints.fixed_u_eq_adp( params=params, proxy=proxy) for i, i_seq in enumerate(proxy.i_seqs): loop.add_row((site_labels[i_seq], fmt % math.sqrt(1/proxy.weight), fmt % proxy.u_eq_ideal, fmt % restraint.delta())) return loop
def distances_as_cif_loop(xray_structure, proxies): space_group_info = sgtbx.space_group_info(group=xray_structure.space_group()) unit_cell = xray_structure.unit_cell() sites_cart = xray_structure.sites_cart() site_labels = xray_structure.scatterers().extract_labels() fmt = "%.4f" loop = model.loop(header=( "_restr_distance_atom_site_label_1", "_restr_distance_atom_site_label_2", "_restr_distance_site_symmetry_2", "_restr_distance_target", "_restr_distance_target_weight_param", "_restr_distance_diff" )) for proxy in proxies: restraint = geometry_restraints.bond( unit_cell=unit_cell, sites_cart=sites_cart, proxy=proxy) i_seqs = proxy.i_seqs sym_op = proxy.rt_mx_ji if sym_op is None: sym_op = sgtbx.rt_mx() loop.add_row((site_labels[i_seqs[0]], site_labels[i_seqs[1]], space_group_info.cif_symmetry_code(sym_op), fmt % restraint.distance_ideal, fmt % math.sqrt(1/restraint.weight), fmt % restraint.delta)) return loop
def __init__(self, pair_asu_table, site_labels, sites_frac=None, sites_cart=None, covariance_matrix=None, cell_covariance_matrix=None, parameter_map=None, include_bonds_to_hydrogen=False, fixed_angles=None, conformer_indices=None, eps=2e-16): assert [sites_frac, sites_cart].count(None) == 1 fmt = "%.1f" asu_mappings = pair_asu_table.asu_mappings() space_group_info = sgtbx.space_group_info(group=asu_mappings.space_group()) unit_cell = asu_mappings.unit_cell() if sites_cart is not None: sites_frac = unit_cell.fractionalize(sites_cart) self.loop = model.loop(header=( "_geom_angle_atom_site_label_1", "_geom_angle_atom_site_label_2", "_geom_angle_atom_site_label_3", "_geom_angle", "_geom_angle_site_symmetry_1", "_geom_angle_site_symmetry_3" )) angles = crystal.calculate_angles( pair_asu_table, sites_frac, covariance_matrix=covariance_matrix, cell_covariance_matrix=cell_covariance_matrix, parameter_map=parameter_map, conformer_indices=conformer_indices) for a in angles: i_seq, j_seq, k_seq = a.i_seqs if (not include_bonds_to_hydrogen and (site_labels[i_seq].startswith('H') or site_labels[k_seq].startswith('H'))): continue sym_code_ji = space_group_info.cif_symmetry_code(a.rt_mx_ji) sym_code_ki = space_group_info.cif_symmetry_code(a.rt_mx_ki) if sym_code_ji == "1": sym_code_ji = "." if sym_code_ki == "1": sym_code_ki = "." if (a.variance is not None and a.variance > eps and not(fixed_angles is not None and ((i_seq, j_seq, k_seq) in fixed_angles or (k_seq, j_seq, i_seq) in fixed_angles))): angle = format_float_with_su(a.angle, math.sqrt(a.variance)) else: angle = fmt % a.angle self.loop.add_row((site_labels[i_seq], site_labels[j_seq], site_labels[k_seq], angle, sym_code_ji, sym_code_ki, )) self.angles = angles.angles self.variances = angles.variances
def __init__(self, crystal_symmetry, cell_covariance_matrix=None, format="coreCIF"): self.format = format.lower() assert self.format in ("corecif", "mmcif") if self.format == "mmcif": self.separator = '.' else: self.separator = '_' self.cif_block = model.block() cell_prefix = '_cell%s' % self.separator if crystal_symmetry.space_group() is not None: sym_loop = model.loop(data=OrderedDict(( ('_space_group_symop' + self.separator + 'id', range(1, len(crystal_symmetry.space_group()) + 1)), ('_space_group_symop' + self.separator + 'operation_xyz', [s.as_xyz() for s in crystal_symmetry.space_group()])))) self.cif_block.add_loop(sym_loop) sg_prefix = '_space_group%s' % self.separator sg_type = crystal_symmetry.space_group_info().type() sg = sg_type.group() self.cif_block[sg_prefix + 'crystal_system'] = sg.crystal_system().lower() self.cif_block[sg_prefix + 'IT_number'] = sg_type.number() self.cif_block[sg_prefix + 'name_H-M_alt'] = sg_type.lookup_symbol() self.cif_block[sg_prefix + 'name_Hall'] = sg_type.hall_symbol() sg_prefix = '_symmetry%s' % self.separator self.cif_block[sg_prefix + 'space_group_name_H-M'] = sg_type.lookup_symbol() self.cif_block[sg_prefix + 'space_group_name_Hall'] = sg_type.hall_symbol() self.cif_block[sg_prefix + 'Int_Tables_number'] = sg_type.number() if crystal_symmetry.unit_cell() is not None: uc = crystal_symmetry.unit_cell() params = list(uc.parameters()) volume = uc.volume() if cell_covariance_matrix is not None: diag = cell_covariance_matrix.matrix_packed_u_diagonal() for i in range(6): if diag[i] > 0: params[i] = format_float_with_su( params[i], math.sqrt(diag[i])) d_v_d_params = matrix.row(uc.d_volume_d_params()) vcv = matrix.sqr( cell_covariance_matrix.matrix_packed_u_as_symmetric()) var_v = (d_v_d_params * vcv).dot(d_v_d_params) volume = format_float_with_su(volume, math.sqrt(var_v)) a, b, c, alpha, beta, gamma = params self.cif_block[cell_prefix + 'length_a'] = a self.cif_block[cell_prefix + 'length_b'] = b self.cif_block[cell_prefix + 'length_c'] = c self.cif_block[cell_prefix + 'angle_alpha'] = alpha self.cif_block[cell_prefix + 'angle_beta'] = beta self.cif_block[cell_prefix + 'angle_gamma'] = gamma self.cif_block[cell_prefix + 'volume'] = volume
def bond_similarity_as_cif_loops(xray_structure, proxies): space_group_info = sgtbx.space_group_info(group=xray_structure.space_group()) unit_cell = xray_structure.unit_cell() sites_cart = xray_structure.sites_cart() site_labels = xray_structure.scatterers().extract_labels() fmt = "%.4f" loop = model.loop(header=( "_restr_equal_distance_atom_site_label_1", "_restr_equal_distance_atom_site_label_2", "_restr_equal_distance_site_symmetry_2", "_restr_equal_distance_class_id", )) class_loop = model.loop(header=( "_restr_equal_distance_class_class_id", "_restr_equal_distance_class_target_weight_param", "_restr_equal_distance_class_average", "_restr_equal_distance_class_esd", "_restr_equal_distance_class_diff_max", )) class_id = 0 for proxy in proxies: restraint = geometry_restraints.bond_similarity( unit_cell=unit_cell, sites_cart=sites_cart, proxy=proxy) class_id += 1 esd = math.sqrt(flex.sum(flex.pow2(restraint.deltas())) * (1./proxy.i_seqs.size())) class_loop.add_row((class_id, fmt % math.sqrt(1/proxy.weights[0]),# assume equal weights fmt % restraint.mean_distance(), fmt % esd, fmt % flex.max_absolute(restraint.deltas()))) for i in range(proxy.i_seqs.size()): i_seq, j_seq = proxy.i_seqs[i] if proxy.sym_ops is None: sym_op = sgtbx.rt_mx() else: sym_op = proxy.sym_ops[i] loop.add_row((site_labels[i_seq], site_labels[j_seq], space_group_info.cif_symmetry_code(sym_op), class_id)) return class_loop, loop
def isotropic_adp_as_cif_loop(xray_structure, proxies): site_labels = xray_structure.scatterers().extract_labels() fmt = "%.4f" loop = model.loop(header=( "_restr_U_iso_atom_site_label", "_restr_U_iso_weight_param", )) for proxy in proxies: loop.add_row((site_labels[proxy.i_seqs[0]], fmt % math.sqrt(1/proxy.weight))) return loop
def add_loop(self, header, columns): if self._current_save is not None: block = self._current_save else: block = self._current_block loop = model.loop() assert len(header) == len(columns) n_columns = len(columns) for i in range(n_columns): loop[header[i]] = columns[i] block.add_loop(loop)
def __init__(self, pair_asu_table, site_labels, sites_frac=None, sites_cart=None, covariance_matrix=None, cell_covariance_matrix=None, parameter_map=None, include_bonds_to_hydrogen=False, fixed_distances=None, eps=2e-16): assert [sites_frac, sites_cart].count(None) == 1 fmt = "%.4f" asu_mappings = pair_asu_table.asu_mappings() space_group_info = sgtbx.space_group_info(group=asu_mappings.space_group()) unit_cell = asu_mappings.unit_cell() if sites_cart is not None: sites_frac = unit_cell.fractionalize(sites_cart) self.loop = model.loop(header=( "_geom_bond_atom_site_label_1", "_geom_bond_atom_site_label_2", "_geom_bond_distance", "_geom_bond_site_symmetry_2" )) distances = crystal.calculate_distances( pair_asu_table, sites_frac, covariance_matrix=covariance_matrix, cell_covariance_matrix=cell_covariance_matrix, parameter_map=parameter_map) for d in distances: if (not include_bonds_to_hydrogen and (site_labels[d.i_seq].startswith('H') or site_labels[d.j_seq].startswith('H'))): continue if (d.variance is not None and d.variance > eps and not(fixed_distances is not None and ((d.i_seq, d.j_seq) in fixed_distances or (d.j_seq, d.i_seq) in fixed_distances))): distance = format_float_with_su(d.distance, math.sqrt(d.variance)) else: distance = fmt % d.distance sym_code = space_group_info.cif_symmetry_code(d.rt_mx_ji) if sym_code == "1": sym_code = "." self.loop.add_row((site_labels[d.i_seq], site_labels[d.j_seq], distance, sym_code)) self.distances = distances.distances self.variances = distances.variances self.pair_counts = distances.pair_counts
def adp_volume_similarity_as_cif_loops(xray_structure, proxies): site_labels = xray_structure.scatterers().extract_labels() fmt = "%.4e" loop = model.loop(header=( "_restr_U_volume_similar_atom_site_label_1", "_restr_U_volume_similar_diff", "_restr_U_volume_similar_class_id", )) class_loop = model.loop(header=( "_restr_U_volume_similar_class_class_id", "_restr_U_volume_similar_class_target_weight_param", "_restr_U_volume_similar_class_average", "_restr_U_volume_similar_class_esd", "_restr_U_volume_similar_class_diff_max", )) unit_cell = xray_structure.unit_cell() params = adp_restraints.adp_restraint_params( u_cart=xray_structure.scatterers().extract_u_cart(unit_cell), u_iso=xray_structure.scatterers().extract_u_iso(), use_u_aniso=xray_structure.use_u_aniso() ) class_id = 0 for proxy in proxies: restraint = adp_restraints.adp_volume_similarity( params=params, proxy=proxy) class_id += 1 class_loop.add_row((class_id, fmt % math.sqrt(1/proxy.weight), fmt % restraint.mean_u_volume, fmt % restraint.rms_deltas(), fmt % flex.max_absolute(restraint.deltas()))) for i, i_seq in enumerate(proxy.i_seqs): loop.add_row((site_labels[i_seq], fmt % restraint.deltas()[i], class_id)) return class_loop, loop
def dihedrals_as_cif_loop(xray_structure, proxies): space_group_info = sgtbx.space_group_info(group=xray_structure.space_group()) unit_cell = xray_structure.unit_cell() sites_cart = xray_structure.sites_cart() site_labels = xray_structure.scatterers().extract_labels() fmt = "%.4f" loop = model.loop(header=( "_restr_torsion_atom_site_label_1", "_restr_torsion_atom_site_label_2", "_restr_torsion_atom_site_label_3", "_restr_torsion_atom_site_label_4", "_restr_torsion_site_symmetry_1", "_restr_torsion_site_symmetry_2", "_restr_torsion_site_symmetry_3", "_restr_torsion_site_symmetry_4", "_restr_torsion_angle_target", "_restr_torsion_weight_param", "_restr_torsion_diff", )) unit_mxs = [sgtbx.rt_mx()]*4 for proxy in proxies: restraint = geometry_restraints.dihedral( unit_cell=unit_cell, sites_cart=sites_cart, proxy=proxy) sym_ops = proxy.sym_ops if sym_ops is None: sym_ops = unit_mxs i_seqs = proxy.i_seqs loop.add_row((site_labels[i_seqs[0]], site_labels[i_seqs[1]], site_labels[i_seqs[2]], site_labels[i_seqs[3]], space_group_info.cif_symmetry_code(sym_ops[0]), space_group_info.cif_symmetry_code(sym_ops[1]), space_group_info.cif_symmetry_code(sym_ops[2]), space_group_info.cif_symmetry_code(sym_ops[3]), fmt % restraint.angle_ideal, fmt % math.sqrt(1/restraint.weight), fmt % restraint.delta)) return loop
def rigid_bond_as_cif_loop(xray_structure, proxies): unit_cell = xray_structure.unit_cell() sites_cart = xray_structure.sites_cart() u_cart = xray_structure.scatterers().extract_u_cart(unit_cell) site_labels = xray_structure.scatterers().extract_labels() fmt = "%.4f" loop = model.loop(header=( "_restr_U_rigid_atom_site_label_1", "_restr_U_rigid_atom_site_label_2", "_restr_U_rigid_target_weight_param", "_restr_U_rigid_U_parallel", "_restr_U_rigid_diff", )) for proxy in proxies: restraint = adp_restraints.rigid_bond( adp_restraint_params(sites_cart=sites_cart, u_cart=u_cart), proxy=proxy) loop.add_row((site_labels[proxy.i_seqs[0]], site_labels[proxy.i_seqs[1]], fmt % math.sqrt(1/proxy.weight), fmt % (0.5*(restraint.z_12()+restraint.z_21())), fmt % restraint.delta_z())) return loop
def __init__(self, hbonds, pair_asu_table, site_labels, sites_frac=None, sites_cart=None, min_dha_angle=150, # degrees max_da_distance=2.9, # angstrom covariance_matrix=None, cell_covariance_matrix=None, parameter_map=None, eps=2e-16): assert [sites_frac, sites_cart].count(None) == 1 fmt_a = "%.1f" pair_asu_table = pair_asu_table asu_mappings = pair_asu_table.asu_mappings() space_group_info = sgtbx.space_group_info(group=asu_mappings.space_group()) self.unit_cell = asu_mappings.unit_cell() if sites_cart is not None: sites_frac = self.unit_cell.fractionalize(sites_cart) if sites_frac is not None: sites_cart = self.unit_cell.orthogonalize(sites_frac) if covariance_matrix is not None: assert parameter_map is not None self.covariance_matrix_cart = covariance.orthogonalize_covariance_matrix( covariance_matrix, self.unit_cell, parameter_map) else: self.covariance_matrix_cart = None self.cell_covariance_matrix = cell_covariance_matrix self.eps = eps self.parameter_map = parameter_map self.loop = model.loop(header=( "_geom_hbond_atom_site_label_D", "_geom_hbond_atom_site_label_H", "_geom_hbond_atom_site_label_A", "_geom_hbond_distance_DH", "_geom_hbond_distance_HA", "_geom_hbond_distance_DA", "_geom_hbond_angle_DHA", "_geom_hbond_site_symmetry_A", )) for hbond in hbonds: d_seq, a_seq = hbond.d_seq, hbond.a_seq site_cart_d = sites_cart[d_seq] if hbond.rt_mx is not None: site_frac_a = sites_frac[a_seq] site_frac_a = hbond.rt_mx * site_frac_a site_cart_a = self.unit_cell.orthogonalize(site_frac_a) else: site_cart_a = sites_cart[a_seq] distance_da = geometry.distance((site_cart_d, site_cart_a)) for h_seq, h_sym_groups in pair_asu_table.table()[hbond.d_seq].items(): if site_labels[h_seq][0] not in ('H','D'): # XXX better to pass scattering types instead? continue site_cart_h = sites_cart[h_seq] distance_dh = geometry.distance((site_cart_d, site_cart_h)) distance_ha = geometry.distance((site_cart_h, site_cart_a)) angle_dha = geometry.angle((site_cart_d, site_cart_h, site_cart_a)) if (angle_dha.angle_model < min_dha_angle or distance_da.distance_model > max_da_distance): continue if hbond.rt_mx is not None: sym_code = space_group_info.cif_symmetry_code(hbond.rt_mx) else: sym_code = '.' self.loop.add_row(( site_labels[d_seq], site_labels[h_seq], site_labels[a_seq], self.formatted_distance(d_seq, h_seq, distance_dh, unit_mx), self.formatted_distance(h_seq, a_seq, distance_ha, unit_mx), self.formatted_distance(d_seq, a_seq, distance_da, hbond.rt_mx), self.formatted_angle(d_seq, h_seq, a_seq, angle_dha, hbond.rt_mx), sym_code ))
def miller_indices_as_cif_loop(indices, prefix='_refln_'): refln_loop = model.loop(header=('%sindex_h' % prefix, '%sindex_k' % prefix, '%sindex_l' % prefix)) for hkl in indices: refln_loop.add_row(hkl) return refln_loop
def atom_type_cif_loop(xray_structure, format="coreCIF"): format = format.lower() assert format in ("corecif", "mmcif") if format == "mmcif": separator = '.' else: separator = '_' sources = { "it1992": "International Tables Volume C Table 6.1.1.4 (pp. 500-502)", "wk1995": "Waasmaier & Kirfel (1995), Acta Cryst. A51, 416-431", } inelastic_references = { "henke": "Henke, Gullikson and Davis, At. Data and Nucl. Data Tables, 1993, 54, 2", "sasaki": "Sasaki, KEK Report, 1989, 88-14, 1", } scattering_type_registry = xray_structure.scattering_type_registry() unique_gaussians = scattering_type_registry.unique_gaussians_as_list() max_n_gaussians = max( [gaussian.n_terms() for gaussian in unique_gaussians]) # _atom_type_* loop header = [ '_atom_type%ssymbol' % separator, '_atom_type%sscat_dispersion_real' % separator, '_atom_type%sscat_dispersion_imag' % separator ] header.extend([ '_atom_type%sscat_Cromer_Mann_a%i' % (separator, i + 1) for i in range(max_n_gaussians) ]) header.extend([ '_atom_type%sscat_Cromer_Mann_b%i' % (separator, i + 1) for i in range(max_n_gaussians) ]) header.extend([ '_atom_type%sscat_Cromer_Mann_c' % separator, '_atom_type%sscat_source' % separator, '_atom_type%sscat_dispersion_source' % separator ]) atom_type_loop = model.loop(header=header) gaussian_dict = scattering_type_registry.as_type_gaussian_dict() scattering_type_registry = xray_structure.scattering_type_registry() params = xray_structure.scattering_type_registry_params fp_fdp_table = {} for sc in xray_structure.scatterers(): fp_fdp_table.setdefault(sc.scattering_type, (sc.fp, sc.fdp)) disp_source = inelastic_references.get( xray_structure.inelastic_form_factors_source) # custom? if disp_source is None: disp_source = xray_structure.inelastic_form_factors_source if disp_source is None: disp_source = "." for atom_type, gaussian in scattering_type_registry.as_type_gaussian_dict( ).iteritems(): scat_source = sources.get(params.table) if params.custom_dict and atom_type in params.custom_dict: scat_source = "Custom %i-Gaussian" % gaussian.n_terms() elif scat_source is None: scat_source = """\ %i-Gaussian fit: Grosse-Kunstleve RW, Sauter NK, Adams PD: Newsletter of the IUCr Commission on Crystallographic Computing 2004, 3, 22-31.""" scat_source = scat_source % gaussian.n_terms() if disp_source == ".": fp, fdp = ".", "." else: fp, fdp = fp_fdp_table[atom_type] fp = "%.5f" % fp fdp = "%.5f" % fdp row = [atom_type, fp, fdp] #gaussian = gaussian_dict[sc.scattering_type] gaussian_a = ["%.5f" % a for a in gaussian.array_of_a()] gaussian_b = ["%.5f" % a for a in gaussian.array_of_b()] gaussian_a.extend(["."] * (max_n_gaussians - gaussian.n_terms())) gaussian_b.extend(["."] * (max_n_gaussians - gaussian.n_terms())) row.extend(gaussian_a + gaussian_b) row.extend([gaussian.c(), scat_source, disp_source]) atom_type_loop.add_row(row) return atom_type_loop
def __init__(self, xray_structure, covariance_matrix=None, cell_covariance_matrix=None): crystal_symmetry_as_cif_block.__init__( self, xray_structure.crystal_symmetry(), cell_covariance_matrix=cell_covariance_matrix) scatterers = xray_structure.scatterers() uc = xray_structure.unit_cell() if covariance_matrix is not None: param_map = xray_structure.parameter_map() covariance_diagonal = covariance_matrix.matrix_packed_u_diagonal() u_star_to_u_cif_linear_map_pow2 = flex.pow2( flex.double(uc.u_star_to_u_cif_linear_map())) u_star_to_u_iso_linear_form = matrix.row( uc.u_star_to_u_iso_linear_form()) fmt = "%.6f" # _atom_site_* loop atom_site_loop = model.loop( header=('_atom_site_label', '_atom_site_type_symbol', '_atom_site_fract_x', '_atom_site_fract_y', '_atom_site_fract_z', '_atom_site_U_iso_or_equiv', '_atom_site_adp_type', '_atom_site_occupancy')) for i_seq, sc in enumerate(scatterers): # site if covariance_matrix is not None and sc.flags.grad_site(): site = [] for i in range(3): idx = param_map[i_seq].site if idx > -1: var = covariance_diagonal[idx + i] else: var = 0 if var > 0: site.append( format_float_with_su(sc.site[i], math.sqrt(var))) else: site.append(fmt % sc.site[i]) else: site = [fmt % sc.site[i] for i in range(3)] # u_eq if (covariance_matrix is not None and (sc.flags.grad_u_iso() or sc.flags.grad_u_aniso())): if sc.flags.grad_u_iso(): u_iso_or_equiv = format_float_with_su( sc.u_iso, math.sqrt( covariance.variance_for_u_iso( i_seq, covariance_matrix, param_map))) else: cov = covariance.extract_covariance_matrix_for_u_aniso( i_seq, covariance_matrix, param_map).matrix_packed_u_as_symmetric() var = (u_star_to_u_iso_linear_form * matrix.sqr(cov)).dot(u_star_to_u_iso_linear_form) u_iso_or_equiv = format_float_with_su( sc.u_iso_or_equiv(uc), math.sqrt(var)) else: u_iso_or_equiv = fmt % sc.u_iso_or_equiv(uc) if sc.flags.use_u_aniso(): adp_type = 'Uani' else: adp_type = 'Uiso' atom_site_loop.add_row( (sc.label, sc.scattering_type, site[0], site[1], site[2], u_iso_or_equiv, adp_type, fmt % sc.occupancy)) self.cif_block.add_loop(atom_site_loop) # _atom_site_aniso_* loop aniso_scatterers = scatterers.select(scatterers.extract_use_u_aniso()) if aniso_scatterers.size(): labels = list(scatterers.extract_labels()) aniso_loop = model.loop( header=('_atom_site_aniso_label', '_atom_site_aniso_U_11', '_atom_site_aniso_U_22', '_atom_site_aniso_U_33', '_atom_site_aniso_U_12', '_atom_site_aniso_U_13', '_atom_site_aniso_U_23')) for sc in aniso_scatterers: u_cif = adptbx.u_star_as_u_cif(uc, sc.u_star) if covariance_matrix is not None: row = [sc.label] idx = param_map[labels.index(sc.label)].u_aniso if idx > -1: var = covariance_diagonal[ idx:idx + 6] * u_star_to_u_cif_linear_map_pow2 for i in range(6): if var[i] > 0: row.append( format_float_with_su( u_cif[i], math.sqrt(var[i]))) else: row.append(fmt % u_cif[i]) else: row = [sc.label] + [fmt % u_cif[i] for i in range(6)] else: row = [sc.label] + [fmt % u_cif[i] for i in range(6)] aniso_loop.add_row(row) self.cif_block.add_loop(aniso_loop) self.cif_block.add_loop(atom_type_cif_loop(xray_structure))