1 """@namespace IMP.pmi.output
2 Classes for writing output files and processing them.
26 """Map indices to multi-character chain IDs.
27 We label the first 26 chains A-Z, then we move to two-letter
28 chain IDs: AA through AZ, then BA through BZ, through to ZZ.
29 This continues with longer chain IDs."""
30 def __getitem__(self, ind):
31 chars = string.ascii_uppercase
35 ids.append(chars[ind % lc])
37 ids.append(chars[ind])
38 return "".join(reversed(ids))
42 """Base class for capturing a modeling protocol.
43 Unlike simple output of model coordinates, a complete
44 protocol includes the input data used, details on the restraints,
45 sampling, and clustering, as well as output models.
46 Use via IMP.pmi.topology.System.add_protocol_output().
48 @see IMP.pmi.mmcif.ProtocolOutput for a concrete subclass that outputs
56 if isinstance(elt, (tuple, list)):
57 for elt2
in _flatten(elt):
63 def _disambiguate_chain(chid, seen_chains):
64 """Make sure that the chain ID is unique; warn and correct if it isn't"""
69 if chid
in seen_chains:
70 warnings.warn(
"Duplicate chain ID '%s' encountered" % chid,
73 for suffix
in itertools.count(1):
74 new_chid = chid +
"%d" % suffix
75 if new_chid
not in seen_chains:
76 seen_chains.add(new_chid)
82 def _write_pdb_internal(flpdb, particle_infos_for_pdb, geometric_center,
83 write_all_residues_per_bead):
84 for n, tupl
in enumerate(particle_infos_for_pdb):
85 (xyz, atom_type, residue_type,
86 chain_id, residue_index, all_indexes, radius) = tupl
88 atom_type = IMP.atom.AT_CA
89 if write_all_residues_per_bead
and all_indexes
is not None:
90 for residue_number
in all_indexes:
92 IMP.atom.get_pdb_string((xyz[0] - geometric_center[0],
93 xyz[1] - geometric_center[1],
94 xyz[2] - geometric_center[2]),
95 n+1, atom_type, residue_type,
96 chain_id[:1], residue_number,
' ',
100 IMP.atom.get_pdb_string((xyz[0] - geometric_center[0],
101 xyz[1] - geometric_center[1],
102 xyz[2] - geometric_center[2]),
103 n+1, atom_type, residue_type,
104 chain_id[:1], residue_index,
' ',
106 flpdb.write(
"ENDMDL\n")
109 _Entity = collections.namedtuple(
'_Entity', (
'id',
'seq'))
110 _ChainInfo = collections.namedtuple(
'_ChainInfo', (
'entity',
'name'))
113 def _get_chain_info(chains, root_hier):
117 for mol
in IMP.atom.get_by_type(root_hier, IMP.atom.MOLECULE_TYPE):
119 chain_id = chains[molname]
121 seq = chain.get_sequence()
122 if seq
not in entities:
123 entities[seq] = e = _Entity(id=len(entities)+1, seq=seq)
124 all_entities.append(e)
125 entity = entities[seq]
126 info = _ChainInfo(entity=entity, name=molname)
127 chain_info[chain_id] = info
128 return chain_info, all_entities
131 def _write_mmcif_internal(flpdb, particle_infos_for_pdb, geometric_center,
132 write_all_residues_per_bead, chains, root_hier):
134 chain_info, entities = _get_chain_info(chains, root_hier)
136 writer = ihm.format.CifWriter(flpdb)
137 writer.start_block(
'model')
138 with writer.category(
"_entry")
as lp:
141 with writer.loop(
"_entity", [
"id",
"type"])
as lp:
143 lp.write(id=e.id, type=
"polymer")
145 with writer.loop(
"_entity_poly",
146 [
"entity_id",
"pdbx_seq_one_letter_code"])
as lp:
148 lp.write(entity_id=e.id, pdbx_seq_one_letter_code=e.seq)
150 with writer.loop(
"_struct_asym", [
"id",
"entity_id",
"details"])
as lp:
152 for chid
in sorted(chains.values(), key=
lambda x: (len(x.strip()), x)):
153 ci = chain_info[chid]
154 lp.write(id=chid, entity_id=ci.entity.id, details=ci.name)
156 with writer.loop(
"_atom_site",
157 [
"group_PDB",
"type_symbol",
"label_atom_id",
158 "label_comp_id",
"label_asym_id",
"label_seq_id",
160 "Cartn_x",
"Cartn_y",
"Cartn_z",
"label_entity_id",
161 "pdbx_pdb_model_num",
164 for n, tupl
in enumerate(particle_infos_for_pdb):
165 (xyz, atom_type, residue_type,
166 chain_id, residue_index, all_indexes, radius) = tupl
167 ci = chain_info[chain_id]
168 if atom_type
is None:
169 atom_type = IMP.atom.AT_CA
170 c = (xyz[0] - geometric_center[0],
171 xyz[1] - geometric_center[1],
172 xyz[2] - geometric_center[2])
173 if write_all_residues_per_bead
and all_indexes
is not None:
174 for residue_number
in all_indexes:
175 lp.write(group_PDB=
'ATOM',
177 label_atom_id=atom_type.get_string(),
178 label_comp_id=residue_type.get_string(),
179 label_asym_id=chain_id,
180 label_seq_id=residue_index,
181 auth_seq_id=residue_index, Cartn_x=c[0],
182 Cartn_y=c[1], Cartn_z=c[2], id=ordinal,
183 pdbx_pdb_model_num=1,
184 label_entity_id=ci.entity.id)
187 lp.write(group_PDB=
'ATOM', type_symbol=
'C',
188 label_atom_id=atom_type.get_string(),
189 label_comp_id=residue_type.get_string(),
190 label_asym_id=chain_id,
191 label_seq_id=residue_index,
192 auth_seq_id=residue_index, Cartn_x=c[0],
193 Cartn_y=c[1], Cartn_z=c[2], id=ordinal,
194 pdbx_pdb_model_num=1,
195 label_entity_id=ci.entity.id)
200 """Class for easy writing of PDBs, RMFs, and stat files
202 @note Model should be updated prior to writing outputs.
204 def __init__(self, ascii=True, atomistic=False):
205 self.dictionary_pdbs = {}
207 self.dictionary_rmfs = {}
208 self.dictionary_stats = {}
209 self.dictionary_stats2 = {}
210 self.best_score_list =
None
211 self.nbestscoring =
None
213 self.replica_exchange =
False
218 self.chainids =
"ABCDEFGHIJKLMNOPQRSTUVWXYZ" \
219 "abcdefghijklmnopqrstuvwxyz0123456789"
221 self.multi_chainids = _ChainIDs()
223 self.particle_infos_for_pdb = {}
224 self.atomistic = atomistic
227 """Get a list of all PDB files being output by this instance"""
228 return list(self.dictionary_pdbs.keys())
230 def get_rmf_names(self):
231 return list(self.dictionary_rmfs.keys())
233 def get_stat_names(self):
234 return list(self.dictionary_stats.keys())
236 def _init_dictchain(self, name, prot, multichar_chain=False, mmcif=False):
237 self.dictchain[name] = {}
241 self.atomistic =
True
242 for n, mol
in enumerate(IMP.atom.get_by_type(
243 prot, IMP.atom.MOLECULE_TYPE)):
245 if not mmcif
and len(chid) > 1:
247 "The system contains at least one chain ID (%s) that "
248 "is more than 1 character long; this cannot be "
249 "represented in PDB. Either write mmCIF files "
250 "instead, or assign 1-character IDs to all chains "
251 "(this can be done with the `chain_ids` argument to "
252 "BuildSystem.add_state())." % chid)
253 chid = _disambiguate_chain(chid, seen_chains)
255 self.dictchain[name][molname] = chid
259 @param name The PDB filename
260 @param prot The hierarchy to write to this pdb file
261 @param mmcif If True, write PDBs in mmCIF format
262 @note if the PDB name is 'System' then will use Selection
265 flpdb = open(name,
'w')
267 self.dictionary_pdbs[name] = prot
268 self._pdb_mmcif[name] = mmcif
269 self._init_dictchain(name, prot, mmcif=mmcif)
271 def write_psf(self, filename, name):
272 flpsf = open(filename,
'w')
273 flpsf.write(
"PSF CMAP CHEQ" +
"\n")
274 index_residue_pair_list = {}
275 (particle_infos_for_pdb, geometric_center) = \
276 self.get_particle_infos_for_pdb_writing(name)
277 nparticles = len(particle_infos_for_pdb)
278 flpsf.write(str(nparticles) +
" !NATOM" +
"\n")
279 for n, p
in enumerate(particle_infos_for_pdb):
284 flpsf.write(
'{0:8d}{1:1s}{2:4s}{3:1s}{4:4s}{5:1s}{6:4s}{7:1s}'
285 '{8:4s}{9:1s}{10:4s}{11:14.6f}{12:14.6f}{13:8d}'
286 '{14:14.6f}{15:14.6f}'.format(
287 atom_index,
" ", chain,
" ", str(resid),
" ",
288 '"'+residue_type.get_string()+
'"',
" ",
"C",
289 " ",
"C", 1.0, 0.0, 0, 0.0, 0.0))
291 if chain
not in index_residue_pair_list:
292 index_residue_pair_list[chain] = [(atom_index, resid)]
294 index_residue_pair_list[chain].append((atom_index, resid))
298 for chain
in sorted(index_residue_pair_list.keys()):
300 ls = index_residue_pair_list[chain]
302 ls = sorted(ls, key=
lambda tup: tup[1])
304 indexes = [x[0]
for x
in ls]
307 indexes, lmin=2, lmax=2))
308 nbonds = len(indexes_pairs)
309 flpsf.write(str(nbonds)+
" !NBOND: bonds"+
"\n")
312 for i
in range(0, len(indexes_pairs), 4):
313 for bond
in indexes_pairs[i:i+4]:
314 flpsf.write(
'{0:8d}{1:8d}'.format(*bond))
317 del particle_infos_for_pdb
320 def write_pdb(self, name, appendmode=True,
321 translate_to_geometric_center=
False,
322 write_all_residues_per_bead=
False):
324 (particle_infos_for_pdb,
325 geometric_center) = self.get_particle_infos_for_pdb_writing(name)
327 if not translate_to_geometric_center:
328 geometric_center = (0, 0, 0)
330 filemode =
'a' if appendmode
else 'w'
331 with open(name, filemode)
as flpdb:
332 if self._pdb_mmcif[name]:
333 _write_mmcif_internal(flpdb, particle_infos_for_pdb,
335 write_all_residues_per_bead,
336 self.dictchain[name],
337 self.dictionary_pdbs[name])
339 _write_pdb_internal(flpdb, particle_infos_for_pdb,
341 write_all_residues_per_bead)
344 """Get the protein name from the particle.
345 This is done by traversing the hierarchy."""
348 def get_particle_infos_for_pdb_writing(self, name):
358 particle_infos_for_pdb = []
360 geometric_center = [0, 0, 0]
365 and self.dictionary_pdbs[name].get_number_of_children() == 0):
369 ps = sel.get_selected_particles()
371 for n, p
in enumerate(ps):
374 if protname
not in resindexes_dict:
375 resindexes_dict[protname] = []
379 rt = residue.get_residue_type()
380 resind = residue.get_index()
384 geometric_center[0] += xyz[0]
385 geometric_center[1] += xyz[1]
386 geometric_center[2] += xyz[2]
388 particle_infos_for_pdb.append(
389 (xyz, atomtype, rt, self.dictchain[name][protname],
390 resind,
None, radius))
391 resindexes_dict[protname].append(resind)
396 resind = residue.get_index()
399 if resind
in resindexes_dict[protname]:
402 resindexes_dict[protname].append(resind)
403 rt = residue.get_residue_type()
406 geometric_center[0] += xyz[0]
407 geometric_center[1] += xyz[1]
408 geometric_center[2] += xyz[2]
410 particle_infos_for_pdb.append(
411 (xyz,
None, rt, self.dictchain[name][protname], resind,
416 resind = resindexes[len(resindexes) // 2]
417 if resind
in resindexes_dict[protname]:
420 resindexes_dict[protname].append(resind)
424 geometric_center[0] += xyz[0]
425 geometric_center[1] += xyz[1]
426 geometric_center[2] += xyz[2]
428 particle_infos_for_pdb.append(
429 (xyz,
None, rt, self.dictchain[name][protname], resind,
436 if len(resindexes) > 0:
437 resind = resindexes[len(resindexes) // 2]
440 geometric_center[0] += xyz[0]
441 geometric_center[1] += xyz[1]
442 geometric_center[2] += xyz[2]
444 particle_infos_for_pdb.append(
445 (xyz,
None, rt, self.dictchain[name][protname],
446 resind, resindexes, radius))
449 geometric_center = (geometric_center[0] / atom_count,
450 geometric_center[1] / atom_count,
451 geometric_center[2] / atom_count)
455 particle_infos_for_pdb = sorted(particle_infos_for_pdb,
456 key=
lambda x: (len(x[3]), x[3], x[4]))
458 return (particle_infos_for_pdb, geometric_center)
460 def write_pdbs(self, appendmode=True, mmcif=False):
461 for pdb
in self.dictionary_pdbs.keys():
462 self.write_pdb(pdb, appendmode)
465 replica_exchange=
False, mmcif=
False,
466 best_score_file=
'best.scores.rex.py'):
467 """Prepare for writing best-scoring PDBs (or mmCIFs) for a
470 @param prefix Initial part of each PDB filename (e.g. 'model').
471 @param prot The top-level Hierarchy to output.
472 @param nbestscoring The number of best-scoring files to output.
473 @param replica_exchange Whether to combine best scores from a
474 replica exchange run.
475 @param mmcif If True, output models in mmCIF format. If False
476 (the default) output in legacy PDB format.
477 @param best_score_file The filename to use for replica
481 self._pdb_best_scoring_mmcif = mmcif
482 fileext =
'.cif' if mmcif
else '.pdb'
483 self.prefixes.append(prefix)
484 self.replica_exchange = replica_exchange
485 if not self.replica_exchange:
489 self.best_score_list = []
493 self.best_score_file_name = best_score_file
494 self.best_score_list = []
495 with open(self.best_score_file_name,
"w")
as best_score_file:
496 best_score_file.write(
497 "self.best_score_list=" + str(self.best_score_list) +
"\n")
499 self.nbestscoring = nbestscoring
500 for i
in range(self.nbestscoring):
501 name = prefix +
"." + str(i) + fileext
502 flpdb = open(name,
'w')
504 self.dictionary_pdbs[name] = prot
505 self._pdb_mmcif[name] = mmcif
506 self._init_dictchain(name, prot, mmcif=mmcif)
508 def write_pdb_best_scoring(self, score):
509 if self.nbestscoring
is None:
510 print(
"Output.write_pdb_best_scoring: init_pdb_best_scoring "
513 mmcif = self._pdb_best_scoring_mmcif
514 fileext =
'.cif' if mmcif
else '.pdb'
516 if self.replica_exchange:
518 with open(self.best_score_file_name)
as fh:
519 self.best_score_list = ast.literal_eval(
520 fh.read().split(
'=')[1])
522 if len(self.best_score_list) < self.nbestscoring:
523 self.best_score_list.append(score)
524 self.best_score_list.sort()
525 index = self.best_score_list.index(score)
526 for prefix
in self.prefixes:
527 for i
in range(len(self.best_score_list) - 2, index - 1, -1):
528 oldname = prefix +
"." + str(i) + fileext
529 newname = prefix +
"." + str(i + 1) + fileext
531 if os.path.exists(newname):
533 os.rename(oldname, newname)
534 filetoadd = prefix +
"." + str(index) + fileext
535 self.write_pdb(filetoadd, appendmode=
False)
538 if score < self.best_score_list[-1]:
539 self.best_score_list.append(score)
540 self.best_score_list.sort()
541 self.best_score_list.pop(-1)
542 index = self.best_score_list.index(score)
543 for prefix
in self.prefixes:
544 for i
in range(len(self.best_score_list) - 1,
546 oldname = prefix +
"." + str(i) + fileext
547 newname = prefix +
"." + str(i + 1) + fileext
548 os.rename(oldname, newname)
549 filenametoremove = prefix + \
550 "." + str(self.nbestscoring) + fileext
551 os.remove(filenametoremove)
552 filetoadd = prefix +
"." + str(index) + fileext
553 self.write_pdb(filetoadd, appendmode=
False)
555 if self.replica_exchange:
557 with open(self.best_score_file_name,
"w")
as best_score_file:
558 best_score_file.write(
559 "self.best_score_list=" + str(self.best_score_list) +
'\n')
561 def init_rmf(self, name, hierarchies, rs=None, geometries=None,
564 Initialize an RMF file
566 @param name the name of the RMF file
567 @param hierarchies the hierarchies to be included (it is a list)
568 @param rs optional, the restraint sets (it is a list)
569 @param geometries optional, the geometries (it is a list)
570 @param listofobjects optional, the list of objects for the stat
573 rh = RMF.create_rmf_file(name)
576 outputkey_rmfkey =
None
580 if geometries
is not None:
582 if listofobjects
is not None:
583 cat = rh.get_category(
"stat")
584 outputkey_rmfkey = {}
585 for o
in listofobjects:
586 if "get_output" not in dir(o):
588 "Output: object %s doesn't have get_output() method"
590 output = o.get_output()
591 for outputkey
in output:
592 rmftag = RMF.string_tag
593 if isinstance(output[outputkey], float):
594 rmftag = RMF.float_tag
595 elif isinstance(output[outputkey], int):
597 elif isinstance(output[outputkey], str):
598 rmftag = RMF.string_tag
600 rmftag = RMF.string_tag
601 rmfkey = rh.get_key(cat, outputkey, rmftag)
602 outputkey_rmfkey[outputkey] = rmfkey
603 outputkey_rmfkey[
"rmf_file"] = \
604 rh.get_key(cat,
"rmf_file", RMF.string_tag)
605 outputkey_rmfkey[
"rmf_frame_index"] = \
606 rh.get_key(cat,
"rmf_frame_index", RMF.int_tag)
608 self.dictionary_rmfs[name] = (rh, cat, outputkey_rmfkey, listofobjects)
610 def add_restraints_to_rmf(self, name, objectlist):
611 for o
in _flatten(objectlist):
613 rs = o.get_restraint_for_rmf()
614 if not isinstance(rs, (list, tuple)):
617 rs = [o.get_restraint()]
619 self.dictionary_rmfs[name][0], rs)
621 def add_geometries_to_rmf(self, name, objectlist):
623 geos = o.get_geometries()
626 def add_particle_pair_from_restraints_to_rmf(self, name, objectlist):
629 pps = o.get_particle_pairs()
632 self.dictionary_rmfs[name][0],
635 def write_rmf(self, name):
637 if self.dictionary_rmfs[name][1]
is not None:
638 outputkey_rmfkey = self.dictionary_rmfs[name][2]
639 listofobjects = self.dictionary_rmfs[name][3]
640 for o
in listofobjects:
641 output = o.get_output()
642 for outputkey
in output:
643 rmfkey = outputkey_rmfkey[outputkey]
645 n = self.dictionary_rmfs[name][0].get_root_node()
646 n.set_value(rmfkey, output[outputkey])
647 except NotImplementedError:
649 rmfkey = outputkey_rmfkey[
"rmf_file"]
650 self.dictionary_rmfs[name][0].get_root_node().set_value(
652 rmfkey = outputkey_rmfkey[
"rmf_frame_index"]
654 self.dictionary_rmfs[name][0].get_root_node().set_value(
656 self.dictionary_rmfs[name][0].flush()
658 def close_rmf(self, name):
659 rh = self.dictionary_rmfs[name][0]
660 del self.dictionary_rmfs[name]
663 def write_rmfs(self):
664 for rmfinfo
in self.dictionary_rmfs.keys():
665 self.write_rmf(rmfinfo[0])
667 def init_stat(self, name, listofobjects):
669 flstat = open(name,
'w')
672 flstat = open(name,
'wb')
676 for o
in listofobjects:
677 if "get_output" not in dir(o):
679 "Output: object %s doesn't have get_output() method"
681 self.dictionary_stats[name] = listofobjects
683 def set_output_entry(self, key, value):
684 self.initoutput.update({key: value})
686 def write_stat(self, name, appendmode=True):
687 output = self.initoutput
688 for obj
in self.dictionary_stats[name]:
691 dfiltered = dict((k, v)
for k, v
in d.items()
if k[0] !=
"_")
692 output.update(dfiltered)
700 flstat = open(name, writeflag)
701 flstat.write(
"%s \n" % output)
704 flstat = open(name, writeflag +
'b')
705 pickle.dump(output, flstat, 2)
708 def write_stats(self):
709 for stat
in self.dictionary_stats.keys():
710 self.write_stat(stat)
712 def get_stat(self, name):
714 for obj
in self.dictionary_stats[name]:
715 output.update(obj.get_output())
718 def write_test(self, name, listofobjects):
719 flstat = open(name,
'w')
720 output = self.initoutput
721 for o
in listofobjects:
722 if "get_test_output" not in dir(o)
and "get_output" not in dir(o):
724 "Output: object %s doesn't have get_output() or "
725 "get_test_output() method" % str(o))
726 self.dictionary_stats[name] = listofobjects
728 for obj
in self.dictionary_stats[name]:
730 d = obj.get_test_output()
734 dfiltered = dict((k, v)
for k, v
in d.items()
if k[0] !=
"_")
735 output.update(dfiltered)
736 flstat.write(
"%s \n" % output)
739 def test(self, name, listofobjects, tolerance=1e-5):
740 output = self.initoutput
741 for o
in listofobjects:
742 if "get_test_output" not in dir(o)
and "get_output" not in dir(o):
744 "Output: object %s doesn't have get_output() or "
745 "get_test_output() method" % str(o))
746 for obj
in listofobjects:
748 output.update(obj.get_test_output())
750 output.update(obj.get_output())
752 flstat = open(name,
'r')
756 test_dict = ast.literal_eval(fl)
759 old_value = str(test_dict[k])
760 new_value = str(output[k])
768 fold = float(old_value)
769 fnew = float(new_value)
770 diff = abs(fold - fnew)
772 print(
"%s: test failed, old value: %s new value %s; "
773 "diff %f > %f" % (str(k), str(old_value),
774 str(new_value), diff,
775 tolerance), file=sys.stderr)
777 elif test_dict[k] != output[k]:
778 if len(old_value) < 50
and len(new_value) < 50:
779 print(
"%s: test failed, old value: %s new value %s"
780 % (str(k), old_value, new_value),
784 print(
"%s: test failed, omitting results (too long)"
785 % str(k), file=sys.stderr)
789 print(
"%s from old objects (file %s) not in new objects"
790 % (str(k), str(name)), file=sys.stderr)
794 def get_environment_variables(self):
796 return str(os.environ)
798 def get_versions_of_relevant_modules(self):
805 versions[
"ISD2_VERSION"] = IMP.isd2.get_module_version()
810 versions[
"ISD_EMXL_VERSION"] = IMP.isd_emxl.get_module_version()
815 def init_stat2(self, name, listofobjects, extralabels=None,
816 listofsummedobjects=
None):
823 if listofsummedobjects
is None:
824 listofsummedobjects = []
825 if extralabels
is None:
827 flstat = open(name,
'w')
829 stat2_keywords = {
"STAT2HEADER":
"STAT2HEADER"}
830 stat2_keywords.update(
831 {
"STAT2HEADER_ENVIRON": str(self.get_environment_variables())})
832 stat2_keywords.update(
833 {
"STAT2HEADER_IMP_VERSIONS":
834 str(self.get_versions_of_relevant_modules())})
837 for obj
in listofobjects:
838 if "get_output" not in dir(obj):
840 "Output: object %s doesn't have get_output() method"
845 dfiltered = dict((k, v)
846 for k, v
in d.items()
if k[0] !=
"_")
847 output.update(dfiltered)
850 for obj
in listofsummedobjects:
852 if "get_output" not in dir(t):
854 "Output: object %s doesn't have get_output() method"
857 if "_TotalScore" not in t.get_output():
859 "Output: object %s doesn't have _TotalScore "
860 "entry to be summed" % str(t))
862 output.update({obj[1]: 0.0})
864 for k
in extralabels:
865 output.update({k: 0.0})
867 for n, k
in enumerate(output):
868 stat2_keywords.update({n: k})
869 stat2_inverse.update({k: n})
871 flstat.write(
"%s \n" % stat2_keywords)
873 self.dictionary_stats2[name] = (
879 def write_stat2(self, name, appendmode=True):
881 (listofobjects, stat2_inverse, listofsummedobjects,
882 extralabels) = self.dictionary_stats2[name]
885 for obj
in listofobjects:
886 od = obj.get_output()
887 dfiltered = dict((k, v)
for k, v
in od.items()
if k[0] !=
"_")
889 output.update({stat2_inverse[k]: od[k]})
892 for so
in listofsummedobjects:
896 partial_score += float(d[
"_TotalScore"])
897 output.update({stat2_inverse[so[1]]: str(partial_score)})
900 for k
in extralabels:
901 if k
in self.initoutput:
902 output.update({stat2_inverse[k]: self.initoutput[k]})
904 output.update({stat2_inverse[k]:
"None"})
911 flstat = open(name, writeflag)
912 flstat.write(
"%s \n" % output)
915 def write_stats2(self):
916 for stat
in self.dictionary_stats2.keys():
917 self.write_stat2(stat)
921 """Collect statistics from ProcessOutput.get_fields().
922 Counters of the total number of frames read, plus the models that
923 passed the various filters used in get_fields(), are provided."""
926 self.passed_get_every = 0
927 self.passed_filterout = 0
928 self.passed_filtertuple = 0
932 """A class for reading stat files (either rmf or ascii v1 and v2)"""
933 def __init__(self, filename):
934 self.filename = filename
939 if self.filename
is None:
940 raise ValueError(
"No file name provided. Use -h for help")
944 rh = RMF.open_rmf_file_read_only(self.filename)
946 cat = rh.get_category(
'stat')
947 rmf_klist = rh.get_keys(cat)
948 self.rmf_names_keys = dict([(rh.get_name(k), k)
953 f = open(self.filename,
"r")
956 for line
in f.readlines():
957 d = ast.literal_eval(line)
958 self.klist = list(d.keys())
960 if "STAT2HEADER" in self.klist:
963 if "STAT2HEADER" in str(k):
969 for k
in sorted(stat2_dict.items(),
970 key=operator.itemgetter(1))]
972 for k
in sorted(stat2_dict.items(),
973 key=operator.itemgetter(1))]
974 self.invstat2_dict = {}
976 self.invstat2_dict.update({stat2_dict[k]: k})
979 "statfile v1 is deprecated. "
980 "Please convert to statfile v2.\n")
989 return sorted(self.rmf_names_keys.keys())
993 def show_keys(self, ncolumns=2, truncate=65):
994 IMP.pmi.tools.print_multicolumn(self.get_keys(), ncolumns, truncate)
996 def get_fields(self, fields, filtertuple=None, filterout=None, get_every=1,
999 Get the desired field names, and return a dictionary.
1000 Namely, "fields" are the queried keys in the stat file
1001 (eg. ["Total_Score",...])
1002 The returned data structure is a dictionary, where each key is
1003 a field and the value is the time series (ie, frame ordered series)
1004 of that field (ie, {"Total_Score":[Score_0,Score_1,Score_2,,...],....})
1006 @param fields (list of strings) queried keys in the stat file
1007 (eg. "Total_Score"....)
1008 @param filterout specify if you want to "grep" out something from
1009 the file, so that it is faster
1010 @param filtertuple a tuple that contains
1011 ("TheKeyToBeFiltered",relationship,value)
1012 where relationship = "<", "==", or ">"
1013 @param get_every only read every Nth line from the file
1014 @param statistics if provided, accumulate statistics in an
1015 OutputStatistics object
1018 if statistics
is None:
1021 for field
in fields:
1026 rh = RMF.open_rmf_file_read_only(self.filename)
1027 nframes = rh.get_number_of_frames()
1028 for i
in range(nframes):
1029 statistics.total += 1
1031 statistics.passed_get_every += 1
1032 statistics.passed_filterout += 1
1033 rh.set_current_frame(RMF.FrameID(i))
1034 if filtertuple
is not None:
1035 keytobefiltered = filtertuple[0]
1036 relationship = filtertuple[1]
1037 value = filtertuple[2]
1038 datavalue = rh.get_root_node().get_value(
1039 self.rmf_names_keys[keytobefiltered])
1040 if self.isfiltered(datavalue, relationship, value):
1043 statistics.passed_filtertuple += 1
1044 for field
in fields:
1045 outdict[field].append(rh.get_root_node().get_value(
1046 self.rmf_names_keys[field]))
1049 f = open(self.filename,
"r")
1052 for line
in f.readlines():
1053 statistics.total += 1
1054 if filterout
is not None:
1055 if filterout
in line:
1057 statistics.passed_filterout += 1
1060 if line_number % get_every != 0:
1061 if line_number == 1
and self.isstat2:
1062 statistics.total -= 1
1063 statistics.passed_filterout -= 1
1065 statistics.passed_get_every += 1
1067 d = ast.literal_eval(line)
1069 print(
"# Warning: skipped line number " + str(line_number)
1070 +
" not a valid line")
1075 if filtertuple
is not None:
1076 keytobefiltered = filtertuple[0]
1077 relationship = filtertuple[1]
1078 value = filtertuple[2]
1079 datavalue = d[keytobefiltered]
1080 if self.isfiltered(datavalue, relationship, value):
1083 statistics.passed_filtertuple += 1
1084 [outdict[field].append(d[field])
for field
in fields]
1087 if line_number == 1:
1088 statistics.total -= 1
1089 statistics.passed_filterout -= 1
1090 statistics.passed_get_every -= 1
1093 if filtertuple
is not None:
1094 keytobefiltered = filtertuple[0]
1095 relationship = filtertuple[1]
1096 value = filtertuple[2]
1097 datavalue = d[self.invstat2_dict[keytobefiltered]]
1098 if self.isfiltered(datavalue, relationship, value):
1101 statistics.passed_filtertuple += 1
1102 [outdict[field].append(d[self.invstat2_dict[field]])
1103 for field
in fields]
1109 def isfiltered(self, datavalue, relationship, refvalue):
1112 _ = float(datavalue)
1114 raise ValueError(
"ProcessOutput.filter: datavalue cannot be "
1115 "converted into a float")
1117 if relationship ==
"<":
1118 if float(datavalue) >= refvalue:
1120 if relationship ==
">":
1121 if float(datavalue) <= refvalue:
1123 if relationship ==
"==":
1124 if float(datavalue) != refvalue:
1130 """ class to allow more advanced handling of RMF files.
1131 It is both a container and a IMP.atom.Hierarchy.
1132 - it is iterable (while loading the corresponding frame)
1133 - Item brackets [] load the corresponding frame
1134 - slice create an iterator
1135 - can relink to another RMF file
1139 @param model: the IMP.Model()
1140 @param rmf_file_name: str, path of the rmf file
1144 self.rh_ref = RMF.open_rmf_file_read_only(rmf_file_name)
1146 raise TypeError(
"Wrong rmf file name or type: %s"
1147 % str(rmf_file_name))
1150 self.root_hier_ref = hs[0]
1151 super().
__init__(self.root_hier_ref)
1153 self.ColorHierarchy =
None
1157 Link to another RMF file
1159 self.rh_ref = RMF.open_rmf_file_read_only(rmf_file_name)
1161 if self.ColorHierarchy:
1162 self.ColorHierarchy.method()
1163 RMFHierarchyHandler.set_frame(self, 0)
1165 def set_frame(self, index):
1169 print(
"skipping frame %s:%d\n" % (self.current_rmf, index))
1173 return self.rh_ref.get_number_of_frames()
1175 def __getitem__(self, int_slice_adaptor):
1176 if isinstance(int_slice_adaptor, int):
1177 self.set_frame(int_slice_adaptor)
1178 return int_slice_adaptor
1179 elif isinstance(int_slice_adaptor, slice):
1180 return self.__iter__(int_slice_adaptor)
1182 raise TypeError(
"Unknown Type")
1185 return self.get_number_of_frames()
1187 def __iter__(self, slice_key=None):
1188 if slice_key
is None:
1189 for nframe
in range(len(self)):
1192 for nframe
in list(range(len(self)))[slice_key]:
1196 class CacheHierarchyCoordinates:
1197 def __init__(self, StatHierarchyHandler):
1204 self.current_index =
None
1205 self.rmfh = StatHierarchyHandler
1207 self.model = self.rmfh.get_model()
1212 self.nrms.append(nrm)
1215 self.xyzs.append(fb)
1217 def do_store(self, index):
1218 self.rb_trans[index] = {}
1219 self.nrm_coors[index] = {}
1220 self.xyz_coors[index] = {}
1222 self.rb_trans[index][rb] = rb.get_reference_frame()
1223 for nrm
in self.nrms:
1224 self.nrm_coors[index][nrm] = nrm.get_internal_coordinates()
1225 for xyz
in self.xyzs:
1226 self.xyz_coors[index][xyz] = xyz.get_coordinates()
1227 self.current_index = index
1229 def do_update(self, index):
1230 if self.current_index != index:
1232 rb.set_reference_frame(self.rb_trans[index][rb])
1233 for nrm
in self.nrms:
1234 nrm.set_internal_coordinates(self.nrm_coors[index][nrm])
1235 for xyz
in self.xyzs:
1236 xyz.set_coordinates(self.xyz_coors[index][xyz])
1237 self.current_index = index
1241 return len(self.rb_trans.keys())
1243 def __getitem__(self, index):
1244 if isinstance(index, int):
1245 return index
in self.rb_trans.keys()
1247 raise TypeError(
"Unknown Type")
1250 return self.get_number_of_frames()
1254 """ class to link stat files to several rmf files """
1255 def __init__(self, model=None, stat_file=None,
1256 number_best_scoring_models=
None, score_key=
None,
1257 StatHierarchyHandler=
None, cache=
None):
1260 @param model: IMP.Model()
1261 @param stat_file: either 1) a list or 2) a single stat file names
1262 (either rmfs or ascii, or pickled data or pickled cluster),
1263 3) a dictionary containing an rmf/ascii
1264 stat file name as key and a list of frames as values
1265 @param number_best_scoring_models:
1266 @param StatHierarchyHandler: copy constructor input object
1267 @param cache: cache coordinates and rigid body transformations.
1270 if StatHierarchyHandler
is not None:
1274 self.model = StatHierarchyHandler.model
1275 self.data = StatHierarchyHandler.data
1276 self.number_best_scoring_models = \
1277 StatHierarchyHandler.number_best_scoring_models
1278 self.is_setup =
True
1279 self.current_rmf = StatHierarchyHandler.current_rmf
1280 self.current_frame =
None
1281 self.current_index =
None
1282 self.score_threshold = StatHierarchyHandler.score_threshold
1283 self.score_key = StatHierarchyHandler.score_key
1284 self.cache = StatHierarchyHandler.cache
1285 super().
__init__(self.model, self.current_rmf)
1287 self.cache = CacheHierarchyCoordinates(self)
1296 self.number_best_scoring_models = number_best_scoring_models
1299 if score_key
is None:
1300 self.score_key =
"Total_Score"
1302 self.score_key = score_key
1303 self.is_setup =
None
1304 self.current_rmf =
None
1305 self.current_frame =
None
1306 self.current_index =
None
1307 self.score_threshold =
None
1309 if isinstance(stat_file, str):
1310 self.add_stat_file(stat_file)
1311 elif isinstance(stat_file, list):
1313 self.add_stat_file(f)
1315 def add_stat_file(self, stat_file):
1317 '''check that it is not a pickle file with saved data
1318 from a previous calculation'''
1319 self.load_data(stat_file)
1321 if self.number_best_scoring_models:
1322 scores = self.get_scores()
1323 max_score = sorted(scores)[
1324 0:min(len(self), self.number_best_scoring_models)][-1]
1325 self.do_filter_by_score(max_score)
1327 except pickle.UnpicklingError:
1328 '''alternatively read the ascii stat files'''
1330 scores, rmf_files, rmf_frame_indexes, features = \
1331 self.get_info_from_stat_file(stat_file,
1332 self.score_threshold)
1333 except (KeyError, SyntaxError):
1338 rh = RMF.open_rmf_file_read_only(stat_file)
1339 nframes = rh.get_number_of_frames()
1340 scores = [0.0]*nframes
1341 rmf_files = [stat_file]*nframes
1342 rmf_frame_indexes = range(nframes)
1347 if len(set(rmf_files)) > 1:
1348 raise (
"Multiple RMF files found")
1351 print(
"StatHierarchyHandler: Error: Trying to set none as "
1352 "rmf_file (probably empty stat file), aborting")
1355 for n, index
in enumerate(rmf_frame_indexes):
1356 featn_dict = dict([(k, features[k][n])
for k
in features])
1358 stat_file, rmf_files[n], index, scores[n], featn_dict))
1360 if self.number_best_scoring_models:
1361 scores = self.get_scores()
1362 max_score = sorted(scores)[
1363 0:min(len(self), self.number_best_scoring_models)][-1]
1364 self.do_filter_by_score(max_score)
1366 if not self.is_setup:
1367 RMFHierarchyHandler.__init__(
1368 self, self.model, self.get_rmf_names()[0])
1370 self.cache = CacheHierarchyCoordinates(self)
1373 self.is_setup =
True
1374 self.current_rmf = self.get_rmf_names()[0]
1378 def save_data(self, filename='data.pkl'):
1379 with open(filename,
'wb')
as fl:
1380 pickle.dump(self.data, fl)
1382 def load_data(self, filename='data.pkl'):
1383 with open(filename,
'rb')
as fl:
1384 data_structure = pickle.load(fl)
1386 if not isinstance(data_structure, list):
1388 "%filename should contain a list of IMP.pmi.output.DataEntry "
1389 "or IMP.pmi.output.Cluster" % filename)
1392 for item
in data_structure):
1393 self.data = data_structure
1395 for item
in data_structure):
1397 for cluster
in data_structure:
1398 nmodels += len(cluster)
1399 self.data = [
None]*nmodels
1400 for cluster
in data_structure:
1401 for n, data
in enumerate(cluster):
1402 index = cluster.members[n]
1403 self.data[index] = data
1406 "%filename should contain a list of IMP.pmi.output.DataEntry "
1407 "or IMP.pmi.output.Cluster" % filename)
1409 def set_frame(self, index):
1410 if self.cache
is not None and self.cache[index]:
1411 self.cache.do_update(index)
1413 nm = self.data[index].rmf_name
1414 fidx = self.data[index].rmf_index
1415 if nm != self.current_rmf:
1417 self.current_rmf = nm
1418 self.current_frame = -1
1419 if fidx != self.current_frame:
1420 RMFHierarchyHandler.set_frame(self, fidx)
1421 self.current_frame = fidx
1422 if self.cache
is not None:
1423 self.cache.do_store(index)
1425 self.current_index = index
1427 def __getitem__(self, int_slice_adaptor):
1428 if isinstance(int_slice_adaptor, int):
1429 self.set_frame(int_slice_adaptor)
1430 return self.data[int_slice_adaptor]
1431 elif isinstance(int_slice_adaptor, slice):
1432 return self.__iter__(int_slice_adaptor)
1434 raise TypeError(
"Unknown Type")
1437 return len(self.data)
1439 def __iter__(self, slice_key=None):
1440 if slice_key
is None:
1441 for i
in range(len(self)):
1444 for i
in range(len(self))[slice_key]:
1447 def do_filter_by_score(self, maximum_score):
1448 self.data = [d
for d
in self.data
if d.score <= maximum_score]
1450 def get_scores(self):
1451 return [d.score
for d
in self.data]
1453 def get_feature_series(self, feature_name):
1454 return [d.features[feature_name]
for d
in self.data]
1456 def get_feature_names(self):
1457 return self.data[0].features.keys()
1459 def get_rmf_names(self):
1460 return [d.rmf_name
for d
in self.data]
1462 def get_stat_files_names(self):
1463 return [d.stat_file
for d
in self.data]
1465 def get_rmf_indexes(self):
1466 return [d.rmf_index
for d
in self.data]
1468 def get_info_from_stat_file(self, stat_file, score_threshold=None):
1472 [stat_file], score_key=self.score_key, feature_keys=fs,
1473 rmf_file_key=
"rmf_file", rmf_file_frame_key=
"rmf_frame_index",
1474 prefiltervalue=score_threshold, get_every=1)
1476 scores = [float(y)
for y
in models[2]]
1477 rmf_files = models[0]
1478 rmf_frame_indexes = models[1]
1479 features = models[3]
1480 return scores, rmf_files, rmf_frame_indexes, features
1485 A class to store data associated to a model
1487 def __init__(self, stat_file=None, rmf_name=None, rmf_index=None,
1488 score=
None, features=
None):
1489 self.rmf_name = rmf_name
1490 self.rmf_index = rmf_index
1492 self.features = features
1493 self.stat_file = stat_file
1496 s =
"IMP.pmi.output.DataEntry\n"
1497 s +=
"---- stat file %s \n" % (self.stat_file)
1498 s +=
"---- rmf file %s \n" % (self.rmf_name)
1499 s +=
"---- rmf index %s \n" % (str(self.rmf_index))
1500 s +=
"---- score %s \n" % (str(self.score))
1501 s +=
"---- number of features %s \n" % (str(len(self.features.keys())))
1507 A container for models organized into clusters
1509 def __init__(self, cid=None):
1510 self.cluster_id = cid
1512 self.precision =
None
1513 self.center_index =
None
1514 self.members_data = {}
1516 def add_member(self, index, data=None):
1517 self.members.append(index)
1518 self.members_data[index] = data
1519 self.average_score = self.compute_score()
1521 def compute_score(self):
1523 score = sum([d.score
for d
in self])/len(self)
1524 except AttributeError:
1529 s =
"IMP.pmi.output.Cluster\n"
1530 s +=
"---- cluster_id %s \n" % str(self.cluster_id)
1531 s +=
"---- precision %s \n" % str(self.precision)
1532 s +=
"---- average score %s \n" % str(self.average_score)
1533 s +=
"---- number of members %s \n" % str(len(self.members))
1534 s +=
"---- center index %s \n" % str(self.center_index)
1537 def __getitem__(self, int_slice_adaptor):
1538 if isinstance(int_slice_adaptor, int):
1539 index = self.members[int_slice_adaptor]
1540 return self.members_data[index]
1541 elif isinstance(int_slice_adaptor, slice):
1542 return self.__iter__(int_slice_adaptor)
1544 raise TypeError(
"Unknown Type")
1547 return len(self.members)
1549 def __iter__(self, slice_key=None):
1550 if slice_key
is None:
1551 for i
in range(len(self)):
1554 for i
in range(len(self))[slice_key]:
1557 def __add__(self, other):
1558 self.members += other.members
1559 self.members_data.update(other.members_data)
1560 self.average_score = self.compute_score()
1561 self.precision =
None
1562 self.center_index =
None
1566 def plot_clusters_populations(clusters):
1569 for cluster
in clusters:
1570 indexes.append(cluster.cluster_id)
1571 populations.append(len(cluster))
1573 import matplotlib.pyplot
as plt
1574 fig, ax = plt.subplots()
1575 ax.bar(indexes, populations, 0.5, color=
'r')
1576 ax.set_ylabel('Population')
1577 ax.set_xlabel((
'Cluster index'))
1581 def plot_clusters_precisions(clusters):
1584 for cluster
in clusters:
1585 indexes.append(cluster.cluster_id)
1587 prec = cluster.precision
1588 print(cluster.cluster_id, prec)
1591 precisions.append(prec)
1593 import matplotlib.pyplot
as plt
1594 fig, ax = plt.subplots()
1595 ax.bar(indexes, precisions, 0.5, color=
'r')
1596 ax.set_ylabel('Precision [A]')
1597 ax.set_xlabel((
'Cluster index'))
1601 def plot_clusters_scores(clusters):
1604 for cluster
in clusters:
1605 indexes.append(cluster.cluster_id)
1607 for data
in cluster:
1608 values[-1].append(data.score)
1611 valuename=
"Scores", positionname=
"Cluster index",
1612 xlabels=
None, scale_plot_length=1.0)
1615 class CrossLinkIdentifierDatabase:
1619 def check_key(self, key):
1620 if key
not in self.clidb:
1621 self.clidb[key] = {}
1623 def set_unique_id(self, key, value):
1625 self.clidb[key][
"XLUniqueID"] = str(value)
1627 def set_protein1(self, key, value):
1629 self.clidb[key][
"Protein1"] = str(value)
1631 def set_protein2(self, key, value):
1633 self.clidb[key][
"Protein2"] = str(value)
1635 def set_residue1(self, key, value):
1637 self.clidb[key][
"Residue1"] = int(value)
1639 def set_residue2(self, key, value):
1641 self.clidb[key][
"Residue2"] = int(value)
1643 def set_idscore(self, key, value):
1645 self.clidb[key][
"IDScore"] = float(value)
1647 def set_state(self, key, value):
1649 self.clidb[key][
"State"] = int(value)
1651 def set_sigma1(self, key, value):
1653 self.clidb[key][
"Sigma1"] = str(value)
1655 def set_sigma2(self, key, value):
1657 self.clidb[key][
"Sigma2"] = str(value)
1659 def set_psi(self, key, value):
1661 self.clidb[key][
"Psi"] = str(value)
1663 def get_unique_id(self, key):
1664 return self.clidb[key][
"XLUniqueID"]
1666 def get_protein1(self, key):
1667 return self.clidb[key][
"Protein1"]
1669 def get_protein2(self, key):
1670 return self.clidb[key][
"Protein2"]
1672 def get_residue1(self, key):
1673 return self.clidb[key][
"Residue1"]
1675 def get_residue2(self, key):
1676 return self.clidb[key][
"Residue2"]
1678 def get_idscore(self, key):
1679 return self.clidb[key][
"IDScore"]
1681 def get_state(self, key):
1682 return self.clidb[key][
"State"]
1684 def get_sigma1(self, key):
1685 return self.clidb[key][
"Sigma1"]
1687 def get_sigma2(self, key):
1688 return self.clidb[key][
"Sigma2"]
1690 def get_psi(self, key):
1691 return self.clidb[key][
"Psi"]
1693 def set_float_feature(self, key, value, feature_name):
1695 self.clidb[key][feature_name] = float(value)
1697 def set_int_feature(self, key, value, feature_name):
1699 self.clidb[key][feature_name] = int(value)
1701 def set_string_feature(self, key, value, feature_name):
1703 self.clidb[key][feature_name] = str(value)
1705 def get_feature(self, key, feature_name):
1706 return self.clidb[key][feature_name]
1708 def write(self, filename):
1709 with open(filename,
'wb')
as handle:
1710 pickle.dump(self.clidb, handle)
1712 def load(self, filename):
1713 with open(filename,
'rb')
as handle:
1714 self.clidb = pickle.load(handle)
1718 """Plot the given fields and save a figure as `output`.
1719 The fields generally are extracted from a stat file
1720 using ProcessOutput.get_fields()."""
1721 import matplotlib
as mpl
1723 import matplotlib.pyplot
as plt
1725 plt.rc(
'lines', linewidth=4)
1726 fig, axs = plt.subplots(nrows=len(fields))
1727 fig.set_size_inches(10.5, 5.5 * len(fields))
1732 if framemin
is None:
1734 if framemax
is None:
1735 framemax = len(fields[key])
1736 x = list(range(framemin, framemax))
1737 y = [float(y)
for y
in fields[key][framemin:framemax]]
1740 axs[n].set_title(key, size=
"xx-large")
1741 axs[n].tick_params(labelsize=18, pad=10)
1744 axs.set_title(key, size=
"xx-large")
1745 axs.tick_params(labelsize=18, pad=10)
1749 plt.subplots_adjust(hspace=0.3)
1754 colors=
None, format=
"png", reference_xline=
None,
1755 yplotrange=
None, xplotrange=
None, normalized=
True,
1757 '''Plot a list of histograms from a value list.
1758 @param name the name of the plot
1759 @param values_lists the list of list of values eg: [[...],[...],[...]]
1760 @param valuename the y-label
1761 @param bins the number of bins
1762 @param colors If None, will use rainbow. Else will use specific list
1763 @param format output format
1764 @param reference_xline plot a reference line parallel to the y-axis
1765 @param yplotrange the range for the y-axis
1766 @param normalized whether the histogram is normalized or not
1767 @param leg_names names for the legend
1770 import matplotlib
as mpl
1772 import matplotlib.pyplot
as plt
1773 import matplotlib.cm
as cm
1774 plt.figure(figsize=(18.0, 9.0))
1777 colors = cm.rainbow(np.linspace(0, 1, len(values_lists)))
1778 for nv, values
in enumerate(values_lists):
1780 if leg_names
is not None:
1781 label = leg_names[nv]
1786 [float(y)
for y
in values], bins=bins, color=col,
1787 density=normalized, histtype=
'step', lw=4, label=label)
1788 except AttributeError:
1790 [float(y)
for y
in values], bins=bins, color=col,
1791 normed=normalized, histtype=
'step', lw=4, label=label)
1794 plt.tick_params(labelsize=12, pad=10)
1795 if valuename
is None:
1796 plt.xlabel(name, size=
"xx-large")
1798 plt.xlabel(valuename, size=
"xx-large")
1799 plt.ylabel(
"Frequency", size=
"xx-large")
1801 if yplotrange
is not None:
1803 if xplotrange
is not None:
1804 plt.xlim(xplotrange)
1808 if reference_xline
is not None:
1815 plt.savefig(name +
"." + format, dpi=150, transparent=
True)
1819 valuename=
"None", positionname=
"None",
1820 xlabels=
None, scale_plot_length=1.0):
1822 Plot time series as boxplots.
1823 fields is a list of time series, positions are the x-values
1824 valuename is the y-label, positionname is the x-label
1827 import matplotlib
as mpl
1829 import matplotlib.pyplot
as plt
1832 fig = plt.figure(figsize=(float(len(positions))*scale_plot_length, 5.0))
1833 fig.canvas.manager.set_window_title(name)
1835 ax1 = fig.add_subplot(111)
1837 plt.subplots_adjust(left=0.1, right=0.990, top=0.95, bottom=0.4)
1839 bps.append(plt.boxplot(values, notch=0, sym=
'', vert=1,
1840 whis=1.5, positions=positions))
1842 plt.setp(bps[-1][
'boxes'], color=
'black', lw=1.5)
1843 plt.setp(bps[-1][
'whiskers'], color=
'black', ls=
":", lw=1.5)
1845 if frequencies
is not None:
1846 for n, v
in enumerate(values):
1847 plist = [positions[n]]*len(v)
1848 ax1.plot(plist, v,
'gx', alpha=0.7, markersize=7)
1851 if xlabels
is not None:
1852 ax1.set_xticklabels(xlabels)
1853 plt.xticks(rotation=90)
1854 plt.xlabel(positionname)
1855 plt.ylabel(valuename)
1857 plt.savefig(name +
".pdf", dpi=150)
1861 def plot_xy_data(x, y, title=None, out_fn=None, display=True,
1862 set_plot_yaxis_range=
None, xlabel=
None, ylabel=
None):
1863 import matplotlib
as mpl
1865 import matplotlib.pyplot
as plt
1866 plt.rc(
'lines', linewidth=2)
1868 fig, ax = plt.subplots(nrows=1)
1869 fig.set_size_inches(8, 4.5)
1870 if title
is not None:
1871 fig.canvas.manager.set_window_title(title)
1873 ax.plot(x, y, color=
'r')
1874 if set_plot_yaxis_range
is not None:
1875 x1, x2, y1, y2 = plt.axis()
1876 y1 = set_plot_yaxis_range[0]
1877 y2 = set_plot_yaxis_range[1]
1878 plt.axis((x1, x2, y1, y2))
1879 if title
is not None:
1881 if xlabel
is not None:
1882 ax.set_xlabel(xlabel)
1883 if ylabel
is not None:
1884 ax.set_ylabel(ylabel)
1885 if out_fn
is not None:
1886 plt.savefig(out_fn +
".pdf")
1892 def plot_scatter_xy_data(x, y, labelx="None", labely="None",
1893 xmin=
None, xmax=
None, ymin=
None, ymax=
None,
1894 savefile=
False, filename=
"None.eps", alpha=0.75):
1896 import matplotlib
as mpl
1898 import matplotlib.pyplot
as plt
1899 from matplotlib
import rc
1900 rc(
'font', **{
'family':
'sans-serif',
'sans-serif': [
'Helvetica']})
1902 fig, axs = plt.subplots(1)
1906 axs0.set_xlabel(labelx, size=
"xx-large")
1907 axs0.set_ylabel(labely, size=
"xx-large")
1908 axs0.tick_params(labelsize=18, pad=10)
1912 plot2.append(axs0.plot(x, y,
'o', color=
'k', lw=2, ms=0.1, alpha=alpha,
1922 fig.set_size_inches(8.0, 8.0)
1923 fig.subplots_adjust(left=0.161, right=0.850, top=0.95, bottom=0.11)
1924 if (ymin
is not None)
and (ymax
is not None):
1925 axs0.set_ylim(ymin, ymax)
1926 if (xmin
is not None)
and (xmax
is not None):
1927 axs0.set_xlim(xmin, xmax)
1930 fig.savefig(filename, dpi=300)
1933 def get_graph_from_hierarchy(hier):
1937 (graph, depth, depth_dict) = recursive_graph(
1938 hier, graph, depth, depth_dict)
1941 node_labels_dict = {}
1942 for key
in depth_dict:
1943 if depth_dict[key] < 3:
1944 node_labels_dict[key] = key
1946 node_labels_dict[key] =
""
1947 draw_graph(graph, labels_dict=node_labels_dict)
1950 def recursive_graph(hier, graph, depth, depth_dict):
1953 index = str(hier.get_particle().
get_index())
1954 name1 = nameh +
"|#" + index
1955 depth_dict[name1] = depth
1959 if len(children) == 1
or children
is None:
1961 return (graph, depth, depth_dict)
1965 (graph, depth, depth_dict) = recursive_graph(
1966 c, graph, depth, depth_dict)
1968 index = str(c.get_particle().
get_index())
1969 namec = nameh +
"|#" + index
1970 graph.append((name1, namec))
1973 return (graph, depth, depth_dict)
1976 def draw_graph(graph, labels_dict=None, graph_layout='spring',
1977 node_size=5, node_color=
None, node_alpha=0.3,
1978 node_text_size=11, fixed=
None, pos=
None,
1979 edge_color=
'blue', edge_alpha=0.3, edge_thickness=1,
1981 validation_edges=
None,
1982 text_font=
'sans-serif',
1985 import matplotlib
as mpl
1987 import networkx
as nx
1988 import matplotlib.pyplot
as plt
1989 from math
import sqrt, pi
1995 if isinstance(edge_thickness, list):
1996 for edge, weight
in zip(graph, edge_thickness):
1997 G.add_edge(edge[0], edge[1], weight=weight)
2000 G.add_edge(edge[0], edge[1])
2002 if node_color
is None:
2003 node_color_rgb = (0, 0, 0)
2004 node_color_hex =
"000000"
2009 for node
in G.nodes():
2010 cctuple = cc.rgb(node_color[node])
2011 tmpcolor_rgb.append((cctuple[0]/255,
2014 tmpcolor_hex.append(node_color[node])
2015 node_color_rgb = tmpcolor_rgb
2016 node_color_hex = tmpcolor_hex
2019 if isinstance(node_size, dict):
2021 for node
in G.nodes():
2022 size = sqrt(node_size[node])/pi*10.0
2023 tmpsize.append(size)
2026 for n, node
in enumerate(G.nodes()):
2027 color = node_color_hex[n]
2029 nx.set_node_attributes(
2031 {node: {
'type':
'ellipse',
'w': size,
'h': size,
2032 'fill':
'#' + color,
'label': node}})
2033 nx.set_node_attributes(
2035 {node: {
'type':
'text',
'text': node,
'color':
'#000000',
2036 'visible':
'true'}})
2038 for edge
in G.edges():
2039 nx.set_edge_attributes(
2041 {edge: {
'width': 1,
'fill':
'#000000'}})
2043 for ve
in validation_edges:
2045 if (ve[0], ve[1])
in G.edges():
2046 print(
"found forward")
2047 nx.set_edge_attributes(
2049 {ve: {
'width': 1,
'fill':
'#00FF00'}})
2050 elif (ve[1], ve[0])
in G.edges():
2051 print(
"found backward")
2052 nx.set_edge_attributes(
2054 {(ve[1], ve[0]): {
'width': 1,
'fill':
'#00FF00'}})
2056 G.add_edge(ve[0], ve[1])
2058 nx.set_edge_attributes(
2060 {ve: {
'width': 1,
'fill':
'#FF0000'}})
2064 if graph_layout ==
'spring':
2066 graph_pos = nx.spring_layout(G, k=1.0/8.0, fixed=fixed, pos=pos)
2067 elif graph_layout ==
'spectral':
2068 graph_pos = nx.spectral_layout(G)
2069 elif graph_layout ==
'random':
2070 graph_pos = nx.random_layout(G)
2072 graph_pos = nx.shell_layout(G)
2075 nx.draw_networkx_nodes(G, graph_pos, node_size=node_size,
2076 alpha=node_alpha, node_color=node_color_rgb,
2078 nx.draw_networkx_edges(G, graph_pos, width=edge_thickness,
2079 alpha=edge_alpha, edge_color=edge_color)
2080 nx.draw_networkx_labels(
2081 G, graph_pos, labels=labels_dict, font_size=node_text_size,
2082 font_family=text_font)
2084 plt.savefig(out_filename)
2085 nx.write_gml(G,
'out.gml')
2093 from ipyD3
import d3object
2094 from IPython.display
import display
2096 d3 = d3object(width=800,
2101 title=
'Example table with d3js',
2102 desc=
'An example table created created with d3js with '
2103 'data generated with Python.')
2104 data = [[1277.0, 654.0, 288.0, 1976.0, 3281.0, 3089.0, 10336.0, 4650.0,
2105 4441.0, 4670.0, 944.0, 110.0],
2106 [1318.0, 664.0, 418.0, 1952.0, 3581.0, 4574.0, 11457.0, 6139.0,
2107 7078.0, 6561.0, 2354.0, 710.0],
2108 [1783.0, 774.0, 564.0, 1470.0, 3571.0, 3103.0, 9392.0, 5532.0,
2109 5661.0, 4991.0, 2032.0, 680.0],
2110 [1301.0, 604.0, 286.0, 2152.0, 3282.0, 3369.0, 10490.0, 5406.0,
2111 4727.0, 3428.0, 1559.0, 620.0],
2112 [1537.0, 1714.0, 724.0, 4824.0, 5551.0, 8096.0, 16589.0, 13650.0,
2113 9552.0, 13709.0, 2460.0, 720.0],
2114 [5691.0, 2995.0, 1680.0, 11741.0, 16232.0, 14731.0, 43522.0,
2115 32794.0, 26634.0, 31400.0, 7350.0, 3010.0],
2116 [1650.0, 2096.0, 60.0, 50.0, 1180.0, 5602.0, 15728.0, 6874.0,
2117 5115.0, 3510.0, 1390.0, 170.0],
2118 [72.0, 60.0, 60.0, 10.0, 120.0, 172.0, 1092.0, 675.0, 408.0,
2119 360.0, 156.0, 100.0]]
2120 data = [list(i)
for i
in zip(*data)]
2121 sRows = [[
'January',
2133 sColumns = [[
'Prod {0}'.format(i)
for i
in range(1, 9)],
2134 [
None,
'',
None,
None,
'Group 1',
None,
None,
'Group 2']]
2135 d3.addSimpleTable(data,
2136 fontSizeCells=[12, ],
2139 sRowsMargins=[5, 50, 0],
2140 sColsMargins=[5, 20, 10],
2143 addOutsideBorders=-1,
2147 html = d3.render(mode=[
'html',
'show'])
static bool get_is_setup(const IMP::ParticleAdaptor &p)
A container for models organized into clusters.
A class for reading stat files (either rmf or ascii v1 and v2)
atom::Hierarchies create_hierarchies(RMF::FileConstHandle fh, Model *m)
RMF::FrameID save_frame(RMF::FileHandle file, std::string name="")
Save the current state of the linked objects as a new RMF frame.
static bool get_is_setup(const IMP::ParticleAdaptor &p)
def plot_field_histogram
Plot a list of histograms from a value list.
def plot_fields_box_plots
Plot time series as boxplots.
Utility classes and functions for reading and storing PMI files.
def get_best_models
Given a list of stat files, read them all and find the best models.
A class to store data associated to a model.
void handle_use_deprecated(std::string message)
Break in this method in gdb to find deprecated uses at runtime.
std::string get_module_version()
Return the version of this module, as a string.
void write_pdb(const Selection &mhd, TextOutput out, unsigned int model=1)
Collect statistics from ProcessOutput.get_fields().
static bool get_is_setup(const IMP::ParticleAdaptor &p)
def get_fields
Get the desired field names, and return a dictionary.
Warning related to handling of structures.
static bool get_is_setup(Model *m, ParticleIndex pi)
def link_to_rmf
Link to another RMF file.
std::string get_molecule_name_and_copy(atom::Hierarchy h)
Walk up a PMI2 hierarchy/representations and get the "molname.copynum".
The standard decorator for manipulating molecular structures.
Ints get_index(const ParticlesTemp &particles, const Subset &subset, const Subsets &excluded)
def init_pdb
Init PDB Writing.
int get_number_of_frames(const ::npctransport_proto::Assignment &config, double time_step)
A decorator for a particle representing an atom.
Base class for capturing a modeling protocol.
void load_frame(RMF::FileConstHandle file, RMF::FrameID frame)
Load the given RMF frame into the state of the linked objects.
A decorator for a particle with x,y,z coordinates.
void add_hierarchies(RMF::NodeHandle fh, const atom::Hierarchies &hs)
Class for easy writing of PDBs, RMFs, and stat files.
void add_geometries(RMF::NodeHandle parent, const display::GeometriesTemp &r)
Add geometries to a given parent node.
void add_restraints(RMF::NodeHandle fh, const Restraints &hs)
A decorator for a particle that is part of a rigid body but not rigid.
Display a segment connecting a pair of particles.
A decorator for a residue.
Basic functionality that is expected to be used by a wide variety of IMP users.
def get_pdb_names
Get a list of all PDB files being output by this instance.
def get_prot_name_from_particle
Get the protein name from the particle.
class to link stat files to several rmf files
class to allow more advanced handling of RMF files.
void link_hierarchies(RMF::FileConstHandle fh, const atom::Hierarchies &hs)
def plot_fields
Plot the given fields and save a figure as output.
void add_geometry(RMF::FileHandle file, display::Geometry *r)
Add a single geometry to the file.
Store info for a chain of a protein.
Python classes to represent, score, sample and analyze models.
def init_pdb_best_scoring
Prepare for writing best-scoring PDBs (or mmCIFs) for a sampling run.
Functionality for loading, creating, manipulating and scoring atomic structures.
Select hierarchy particles identified by the biological name.
def init_rmf
Initialize an RMF file.
static bool get_is_setup(const IMP::ParticleAdaptor &p)
std::string get_module_version()
Return the version of this module, as a string.
A decorator for a particle with x,y,z coordinates and a radius.