| 1 |
|
|---|
| 2 | def open_mtz(session, path, structure_model = None,
|
|---|
| 3 | over_sampling=1.5, always_raise_errors=False):
|
|---|
| 4 | if structure_model is None:
|
|---|
| 5 | if always_raise_errors:
|
|---|
| 6 | raise TypeError('Reflection data must be associated with an atomic '
|
|---|
| 7 | 'structure, provided via the structure_model argument.')
|
|---|
| 8 | else:
|
|---|
| 9 | session.logger.warning('structureModel argument is required when '
|
|---|
| 10 | 'opening a reflection data file!')
|
|---|
| 11 | from .symmetry import get_map_mgr
|
|---|
| 12 | mmgr = get_map_mgr(structure_model, create=True)
|
|---|
| 13 | try:
|
|---|
| 14 | xmapset = mmgr.add_xmapset_from_mtz(path, oversampling_rate=over_sampling)
|
|---|
| 15 | log_str = 'Opened crystallographic dataset from {}\n'.format(path)
|
|---|
| 16 | if xmapset.experimental_data:
|
|---|
| 17 | log_str += 'Found experimental reflection data: \n'
|
|---|
| 18 | log_str += '\n'.join(['\t{}'.format(n) for n in xmapset.experimental_data.keys()])
|
|---|
| 19 | log_str += '\n'
|
|---|
| 20 | log_str += 'Rwork: {:.4f}; Rfree: {:.4f}'.format(
|
|---|
| 21 | xmapset.rwork, xmapset.rfree
|
|---|
| 22 | )
|
|---|
| 23 | log_str += 'Generated maps: \n{}\n'.format(
|
|---|
| 24 | '\n'.join(['\t{}'.format(m.name) for m in xmapset]))
|
|---|
| 25 | log_str += 'Any unwanted maps may be safely closed via the Model panel.'
|
|---|
| 26 | return [mmgr.crystal_mgr], log_str
|
|---|
| 27 |
|
|---|
| 28 | except RuntimeError as e:
|
|---|
| 29 | if always_raise_errors:
|
|---|
| 30 | raise e
|
|---|
| 31 | else:
|
|---|
| 32 | session.logger.warning(str(e))
|
|---|
| 33 | return None, None
|
|---|
| 34 |
|
|---|
| 35 | def spotlight(session, models=None, enable=True):
|
|---|
| 36 | from chimerax.clipper.symmetry import get_symmetry_handler
|
|---|
| 37 | if models is None:
|
|---|
| 38 | from chimerax.atomic import AtomicStructure
|
|---|
| 39 | models = session.models.list(type=AtomicStructure)
|
|---|
| 40 | for m in models:
|
|---|
| 41 | sh = get_symmetry_handler(m, create=True)
|
|---|
| 42 | session.logger.info('Setting spotlight mode for model {} to {}'.format(
|
|---|
| 43 | m.id_string, enable
|
|---|
| 44 | ))
|
|---|
| 45 | sh.spotlight_mode=enable
|
|---|
| 46 |
|
|---|
| 47 | def associate_volumes(session, volumes, to_model=None):
|
|---|
| 48 | if to_model is None:
|
|---|
| 49 | from chimerax.core.errors import UserError
|
|---|
| 50 | raise UserError('The toModel argument must be provided!')
|
|---|
| 51 | from chimerax.clipper.symmetry import get_map_mgr
|
|---|
| 52 | mgr = get_map_mgr(to_model, create=True)
|
|---|
| 53 | for v in volumes:
|
|---|
| 54 | mgr.nxmapset.add_nxmap_handler_from_volume(v)
|
|---|
| 55 |
|
|---|
| 56 | def isolate(session, atoms,
|
|---|
| 57 | surround_distance=5,
|
|---|
| 58 | context_distance=5,
|
|---|
| 59 | mask_radius=3,
|
|---|
| 60 | hide_surrounds=True,
|
|---|
| 61 | focus=False,
|
|---|
| 62 | include_symmetry=True):
|
|---|
| 63 | from chimerax.clipper.symmetry import get_symmetry_handler
|
|---|
| 64 | us = atoms.unique_structures
|
|---|
| 65 | for s in us:
|
|---|
| 66 | sel = us.atoms.intersect(atoms)
|
|---|
| 67 | sh = get_symmetry_handler(s, create=True)
|
|---|
| 68 | sh.isolate_and_cover_selection(sel,
|
|---|
| 69 | include_surrounding_residues = surround_distance,
|
|---|
| 70 | show_context = context_distance,
|
|---|
| 71 | mask_radius = mask_radius,
|
|---|
| 72 | hide_surrounds = hide_surrounds,
|
|---|
| 73 | focus = focus,
|
|---|
| 74 | include_symmetry = include_symmetry)
|
|---|
| 75 |
|
|---|
| 76 |
|
|---|
| 77 |
|
|---|
| 78 |
|
|---|
| 79 | from chimerax.core.commands.atomspec import AtomSpecArg
|
|---|
| 80 | class VolumesArg(AtomSpecArg):
|
|---|
| 81 | """Parse command models specifier"""
|
|---|
| 82 | name = "a models specifier"
|
|---|
| 83 |
|
|---|
| 84 | @classmethod
|
|---|
| 85 | def parse(cls, text, session):
|
|---|
| 86 | '''
|
|---|
| 87 | Returns only Volume objects (not subclasses)
|
|---|
| 88 | '''
|
|---|
| 89 | from chimerax.map import Volume
|
|---|
| 90 | aspec, text, rest = super().parse(text, session)
|
|---|
| 91 | models = aspec.evaluate(session).models
|
|---|
| 92 | volumes = [m for m in models if type(m) == Volume]
|
|---|
| 93 | return volumes, text, rest
|
|---|
| 94 |
|
|---|
| 95 |
|
|---|
| 96 | def register_clipper_cmd(logger):
|
|---|
| 97 | from chimerax.core.commands import (
|
|---|
| 98 | register, CmdDesc,
|
|---|
| 99 | BoolArg, FloatArg
|
|---|
| 100 | )
|
|---|
| 101 | from chimerax.atomic import StructuresArg, StructureArg, AtomsArg
|
|---|
| 102 |
|
|---|
| 103 | spot_desc = CmdDesc(
|
|---|
| 104 | optional=[
|
|---|
| 105 | ('models', StructuresArg),
|
|---|
| 106 | ('enable', BoolArg)
|
|---|
| 107 | ],
|
|---|
| 108 | synopsis='Switch on/off "Scrolling sphere" visualisation with live atomic symmetry'
|
|---|
| 109 | )
|
|---|
| 110 | register('cxclipper spotlight', spot_desc, spotlight, logger=logger)
|
|---|
| 111 |
|
|---|
| 112 | vol_desc = CmdDesc(
|
|---|
| 113 | required=[
|
|---|
| 114 | ('volumes', VolumesArg),
|
|---|
| 115 | ],
|
|---|
| 116 | keyword=[
|
|---|
| 117 | ('to_model', StructureArg)
|
|---|
| 118 | ],
|
|---|
| 119 | synopsis='Have Clipper take control of the chosen volumes and associate them with the given model'
|
|---|
| 120 | )
|
|---|
| 121 | register('cxclipper associate', vol_desc, associate_volumes, logger=logger)
|
|---|
| 122 |
|
|---|
| 123 | isol_desc = CmdDesc(
|
|---|
| 124 | required=[('atoms', AtomsArg)],
|
|---|
| 125 | keyword=[
|
|---|
| 126 | ('surround_distance', FloatArg),
|
|---|
| 127 | ('context_distance', FloatArg),
|
|---|
| 128 | ('mask_radius', FloatArg),
|
|---|
| 129 | ('hide_surrounds', BoolArg),
|
|---|
| 130 | ('focus', BoolArg),
|
|---|
| 131 | ('include_symmetry', BoolArg)
|
|---|
| 132 | ],
|
|---|
| 133 | synopsis=('Visually isolate the selected atoms from their surroundings, '
|
|---|
| 134 | 'and mask their maps to their immediate vicinity. The selection '
|
|---|
| 135 | 'covered by the map(s) will be expanded to include all residues '
|
|---|
| 136 | 'approaching within surroundDistance of the given selection. Any '
|
|---|
| 137 | 'residues approaching within contextDistance of the result will be '
|
|---|
| 138 | 'displayed, but not covered by the map(s). If hideSurrounds is '
|
|---|
| 139 | 'True, all other atoms will be hidden. If focus is True, the view '
|
|---|
| 140 | 'will be reset to cover the visible atoms. If includeSymmetry is '
|
|---|
| 141 | 'True, symmetry atoms will be included in the contextDistance '
|
|---|
| 142 | 'calculation. To revert to the default viewing mode, use '
|
|---|
| 143 | '"cxclipper spotlight".')
|
|---|
| 144 | )
|
|---|
| 145 | register('cxclipper isolate', isol_desc, isolate, logger=logger)
|
|---|