1 """@namespace IMP.pmi.topology
2 Set up of system representation from topology files.
4 * Class for storing topology elements of PMI components
5 * Functions for reading these elementsfrom a formatted PMI topology file
6 * Functions for converting an existing IMP hierarchy into PMI topology
7 * TopologyWriter for writing PMI topology files
10 from __future__
import print_function
17 from collections
import defaultdict
18 from .
import system_tools
21 def get_residue_type_from_one_letter_code(code):
22 threetoone = {
'ALA':
'A',
'ARG':
'R', 'ASN': 'N', 'ASP': 'D',
23 'CYS':
'C',
'GLU':
'E',
'GLN':
'Q',
'GLY':
'G',
24 'HIS':
'H',
'ILE':
'I',
'LEU':
'L',
'LYS':
'K',
25 'MET':
'M',
'PHE':
'F',
'PRO':
'P',
'SER':
'S',
26 'THR':
'T',
'TRP':
'W',
'TYR':
'Y',
'VAL':
'V',
'UNK':
'X'}
29 one_to_three[threetoone[k]] = k
37 """Utility to retrieve particles from a hierarchy within a
38 zone around a set of ps.
39 @param hier The hierarchy in which to look for neighbors
40 @param target_ps The particles for zoning
41 @param sel_zone The maximum distance
42 @param entire_residues If True, will grab entire residues
43 @param exclude_backbone If True, will only return sidechain particles
47 backbone_types=[
'C',
'N',
'CB',
'O']
50 for n
in backbone_types])
51 test_ps = test_sel.get_selected_particles()
52 nn = IMP.algebra.NearestNeighbor3D([
IMP.core.XYZ(p).get_coordinates()
55 for target
in target_ps:
56 zone|=set(nn.get_in_ball(
IMP.core.XYZ(target).get_coordinates(),sel_zone))
57 zone_ps = [test_ps[z]
for z
in zone]
62 zone_ps = [h.get_particle()
for h
in final_ps]
70 class SystemBase(object):
71 """The base class for System, State and Molecule
72 classes. It contains shared functions in common to these classes
75 def __init__(self,mdl=None):
81 def _create_hierarchy(self):
82 """create a new hierarchy"""
86 def _create_child(self,parent_hierarchy):
87 """create a new hierarchy, set it as child of the input
89 child_hierarchy=self._create_hierarchy()
90 parent_hierarchy.add_child(child_hierarchy)
91 return child_hierarchy
94 """Build the coordinates of the system.
95 Loop through stored(?) hierarchies and set up coordinates!"""
100 class System(SystemBase):
101 """This class initializes the root node of the global IMP.atom.Hierarchy."""
102 def __init__(self,mdl=None,name="System"):
103 SystemBase.__init__(self,mdl)
104 self._number_of_states = 0
109 self.hier=self._create_hierarchy()
110 self.hier.set_name(name)
113 """returns a new IMP.pmi.representation_new.State(), increment the state index"""
114 self._number_of_states+=1
115 state =
State(self,self._number_of_states-1)
116 self.states.append(state)
120 return self.hier.get_name()
123 """returns the total number of states generated"""
124 return self._number_of_states
126 def get_hierarchy(self):
130 """call build on all states"""
132 for state
in self.states:
133 state.build(**kwargs)
140 """This private class is constructed from within the System class.
141 It wraps an IMP.atom.State
144 """Define a new state
145 @param system the PMI System
146 @param state_index the index of the new state
148 self.mdl = system.get_hierarchy().get_model()
150 self.hier = self._create_child(system.get_hierarchy())
151 self.hier.set_name(
"State_"+str(state_index))
152 self.molecules = defaultdict(list)
157 return self.system.__repr__()+
'.'+self.hier.get_name()
160 """Create a new Molecule within this State
161 @param name the name of the molecule (string) it must not
163 @param sequence sequence (string)
164 @param chain_id Chain id to assign to this molecule
167 if name
in self.molecules:
168 raise WrongMoleculeName(
'Cannot use a molecule name already used')
170 mol =
Molecule(self,name,sequence,chain_id,copy_num=0)
171 self.molecules[name].append(mol)
174 def get_hierarchy(self):
177 def get_number_of_copies(self,molname):
178 return len(self.molecules[molname])
180 def _register_copy(self,molecule):
181 molname = molecule.get_hierarchy().get_name()
182 if molname
not in self.molecules:
183 raise StructureError(
"Trying to add a copy when the original doesn't exist!")
184 self.molecules[molname].append(molecule)
187 """call build on all molecules (automatically makes clones)"""
189 for molname
in self.molecules:
190 for mol
in self.molecules[molname]:
198 """This class is constructed from within the State class.
199 It wraps an IMP.atom.Molecule and IMP.atom.Copy
200 Structure is read using this class
201 Resolutions and copies can be registered, but are only created when build() is called
204 def __init__(self,state,name,sequence,chain_id,copy_num,mol_to_clone=None,transformation=None):
205 """The user should not call this direclty, instead call State::create_molecule()
206 @param state The parent PMI State
207 @param name The name of the molecule (string)
208 @param sequence Sequence (string)
209 @param mol_to_clone The original molecule (for cloning ONLY)
210 @param transformation A transform to apply during building (primarily for cloning)
213 self.mdl = state.get_hierarchy().get_model()
215 self.sequence = sequence
217 self.mol_to_clone = mol_to_clone
218 self.transformation = transformation
221 self.hier = self._create_child(self.state.get_hierarchy())
222 self.hier.set_name(name)
228 for ns,s
in enumerate(sequence):
229 r=_Residue(self,s,ns+1)
230 self.residues.append(r)
233 return self.state.__repr__()+
'.'+self.get_name()+
'.'+ \
237 def __getitem__(self,val):
238 if isinstance(val,int):
239 return self.residues[val]
240 elif isinstance(val,str):
241 return self.residues[int(val)-1]
242 elif isinstance(val,slice):
243 return set(self.residues[val])
245 print(
"ERROR: range ends must be int or str. Stride must be int.")
247 def get_hierarchy(self):
251 return self.hier.get_name()
254 """get residue range. Use integers to get 0-indexing, or strings to get PDB-indexing"""
255 if isinstance(a,int)
and isinstance(b,int)
and isinstance(stride,int):
256 return set(self.residues[a:b:stride])
257 elif isinstance(a,str)
and isinstance(b,str)
and isinstance(stride,int):
258 return set(self.residues[int(a)-1:int(b)-1:stride])
260 print(
"ERROR: range ends must be int or str. Stride must be int.")
263 """ Return all Residues as a set"""
265 for res
in self.residues:
270 """ Return a set of Residues that have associated structure coordinates """
272 for res
in self.residues:
273 if res.get_has_coordinates():
278 """ Return a set of Residues that don't have associated structure coordinates """
280 for res
in self.residues:
281 if not res.get_has_coordinates():
282 non_atomic_res.add(res)
283 return non_atomic_res
286 """Create a new Molecule with the same name and sequence but a higher copy number.
287 Returns the Molecule. No structure or representation will be copied!
288 @param chain_id Chain ID of the new molecule
290 mol =
Molecule(self.state,self.get_name(),self.sequence,chain_id,
291 copy_num=self.state.get_number_of_copies(self.get_name()))
292 self.state._register_copy(mol)
296 """Create a Molecule clone (automatically builds same structure and representation)
297 @param chain_id If you want to set the chain ID of the copy to something
298 @param transformation Apply transformation after building (at the end)
300 mol =
Molecule(self.state,self.get_name(),self.sequence,chain_id,
301 copy_num=self.state.get_number_of_copies(self.get_name()),
302 mol_to_clone=self,transformation=transformation)
303 self.state._register_copy(mol)
305 def add_structure(self,pdb_fn,chain_id,res_range=[],offset=0,model_num=None,ca_only=False,soft_check=False):
306 """Read a structure and store the coordinates.
307 Returns the atomic residues (as a set)
308 @param pdb_fn The file to read
309 @param chain_id Chain ID to read
310 @param res_range Add only a specific set of residues
311 @param offset Apply an offset to the residue indexes of the PDB file
312 @param model_num Read multi-model PDB and return that model
313 @param soft_check If True, it only warns if there are sequence mismatches between the pdb and the Molecules sequence
314 If False (Default), it raises and exit when there are sequence mismatches.
315 \note After offset, we expect the PDB residue numbering to match the FASTA file
318 rhs=system_tools.get_structure(self.mdl,pdb_fn,chain_id,res_range,offset,ca_only=ca_only)
319 if len(rhs)>len(self.residues):
320 print(
'ERROR: You are loading',len(rhs), \
321 'pdb residues for a sequence of length',len(self.residues),
'(too many)')
325 for nrh,rh
in enumerate(rhs):
327 internal_res=self.residues[idx-1]
330 raise StructureError(
'ERROR: PDB residue index',idx,
'is',
332 'and sequence residue is',internal_res.get_code())
334 print(
'WARNING: PDB residue index',idx,
'is',
336 'and sequence residue is',internal_res.get_code())
337 internal_res.set_structure(rh,soft_check)
338 atomic_res.add(internal_res)
342 """handles the IMP.atom.Representation decorators, such as multi-scale,
344 @param res_set set of PMI residues for adding the representation
345 @param representation_type currently supports only balls
346 @param resolutions what resolutions to add to the
347 residues (see @ref pmi_resolution)
349 allowed_types=[
"balls"]
350 if representation_type
not in allowed_types:
351 print(
"ERROR: Allowed representation types:",allowed_types)
354 res_set=set(self.residues)
356 res.add_representation(representation_type,resolutions)
358 def build(self,merge_type="backbone",ca_centers=True,fill_in_missing_residues=True):
359 """Create all parts of the IMP hierarchy
360 including Atoms, Residues, and Fragments/Representations and, finally, Copies
361 /note Any residues assigned a resolution must have an IMP.atom.Residue hierarchy
362 containing at least a CAlpha. For missing residues, these can be constructed
364 @param merge_type Principle for grouping into fragments.
365 "backbone": linear sequences along backbone are grouped
366 into fragments if they have identical sets of representations.
367 "volume": at each resolution, groups are made based on
368 spatial distance (not currently implemented)
369 @param ca_centers For single-bead-per-residue only. Set the center over the CA position.
371 allowed_types=(
"backbone")
372 if merge_type
not in allowed_types:
373 print(
"ERROR: Allowed merge types:",allowed_types)
378 if self.mol_to_clone
is not None:
379 for nr,r
in enumerate(self.mol_to_clone.residues):
381 if self.transformation
is not None:
382 for r
in self.residues:
384 for orig,new
in zip(self.mol_to_clone.residues,self.residues):
385 new.representations=orig.representations
389 if merge_type==
"backbone":
390 system_tools.build_along_backbone(self.mdl,self.hier,self.residues,
391 IMP.atom.BALLS,ca_centers)
394 elif merge_type==
"volume":
405 """A dictionary-like wrapper for reading and storing sequence data"""
406 def __init__(self,fasta_fn,name_map=None):
407 """read a fasta file and extract all the requested sequences
408 @param fasta_fn sequence file
409 @param name_map dictionary mapping the fasta name to the stored name
412 self.read_sequences(fasta_fn,name_map)
414 return len(self.sequences)
415 def __contains__(self,x):
416 return x
in self.sequences
417 def __getitem__(self,key):
418 return self.sequences[key]
421 for s
in self.sequences:
422 ret+=
'%s\t%s\n'%(s,self.sequences[s])
424 def read_sequences(self,fasta_fn,name_map=None):
426 handle = open(fasta_fn,
"rU")
427 record_dict = SeqIO.to_dict(SeqIO.parse(handle,
"fasta"))
430 for pn
in record_dict:
431 self.sequences[pn]=str(record_dict[pn].seq).replace(
"*",
"")
435 self.sequences[name_map[pn]]=str(record_dict[pn].seq).replace(
"*",
"")
437 print(
"tried to add sequence but: id %s not found in fasta file" % pn)
443 class _Residue(object):
444 """Stores basic residue information, even without structure available."""
446 def __init__(self,molecule,code,index):
448 @param molecule PMI Molecule to which this residue belongs
449 @param code one-letter residue type code
450 @param index PDB index
452 self.molecule = molecule
454 get_residue_type_from_one_letter_code(code),
456 self.representations = defaultdict(set)
458 return self.get_code()+str(self.get_index())
460 return self.__str__()
462 return (self.molecule,self.hier,
463 frozenset((k,tuple(self.representations[k]))
for k
in self.representations))
464 def __eq__(self,other):
465 return type(other)==type(self)
and self.__key() == other.__key()
467 return hash(self.__key())
469 return self.hier.get_index()
472 def get_residue_type(self):
473 return self.hier.get_residue_type()
474 def get_hierarchy(self):
476 def get_has_coordinates(self):
477 if len(self.hier.get_children())>0:
481 def set_structure(self,res,soft_check=False):
482 if res.get_residue_type()!=self.hier.get_residue_type():
484 raise StructureError(
"Adding structure to this residue, but it's the wrong type!")
485 for a
in res.get_children():
486 self.hier.add_child(a)
488 a.get_particle().set_name(
'Atom %s of residue %i'%(atype.__str__().strip(
'"'),
489 self.hier.get_index()))
490 def add_representation(self,rep_type,resolutions):
491 self.representations[rep_type] |= set(resolutions)
496 Read a pipe-delimited PMI topology file.
498 The topology file should be in a simple pipe-delimited format, such as
505 |topology_dictionary|
506 |component_name|domain_name|fasta_fn|fasta_id|pdb_fn|chain|residue_range|pdb_offset|bead_size|em_residues_per_gaussian|rmf_file|rmf_frame_number|
507 |Rpb1 |Rpb1_1|1WCM.fasta|1WCM:A|1WCM.pdb|A|1,1140 |0|10|0 |None | None|
508 |Rpb1 |Rpb1_2|1WCM.fasta|1WCM:A|1WCM.pdb|A|1141,1274|0|10|0 |0.rmf3 | 0 |
509 |Rpb1 |Rpb1_3|1WCM.fasta|1WCM:A|1WCM.pdb|A|1275,-1 |0|10|0 |None | None|
510 |Rpb2 |Rpb2 |1WCM.fasta|1WCM:B|1WCM.pdb|B|all |0|10|0 |None | None|
513 The `|directories|` section lists paths (relative to the topology file)
514 where various inputs can be found.
516 The columns under `|topology_dictionary|`:
517 - `component_name`: Name of the component (chain). Serves as the parent
518 hierarchy for this structure.
519 - `domain_name`: Allows subdivision of chains into individual domains.
520 A model consists of a number of individual units, referred to as
521 domains. Each domain can be an individual chain, or a subset of a
522 chain, and these domains are used to set rigid body movers. A chain
523 may be separated into multiple domains if the user wishes different
524 sections to move independently, and/or analyze the portions separately.
525 - `fasta_fn`: Name of FASTA file containing this component.
526 - `fasta_id`: String found in FASTA sequence header line.
527 - `pdb_fn`: Name of PDB file with coordinates (if available).
528 - `chain`: Chain ID of this domain in the PDB file.
529 - `residue_range`: Comma delimited pair defining range. -1 = last residue.
531 - `pdb_offset`: Offset to sync PDB residue numbering with FASTA numbering.
532 - `bead_size`: The size (in residues) of beads used to model areas not
533 covered by PDB coordinates.
534 - `em_residues`: The number of Gaussians used to model the electron
535 density of this domain. Set to zero if no EM fitting will be done.
536 - `rmf_file`: File path of rmf file with coordinates (if available).
537 - `rmf_frame_number`: File path of rmf file.
539 The file is read in and each part of the topology is stored as a
540 ComponentTopology object for input into IMP::pmi::macros::BuildModel.
542 def __init__(self, topology_file):
543 self.topology_file=topology_file
544 self.component_list=[]
545 self.defaults={
'bead_size' : 10,
546 'residue_range' :
'all',
548 'em_residues_per_gaussian' : 0,
550 'rmf_frame_number' :
None};
554 def write_topology_file(self,outfile):
556 f.write(
"|directories|\n")
558 for key, value
in self.defaults.items():
559 output=
"|"+str(key)+
"|"+str(value)+
"|\n"
562 f.write(
"|topology_dictionary|\n")
563 f.write(
"|component_name|domain_name|fasta_fn|fasta_id|pdb_fn|chain|residue_range|pdb_offset|bead_size|em_residues_per_gaussian|rmf_file|rmf_frame_number|\n")
564 for c
in self.component_list:
565 output=
"|"+str(c.name)+
"|"+str(c.domain_name)+
"|"+str(c.fasta_file)+
"|"+str(c.fasta_id)+
"|"+str(c.pdb_file)+
"|"+str(c.chain)+
"|"+str(c.residue_range).strip(
"(").strip(
")")+
"|"+str(c.pdb_offset)+
"|"+str(c.bead_size)+
"|"+str(c.em_residues_per_gaussian)+
"|"+str(c.rmf_file)+
"|"+str(c.rmf_frame_number)+
"|\n"
570 """ Return list of ComponentTopologies for selected components given a list of indices"""
571 if topology_list ==
"all":
572 topologies = self.component_list
575 for i
in topology_list:
576 topologies.append(self.component_list[i])
580 """ Changes the default directories and renames the files for each ComponentTopology object """
581 if default_dir
in self.defaults.keys():
582 self.defaults[default_dir]=new_dir
584 print(default_dir,
"is not a correct directory key")
586 for c
in self.component_list:
587 pdb_file=c.pdb_file.split(
"/")[-1]
588 c.pdb_file=self._make_path(self.defaults[
'pdb_dir'],
590 fasta_file=c.fasta_file.split(
"/")[-1]
591 c.fasta_file=self._make_path(self.defaults[
'fasta_dir'],
593 if c.gmm_file
is not None:
594 gmm_file=c.gmm_file.split(
"/")[-1]
595 c.gmm_file=self._make_path(self.defaults[
'gmm_dir'],
597 mrc_file=c.mrc_file.split(
"/")[-1]
598 c.mrc_file=self._make_path(self.defaults[
'gmm_dir'],
603 """ Import system components from topology file. append=False will erase current topology and overwrite with new """
610 self.component_list=[]
612 with open(topology_file)
as infile:
615 if line.lstrip()==
"" or line[0]==
"#":
618 elif line.split(
'|')[1]==
"topology_dictionary":
621 elif is_topology==
True and is_defaults==
True:
626 elif is_topology==
True:
628 new_component=self.create_component_topology(line, topology_fields, self.defaults, linenum)
629 self.component_list.append(new_component)
631 elif is_defaults==
True:
633 self.add_default_parameter(line, linenum)
635 elif line.split(
'|')[1]==
"directories":
641 return self.component_list
643 def _make_path(self, dirname, fname):
644 "Get the full path to a file, possibly relative to the topology file"
646 return os.path.join(dirname, fname)
648 def create_component_topology(self, component_line, topology_fields, defaults, linenum, color="0.1"):
654 fields=topology_fields.split(
'|')
655 values=component_line.split(
'|')
659 c.name = values[fields.index(
"component_name")].strip()
660 c.domain_name = values[fields.index(
"domain_name")].strip()
661 c.fasta_file = self._make_path(defaults[
'fasta_dir'],
662 values[fields.index(
"fasta_fn")])
663 c.fasta_id = values[fields.index(
"fasta_id")].strip()
664 c.pdb_file = self._make_path(defaults[
'pdb_dir'],
665 values[fields.index(
"pdb_fn")])
669 t_chain = values[fields.index(
"chain")].strip()
672 if len(t_chain)==1
or len(t_chain)==2:
675 errors.append(
"PDB Chain identifier must be one or two characters.")
676 errors.append(
"For component %s line %d is not correct |%s| was given." % (c.name,linenum,t_chain))
680 if "residue_range" in fields:
681 f=values[fields.index(
"residue_range")].strip()
682 if f.strip()==
'all' or str(f)==
"":
683 c.residue_range=(1,-1)
685 elif len(f.split(
','))==2
and self.is_int(f.split(
',')[0])
and self.is_int(f.split(
',')[1]):
686 c.residue_range=(int(f.split(
',')[0]), int(f.split(
',')[1]))
688 errors.append(
"Residue Range format for component %s line %d is not correct" % (c.name, linenum))
689 errors.append(
"Correct syntax is two comma separated integers: |start_res, end_res|. |%s| was given." % f)
690 errors.append(
"To select all residues, indicate |\"all\"|")
692 c.residue_range=defaults[
"residue_range"]
696 if "pdb_offset" in fields:
697 f=values[fields.index(
"pdb_offset")].strip()
701 errors.append(
"PDB Offset format for component %s line %d is not correct" % (c.name, linenum))
702 errors.append(
"The value must be a single integer. |%s| was given." % f)
704 c.pdb_offset=defaults[
"pdb_offset"]
707 if "bead_size" in fields:
708 f=values[fields.index(
"bead_size")].strip()
712 errors.append(
"Bead Size format for component %s line %d is not correct" % (c.name, linenum))
713 errors.append(
"The value must be a single integer. |%s| was given." % f)
715 c.bead_size=defaults[
"bead_size"]
718 if "em_residues_per_gaussian" in fields:
719 f=values[fields.index(
"em_residues_per_gaussian")].strip()
722 c.gmm_file=self._make_path(defaults[
'gmm_dir'],
723 c.domain_name.strip() +
".txt")
724 c.mrc_file=self._make_path(defaults[
'gmm_dir'],
725 c.domain_name.strip() +
".mrc")
726 c.em_residues_per_gaussian=int(f)
728 errors.append(
"em_residues_per_gaussian format for component %s line %d is not correct" % (c.name, linenum))
729 errors.append(
"The value must be a single integer. |%s| was given." % f)
731 c.em_residues_per_gaussian=defaults[
"em_residues_per_gaussian"]
733 if "rmf_file" in fields:
734 f=values[fields.index(
"rmf_file")].strip()
738 if not os.path.isfile(f):
739 errors.append(
"rmf_file %s must be an existing file or None" % c.name)
743 c.rmf_file=defaults[
"rmf_file"]
745 if "rmf_frame_number" in fields:
746 f=values[fields.index(
"rmf_frame_number")].strip()
750 if not self.is_int(f):
751 errors.append(
"rmf_frame_number %s must be an integer or None" % c.name)
755 c.rmf_frame_number=defaults[
"rmf_frame_number"]
758 raise ValueError(
"Fix Topology File syntax errors and rerun: " \
767 return float(s).is_integer()
772 def add_default_parameter(self,line, linenum):
777 print(
"Default value syntax not correct for ", line)
778 print(
"Line number", linenum,
" contains ", len(f)-2,
" fields.")
779 print(
"Please reformat to |KEY|VALUE|")
780 self.defaults[f[1]]=f[2]
786 Topology class stores the components required to build a standard IMP hierarchy
787 using IMP.pmi.autobuild_model()
791 self.domain_name=
None
796 self.residue_range=
None
799 self.em_residues_per_gaussian=
None
803 self.rmf_file_name=
None
804 self.rmf_frame_number=
None
806 def recompute_default_dirs(self, topology):
807 pdb_filename=self.pdb_file.split(
"/")[-1]
Topology class stores the components required to build a standard IMP hierarchy using IMP...
def build
call build on all molecules (automatically makes clones)
def get_atomic_residues
Return a set of Residues that have associated structure coordinates.
def get_residues
Return all Residues as a set.
def get_particles_within_zone
Utility to retrieve particles from a hierarchy within a zone around a set of ps.
def build
call build on all states
def __init__
read a fasta file and extract all the requested sequences
Hierarchy create_clone(Hierarchy d)
Clone the Hierarchy.
def __init__
The user should not call this direclty, instead call State::create_molecule()
def residue_range
get residue range.
def __init__
Define a new state.
def add_representation
handles the IMP.atom.Representation decorators, such as multi-scale, density, etc.
static State setup_particle(Model *m, ParticleIndex pi, unsigned int index)
def create_molecule
Create a new Molecule within this State.
def build
Create all parts of the IMP hierarchy including Atoms, Residues, and Fragments/Representations and...
static Residue setup_particle(Model *m, ParticleIndex pi, ResidueType t, int index, int insertion_code)
char get_one_letter_code(ResidueType c)
Get the 1-letter amino acid code from the residue type.
def get_non_atomic_residues
Return a set of Residues that don't have associated structure coordinates.
The base class for System, State and Molecule classes.
Class for storing model, its restraints, constraints, and particles.
This class is constructed from within the State class.
A decorator for keeping track of copies of a molecule.
static Hierarchy setup_particle(Model *m, ParticleIndex pi, ParticleIndexesAdaptor children=ParticleIndexesAdaptor())
Create a Hierarchy of level t by adding the needed attributes.
void transform(Hierarchy h, const algebra::Transformation3D &tr)
Transform a hierarchy. This is aware of rigid bodies.
The standard decorator for manipulating molecular structures.
Ints get_index(const ParticlesTemp &particles, const Subset &subset, const Subsets &excluded)
A decorator for a particle representing an atom.
def get_component_topologies
Return list of ComponentTopologies for selected components given a list of indices.
def build
Build the coordinates of the system.
std::string get_relative_path(std::string base, std::string relative)
Return a path to a file relative to another file.
A decorator for a particle with x,y,z coordinates.
def create_clone
Create a Molecule clone (automatically builds same structure and representation)
def add_structure
Read a structure and store the coordinates.
static Copy setup_particle(Model *m, ParticleIndex pi, Int number)
A decorator for a residue.
General purpose algebraic and geometric methods that are expected to be used by a wide variety of IMP...
Read a pipe-delimited PMI topology file.
The general base class for IMP exceptions.
Class to handle individual model particles.
This private class is constructed from within the System class.
int get_copy_index(Hierarchy h)
Walk up the hierarchy to find the current copy index.
Python classes to represent, score, sample and analyze models.
A dictionary-like wrapper for reading and storing sequence data.
def create_copy
Create a new Molecule with the same name and sequence but a higher copy number.
Functionality for loading, creating, manipulating and scoring atomic structures.
static Chain setup_particle(Model *m, ParticleIndex pi, std::string id)
Select hierarchy particles identified by the biological name.
def get_number_of_states
returns the total number of states generated
def set_dir
Changes the default directories and renames the files for each ComponentTopology object.
def import_topology_file
Import system components from topology file.
def create_state
returns a new IMP.pmi.representation_new.State(), increment the state index