6 from collections
import defaultdict
17 """Take iterable of TempResidues and return compatified string"""
20 idxs = [r.get_index()
for r
in res]
23 cur_range = [idxs[0], idxs[0]]
25 if idx != cur_range[1]+1:
26 all_ranges.append(cur_range)
27 cur_range = [idx, idx]
29 all_ranges.append(cur_range)
31 for nr, r
in enumerate(all_ranges):
32 ret +=
'%i-%i' % (r[0], r[1])
33 if nr < len(all_ranges)-1:
38 def _select_ca_or_p(hiers, **kwargs):
39 """Select all CA (amino acids) or P (nucleic acids) as appropriate"""
41 ps = sel_p.get_selected_particles()
49 atom_type=_AT_HET_CA, **kwargs)
50 return sel.get_selected_particles()
53 def get_structure(model, pdb_fn, chain_id, res_range=None, offset=0,
54 model_num=
None, ca_only=
False):
55 """read a structure from a PDB file and return a list of residues
56 @param model The IMP model
57 @param pdb_fn The file to read (in traditional PDB or mmCIF format)
58 @param chain_id Chain ID to read
59 @param res_range Add only a specific set of residues.
60 res_range[0] is the starting and res_range[1] is the ending
62 The ending residue can be "END", that will take everything
63 to the end of the sequence.
65 @param offset Apply an offset to the residue indexes of the PDB file
66 @param model_num Read multi-model PDB and return that model (0-based index)
67 @param ca_only Read only CA atoms (by default, all non-waters are read)
70 if pdb_fn.endswith(
'.cif'):
71 read_file = IMP.atom.read_mmcif
72 read_multi_file = IMP.atom.read_multimodel_mmcif
74 read_file = IMP.atom.read_pdb
75 read_multi_file = IMP.atom.read_multimodel_pdb
81 reader = read_file
if model_num
is None else read_multi_file
83 if model_num
is not None:
86 if res_range == []
or res_range
is None:
87 ps = _select_ca_or_p(mh, chain=chain_id)
93 mh.get_children()[0].get_children()[-1]).
get_index()
94 ps = _select_ca_or_p(mh, chain=chain_id,
95 residue_indexes=range(start, end+1))
100 res.set_index(res.get_index() + offset)
104 "no residues selected from %s in range %s" % (pdb_fn, res_range),
109 def build_bead(model, residues, input_coord=None):
110 """Generates a single bead"""
118 if ds_frag[0] == ds_frag[-1]:
119 rt = residues[0].get_residue_type()
121 h.set_name(
'%i_bead' % (ds_frag[0]))
122 prt.set_name(
'%i_bead' % (ds_frag[0]))
129 ptem.set_radius(radius)
132 h.set_name(
'%i-%i_bead' % (ds_frag[0], ds_frag[-1]))
133 prt.set_name(
'%i-%i_bead' % (ds_frag[0], ds_frag[-1]))
134 h.set_residue_indexes(range(ds_frag[0], ds_frag[-1] + 1))
136 radius = 0.8 * (3.0 / 4.0 / pi * volume) ** (1.0 / 3.0)
137 ptem.set_radius(radius)
141 if tuple(input_coord)
is not None:
142 ptem.set_coordinates(input_coord)
148 def build_necklace(model, residues, resolution, input_coord=None):
149 """Generates a string of beads with given length"""
153 out_hiers.append(build_bead(model, chunk, input_coord=input_coord))
157 def build_ca_centers(model, residues):
158 """Create a bead on the CA position with coarsened size and mass"""
160 for tempres
in residues:
161 residue = tempres.get_hierarchy()
163 rp1.set_name(
"Residue_%i" % residue.get_index())
164 rt = residue.get_residue_type()
177 atom_types=[IMP.atom.AT_CA, _AT_HET_CA]).get_selected_particles()
179 residue, atom_type=IMP.atom.AT_P).get_selected_particles()
182 central_atom = calpha[0]
187 "build_ca_centers: weird selection (no CA, no "
188 "nucleotide P or ambiguous selection found)")
194 out_hiers.append(this_res)
198 def setup_bead_as_gaussian(mh):
199 """Setup bead as spherical gaussian, using radius as variance"""
200 p = mh.get_particle()
210 def show_representation(node):
214 resolutions = repr.get_resolutions()
215 for r
in resolutions:
216 print(
'---- resolution %i ----' % r)
223 def _get_color_for_representation(rep):
224 """Return an IMP.display.Color object (or None) for the given
226 if rep.color
is not None:
227 if isinstance(rep.color, float):
229 elif isinstance(rep.color, str):
231 elif hasattr(rep.color,
'__iter__')
and len(rep.color) == 3:
236 raise TypeError(
"Color must be Chimera color name, a hex "
237 "string, a float or (r,g,b) tuple")
240 def _add_fragment_provenance(fragment, first_residue, rephandler):
241 """Track the original source of a fragment's structure.
242 If the residues in the given fragment were extracted from a PDB
243 file, add suitable provenance information to the Model (the name
244 of that file, chain ID, and residue index offset)."""
245 pdb_element = rephandler.pdb_for_residue.get(first_residue.get_index())
247 m = fragment.get_model()
250 p, pdb_element.filename, pdb_element.chain_id, pdb_element.offset)
255 def build_representation(parent, rep, coord_finder, rephandler):
256 """Create requested representation.
257 For beads, identifies continuous segments and sets up as Representation.
258 If any volume-based representations (e.g.,densities) are requested,
259 will instead create a single Representation node.
260 All reps are added as children of the passed parent.
261 @param parent The Molecule to which we'll add representations
262 @param rep What to build. An instance of pmi::topology::_Representation
263 @param coord_finder A _FindCloseStructure object to help localize beads
268 model = parent.hier.get_model()
269 color = _get_color_for_representation(rep)
273 primary_resolution = min(rep.bead_resolutions)
280 if rep.density_residues_per_component:
282 num_components = (len(rep.residues)
283 // rep.density_residues_per_component+1)
284 rep_dict = defaultdict(list)
287 segp, primary_resolution)
288 built_reps.append(root_representation)
289 res_nums = [r.get_index()
for r
in rep.residues]
293 density_frag.get_particle().set_name(
294 "Densities %i" % rep.density_residues_per_component)
297 if os.path.exists(rep.density_prefix +
'.txt') \
298 and not rep.density_force_compute:
300 rep.density_prefix +
'.txt', density_ps, model)
301 if (len(density_ps) != num_components
302 or not os.path.exists(rep.density_prefix +
'.txt')
303 or rep.density_force_compute):
306 for r
in rep.residues:
318 mass_multiplier=total_mass)
321 rep.density_prefix +
'.txt')
322 if rep.density_voxel_size > 0.0:
324 density_ps, rep.density_prefix +
'.mrc',
325 rep.density_voxel_size, fast=
True)
327 for n, d
in enumerate(density_ps):
328 d.set_name(
'Density #%d' % n)
329 density_frag.add_child(d)
330 root_representation.add_representation(
331 density_frag, IMP.atom.DENSITIES,
332 rep.density_residues_per_component)
336 rsort = sorted(list(rep.residues), key=
lambda r: r.get_index())
338 prev_structure = rsort[0].get_has_structure()
341 for nr, r
in enumerate(rsort):
342 if (r.get_index() != prev_idx+1
343 or r.get_has_structure() != prev_structure
or force_break):
344 segments.append(cur_seg)
348 prev_idx = r.get_index()
349 prev_structure = r.get_has_structure()
350 if r.get_index()-1
in rep.bead_extra_breaks:
353 segments.append(cur_seg)
358 for frag_res
in segments:
359 res_nums = [r.get_index()
for r
in frag_res]
360 rrange =
"%i-%i" % (res_nums[0], res_nums[-1])
361 name =
"Frag_" + rrange
363 name_all += rrange +
','
364 elif name_count == 3:
371 segp, primary_resolution)
372 built_reps.append(this_representation)
373 for resolution
in rep.bead_resolutions:
376 this_resolution.set_name(
"%s: Res %i" % (name, resolution))
377 if frag_res[0].get_has_structure():
378 pdb_element = _add_fragment_provenance(
379 this_resolution, frag_res[0], rephandler)
380 if pdb_element
is not None:
381 prov_dict[resolution] = pdb_element
383 if resolution == atomic_res:
384 for residue
in frag_res:
385 this_resolution.add_child(residue.get_hierarchy())
386 elif resolution == ca_res
and rep.bead_ca_centers:
387 beads = build_ca_centers(model, frag_res)
389 this_resolution.add_child(bead)
393 for residue
in frag_res:
394 tempc.add_child(IMP.atom.create_clone(residue.hier))
397 for bead
in beads.get_children():
398 this_resolution.add_child(bead)
403 input_coord = coord_finder.find_nearest_coord(
404 min(r.get_index()
for r
in frag_res))
405 if input_coord
is None:
406 input_coord = rep.bead_default_coord
407 beads = build_necklace(model,
412 this_resolution.add_child(bead)
423 rep_dict[resolution] += this_resolution.get_children()
425 if resolution == primary_resolution:
426 this_representation.add_child(this_resolution)
428 this_representation.add_representation(this_resolution,
432 if rep.setup_particles_as_densities:
434 setup_bead_as_gaussian(p)
435 this_resolution.set_name(
436 this_resolution.get_name() +
' Densities %i' % resolution)
437 this_representation.add_representation(this_resolution,
442 root_representation.set_name(name_all.strip(
',') +
": Base")
443 d = root_representation.get_representations(IMP.atom.DENSITIES)
444 d[0].set_name(
'%s: ' % name_all + d[0].get_name())
445 for resolution
in rep.bead_resolutions:
448 [r.get_index()
for r
in rep.residues])
449 this_resolution.set_name(
"%s: Res %i" % (name_all, resolution))
453 if prov_dict.get(resolution):
454 pdb_element = prov_dict[resolution]
457 pdb_element.filename,
458 pdb_element.chain_id, pdb_element.offset)
460 for hier
in rep_dict[resolution]:
461 this_resolution.add_child(hier)
462 if resolution == primary_resolution:
463 root_representation.add_child(this_resolution)
465 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)
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.