1 """@namespace IMP.pmi.metadata
2 Classes for attaching metadata to PMI objects.
5 from __future__
import print_function, division
10 """Base class for all metadata"""
15 """Metadata that only makes sense for the top-level PMI object."""
20 """Software (other than IMP) used as part of the modeling protocol."""
21 def __init__(self, name, classification, description, url, type='program',
24 self.classification = classification
25 self.description = description
28 self.version = version
32 """A publication that describes the modeling."""
33 def __init__(self, pmid, title, journal, volume, page_range, year, authors,
35 self.title, self.journal, self.volume = title, journal, volume
36 self.page_range, self.year = page_range, year
37 self.pmid, self.authors, self.doi = pmid, authors, doi
41 """A Python script used as part of the modeling."""
42 def __init__(self, location):
43 self.location = location
47 """A set of input data, for example, a crystal structure or EM map."""
49 _eq_keys = [
'location']
54 return tuple([self.__class__]
55 + [getattr(self, x)
for x
in self._eq_keys])
56 def __eq__(self, other):
57 return self._eq_vals() == other._eq_vals()
59 return hash(self._eq_vals())
61 _data_type =
'unspecified'
62 def __init__(self, location):
63 self.location = location
64 self._parents = OrderedDict()
67 """Add another Dataset from which this one was derived.
68 For example, a 3D EM map may be derived from a set of 2D images."""
69 self._parents[dataset] =
None
72 """Add another Dataset from which the ultimate parent of this one
74 if len(self._parents) == 0:
76 elif len(self._parents) == 1:
77 list(self._parents.keys())[0].
add_parent(dataset)
79 raise ValueError(
"This dataset has multiple parents - don't "
80 "know which one to add to")
83 """Processed crosslinks from a CX-MS experiment"""
84 _data_type =
'CX-MS data'
87 """Raw mass spectrometry files such as peaklists"""
88 _data_type =
'Mass Spectrometry data'
91 """A 3D electron microscopy dataset"""
92 _data_type =
'3DEM volume'
95 """An experimentally-determined 3D structure as a set of a coordinates,
96 usually in a PDB file"""
97 _data_type =
'Experimental model'
100 """A 3D structure determined by comparative modeling"""
101 _data_type =
'Comparative model'
104 """Raw 2D electron micrographs"""
105 _eq_keys = Dataset._eq_keys + [
'number']
107 _data_type =
'EM raw micrographs'
108 def __init__(self, location, number):
109 super(EMMicrographsDataset, self).__init__(location)
113 """2DEM class average"""
114 _data_type =
'2DEM class average'
117 """Identifies the location where a resource can be found."""
121 _allow_duplicates =
False
123 def __init__(self, details=None):
124 self.details = details
129 if self._allow_duplicates:
132 return tuple([self.__class__]
133 + [getattr(self, x)
for x
in self._eq_keys])
134 def __eq__(self, other):
135 return self._eq_vals() == other._eq_vals()
137 return hash(self._eq_vals())
140 """A dataset stored in an official database (PDB, EMDB, PRIDE, etc.)"""
142 _eq_keys = Location._eq_keys + [
'db_name',
'access_code',
'version']
144 def __init__(self, db_name, db_code, version=None, details=None):
145 super(DatabaseLocation, self).__init__(details)
146 self.db_name = db_name
147 self.access_code = db_code
148 self.version = version
151 """Something stored in the EMDB database."""
152 def __init__(self, db_code, version=None, details=None):
153 DatabaseLocation.__init__(self,
'EMDB', db_code, version, details)
156 """Something stored in the PDB database."""
157 def __init__(self, db_code, version=None, details=None):
158 DatabaseLocation.__init__(self,
'PDB', db_code, version, details)
161 """Something stored in the MassIVE database."""
162 def __init__(self, db_code, version=None, details=None):
163 DatabaseLocation.__init__(self,
'MASSIVE', db_code, version, details)
166 """An individual file or directory.
167 This may be in a repository (if `repo` is not None) or only on the
168 local disk (if `repo` is None)."""
170 _eq_keys = Location._eq_keys + [
'repo',
'path']
174 @param path the location of the file or directory.
175 @param repo a Repository object that describes the repository
176 containing the file (if any).
178 super(FileLocation, self).
__init__(details)
183 self.file_size =
None
185 if not os.path.exists(path):
186 raise ValueError(
"%s does not exist" % path)
187 self.file_size = os.stat(path).st_size
189 self.path = os.path.abspath(path)
192 """A repository containing modeling files.
193 This can be used if the PMI script plus input files are part of a
194 repository, which has been archived somewhere with a DOI.
195 This will be used to construct permanent references to files
196 used in this modeling, even if they haven't been uploaded to
197 a database such as PDB or EMDB.
199 @see FileLocation."""
202 def __eq__(self, other):
203 return self.doi == other.doi
and self.url == other.url
205 return hash((self.doi, self.url))
210 @param doi the Digital Object Identifier for the repository.
211 @param root the relative path to the top-level directory
212 of the repository from the working directory of the script,
213 or None if files in this repository aren't checked out.
214 @param url If given, a location that this repository can be
216 @param top_directory If given, prefix all paths for files in this
217 repository with this value. This is useful when the archived
218 version of the repository is found in a subdirectory at the
219 URL or DOI (for example, GitHub repositories archived at
220 Zenodo get placed in a subdirectory named for the repository
225 self.url, self.top_directory = url, top_directory
228 self._root = os.path.abspath(root)
232 """If the given FileLocation maps to somewhere within one of the
233 passed repositories, update it to reflect that."""
236 orig_path = fileloc.path
238 relpath = os.path.relpath(orig_path, repo._root)
239 if not relpath.startswith(
'..'):
241 if fileloc.repo
is None or len(fileloc.path) > len(relpath):
243 fileloc.path = relpath
245 def _get_full_path(self, path):
246 """Prefix the given path with our top-level directory"""
247 return os.path.join(self.top_directory
or "", path)