Skip to content

Commit

Permalink
Squashed 'modules/core/dependency/python-ihm/' changes from 0a6e31129…
Browse files Browse the repository at this point in the history
…e..1d6f0599b1

1d6f0599b1 Fix typos
b190922c24 Fix typos
614bf5e84e Fix hyperlinks
1e2e35a308 Merge pull request ihmwg/python-ihm#122 from grandrea/cross_linkers_ag
1828c76e41 Match names in doc against Python code
1c53df70b9 Match crosslink names with dictionary
da722510f7 Drop testing with Python 2.7
779b38d71f formatting
d0a038af5d define dsbu, PhoX and tbu-PhoX. Missing smiles and inchi on PhoX and tbu-PhoX as they don't seem to exist yet.
1022dbf56e define photoL
363f48172d define photoL
1805462213 define photoL
a05ef17b53 Fill in entity for Residues in asyms
57c2d25f40 Remove db_name parameter from DatabaseLocation
660ccf8fb1 Make sure that input and output are not the same file

git-subtree-dir: modules/core/dependency/python-ihm
git-subtree-split: 1d6f0599b180267a13d64a0dd1ddcc2a1910d5d8
  • Loading branch information
benmwebb committed Jul 20, 2023
1 parent d1d30f4 commit 56f9412
Show file tree
Hide file tree
Showing 17 changed files with 114 additions and 99 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,6 @@ jobs:
os: [ubuntu-22.04]
python-version: ['3.7', '3.8', '3.9', '3.10', '3.11']
include:
- os: ubuntu-20.04
python-version: '2.7'
- os: ubuntu-20.04
python-version: '3.6'
- os: macos-latest
Expand Down
7 changes: 7 additions & 0 deletions modules/core/dependency/python-ihm/ChangeLog.rst
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
HEAD
====
- :class:`ihm.location.DatabaseLocation` no longer accepts a ``db_name``
parameter. Derived classes (such as :class:`ihm.location.PDBLocation`)
should be used instead; the base class should only be used for "other"
databases that are not described in the IHM dictionary (#116).

0.38 - 2023-05-26
=================
- Convenience classes are added to describe datasets stored in
Expand Down
27 changes: 27 additions & 0 deletions modules/core/dependency/python-ihm/docs/cross_linkers.rst
Original file line number Diff line number Diff line change
Expand Up @@ -49,3 +49,30 @@ The :mod:`ihm.cross_linkers` Python module
SDA (NHS-Diazirine) (succinimidyl 4,4′-azipentanoate) cross-linker that
links primary amines with nearly any other functional group via
long-wave UV-light activation.

.. data:: photo_leucine

L-photo-leucine. Non-canonical amino acid incorporated at leucine
positions that links leucine to any other functional group via long-wave
UV-light activation.
See `Suchanek et al, 2005 <https://doi.org/10.1038/nmeth752>`_.

.. data:: dsbu

dsbu (disuccinimidyl dibutyric urea) cross-linker that links a primary
amine with another primary amine (non-water-soluble).
Cleavable in the gas phase using collision-induced dissociation.
See `Müller et al, 2011 <https://doi.org/10.1021/ac101241t>`_.

.. data:: phoX

PhoX cross-linker that links a primary amine with another primary amine.
The spacer group contains a phosphonate group, making the cross-linker
IMAC-enrichable. Also known by the name DSPP. See
`Steigenberger et al, 2019 <https://doi.org/10.1021/acscentsci.9b00416>`_.

.. data:: tbuphoX

Tert-butyl PhoX cross-linker. Similar to PhoX, but containing a tert-butyl
group that renders the cross-linker cell permeable.
See `Jiang et al, 2021 <https://doi.org/10.1002/anie.202113937>`_.
7 changes: 4 additions & 3 deletions modules/core/dependency/python-ihm/ihm/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -575,7 +575,7 @@ class Software(object):
"""Software used as part of the modeling protocol.
:param str name: The name of the software.
:param str classification: The major function of the sofware, for
:param str classification: The major function of the software, for
example 'model building', 'sample preparation',
'data collection'.
:param str description: A longer text description of the software.
Expand Down Expand Up @@ -1086,6 +1086,8 @@ class Residue(object):
def __init__(self, seq_id, entity=None, asym=None):
self.entity = entity
self.asym = asym
if entity is None and asym:
self.entity = asym.entity
# todo: check id for validity (at property read time)
self.seq_id = seq_id

Expand All @@ -1106,8 +1108,7 @@ def _get_ins_code(self):
"for asymmetric units")

def _get_comp(self):
entity = self.entity or self.asym.entity
return entity.sequence[self.seq_id - 1]
return self.entity.sequence[self.seq_id - 1]
comp = property(_get_comp,
doc="Chemical component (residue type)")

Expand Down
23 changes: 23 additions & 0 deletions modules/core/dependency/python-ihm/ihm/cross_linkers.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,3 +64,26 @@
inchi='1S/C9H11N3O4/c1-9(10-11-9)5-4-8(15)16-12-6(13)2-3-'
'7(12)14/h2-5H2,1H3',
inchi_key=' SYYLQNPWAPHRFV-UHFFFAOYSA-N')

photo_leucine = ihm.ChemDescriptor(
'L-Photo-Leucine', chemical_name='L-Photo-Leucine',
smiles='CC1(C[C@H](N)C(O)=O)N=N1',
inchi='1S/C5H9N3O2/c1-5(7-8-5)'
'2-3(6)4(9)10/h3H,2,6H2,1H3,(H,9,10)/t3-/m0/s1',
inchi_key='MJRDGTVDJKACQZ-VKHMYHEASA-N')

dsbu = ihm.ChemDescriptor(
'DSBU', chemical_name='disuccinimidyl dibutyric urea',
smiles='O=C(NCCCC(=O)ON1C(=O)CCC1=O)NCCCC(=O)ON2C(=O)CCC2=O',
inchi='S/C17H22N4O9/c22-11-5-6-12(23)20(11)29-15(26)'
'3-1-9-18-17(28)19-10-2-4-16(27)30-21-13(24)7-8-14(21)'
'25/h1-10H2,(H2,18,19,28)',
inchi_key='XZSQCCZQFXUQCY-UHFFFAOYSA-N')

phoX = ihm.ChemDescriptor(
'DSPP', chemical_name='(3,5-bis(((2,5-dioxopyrrolidin-1-yl)oxy)'
'carbonyl) phenyl)phosphonic acid')

tbuphoX = ihm.ChemDescriptor(
'TBDSPP', chemical_name='tert-butyl disuccinimidyl'
'phenyl phosphonate, tBu-PhoX')
2 changes: 1 addition & 1 deletion modules/core/dependency/python-ihm/ihm/dumper.py
Original file line number Diff line number Diff line change
Expand Up @@ -718,7 +718,7 @@ def get_next_id(self):
self.index += 1
while self.ids[self.index] in self.seen_ids:
self.index += 1
# Note tha we don't need to add our own IDs to seen_ids since
# Note that we don't need to add our own IDs to seen_ids since
# they are already guaranteed to be unique
return self.ids[self.index]

Expand Down
2 changes: 1 addition & 1 deletion modules/core/dependency/python-ihm/ihm/format_bcif.py
Original file line number Diff line number Diff line change
Expand Up @@ -504,7 +504,7 @@ def _get_mask_and_type(data):
mask[i] = 1 if val is None else 2
else:
seen_types.add(type(val))
# If a mix of types, coerce to that of the highest precendence
# If a mix of types, coerce to that of the highest precedence
# (mixed int/float can be represented as float; mix int/float/str can
# be represented as str; bool is represented as str)
if not seen_types or bool in seen_types or str in seen_types:
Expand Down
93 changes: 20 additions & 73 deletions modules/core/dependency/python-ihm/ihm/location.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,18 +61,21 @@ def __hash__(self):

class DatabaseLocation(Location):
"""A dataset stored in an official database (PDB, EMDB, PRIDE, etc.).
Generally a subclass should be used specific to the database -
for example, :class:`PDBLocation`, :class:`EMDBLocation`, or
:class:`PRIDELocation`, although this base class can be used directly
for "other" databases not currently supported by the IHM dictionary.
:param str db_name: The name of the database.
:param str db_code: The accession code inside the database.
:param str version: The version of the dataset in the database.
:param str details: Additional details about the dataset, if known.
"""

_eq_keys = Location._eq_keys + ['db_name', 'access_code', 'version']
db_name = 'Other'

def __init__(self, db_name, db_code, version=None, details=None):
def __init__(self, db_code, version=None, details=None):
super(DatabaseLocation, self).__init__(details)
self.db_name = db_name
self.access_code = db_code
self.version = version

Expand All @@ -81,154 +84,98 @@ class EMDBLocation(DatabaseLocation):
"""Something stored in the EMDB database.
See :class:`DatabaseLocation` for a description of the parameters
and :class:`Location` for discussion of the usage of these objects."""
_db_name = 'EMDB'

def __init__(self, db_code, version=None, details=None):
super(EMDBLocation, self).__init__(self._db_name, db_code,
version, details)
db_name = 'EMDB'


class PDBLocation(DatabaseLocation):
"""Something stored in the PDB database.
See :class:`DatabaseLocation` for a description of the parameters
and :class:`Location` for discussion of the usage of these objects."""
_db_name = 'PDB'

def __init__(self, db_code, version=None, details=None):
super(PDBLocation, self).__init__(self._db_name, db_code,
version, details)
db_name = 'PDB'


class PDBDevLocation(DatabaseLocation):
"""Something stored in the PDB-Dev database.
See :class:`DatabaseLocation` for a description of the parameters
and :class:`Location` for discussion of the usage of these objects."""
_db_name = 'PDB-Dev'

def __init__(self, db_code, version=None, details=None):
super(PDBDevLocation, self).__init__(self._db_name, db_code,
version, details)
db_name = 'PDB-Dev'


class ModelArchiveLocation(DatabaseLocation):
"""Something stored in Model Archive.
See :class:`DatabaseLocation` for a description of the parameters
and :class:`Location` for discussion of the usage of these objects."""
_db_name = 'MODEL ARCHIVE'

def __init__(self, db_code, version=None, details=None):
super(ModelArchiveLocation, self).__init__(self._db_name, db_code,
version, details)
db_name = 'MODEL ARCHIVE'


class BMRBLocation(DatabaseLocation):
"""Something stored in the BMRB database.
See :class:`DatabaseLocation` for a description of the parameters
and :class:`Location` for discussion of the usage of these objects."""
_db_name = 'BMRB'

def __init__(self, db_code, version=None, details=None):
super(BMRBLocation, self).__init__(self._db_name, db_code,
version, details)
db_name = 'BMRB'


class MassIVELocation(DatabaseLocation):
"""Something stored in the MassIVE database.
See :class:`DatabaseLocation` for a description of the parameters
and :class:`Location` for discussion of the usage of these objects."""
_db_name = 'MASSIVE'

def __init__(self, db_code, version=None, details=None):
super(MassIVELocation, self).__init__(self._db_name, db_code, version,
details)
db_name = 'MASSIVE'


class EMPIARLocation(DatabaseLocation):
"""Something stored in the EMPIAR database.
See :class:`DatabaseLocation` for a description of the parameters
and :class:`Location` for discussion of the usage of these objects."""
_db_name = 'EMPIAR'

def __init__(self, db_code, version=None, details=None):
super(EMPIARLocation, self).__init__(self._db_name, db_code, version,
details)
db_name = 'EMPIAR'


class SASBDBLocation(DatabaseLocation):
"""Something stored in the SASBDB database.
See :class:`DatabaseLocation` for a description of the parameters
and :class:`Location` for discussion of the usage of these objects."""
_db_name = 'SASBDB'

def __init__(self, db_code, version=None, details=None):
super(SASBDBLocation, self).__init__(self._db_name, db_code, version,
details)
db_name = 'SASBDB'


class PRIDELocation(DatabaseLocation):
"""Something stored in the PRIDE database.
See :class:`DatabaseLocation` for a description of the parameters
and :class:`Location` for discussion of the usage of these objects."""
_db_name = 'PRIDE'

def __init__(self, db_code, version=None, details=None):
super(PRIDELocation, self).__init__(self._db_name, db_code, version,
details)
db_name = 'PRIDE'


class JPOSTLocation(DatabaseLocation):
"""Something stored in the JPOST database.
See :class:`DatabaseLocation` for a description of the parameters
and :class:`Location` for discussion of the usage of these objects."""
_db_name = 'jPOSTrepo'

def __init__(self, db_code, version=None, details=None):
super(JPOSTLocation, self).__init__(self._db_name, db_code, version,
details)
db_name = 'jPOSTrepo'


class BioGRIDLocation(DatabaseLocation):
"""Something stored in the BioGRID database.
See :class:`DatabaseLocation` for a description of the parameters
and :class:`Location` for discussion of the usage of these objects."""
_db_name = 'BioGRID'

def __init__(self, db_code, version=None, details=None):
super(BioGRIDLocation, self).__init__(self._db_name, db_code, version,
details)
db_name = 'BioGRID'


class ProXLLocation(DatabaseLocation):
"""Something stored in the ProXL database.
See :class:`DatabaseLocation` for a description of the parameters
and :class:`Location` for discussion of the usage of these objects."""
_db_name = 'ProXL'

def __init__(self, db_code, version=None, details=None):
super(ProXLLocation, self).__init__(self._db_name, db_code, version,
details)
db_name = 'ProXL'


class IProXLocation(DatabaseLocation):
"""Something stored in the iProX database.
See :class:`DatabaseLocation` for a description of the parameters
and :class:`Location` for discussion of the usage of these objects."""
_db_name = 'iProX'

def __init__(self, db_code, version=None, details=None):
super(IProXLocation, self).__init__(self._db_name, db_code, version,
details)
db_name = 'iProX'


class AlphaFoldDBLocation(DatabaseLocation):
"""Something stored in the AlphaFoldDB database.
See :class:`DatabaseLocation` for a description of the parameters
and :class:`Location` for discussion of the usage of these objects."""
_db_name = 'AlphaFoldDB'

def __init__(self, db_code, version=None, details=None):
super(AlphaFoldDBLocation, self).__init__(
self._db_name, db_code, version, details)
db_name = 'AlphaFoldDB'


class FileLocation(Location):
Expand Down
8 changes: 4 additions & 4 deletions modules/core/dependency/python-ihm/ihm/reader.py
Original file line number Diff line number Diff line change
Expand Up @@ -1421,11 +1421,11 @@ def __init__(self, *args):
super(_DatasetDBRefHandler, self).__init__(*args)
# Map data_type to corresponding
# subclass of ihm.location.DatabaseLocation
# or ihm.location.DatabaseLocation itself
self.type_map = dict(
(x[1]._db_name.lower(), x[1])
(x[1].db_name.lower(), x[1])
for x in inspect.getmembers(ihm.location, inspect.isclass)
if issubclass(x[1], ihm.location.DatabaseLocation)
and x[1] is not ihm.location.DatabaseLocation)
if issubclass(x[1], ihm.location.DatabaseLocation))

def __call__(self, dataset_list_id, db_name, id, version, details,
accession_code):
Expand All @@ -1434,7 +1434,7 @@ def __call__(self, dataset_list_id, db_name, id, version, details,
dbloc = self.sysr.db_locations.get_by_id(id,
self.type_map.get(typ, None))
# Preserve user-provided name for unknown databases
if dbloc.db_name is None and db_name is not None:
if dbloc.db_name == 'Other' and db_name is not None:
dbloc.db_name = db_name
ds.location = dbloc
self.copy_if_present(
Expand Down
2 changes: 1 addition & 1 deletion modules/core/dependency/python-ihm/src/ihm_format.c
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@ struct ihm_mapping {
ihm_destroy_callback value_destroy_func;
};

/* Make a new mapping from case-insensitive strings to arbitary pointers.
/* Make a new mapping from case-insensitive strings to arbitrary pointers.
The mapping uses a simple binary search (more memory efficient than
a hash table and generally faster too since the number of keys is quite
small). */
Expand Down
8 changes: 4 additions & 4 deletions modules/core/dependency/python-ihm/test/test_dumper.py
Original file line number Diff line number Diff line change
Expand Up @@ -1230,7 +1230,7 @@ def test_dataset_dumper_duplicates_details(self):
def test_dataset_dumper_duplicates_samedata_sameloc(self):
"""DatasetDumper doesn't duplicate same datasets in same location"""
system = ihm.System()
loc1 = ihm.location.DatabaseLocation("mydb", "abc", "1.0", "")
loc1 = ihm.location.DatabaseLocation("abc", "1.0", "")

# Identical datasets in the same location aren't duplicated
cx1 = ihm.dataset.CXMSDataset(loc1)
Expand All @@ -1246,8 +1246,8 @@ def test_dataset_dumper_duplicates_samedata_sameloc(self):
def test_dataset_dumper_duplicates_samedata_diffloc(self):
"""DatasetDumper is OK with same datasets in different locations"""
system = ihm.System()
loc1 = ihm.location.DatabaseLocation("mydb", "abc", "1.0", "")
loc2 = ihm.location.DatabaseLocation("mydb", "xyz", "1.0", "")
loc1 = ihm.location.DatabaseLocation("abc", "1.0", "")
loc2 = ihm.location.DatabaseLocation("xyz", "1.0", "")
cx1 = ihm.dataset.CXMSDataset(loc1)
cx2 = ihm.dataset.CXMSDataset(loc2)
dump = ihm.dumper._DatasetDumper()
Expand All @@ -1261,7 +1261,7 @@ def test_dataset_dumper_duplicates_diffdata_sameloc(self):
"""DatasetDumper is OK with different datasets in same location"""
system = ihm.System()
# Different datasets in same location are OK (but odd)
loc2 = ihm.location.DatabaseLocation("mydb", "xyz", "1.0", "")
loc2 = ihm.location.DatabaseLocation("xyz", "1.0", "")
cx2 = ihm.dataset.CXMSDataset(loc2)
em3d = ihm.dataset.EMDensityDataset(loc2)
dump = ihm.dumper._DatasetDumper()
Expand Down
4 changes: 2 additions & 2 deletions modules/core/dependency/python-ihm/test/test_flr.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ def test_probe_eq(self):
self.assertTrue(p_ref != p_unequal)

def test_probe_descriptor_init(self):
""" Test initalization of ProbeDescriptor """
""" Test initialization of ProbeDescriptor """
p = ihm.flr.ProbeDescriptor(reactive_probe_chem_descriptor='foo',
chromophore_chem_descriptor='bar',
chromophore_center_atom='foo2')
Expand Down Expand Up @@ -399,7 +399,7 @@ def test_exp_condition_eq(self):
self.assertTrue(e_ref != e_unequal)

def test_fret_analysis_init(self):
"""Test initalization of FRETAnalysis."""
"""Test initialization of FRETAnalysis."""
f = ihm.flr.FRETAnalysis(
experiment='this_experiment',
sample_probe_1='this_sample_probe_1',
Expand Down
Loading

0 comments on commit 56f9412

Please sign in to comment.