1 from __future__
import print_function, division
7 from collections
import defaultdict
13 """Take iterable of TempResidues and return compatified string"""
16 idxs = [r.get_index()
for r
in res]
19 cur_range=[idxs[0],idxs[0]]
21 if idx!=cur_range[1]+1:
22 all_ranges.append(cur_range)
25 all_ranges.append(cur_range)
27 for nr,r
in enumerate(all_ranges):
28 ret+=
'%i-%i'%(r[0],r[1])
29 if nr<len(all_ranges)-1:
34 def _select_ca_or_p(hiers, **kwargs):
35 """Select all CA (amino acids) or P (nucleic acids) as appropriate"""
37 ps = sel_p.get_selected_particles()
43 return sel.get_selected_particles()
46 def get_structure(model,pdb_fn,chain_id,res_range=None,offset=0,model_num=None,ca_only=False):
47 """read a structure from a PDB file and return a list of residues
48 @param model The IMP model
49 @param pdb_fn The file to read (in traditional PDB or mmCIF format)
50 @param chain_id Chain ID to read
51 @param res_range Add only a specific set of residues.
52 res_range[0] is the starting and res_range[1] is the ending residue index
53 The ending residue can be "END", that will take everything to the end of the sequence.
55 @param offset Apply an offset to the residue indexes of the PDB file
56 @param model_num Read multi-model PDB and return that model
57 @param ca_only Read only CA atoms (by default, all non-waters are read)
61 read_file = IMP.atom.read_pdb
62 read_multi_file = IMP.atom.read_multimodel_pdb
63 if pdb_fn.endswith(
'.cif'):
64 read_file = IMP.atom.read_mmcif
65 read_multi_file = IMP.atom.read_multimodel_mmcif
69 mh = read_file(pdb_fn,model,
73 mhs = read_multi_file(pdb_fn,model,sel)
74 if model_num>=len(mhs):
75 raise Exception(
"you requested model num "+str(model_num)+\
76 " but the PDB file only contains "+str(len(mhs))+
" models")
79 if res_range==[]
or res_range
is None:
80 ps = _select_ca_or_p(mh, chain=chain_id)
86 ps = _select_ca_or_p(mh, chain=chain_id,
87 residue_indexes=range(start,end+1))
92 res.set_index(res.get_index() + offset)
96 "no residues selected from %s in range %s" % (pdb_fn, res_range),
100 def build_bead(model,residues,input_coord=None):
101 """Generates a single bead"""
109 if ds_frag[0] == ds_frag[-1]:
110 rt = residues[0].get_residue_type()
112 h.set_name(
'%i_bead' % (ds_frag[0]))
113 prt.set_name(
'%i_bead' % (ds_frag[0]))
120 ptem.set_radius(radius)
123 h.set_name(
'%i-%i_bead' % (ds_frag[0], ds_frag[-1]))
124 prt.set_name(
'%i-%i_bead' % (ds_frag[0], ds_frag[-1]))
125 h.set_residue_indexes(range(ds_frag[0], ds_frag[-1] + 1))
127 radius = 0.8 * (3.0 / 4.0 / pi * volume) ** (1.0 / 3.0)
128 ptem.set_radius(radius)
132 if tuple(input_coord)
is not None:
133 ptem.set_coordinates(input_coord)
138 def build_necklace(model,residues, resolution, input_coord=None):
139 """Generates a string of beads with given length"""
142 out_hiers.append(build_bead(model,chunk, input_coord=input_coord))
145 def build_ca_centers(model,residues):
146 """Create a bead on the CA position with coarsened size and mass"""
148 for tempres
in residues:
149 residue = tempres.get_hierarchy()
151 rp1.set_name(
"Residue_%i"%residue.get_index())
152 rt = residue.get_residue_type()
164 get_selected_particles()
166 get_selected_particles()
169 central_atom=calpha[0]
173 raise(
"build_ca_centers: weird selection (no Ca, no nucleotide P or ambiguous selection found)")
178 out_hiers.append(this_res)
181 def setup_bead_as_gaussian(mh):
182 """Setup bead as spherical gaussian, using radius as variance"""
183 p = mh.get_particle()
192 def show_representation(node):
196 resolutions = repr.get_resolutions()
197 for r
in resolutions:
198 print(
'---- resolution %i ----' %r)
204 def _get_color_for_representation(rep):
205 """Return an IMP.display.Color object (or None) for the given
207 if rep.color
is not None:
208 if isinstance(rep.color, float):
210 elif isinstance(rep.color, str):
212 elif hasattr(rep.color,
'__iter__')
and len(rep.color)==3:
217 raise TypeError(
"Color must be Chimera color name, a hex "
218 "string, a float or (r,g,b) tuple")
221 def _add_fragment_provenance(fragment, first_residue, rephandler):
222 """Track the original source of a fragment's structure.
223 If the residues in the given fragment were extracted from a PDB
224 file, add suitable provenance information to the Model (the name
225 of that file, chain ID, and residue index offset)."""
226 pdb_element = rephandler.pdb_for_residue.get(first_residue.get_index())
228 m = fragment.get_model()
231 p, pdb_element.filename, pdb_element.chain_id, pdb_element.offset)
235 def build_representation(parent, rep, coord_finder, rephandler):
236 """Create requested representation.
237 For beads, identifies continuous segments and sets up as Representation.
238 If any volume-based representations (e.g.,densities) are requested,
239 will instead create a single Representation node.
240 All reps are added as children of the passed parent.
241 @param parent The Molecule to which we'll add add representations
242 @param rep What to build. An instance of pmi::topology::_Representation
243 @param coord_finder A _FindCloseStructure object to help localize beads
248 model = parent.hier.get_model()
249 color = _get_color_for_representation(rep)
253 primary_resolution = min(rep.bead_resolutions)
258 if rep.density_residues_per_component:
260 num_components = len(rep.residues)//rep.density_residues_per_component+1
261 rep_dict = defaultdict(list)
265 built_reps.append(root_representation)
266 res_nums = [r.get_index()
for r
in rep.residues]
269 density_frag.get_particle().set_name(
"Densities %i"%rep.density_residues_per_component)
272 if os.path.exists(rep.density_prefix+
'.txt')
and not rep.density_force_compute:
276 if len(density_ps)!=num_components
or not os.path.exists(rep.density_prefix+
'.txt')
or rep.density_force_compute:
279 for r
in rep.residues:
291 mass_multiplier=total_mass)
294 if rep.density_voxel_size>0.0:
296 rep.density_voxel_size,fast=
True)
298 for n, d
in enumerate(density_ps):
299 d.set_name(
'Density #%d' % n)
300 density_frag.add_child(d)
301 root_representation.add_representation(density_frag,
303 rep.density_residues_per_component)
307 rsort = sorted(list(rep.residues),key=
lambda r:r.get_index())
309 prev_structure = rsort[0].get_has_structure()
312 for nr,r
in enumerate(rsort):
313 if r.get_index()!=prev_idx+1
or r.get_has_structure()!=prev_structure
or force_break:
314 segments.append(cur_seg)
318 prev_idx = r.get_index()
319 prev_structure = r.get_has_structure()
320 if r.get_index()-1
in rep.bead_extra_breaks:
323 segments.append(cur_seg)
328 for frag_res
in segments:
329 res_nums = [r.get_index()
for r
in frag_res]
330 rrange =
"%i-%i"%(res_nums[0],res_nums[-1])
331 name =
"Frag_"+rrange
333 name_all +=rrange+
','
341 built_reps.append(this_representation)
342 for resolution
in rep.bead_resolutions:
345 this_resolution.set_name(
"%s: Res %i"%(name,resolution))
346 if frag_res[0].get_has_structure():
347 _add_fragment_provenance(this_resolution, frag_res[0],
350 if resolution==atomic_res:
351 for residue
in frag_res:
352 this_resolution.add_child(residue.get_hierarchy())
353 elif resolution==ca_res
and rep.bead_ca_centers:
354 beads = build_ca_centers(model,frag_res)
356 this_resolution.add_child(bead)
359 for residue
in frag_res:
360 tempc.add_child(IMP.atom.create_clone(residue.hier))
362 for bead
in beads.get_children():
363 this_resolution.add_child(bead)
368 input_coord = coord_finder.find_nearest_coord(min(r.get_index()
for r
in frag_res))
369 if input_coord
is None:
370 input_coord = rep.bead_default_coord
371 beads = build_necklace(model,
376 this_resolution.add_child(bead)
386 rep_dict[resolution]+=this_resolution.get_children()
388 if resolution==primary_resolution:
389 this_representation.add_child(this_resolution)
391 this_representation.add_representation(this_resolution,
395 if rep.setup_particles_as_densities:
397 setup_bead_as_gaussian(p)
398 this_resolution.set_name(this_resolution.get_name()+
' Densities %i'%resolution)
399 this_representation.add_representation(this_resolution,
404 root_representation.set_name(name_all.strip(
',')+
": Base")
405 d = root_representation.get_representations(IMP.atom.DENSITIES)
406 d[0].set_name(
'%s: '%name_all + d[0].get_name())
407 for resolution
in rep.bead_resolutions:
410 [r.get_index()
for r
in rep.residues])
411 this_resolution.set_name(
"%s: Res %i"%(name_all,resolution))
412 for hier
in rep_dict[resolution]:
413 this_resolution.add_child(hier)
414 if resolution==primary_resolution:
415 root_representation.add_child(this_resolution)
417 root_representation.add_representation(this_resolution,
double get_volume_from_residue_type(ResidueType rt)
Return an estimate for the volume of a given residue.
static Gaussian setup_particle(Model *m, ParticleIndex pi)
void show_molecular_hierarchy(Hierarchy h)
Print out the molecular hierarchy.
static Fragment setup_particle(Model *m, ParticleIndex pi)
double get_mass(const Selection &s)
Get the total mass of a hierarchy, in Daltons.
static XYZR setup_particle(Model *m, ParticleIndex pi)
Select atoms which are selected by both selectors.
double get_mass(ResidueType c)
Get the mass from the residue type.
static StructureProvenance setup_particle(Model *m, ParticleIndex pi, std::string filename, std::string chain_id, int residue_offset)
Color get_rgb_color(double f)
Return the color for f from the RGB color map.
double get_mass_from_number_of_residues(unsigned int num_aa)
Estimate the mass of a protein from the number of amino acids.
double get_ball_radius_from_volume_3d(double volume)
Return the radius of a sphere with a given volume.
static Residue setup_particle(Model *m, ParticleIndex pi, ResidueType t, int index, int insertion_code)
static Representation setup_particle(Model *m, ParticleIndex pi)
GenericHierarchies get_leaves(Hierarchy mhd)
Get all the leaves of the bit of hierarchy.
Warning related to handling of structures.
A Gaussian distribution in 3D.
A decorator for a representation.
double get_volume_from_mass(double m, ProteinDensityReference ref=ALBER)
Estimate the volume of a protein from its mass.
Ints get_index(const ParticlesTemp &particles, const Subset &subset, const Subsets &excluded)
A decorator for a particle representing an atom.
static Mass setup_particle(Model *m, ParticleIndex pi, Float mass)
PDBSelector * get_default_pdb_selector()
A decorator for a particle with x,y,z coordinates.
static Colored setup_particle(Model *m, ParticleIndex pi, Color color)
A decorator for a residue.
static bool get_is_setup(const IMP::ParticleAdaptor &p)
Hierarchy create_simplified_along_backbone(Chain input, const IntRanges &residue_segments, bool keep_detailed=false)
Rotation3D get_identity_rotation_3d()
Return a rotation that does not do anything.
Class to handle individual particles of a Model object.
Select all CA ATOM records.
Python classes to represent, score, sample and analyze models.
Functionality for loading, creating, manipulating and scoring atomic structures.
void add_provenance(Model *m, ParticleIndex pi, Provenance p)
Add provenance to part of the model.
static Chain setup_particle(Model *m, ParticleIndex pi, std::string id)
An exception for an invalid value being passed to IMP.
Select hierarchy particles identified by the biological name.
Select all ATOM and HETATM records with the given chain ids.
A decorator for a particle with x,y,z coordinates and a radius.