def main(): usage = """ python average_atom_positions.py file1.pdb file2.pdb ... """ num_args= 0 parser = OptionParser(usage=usage) #parser.add_option('-o', '--options', dest='some_option', default='yo', help="Place holder for a real option", type='str') #parser.add_option('-u', '--useless', dest='uselesss', default=False, action='store_true', help='Another useless option') parser.add_option('-a', '--all', dest='all_entries', default=False, action='store_true', help='Store all positions') (options, args) = parser.parse_args() if len(args) < num_args: parser.print_help() sys.exit(1) poss = c.defaultdict(list) sources = c.defaultdict(list) for i,arg in enumerate(args): cg = ftmc.from_pdb(arg) for d in cg.defines.keys(): origin, basis = ftug.element_coord_system(cg, d) if d[0] == 'i' or d[0] == 'm': conn = cg.connections(d) conn_type = cg.connection_type(d, conn) else: conn_type = 0 for i, r in it.izip(it.count(), cg.define_residue_num_iterator(d)): # add only the base atoms which are relevant to the calculation # of the chi torsion angle resname = cg.chain[r].resname.strip() atoms = ftup.nonsidechain_atoms + ftup.chi_torsion_atoms[resname][-2:] for aname in atoms: try: a = cg.chain[r][aname] except KeyError as ke: # missing an atom continue # The C1'->B1 and B1->B2 vectors define the plane of the base # The O4'->C1'->B1->B2 sequence defines the torsion # angle chi if aname == ftup.chi_torsion_atoms[resname][-2]: aname = 'B1' elif aname == ftup.chi_torsion_atoms[resname][-1]: aname = 'B2' avec = a.get_vector().get_array() atom_pos = ftuv.change_basis(avec - origin, basis, ftuv.standard_basis) identifier = "%s %s %d %d %s" % (d[0], " ".join(map(str, cg.get_node_dimensions(d))), conn_type, i, aname) poss[identifier] += [atom_pos] sources[identifier] += [d] print "import collections as co" if options.all_entries: print "all_atom_poss = dict()" for key in poss.keys(): print 'all_atom_poss["%s"] = [%s] #%d' % (key, ",".join(["[%s]" % (",".join(map(str, pos))) for pos in poss[key]]), len(poss[key])) else: print "avg_atom_poss = dict()" for key in poss.keys(): pos = np.mean(poss[key], axis=0) print 'avg_atom_poss["%s"] = [%s] #%d' % (key, ",".join(map(str, pos)), len(poss[key])) print "sources = dict()" for key in sources.keys(): print 'sources["%s"] = [%s]' % (key, ",".join(sources[key]))
def main(): usage = """ python average_atom_positions.py file1.pdb file2.pdb ... """ num_args= 0 parser = OptionParser(usage=usage) #parser.add_option('-o', '--options', dest='some_option', default='yo', help="Place holder for a real option", type='str') #parser.add_option('-u', '--useless', dest='uselesss', default=False, action='store_true', help='Another useless option') parser.add_option('-p', '--pseudoknots', dest='pseudoknots', default=False, action='store_true', help='Allow pseudoknots in the CG structure') (options, args) = parser.parse_args() if len(args) < num_args: parser.print_help() sys.exit(1) poss = c.defaultdict(list) sources = c.defaultdict(list) for i,arg in enumerate(args): cg = ftmc.from_pdb(arg, remove_pseudoknots=not options.pseudoknots) if len(list(cg.stem_iterator())) == 0: print >>sys.stderr, "skipping {}: no stems".format(arg) continue for d in cg.defines.keys(): if np.allclose(cg.coords[d][0], cg.coords[d][1]): print >>sys.stderr, "File {}: Degenerate coordinates for element: {}".format(i, d) continue origin, basis = ftug.element_coord_system(cg, d) if d[0] == 'i' or d[0] == 'm': conn = cg.connections(d) conn_type = cg.connection_type(d, conn) else: conn_type = 0 for i, r in it.izip(it.count(), cg.define_residue_num_iterator(d)): # add only the base atoms which are relevant to the calculation # of the chi torsion angle resname = cg.chain[cg.seq_ids[r-1]].resname.strip() if resname not in ftup.chi_torsion_atoms.keys(): print >>sys.stderr, "Unknown nucleotide name:", resname continue atoms = ftup.nonsidechain_atoms + ftup.chi_torsion_atoms[resname][-2:] scatoms=ftup.side_chain_atoms[resname] for aname in atoms+scatoms: try: a = cg.chain[cg.seq_ids[r-1]][aname] except KeyError as ke: # missing an atom continue # The C1'->B1 and B1->B2 vectors define the plane of the base # The O4'->C1'->B1->B2 sequence defines the torsion # angle chi if aname == ftup.chi_torsion_atoms[resname][-2]: aname = 'B1' elif aname == ftup.chi_torsion_atoms[resname][-1]: aname = 'B2' elif aname in scatoms: aname=resname+"."+aname avec = a.get_vector().get_array() atom_pos = ftuv.change_basis(avec - origin, basis, ftuv.standard_basis) identifier = "%s %s %d %d %s" % (d[0], " ".join(map(str, cg.get_node_dimensions(d))), conn_type, i, aname) poss[identifier] += [atom_pos] sources[identifier] += [d] print "{}:{}".format(identifier, ",".join(map(str, atom_pos)))
def main(parser): args = parser.parse_args() poss = c.defaultdict(list) sources = c.defaultdict(list) cgs = fuc.cgs_from_args(args, rna_type="pdb", enable_logging=True) for i, cg in enumerate(cgs): if len(list(cg.stem_iterator())) == 0: log.warning("Skipping RNA %s (%s): no stems", i, cg.pdb_name) continue for d in cg.defines.keys(): if np.allclose(cg.coords[d][0], cg.coords[d][1]): log.warning( "Skipping element %s of RNA %s (%s): degenerate coordinates.", d, i, cg.pdb_name) continue origin, basis = ftug.element_coord_system(cg, d) if d[0] == 'i' or d[0] == 'm': conn = cg.connections(d) conn_type = cg.connection_type(d, conn) else: conn_type = 0 for i, r in it.izip(it.count(), cg.define_residue_num_iterator(d)): # add only the base atoms which are relevant to the calculation # of the chi torsion angle seq_id = cg.seq_ids[r - 1] resname = cg.chains[seq_id.chain][seq_id.resid].resname.strip() if resname not in ftup.chi_torsion_atoms.keys(): print("Unknown nucleotide name:", resname, file=sys.stderr) continue atoms = ftup.nonsidechain_atoms + \ ftup.chi_torsion_atoms[resname][-2:] scatoms = ftup.side_chain_atoms[resname] for aname in atoms + scatoms: try: resid = cg.seq_ids[r - 1] a = cg.chains[resid.chain][resid.resid][aname] except KeyError as ke: # missing an atom continue # The C1'->B1 and B1->B2 vectors define the plane of the base # The O4'->C1'->B1->B2 sequence defines the torsion # angle chi if aname == ftup.chi_torsion_atoms[resname][-2]: aname = 'B1' elif aname == ftup.chi_torsion_atoms[resname][-1]: aname = 'B2' elif aname in scatoms: aname = resname + "." + aname avec = a.get_vector().get_array() atom_pos = ftuv.change_basis(avec - origin, basis, ftuv.standard_basis) identifier = "%s %s %d %d %s" % (d[0], " ".join( map(str, cg.get_node_dimensions(d))), conn_type, i, aname) poss[identifier] += [atom_pos] sources[identifier] += [d] print("{}:{}".format(identifier, ",".join(map(str, atom_pos))))
def add_cg(self, cg, labels, color_modifier=1.0): """ :param labels: A dictionary with element names as keys and labels as values. """ rna_plotter = PyMolRNA(cg.name, color_modifier) for key in cg.coords.keys(): if self.only_elements is not None: if key not in self.only_elements: continue (p, n) = cg.coords[key] color = self.get_element_color(key) if key[0] == 's': try: text = labels[key] except KeyError: text = key self.add_stem_like(rna_plotter, cg, text, key, color=color) if self.show_bounding_boxes: self.draw_bounding_boxes(rna_plotter, cg, key) else: if key[0] == 'h': if self.add_loops: try: text = labels[key] except KeyError: text = key + " " + str(cg.get_length(key)) rna_plotter.add_segment(p, n, color, self.cylinder_width, text, key=key) elif key[0] == 'm': twists = cg.get_twists(key) try: text = labels[key] except KeyError: # check if the multiloop is longer than one. If it's not, then # it has an empty define and its length will be 0 if len(cg.defines[key]) == 0: text = key + " 0" else: text = key + " " + \ str(cg.defines[key][1] - cg.defines[key][0] + 1) rna_plotter.add_segment(p, n, color, self.cylinder_width, text, key=key) elif key[0] in 'ft': try: text = labels[key] except KeyError: text = key + " " + \ str(cg.defines[key][1] - cg.defines[key][0] + 1) if self.visualize_three_and_five_prime: rna_plotter.add_segment(p, n, color, self.cylinder_width, text, key=key) elif key[0] == "i": try: text = labels[key] except KeyError: text = key rna_plotter.add_segment(p, n, color, self.cylinder_width, text, key=key) if self.display_virtual_residues: for i in range(1, cg.seq_length + 1): pos = cg.get_virtual_residue(i, True) if cg.get_node_from_residue_num(i)[0] == "s": c = "cyan" else: c = "magenta" rna_plotter.add_sphere(pos, c, 1.) if self.add_longrange: for key1 in cg.longrange.keys(): for key2 in cg.longrange[key1]: if self.only_elements is not None: if key1 not in self.only_elements or key2 not in self.only_elements: continue try: p = cuv.line_segment_distance(cg.coords[key1][0], cg.coords[key1][1], cg.coords[key2][0], cg.coords[key2][1]) rna_plotter.add_dashed(p[0], p[1]) except: continue if self.encompassing_stems: self.add_encompassing_cylinders(rna_plotter, cg, 7.) if self.max_stem_distances > 0: for (s1, s2) in it.permutations(cg.stem_iterator(), r=2): (i1, i2) = cuv.line_segment_distance(cg.coords[s1][0], cg.coords[s1][1], cg.coords[s2][0], cg.coords[s2][1]) if cuv.magnitude(i2 - i1) < self.max_stem_distances: #self.add_segment(i1, i2, 'cyan', 0.3, s1 + " " + s2, key=key) rna_plotter.add_segment(i1, i2, 'cyan', 0.3, key=key) if self.virtual_atoms or self.sidechain_atoms: cg.add_all_virtual_residues() va = ftug.virtual_atoms(cg, sidechain=self.sidechain_atoms) atom_width = 0.5 for i, r in enumerate(sorted(va.keys())): for a in va[r].keys(): if self.rainbow: import matplotlib matplotlib.use('Agg') import matplotlib.pyplot as plt cmap = plt.get_cmap('gist_rainbow') rna_plotter.add_sphere(va[r][a], color=cmap( i / float(len(va.keys()))), width=atom_width) else: d = cg.get_node_from_residue_num(r) if d[0] == 's': if a in ftup.nonsidechain_atoms: rna_plotter.add_sphere(va[r][a], self.stem_color, width=atom_width) else: rna_plotter.add_sphere(va[r][a], 'forest', width=atom_width) elif d[0] == 'i': rna_plotter.add_sphere(va[r][a], 'yellow', width=atom_width) elif d[0] == 'm': rna_plotter.add_sphere(va[r][a], self.multiloop_color, width=atom_width) elif d[0] == 'h': rna_plotter.add_sphere(va[r][a], 'blue', width=atom_width) if self.basis: for d in cg.defines.keys(): origin, basis = ftug.element_coord_system(cg, d) rna_plotter.add_segment(origin, origin + 7. * basis[1], 'purple', 0.5, key=key) self.plotters.append(rna_plotter)
def coordinates_to_pymol(self, cg): loops = list(cg.hloop_iterator()) for key in cg.coords.keys(): if self.constraints is not None: if key not in self.constraints: continue (p, n) = cg.coords[key] color = self.get_element_color(key) if key[0] == 's': self.add_stem_like(cg, key) self.draw_bounding_boxes(cg, key) else: if key[0] == 'h': if self.add_loops: if key in loops: self.add_segment(p, n, color, 1.0, key + " " + str(cg.get_length(key))) elif key[0] == 'm': twists = cg.get_twists(key) # check if the multiloop is longer than one. If it's not, then # it has an empty define and we its length will be 1 if len(cg.defines[key]) == 0: self.add_segment(p, n, color, 1.0, key + " 1") else: self.add_segment(p, n, color, 1.0, key + " " + str(cg.defines[key][1] - cg.defines[key][0] + 1)) self.add_segment(p, p+ 7 * twists[0], 'light gray', 0.3) self.add_segment(n, n+ 7 * twists[1], 'light gray', 0.3) x = (p + n) / 2 t = ftuv.normalize((twists[0] + twists[1]) / 2.) self.add_segment(x, x + 7 * t, 'middle gray', 0.3) elif key[0] == 'f': if self.visualize_three_and_five_prime: self.add_segment(p, n, color, 1.0, key + " " + str(cg.defines[key][1] - cg.defines[key][0] + 1) + "") elif key[0] == 't': if self.visualize_three_and_five_prime: self.add_segment(p, n, color, 1.0, key + " " + str(cg.defines[key][1] - cg.defines[key][0]) + "") else: #self.add_stem_like(cg, key, "yellow", 1.0) self.add_segment(p, n, color, 1.0, key) if self.add_longrange: for key1 in cg.longrange.keys(): for key2 in cg.longrange[key1]: try: p = cuv.line_segment_distance(cg.coords[key1][0], cg.coords[key1][1], cg.coords[key2][0], cg.coords[key2][1]) (point1, point2) = p #point1 = cg.get_point(key1) #point2 = cg.get_point(key2) dash_length = 0.6 gap_length = dash_length * 2 direction = ftuv.normalize(point2 - point1) num_dashes = ftuv.magnitude(point2 - point1) / (dash_length + gap_length) fud.pv('num_dashes') for i in range(int(num_dashes)): self.add_segment(point1 + i * (dash_length + gap_length) * direction, point1 + (i * (dash_length + gap_length) + dash_length) * direction, "purple", 0.3, "") ''' self.add_segment(point1, point2, "purple", 0.3, key1 + " " + key2) ''' except: continue if self.encompassing_stems: self.add_encompassing_cylinders(cg, 7.) if self.max_stem_distances > 0: for (s1, s2) in it.permutations(cg.stem_iterator(), r=2): (i1, i2) = cuv.line_segment_distance(cg.coords[s1][0], cg.coords[s1][1], cg.coords[s2][0], cg.coords[s2][1]) if cuv.magnitude(i2 - i1) < self.max_stem_distances: #self.add_segment(i1, i2, 'cyan', 0.3, s1 + " " + s2) self.add_segment(i1, i2, 'cyan', 0.3) if self.virtual_atoms: va = ftug.virtual_atoms(cg, sidechain=False) atom_width = 0.5 for i,r in enumerate(sorted(va.keys())): for a in va[r].keys(): if self.rainbow: import matplotlib matplotlib.use('Agg') import matplotlib.pyplot as plt cmap = plt.get_cmap('gist_rainbow') self.add_sphere(va[r][a], color_rgb = cmap(i / float(len(va.keys()))), width=atom_width) else: d = cg.get_node_from_residue_num(r) if d[0] == 's': self.add_sphere(va[r][a], 'green', width=atom_width) elif d[0] == 'i': self.add_sphere(va[r][a], 'yellow', width=atom_width) elif d[0] == 'm': self.add_sphere(va[r][a], 'red', width=atom_width) elif d[0] == 'h': self.add_sphere(va[r][a], 'blue', width=atom_width) if self.basis: for d in cg.defines.keys(): origin, basis = ftug.element_coord_system(cg, d) self.add_segment(origin, origin + 7. * basis[1], 'purple', 2.) print >>sys.stderr, "energy_function:", self.energy_function # print the contributions of the energy function, if one is specified if self.energy_function is not None: print >>sys.stderr, "key" sum_energy = 0. e_func = self.energy_function e_func_iter = e_func.interaction_energy_iter(cg, background=False) int_energies = list(e_func_iter) max_energy = max(int_energies, key=lambda x: x[1]) print >>sys.stderr, "max_energy:", max_energy for (interaction, energy) in int_energies: (p, n) = (cg.get_point(interaction[0]), cg.get_point(interaction[1])) scaled_energy = - max_energy[1] + energy self.add_segment(p, n, 'purple', 3 * np.exp(scaled_energy)) sum_energy += energy if self.stem_stem_orientations is not None: for (s1, s2) in it.permutations(cg.stem_iterator(), 2): ''' if cg.are_adjacent_stems(s1, s2): continue ''' if s1 != 's65': if s2 != 's65': continue s1_vec = cg.coords[s1][1] - cg.coords[s1][0] s2_vec = cg.coords[s2][1] - cg.coords[s2][0] (i1, i2) = cuv.line_segment_distance(cg.coords[s1][0], cg.coords[s1][1], cg.coords[s2][0], cg.coords[s2][1]) i_vec = i2 - i1 #i_rej will be orthogonal to s1_vec in the direction #of s2 i_rej = cuv.vector_rejection(i_vec, s1_vec) #plane_vec will be orthogonal to s1_vec and to the direction # of s2 plane_vec = np.cross(i_rej, s1_vec) # s2_proj is in the intersection plane s2_proj_in = cuv.vector_rejection(s2_vec, plane_vec) # s2 proj_out is out of the intersection plane #s2_proj_out = cuv.vector_rejection(s2_vec, i_rej) start_point = cg.coords[s1][0] + 5 * cg.twists[s1][0] ortho_offset = cuv.magnitude(i_rej) dist = cuv.magnitude(i_vec) + 0.0001 lateral_offset = m.sqrt(dist ** 2 - ortho_offset ** 2) if lateral_offset > 10: continue ''' #self.add_segment(start_point, start_point + 10 * cuv.normalize(s2_vec), 'white', 0.5) #self.add_segment(start_point, start_point + 5 * cuv.normalize(plane_vec), 'magenta', 0.5) #self.add_segment(start_point, start_point + 5 * cuv.normalize(i_vec), 'cyan', 0.5) #self.add_segment(i1, i1 + i_rej, 'cyan', 0.5) ''' self.add_segment(start_point, start_point + 7 * cuv.normalize(s2_proj_in), 'white', 1.5) '''
def add_cg(self, cg, labels, color_modifier=1.0): """ :param labels: A dictionary with element names as keys and labels as values. """ rna_plotter = PyMolRNA(cg.name, color_modifier) for key in cg.coords.keys(): if self.only_elements is not None: if key not in self.only_elements: continue (p, n) = cg.coords[key] color = self.get_element_color(key) if key[0] == 's': try: text = labels[key] except KeyError: text = key self.add_stem_like(rna_plotter, cg, text, key, color=color) if self.show_bounding_boxes: self.draw_bounding_boxes(rna_plotter, cg, key) else: if key[0] == 'h': if self.add_loops: try: text = labels[key] except KeyError: text = key + " " + str(cg.get_length(key)) rna_plotter.add_segment(p, n, color, self.cylinder_width, text, key=key) elif key[0] == 'm': twists = cg.get_twists(key) try: text = labels[key] except KeyError: # check if the multiloop is longer than one. If it's not, then # it has an empty define and its length will be 0 if len(cg.defines[key]) == 0: text = key + " 0" else: text = key + " " + \ str(cg.defines[key][1] - cg.defines[key][0] + 1) rna_plotter.add_segment(p, n, color, self.cylinder_width, text, key=key) elif key[0] in 'ft': try: text = labels[key] except KeyError: text = key + " " + \ str(cg.defines[key][1] - cg.defines[key][0] + 1) if self.visualize_three_and_five_prime: rna_plotter.add_segment(p, n, color, self.cylinder_width, text, key=key) elif key[0] == "i": try: text = labels[key] except KeyError: text = key rna_plotter.add_segment( p, n, color, self.cylinder_width, text, key=key) if self.display_virtual_residues: for i in range(1, cg.seq_length + 1): pos = cg.get_virtual_residue(i, True) if cg.get_node_from_residue_num(i)[0] == "s": c = "cyan" else: c = "magenta" rna_plotter.add_sphere(pos, c, 1.) if self.add_longrange: for key1 in cg.longrange.keys(): for key2 in cg.longrange[key1]: if self.only_elements is not None: if key1 not in self.only_elements or key2 not in self.only_elements: continue try: p = cuv.line_segment_distance(cg.coords[key1][0], cg.coords[key1][1], cg.coords[key2][0], cg.coords[key2][1]) rna_plotter.add_dashed(p[0], p[1]) except: continue if self.encompassing_stems: self.add_encompassing_cylinders(rna_plotter, cg, 7.) if self.max_stem_distances > 0: for (s1, s2) in it.permutations(cg.stem_iterator(), r=2): (i1, i2) = cuv.line_segment_distance(cg.coords[s1][0], cg.coords[s1][1], cg.coords[s2][0], cg.coords[s2][1]) if cuv.magnitude(i2 - i1) < self.max_stem_distances: #self.add_segment(i1, i2, 'cyan', 0.3, s1 + " " + s2, key=key) rna_plotter.add_segment(i1, i2, 'cyan', 0.3, key=key) if self.virtual_atoms or self.sidechain_atoms: cg.add_all_virtual_residues() va = ftug.virtual_atoms(cg, sidechain=self.sidechain_atoms) atom_width = 0.5 for i, r in enumerate(sorted(va.keys())): for a in va[r].keys(): if self.rainbow: import matplotlib matplotlib.use('Agg') import matplotlib.pyplot as plt cmap = plt.get_cmap('gist_rainbow') rna_plotter.add_sphere(va[r][a], color=cmap( i / float(len(va.keys()))), width=atom_width) else: d = cg.get_node_from_residue_num(r) if d[0] == 's': if a in ftup.nonsidechain_atoms: rna_plotter.add_sphere( va[r][a], self.stem_color, width=atom_width) else: rna_plotter.add_sphere( va[r][a], 'forest', width=atom_width) elif d[0] == 'i': rna_plotter.add_sphere( va[r][a], 'yellow', width=atom_width) elif d[0] == 'm': rna_plotter.add_sphere( va[r][a], self.multiloop_color, width=atom_width) elif d[0] == 'h': rna_plotter.add_sphere( va[r][a], 'blue', width=atom_width) if self.basis: for d in cg.defines.keys(): origin, basis = ftug.element_coord_system(cg, d) rna_plotter.add_segment( origin, origin + 7. * basis[1], 'purple', 0.5, key=key) self.plotters.append(rna_plotter)
def main(): usage = """ python average_atom_positions.py file1.pdb file2.pdb ... """ num_args = 0 parser = OptionParser(usage=usage) #parser.add_option('-o', '--options', dest='some_option', default='yo', help="Place holder for a real option", type='str') #parser.add_option('-u', '--useless', dest='uselesss', default=False, action='store_true', help='Another useless option') parser.add_option('-p', '--pseudoknots', dest='pseudoknots', default=False, action='store_true', help='Allow pseudoknots in the CG structure') (options, args) = parser.parse_args() if len(args) < num_args: parser.print_help() sys.exit(1) poss = c.defaultdict(list) sources = c.defaultdict(list) for i, arg in enumerate(args): cg = ftmc.from_pdb(arg, remove_pseudoknots=not options.pseudoknots) if len(list(cg.stem_iterator())) == 0: print >> sys.stderr, "skipping {}: no stems".format(arg) continue for d in cg.defines.keys(): if np.allclose(cg.coords[d][0], cg.coords[d][1]): print >> sys.stderr, "File {}: Degenerate coordinates for element: {}".format( i, d) continue origin, basis = ftug.element_coord_system(cg, d) if d[0] == 'i' or d[0] == 'm': conn = cg.connections(d) conn_type = cg.connection_type(d, conn) else: conn_type = 0 for i, r in it.izip(it.count(), cg.define_residue_num_iterator(d)): # add only the base atoms which are relevant to the calculation # of the chi torsion angle resname = cg.chain[cg.seq_ids[r - 1]].resname.strip() if resname not in ftup.chi_torsion_atoms.keys(): print >> sys.stderr, "Unknown nucleotide name:", resname continue atoms = ftup.nonsidechain_atoms + ftup.chi_torsion_atoms[ resname][-2:] scatoms = ftup.side_chain_atoms[resname] for aname in atoms + scatoms: try: a = cg.chain[cg.seq_ids[r - 1]][aname] except KeyError as ke: # missing an atom continue # The C1'->B1 and B1->B2 vectors define the plane of the base # The O4'->C1'->B1->B2 sequence defines the torsion # angle chi if aname == ftup.chi_torsion_atoms[resname][-2]: aname = 'B1' elif aname == ftup.chi_torsion_atoms[resname][-1]: aname = 'B2' elif aname in scatoms: aname = resname + "." + aname avec = a.get_vector().get_array() atom_pos = ftuv.change_basis(avec - origin, basis, ftuv.standard_basis) identifier = "%s %s %d %d %s" % (d[0], " ".join( map(str, cg.get_node_dimensions(d))), conn_type, i, aname) poss[identifier] += [atom_pos] sources[identifier] += [d] print "{}:{}".format(identifier, ",".join(map(str, atom_pos)))