1 from __future__
import print_function, division
7 from collections
import defaultdict
18 """Take iterable of TempResidues and return compatified string"""
21 idxs = [r.get_index()
for r
in res]
24 cur_range = [idxs[0], idxs[0]]
26 if idx != cur_range[1]+1:
27 all_ranges.append(cur_range)
28 cur_range = [idx, idx]
30 all_ranges.append(cur_range)
32 for nr, r
in enumerate(all_ranges):
33 ret +=
'%i-%i' % (r[0], r[1])
34 if nr < len(all_ranges)-1:
39 def _select_ca_or_p(hiers, **kwargs):
40 """Select all CA (amino acids) or P (nucleic acids) as appropriate"""
42 ps = sel_p.get_selected_particles()
50 atom_type=_AT_HET_CA, **kwargs)
51 return sel.get_selected_particles()
54 def get_structure(model, pdb_fn, chain_id, res_range=None, offset=0,
55 model_num=
None, ca_only=
False):
56 """read a structure from a PDB file and return a list of residues
57 @param model The IMP model
58 @param pdb_fn The file to read (in traditional PDB or mmCIF format)
59 @param chain_id Chain ID to read
60 @param res_range Add only a specific set of residues.
61 res_range[0] is the starting and res_range[1] is the ending
63 The ending residue can be "END", that will take everything
64 to the end of the sequence.
66 @param offset Apply an offset to the residue indexes of the PDB file
67 @param model_num Read multi-model PDB and return that model (0-based index)
68 @param ca_only Read only CA atoms (by default, all non-waters are read)
71 if pdb_fn.endswith(
'.cif'):
72 read_file = IMP.atom.read_mmcif
73 read_multi_file = IMP.atom.read_multimodel_mmcif
75 read_file = IMP.atom.read_pdb
76 read_multi_file = IMP.atom.read_multimodel_pdb
82 reader = read_file
if model_num
is None else read_multi_file
84 if model_num
is not None:
87 if res_range == []
or res_range
is None:
88 ps = _select_ca_or_p(mh, chain=chain_id)
94 mh.get_children()[0].get_children()[-1]).
get_index()
95 ps = _select_ca_or_p(mh, chain=chain_id,
96 residue_indexes=range(start, end+1))
101 res.set_index(res.get_index() + offset)
105 "no residues selected from %s in range %s" % (pdb_fn, res_range),
110 def build_bead(model, residues, input_coord=None):
111 """Generates a single bead"""
119 if ds_frag[0] == ds_frag[-1]:
120 rt = residues[0].get_residue_type()
122 h.set_name(
'%i_bead' % (ds_frag[0]))
123 prt.set_name(
'%i_bead' % (ds_frag[0]))
130 ptem.set_radius(radius)
133 h.set_name(
'%i-%i_bead' % (ds_frag[0], ds_frag[-1]))
134 prt.set_name(
'%i-%i_bead' % (ds_frag[0], ds_frag[-1]))
135 h.set_residue_indexes(range(ds_frag[0], ds_frag[-1] + 1))
137 radius = 0.8 * (3.0 / 4.0 / pi * volume) ** (1.0 / 3.0)
138 ptem.set_radius(radius)
142 if tuple(input_coord)
is not None:
143 ptem.set_coordinates(input_coord)
149 def build_necklace(model, residues, resolution, input_coord=None):
150 """Generates a string of beads with given length"""
154 out_hiers.append(build_bead(model, chunk, input_coord=input_coord))
158 def build_ca_centers(model, residues):
159 """Create a bead on the CA position with coarsened size and mass"""
161 for tempres
in residues:
162 residue = tempres.get_hierarchy()
164 rp1.set_name(
"Residue_%i" % residue.get_index())
165 rt = residue.get_residue_type()
178 atom_types=[IMP.atom.AT_CA, _AT_HET_CA]).get_selected_particles()
180 residue, atom_type=IMP.atom.AT_P).get_selected_particles()
183 central_atom = calpha[0]
188 "build_ca_centers: weird selection (no CA, no "
189 "nucleotide P or ambiguous selection found)")
195 out_hiers.append(this_res)
199 def setup_bead_as_gaussian(mh):
200 """Setup bead as spherical gaussian, using radius as variance"""
201 p = mh.get_particle()
211 def show_representation(node):
215 resolutions = repr.get_resolutions()
216 for r
in resolutions:
217 print(
'---- resolution %i ----' % r)
224 def _get_color_for_representation(rep):
225 """Return an IMP.display.Color object (or None) for the given
227 if rep.color
is not None:
228 if isinstance(rep.color, float):
230 elif isinstance(rep.color, str):
232 elif hasattr(rep.color,
'__iter__')
and len(rep.color) == 3:
237 raise TypeError(
"Color must be Chimera color name, a hex "
238 "string, a float or (r,g,b) tuple")
241 def _add_fragment_provenance(fragment, first_residue, rephandler):
242 """Track the original source of a fragment's structure.
243 If the residues in the given fragment were extracted from a PDB
244 file, add suitable provenance information to the Model (the name
245 of that file, chain ID, and residue index offset)."""
246 pdb_element = rephandler.pdb_for_residue.get(first_residue.get_index())
248 m = fragment.get_model()
251 p, pdb_element.filename, pdb_element.chain_id, pdb_element.offset)
256 def build_representation(parent, rep, coord_finder, rephandler):
257 """Create requested representation.
258 For beads, identifies continuous segments and sets up as Representation.
259 If any volume-based representations (e.g.,densities) are requested,
260 will instead create a single Representation node.
261 All reps are added as children of the passed parent.
262 @param parent The Molecule to which we'll add representations
263 @param rep What to build. An instance of pmi::topology::_Representation
264 @param coord_finder A _FindCloseStructure object to help localize beads
269 model = parent.hier.get_model()
270 color = _get_color_for_representation(rep)
274 primary_resolution = min(rep.bead_resolutions)
281 if rep.density_residues_per_component:
283 num_components = (len(rep.residues)
284 // rep.density_residues_per_component+1)
285 rep_dict = defaultdict(list)
288 segp, primary_resolution)
289 built_reps.append(root_representation)
290 res_nums = [r.get_index()
for r
in rep.residues]
294 density_frag.get_particle().set_name(
295 "Densities %i" % rep.density_residues_per_component)
298 if os.path.exists(rep.density_prefix +
'.txt') \
299 and not rep.density_force_compute:
301 rep.density_prefix +
'.txt', density_ps, model)
302 if (len(density_ps) != num_components
303 or not os.path.exists(rep.density_prefix +
'.txt')
304 or rep.density_force_compute):
307 for r
in rep.residues:
319 mass_multiplier=total_mass)
322 rep.density_prefix +
'.txt')
323 if rep.density_voxel_size > 0.0:
325 density_ps, rep.density_prefix +
'.mrc',
326 rep.density_voxel_size, fast=
True)
328 for n, d
in enumerate(density_ps):
329 d.set_name(
'Density #%d' % n)
330 density_frag.add_child(d)
331 root_representation.add_representation(
332 density_frag, IMP.atom.DENSITIES,
333 rep.density_residues_per_component)
337 rsort = sorted(list(rep.residues), key=
lambda r: r.get_index())
339 prev_structure = rsort[0].get_has_structure()
342 for nr, r
in enumerate(rsort):
343 if (r.get_index() != prev_idx+1
344 or r.get_has_structure() != prev_structure
or force_break):
345 segments.append(cur_seg)
349 prev_idx = r.get_index()
350 prev_structure = r.get_has_structure()
351 if r.get_index()-1
in rep.bead_extra_breaks:
354 segments.append(cur_seg)
359 for frag_res
in segments:
360 res_nums = [r.get_index()
for r
in frag_res]
361 rrange =
"%i-%i" % (res_nums[0], res_nums[-1])
362 name =
"Frag_" + rrange
364 name_all += rrange +
','
365 elif name_count == 3:
372 segp, primary_resolution)
373 built_reps.append(this_representation)
374 for resolution
in rep.bead_resolutions:
377 this_resolution.set_name(
"%s: Res %i" % (name, resolution))
378 if frag_res[0].get_has_structure():
379 pdb_element = _add_fragment_provenance(
380 this_resolution, frag_res[0], rephandler)
381 if pdb_element
is not None:
382 prov_dict[resolution] = pdb_element
384 if resolution == atomic_res:
385 for residue
in frag_res:
386 this_resolution.add_child(residue.get_hierarchy())
387 elif resolution == ca_res
and rep.bead_ca_centers:
388 beads = build_ca_centers(model, frag_res)
390 this_resolution.add_child(bead)
394 for residue
in frag_res:
395 tempc.add_child(IMP.atom.create_clone(residue.hier))
398 for bead
in beads.get_children():
399 this_resolution.add_child(bead)
404 input_coord = coord_finder.find_nearest_coord(
405 min(r.get_index()
for r
in frag_res))
406 if input_coord
is None:
407 input_coord = rep.bead_default_coord
408 beads = build_necklace(model,
413 this_resolution.add_child(bead)
424 rep_dict[resolution] += this_resolution.get_children()
426 if resolution == primary_resolution:
427 this_representation.add_child(this_resolution)
429 this_representation.add_representation(this_resolution,
433 if rep.setup_particles_as_densities:
435 setup_bead_as_gaussian(p)
436 this_resolution.set_name(
437 this_resolution.get_name() +
' Densities %i' % resolution)
438 this_representation.add_representation(this_resolution,
443 root_representation.set_name(name_all.strip(
',') +
": Base")
444 d = root_representation.get_representations(IMP.atom.DENSITIES)
445 d[0].set_name(
'%s: ' % name_all + d[0].get_name())
446 for resolution
in rep.bead_resolutions:
449 [r.get_index()
for r
in rep.residues])
450 this_resolution.set_name(
"%s: Res %i" % (name_all, resolution))
454 if prov_dict.get(resolution):
455 pdb_element = prov_dict[resolution]
458 pdb_element.filename,
459 pdb_element.chain_id, pdb_element.offset)
461 for hier
in rep_dict[resolution]:
462 this_resolution.add_child(hier)
463 if resolution == primary_resolution:
464 root_representation.add_child(this_resolution)
466 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.