1 """@namespace IMP.mmcif.restraint
2 @brief Map IMP restraints to mmCIF categories
10 """Yield all input ParticleIndexes for a given Restraint"""
11 for inp
in r.get_inputs():
13 p = IMP.Particle.get_from(inp)
19 def _get_by_residue(m, p):
20 """Determine whether the given particle represents a specific residue
21 or a more coarse-grained object."""
27 """Get the numerical value of the Scale particle"""
29 raise ValueError(
"not scale particle")
33 class _AsymMapper(object):
34 """Map ParticleIndexes to ihm.AsymUnit"""
35 def __init__(self, m, system):
37 self.components = system.components
38 self._seen_ranges = {}
40 def __getitem__(self, pi):
50 raise KeyError(
"Could not find top-level Chain for "
51 + m.get_particle_name(pi))
53 def get_feature(self, ps):
54 """Get an ihm.restraint.Feature that covers the given particles"""
63 rng = asym(rind, rind)
67 rng = asym(rinds[0], rinds[-1])
69 raise ValueError(
"Unsupported particle type %s" % str(p))
71 if len(rngs) > 0
and rngs[-1].asym == asym \
72 and rngs[-1].seq_id_range[1] == rng.seq_id_range[0] - 1:
73 rngs[-1].seq_id_range = (rngs[-1].seq_id_range[0],
80 if hrngs
in self._seen_ranges:
81 return self._seen_ranges[hrngs]
83 feat = ihm.restraint.ResidueFeature(rngs)
84 self._seen_ranges[hrngs] = feat
88 def _parse_restraint_info(info):
89 """Convert RestraintInfo object to Python dict"""
93 info.set_was_used(
True)
94 for typ
in (
'int',
'float',
'string',
'filename',
'floats',
'filenames',
96 for i
in range(getattr(info,
'get_number_of_' + typ)()):
97 key = getattr(info,
'get_%s_key' % typ)(i)
98 value = getattr(info,
'get_%s_value' % typ)(i)
103 class _GaussianEMRestraint(ihm.restraint.EM3DRestraint):
104 """Handle an IMP.isd.GaussianEMRestraint"""
106 def __init__(self, imp_restraint, info, modeled_assembly, system):
107 self._imp_restraint = imp_restraint
108 p = IMP.mmcif.metadata._GMMParser()
109 r = p.parse_file(info[
'filename'])
110 super(_GaussianEMRestraint, self).__init__(
111 dataset=r[
'dataset'],
112 assembly=modeled_assembly,
113 number_of_gaussians=r[
'number_of_gaussians'],
114 fitting_method=
'Gaussian mixture model')
116 def add_model_fit(self, model):
117 info = _parse_restraint_info(self._imp_restraint.get_dynamic_info())
118 self.fits[model] = ihm.restraint.EM3DRestraintFit(
119 cross_correlation_coefficient=info[
'cross correlation'])
122 class _CrossLinkRestraint(ihm.restraint.CrossLinkRestraint):
123 def __init__(self, imp_restraint, info, modeled_assembly, system):
124 self._imp_restraint = imp_restraint
125 loc = ihm.location.InputFileLocation(
126 info[
'filename'], details=
'Crosslinks')
127 dataset = ihm.dataset.CXMSDataset(loc)
128 linker = ihm.ChemDescriptor(
129 auth_name=info[
'linker author name'],
130 chemical_name=info.get(
'linker chemical name'),
131 smiles=info.get(
'linker smiles'),
132 smiles_canonical=info.get(
'linker smiles canonical'),
133 inchi=info.get(
'linker inchi'),
134 inchi_key=info.get(
'linker inchi key'))
135 super(_CrossLinkRestraint, self).__init__(
136 dataset=dataset, linker=linker)
138 cmap = dict((e.description, e)
for e
in system.entities.get_all())
139 dist = ihm.restraint.UpperBoundDistanceRestraint(info[
'linker length'])
140 asym = _AsymMapper(imp_restraint.get_model(), system)
141 self._add_all_links(IMP.RestraintSet.get_from(imp_restraint), cmap,
144 def _add_all_links(self, rset, cmap, asym, dist):
145 """Add info for each cross-link in the given RestraintSet"""
146 for link
in rset.restraints:
149 child_rs = IMP.RestraintSet.get_from(link)
153 self._add_all_links(child_rs, cmap, asym, dist)
155 info = _parse_restraint_info(link.get_static_info())
157 r1 = cmap[info[
'protein1']].residue(info[
'residue1'])
158 r2 = cmap[info[
'protein2']].residue(info[
'residue2'])
159 ex_xl = ihm.restraint.ExperimentalCrossLink(residue1=r1,
161 self.experimental_cross_links.append([ex_xl])
164 endp1, endp2 = info[
'endpoints']
167 if _get_by_residue(m, endp1)
and _get_by_residue(m, endp2):
168 cls = ihm.restraint.ResidueCrossLink
170 cls = ihm.restraint.FeatureCrossLink
171 xl = cls(ex_xl, asym1=asym1, asym2=asym2, distance=dist,
173 psi=_get_scale(m, info[
'psis'][0]),
174 sigma1=_get_scale(m, info[
'sigmas'][0]),
175 sigma2=_get_scale(m, info[
'sigmas'][1]))
176 self.cross_links.append(xl)
178 def add_model_fit(self, model):
182 class _EM2DRestraint(ihm.restraint.EM2DRestraint):
183 """Handle an IMP.em2d.PCAFitRestraint"""
185 def __init__(self, imp_restraint, info, modeled_assembly, system):
187 self._imp_restraint = imp_restraint
188 loc = ihm.location.InputFileLocation(
189 info[
'image files'][0],
190 details=
"Electron microscopy class average")
191 dataset = ihm.dataset.EM2DClassDataset(loc)
192 super(_EM2DRestraint, self).__init__(
194 assembly=modeled_assembly,
196 number_raw_micrographs=info[
'micrographs number']
or None,
197 pixel_size_width=info[
'pixel size'],
198 pixel_size_height=info[
'pixel size'],
199 image_resolution=info[
'resolution'],
200 number_of_projections=info[
'projection number'])
202 def add_model_fit(self, model):
205 info = _parse_restraint_info(self._imp_restraint.get_dynamic_info())
206 ccc = info[
'cross correlation'][nimage]
207 transform = self._get_transformation(model, info, nimage)
208 rot = transform.get_rotation()
209 rm = [[e
for e
in rot.get_rotation_matrix_row(i)]
for i
in range(3)]
210 self.fits[model] = ihm.restraint.EM2DRestraintFit(
211 cross_correlation_coefficient=ccc, rot_matrix=rm,
212 tr_vector=transform.get_translation())
214 def _get_transformation(self, model, info, nimage):
215 """Get the transformation that places the model on image nimage"""
216 r = info[
'rotation'][nimage * 4: nimage * 4 + 4]
217 t = info[
'translation'][nimage * 3: nimage * 3 + 3]
222 class _GeometricRestraint(ihm.restraint.GeometricRestraint):
223 """Base for all geometric restraints"""
225 def __init__(self, imp_restraint, info, modeled_assembly, system):
226 self._imp_restraint = imp_restraint
227 asym = _AsymMapper(imp_restraint.get_model(), system)
228 super(_GeometricRestraint, self).__init__(
230 geometric_object=self._geom_object,
231 feature=asym.get_feature(_get_input_pis(imp_restraint)),
232 distance=self._get_distance(info),
233 harmonic_force_constant=1. / info[
'sigma'],
236 def _get_distance(self, info):
239 def add_model_fit(self, model):
243 class _ZAxialRestraint(_GeometricRestraint):
244 """Handle an IMP.npc.ZAxialRestraint"""
245 _geom_object = ihm.geometry.XYPlane()
247 def _get_distance(self, info):
248 return ihm.restraint.LowerUpperBoundDistanceRestraint(
249 info[
'lower bound'], info[
'upper bound'])
252 class _SAXSRestraint(ihm.restraint.SASRestraint):
253 """Handle an IMP.saxs.Restraint"""
255 def __init__(self, imp_restraint, info, modeled_assembly, system):
256 self._imp_restraint = imp_restraint
257 loc = ihm.location.InputFileLocation(
258 info[
'filename'], details=
'SAXS profile')
259 dataset = ihm.dataset.SASDataset(loc)
260 super(_SAXSRestraint, self).__init__(
262 assembly=modeled_assembly,
263 segment=
False, fitting_method=
'IMP SAXS restraint',
264 fitting_atom_type=info[
'form factor type'],
267 def add_model_fit(self, model):
269 self.fits[model] = ihm.restraint.SASRestraintFit(chi_value=
None)
272 class _RestraintMapper(object):
273 """Map IMP restraints to mmCIF objects"""
274 def __init__(self, system):
276 "IMP.isd.GaussianEMRestraint": _GaussianEMRestraint,
277 "IMP.pmi.CrossLinkingMassSpectrometryRestraint":
279 "IMP.em2d.PCAFitRestraint": _EM2DRestraint,
280 "IMP.npc.ZAxialPositionRestraint": _ZAxialRestraint,
281 "IMP.saxs.Restraint": _SAXSRestraint}
282 self._system = system
284 def handle(self, r, model, modeled_assembly):
285 """Handle an individual IMP restraint.
286 @return a wrapped version of the restraint if it is handled in
287 mmCIF, otherwise None."""
288 info = _parse_restraint_info(r.get_static_info())
289 if 'type' in info
and info[
'type']
in self._typemap:
290 r = self._typemap[info[
'type']](r, info, modeled_assembly,
292 r.add_model_fit(model)
static bool get_is_setup(const IMP::ParticleAdaptor &p)
A decorator to associate a particle with a part of a protein/DNA/RNA.
static bool get_is_setup(const IMP::ParticleAdaptor &p)
Add scale parameter to particle.
static bool get_is_setup(Model *m, ParticleIndex pi)
The standard decorator for manipulating molecular structures.
Ints get_index(const ParticlesTemp &particles, const Subset &subset, const Subsets &excluded)
static bool get_is_setup(const IMP::ParticleAdaptor &p)
A decorator for a residue.
static bool get_is_setup(const IMP::ParticleAdaptor &p)
static bool get_is_setup(Model *m, ParticleIndex p)
Check if the particle has the needed attributes for a cast to succeed.
Store info for a chain of a protein.