1 from __future__
import print_function, division
7 from collections
import defaultdict
14 """Take iterable of TempResidues and return compatified string"""
17 idxs = [r.get_index()
for r
in res]
20 cur_range = [idxs[0], idxs[0]]
22 if idx != cur_range[1]+1:
23 all_ranges.append(cur_range)
24 cur_range = [idx, idx]
26 all_ranges.append(cur_range)
28 for nr, r
in enumerate(all_ranges):
29 ret +=
'%i-%i' % (r[0], r[1])
30 if nr < len(all_ranges)-1:
35 def _select_ca_or_p(hiers, **kwargs):
36 """Select all CA (amino acids) or P (nucleic acids) as appropriate"""
38 ps = sel_p.get_selected_particles()
44 return sel.get_selected_particles()
47 def get_structure(model, pdb_fn, chain_id, res_range=None, offset=0,
48 model_num=
None, ca_only=
False):
49 """read a structure from a PDB file and return a list of residues
50 @param model The IMP model
51 @param pdb_fn The file to read (in traditional PDB or mmCIF format)
52 @param chain_id Chain ID to read
53 @param res_range Add only a specific set of residues.
54 res_range[0] is the starting and res_range[1] is the ending
56 The ending residue can be "END", that will take everything
57 to the end of the sequence.
59 @param offset Apply an offset to the residue indexes of the PDB file
60 @param model_num Read multi-model PDB and return that model (0-based index)
61 @param ca_only Read only CA atoms (by default, all non-waters are read)
64 if pdb_fn.endswith(
'.cif'):
65 read_file = IMP.atom.read_mmcif
66 read_multi_file = IMP.atom.read_multimodel_mmcif
68 read_file = IMP.atom.read_pdb
69 read_multi_file = IMP.atom.read_multimodel_pdb
75 reader = read_file
if model_num
is None else read_multi_file
76 mh = reader(pdb_fn, model,
79 if model_num
is not None:
82 if res_range == []
or res_range
is None:
83 ps = _select_ca_or_p(mh, chain=chain_id)
89 mh.get_children()[0].get_children()[-1]).
get_index()
90 ps = _select_ca_or_p(mh, chain=chain_id,
91 residue_indexes=range(start, end+1))
96 res.set_index(res.get_index() + offset)
100 "no residues selected from %s in range %s" % (pdb_fn, res_range),
105 def build_bead(model, residues, input_coord=None):
106 """Generates a single bead"""
114 if ds_frag[0] == ds_frag[-1]:
115 rt = residues[0].get_residue_type()
117 h.set_name(
'%i_bead' % (ds_frag[0]))
118 prt.set_name(
'%i_bead' % (ds_frag[0]))
125 ptem.set_radius(radius)
128 h.set_name(
'%i-%i_bead' % (ds_frag[0], ds_frag[-1]))
129 prt.set_name(
'%i-%i_bead' % (ds_frag[0], ds_frag[-1]))
130 h.set_residue_indexes(range(ds_frag[0], ds_frag[-1] + 1))
132 radius = 0.8 * (3.0 / 4.0 / pi * volume) ** (1.0 / 3.0)
133 ptem.set_radius(radius)
137 if tuple(input_coord)
is not None:
138 ptem.set_coordinates(input_coord)
144 def build_necklace(model, residues, resolution, input_coord=None):
145 """Generates a string of beads with given length"""
149 out_hiers.append(build_bead(model, chunk, input_coord=input_coord))
153 def build_ca_centers(model, residues):
154 """Create a bead on the CA position with coarsened size and mass"""
156 for tempres
in residues:
157 residue = tempres.get_hierarchy()
159 rp1.set_name(
"Residue_%i" % residue.get_index())
160 rt = residue.get_residue_type()
172 residue, atom_type=IMP.atom.AT_CA).get_selected_particles()
174 residue, atom_type=IMP.atom.AT_P).get_selected_particles()
177 central_atom = calpha[0]
181 raise(
"build_ca_centers: weird selection (no Ca, no "
182 "nucleotide P or ambiguous selection found)")
188 out_hiers.append(this_res)
192 def setup_bead_as_gaussian(mh):
193 """Setup bead as spherical gaussian, using radius as variance"""
194 p = mh.get_particle()
204 def show_representation(node):
208 resolutions = repr.get_resolutions()
209 for r
in resolutions:
210 print(
'---- resolution %i ----' % r)
217 def _get_color_for_representation(rep):
218 """Return an IMP.display.Color object (or None) for the given
220 if rep.color
is not None:
221 if isinstance(rep.color, float):
223 elif isinstance(rep.color, str):
225 elif hasattr(rep.color,
'__iter__')
and len(rep.color) == 3:
230 raise TypeError(
"Color must be Chimera color name, a hex "
231 "string, a float or (r,g,b) tuple")
234 def _add_fragment_provenance(fragment, first_residue, rephandler):
235 """Track the original source of a fragment's structure.
236 If the residues in the given fragment were extracted from a PDB
237 file, add suitable provenance information to the Model (the name
238 of that file, chain ID, and residue index offset)."""
239 pdb_element = rephandler.pdb_for_residue.get(first_residue.get_index())
241 m = fragment.get_model()
244 p, pdb_element.filename, pdb_element.chain_id, pdb_element.offset)
248 def build_representation(parent, rep, coord_finder, rephandler):
249 """Create requested representation.
250 For beads, identifies continuous segments and sets up as Representation.
251 If any volume-based representations (e.g.,densities) are requested,
252 will instead create a single Representation node.
253 All reps are added as children of the passed parent.
254 @param parent The Molecule to which we'll add add representations
255 @param rep What to build. An instance of pmi::topology::_Representation
256 @param coord_finder A _FindCloseStructure object to help localize beads
261 model = parent.hier.get_model()
262 color = _get_color_for_representation(rep)
266 primary_resolution = min(rep.bead_resolutions)
272 if rep.density_residues_per_component:
274 num_components = (len(rep.residues)
275 // rep.density_residues_per_component+1)
276 rep_dict = defaultdict(list)
279 segp, primary_resolution)
280 built_reps.append(root_representation)
281 res_nums = [r.get_index()
for r
in rep.residues]
285 density_frag.get_particle().set_name(
286 "Densities %i" % rep.density_residues_per_component)
289 if os.path.exists(rep.density_prefix +
'.txt') \
290 and not rep.density_force_compute:
292 rep.density_prefix +
'.txt', density_ps, model)
293 if (len(density_ps) != num_components
294 or not os.path.exists(rep.density_prefix +
'.txt')
295 or rep.density_force_compute):
298 for r
in rep.residues:
310 mass_multiplier=total_mass)
313 rep.density_prefix +
'.txt')
314 if rep.density_voxel_size > 0.0:
316 density_ps, rep.density_prefix +
'.mrc',
317 rep.density_voxel_size, fast=
True)
319 for n, d
in enumerate(density_ps):
320 d.set_name(
'Density #%d' % n)
321 density_frag.add_child(d)
322 root_representation.add_representation(
323 density_frag, IMP.atom.DENSITIES,
324 rep.density_residues_per_component)
328 rsort = sorted(list(rep.residues), key=
lambda r: r.get_index())
330 prev_structure = rsort[0].get_has_structure()
333 for nr, r
in enumerate(rsort):
334 if (r.get_index() != prev_idx+1
335 or r.get_has_structure() != prev_structure
or force_break):
336 segments.append(cur_seg)
340 prev_idx = r.get_index()
341 prev_structure = r.get_has_structure()
342 if r.get_index()-1
in rep.bead_extra_breaks:
345 segments.append(cur_seg)
350 for frag_res
in segments:
351 res_nums = [r.get_index()
for r
in frag_res]
352 rrange =
"%i-%i" % (res_nums[0], res_nums[-1])
353 name =
"Frag_" + rrange
355 name_all += rrange +
','
356 elif name_count == 3:
363 segp, primary_resolution)
364 built_reps.append(this_representation)
365 for resolution
in rep.bead_resolutions:
368 this_resolution.set_name(
"%s: Res %i" % (name, resolution))
369 if frag_res[0].get_has_structure():
370 _add_fragment_provenance(this_resolution, frag_res[0],
373 if resolution == atomic_res:
374 for residue
in frag_res:
375 this_resolution.add_child(residue.get_hierarchy())
376 elif resolution == ca_res
and rep.bead_ca_centers:
377 beads = build_ca_centers(model, frag_res)
379 this_resolution.add_child(bead)
383 for residue
in frag_res:
384 tempc.add_child(IMP.atom.create_clone(residue.hier))
387 for bead
in beads.get_children():
388 this_resolution.add_child(bead)
393 input_coord = coord_finder.find_nearest_coord(
394 min(r.get_index()
for r
in frag_res))
395 if input_coord
is None:
396 input_coord = rep.bead_default_coord
397 beads = build_necklace(model,
402 this_resolution.add_child(bead)
413 rep_dict[resolution] += this_resolution.get_children()
415 if resolution == primary_resolution:
416 this_representation.add_child(this_resolution)
418 this_representation.add_representation(this_resolution,
422 if rep.setup_particles_as_densities:
424 setup_bead_as_gaussian(p)
425 this_resolution.set_name(
426 this_resolution.get_name() +
' Densities %i' % resolution)
427 this_representation.add_representation(this_resolution,
432 root_representation.set_name(name_all.strip(
',') +
": Base")
433 d = root_representation.get_representations(IMP.atom.DENSITIES)
434 d[0].set_name(
'%s: ' % name_all + d[0].get_name())
435 for resolution
in rep.bead_resolutions:
438 [r.get_index()
for r
in rep.residues])
439 this_resolution.set_name(
"%s: Res %i" % (name_all, resolution))
440 for hier
in rep_dict[resolution]:
441 this_resolution.add_child(hier)
442 if resolution == primary_resolution:
443 root_representation.add_child(this_resolution)
445 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.