pymzqc 1.0.0rc2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,24 @@
1
+ Copyright (c) 2019-22, Mathias Walzer
2
+ All rights reserved.
3
+
4
+ Redistribution and use in source and binary forms, with or without
5
+ modification, are permitted provided that the following conditions are met:
6
+ * Redistributions of source code must retain the above copyright
7
+ notice, this list of conditions and the following disclaimer.
8
+ * Redistributions in binary form must reproduce the above copyright
9
+ notice, this list of conditions and the following disclaimer in the
10
+ documentation and/or other materials provided with the distribution.
11
+ * Neither the name of EBI nor HUPO-PSI nor MS-Quality-Hub nor the
12
+ names of its contributors may be used to endorse or promote products
13
+ derived from this software without specific prior written permission.
14
+
15
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
19
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,77 @@
1
+ Metadata-Version: 2.1
2
+ Name: pymzqc
3
+ Version: 1.0.0rc2
4
+ Summary: Python library for the PSI-mzQC quality control file format.
5
+ Home-page: https://github.com/MS-Quality-hub/pymzqc
6
+ Author: Mathias Walzer
7
+ Author-email: walzer@ebi.ack.uk
8
+ Requires-Python: >=3.8
9
+ Description-Content-Type: text/markdown
10
+ License-File: LICENSE
11
+ Requires-Dist: jsonschema>=3.2.0
12
+ Requires-Dist: strict-rfc3339
13
+ Requires-Dist: rfc3339-validator
14
+ Requires-Dist: numpy
15
+ Requires-Dist: pandas>=1.1.5
16
+ Requires-Dist: pronto
17
+ Requires-Dist: requests>=2.27.1
18
+ Requires-Dist: click
19
+
20
+ # MZQC python library
21
+ [![unit-tests](https://github.com/MS-Quality-hub/pymzqc/actions/workflows/unit_tests.yml/badge.svg)](https://github.com/MS-Quality-hub/pymzqc/actions/workflows/unit_tests.yml)
22
+ [![Documentation Status](https://readthedocs.org/projects/pymzqc/badge/?version=latest)](https://pymzqc.readthedocs.io/en/latest/?badge=latest)
23
+ [![Docker Repository on Quay](https://img.shields.io/badge/container-ready-brightgreen.svg "Docker Repository on Quay")](https://quay.io/repository/mwalzer/pymzqc?tab=tags)
24
+ [![PyPi version](https://badgen.net/pypi/v/pymzqc/)](https://pypi.com/project/pymzqc)
25
+ [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/MS-Quality-hub/pymzqc/blob/main/jupyter/mzqc_in_5/write_in_5_minutes.ipynb)
26
+
27
+ A python library to create and use mzQC files. Specifically, the library facilitates access to
28
+ mzQC files in form of a **directly usable object representation of mzQC** and offers additional
29
+ functionality to:
30
+ * serialise
31
+ * deserialise
32
+ * check syntax
33
+ * check semantics
34
+ * file-info
35
+ * experimental file-merging
36
+
37
+ **The library follows the formats versioning** (which is 'v(Major).(Minor).(Patch)').
38
+
39
+ This library implements python modules for (de-)serialisation and validity checks of the [PSI fileformat](http://www.psidev.info/groups/quality-control) [**mzQC**](https://hupo-psi.github.io/mzQC/). Find the specification document, examples, and and further documentation there.
40
+
41
+
42
+ ## Install
43
+
44
+ ### Latest Release
45
+ Most people will want to install the latest release version of pymzqc. Please install pymzqc via [**pypi**](https://pypi.org/project/pymzqc/):
46
+ ```
47
+ pip install pymzqc
48
+ ```
49
+
50
+ ### From Git
51
+ If you want a development version, use:
52
+ ```
53
+ pip install -U git+https://github.com/MS-Quality-hub/pymzqc.git#v1.0.0rc2
54
+ ```
55
+ You can select a development branch of your choice by changing the command after the `.git#`
56
+
57
+ ### Containers
58
+ However, we recommend using the ready-built [**containers**](https://quay.io/repository/mwalzer/pymzqc?tab=tags) to check out the latest updates.
59
+
60
+ ## Online docs
61
+ To get a nice and simple overview of how pymzqc works, visit [here](https://pymzqc.readthedocs.io/en/latest/examples.html).
62
+ If you've successfully installed the library and want to **jump right in and work on the library**, we suggest a peek at the [codestructure](https://pymzqc.readthedocs.io/en/latest/codestructure.html).
63
+
64
+ If you however just want to get your toes wet, or use it as-is, have a look at the interactive guides (below).
65
+
66
+ ### Interactive pymzqc
67
+ Have a go with our [interactive python notebooks](jupyter/README.md) to explore what is possible.
68
+
69
+ ## Development
70
+ Contributions are welcome! (Just fork, develop, and open PR.)
71
+
72
+ ### Repository structure
73
+ The python package's code is located in the `mzqc` folder, continuous testing code in `tests`, the documentation in `doc`. The libray-**use** container descriptions are in `containers`, if you want a container for library-**development**, you can use the container description within `.devcontainer`, more development presets can be found in `.vscode`. The `jupyter` and `accessories` folders are subprojects making use of the library. See their README in the respective sub-folders.
74
+
75
+ ### Documentation
76
+ The code documentation style convention is of the type `Sphinx/numpy`.
77
+
@@ -0,0 +1,58 @@
1
+ # MZQC python library
2
+ [![unit-tests](https://github.com/MS-Quality-hub/pymzqc/actions/workflows/unit_tests.yml/badge.svg)](https://github.com/MS-Quality-hub/pymzqc/actions/workflows/unit_tests.yml)
3
+ [![Documentation Status](https://readthedocs.org/projects/pymzqc/badge/?version=latest)](https://pymzqc.readthedocs.io/en/latest/?badge=latest)
4
+ [![Docker Repository on Quay](https://img.shields.io/badge/container-ready-brightgreen.svg "Docker Repository on Quay")](https://quay.io/repository/mwalzer/pymzqc?tab=tags)
5
+ [![PyPi version](https://badgen.net/pypi/v/pymzqc/)](https://pypi.com/project/pymzqc)
6
+ [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/MS-Quality-hub/pymzqc/blob/main/jupyter/mzqc_in_5/write_in_5_minutes.ipynb)
7
+
8
+ A python library to create and use mzQC files. Specifically, the library facilitates access to
9
+ mzQC files in form of a **directly usable object representation of mzQC** and offers additional
10
+ functionality to:
11
+ * serialise
12
+ * deserialise
13
+ * check syntax
14
+ * check semantics
15
+ * file-info
16
+ * experimental file-merging
17
+
18
+ **The library follows the formats versioning** (which is 'v(Major).(Minor).(Patch)').
19
+
20
+ This library implements python modules for (de-)serialisation and validity checks of the [PSI fileformat](http://www.psidev.info/groups/quality-control) [**mzQC**](https://hupo-psi.github.io/mzQC/). Find the specification document, examples, and and further documentation there.
21
+
22
+
23
+ ## Install
24
+
25
+ ### Latest Release
26
+ Most people will want to install the latest release version of pymzqc. Please install pymzqc via [**pypi**](https://pypi.org/project/pymzqc/):
27
+ ```
28
+ pip install pymzqc
29
+ ```
30
+
31
+ ### From Git
32
+ If you want a development version, use:
33
+ ```
34
+ pip install -U git+https://github.com/MS-Quality-hub/pymzqc.git#v1.0.0rc2
35
+ ```
36
+ You can select a development branch of your choice by changing the command after the `.git#`
37
+
38
+ ### Containers
39
+ However, we recommend using the ready-built [**containers**](https://quay.io/repository/mwalzer/pymzqc?tab=tags) to check out the latest updates.
40
+
41
+ ## Online docs
42
+ To get a nice and simple overview of how pymzqc works, visit [here](https://pymzqc.readthedocs.io/en/latest/examples.html).
43
+ If you've successfully installed the library and want to **jump right in and work on the library**, we suggest a peek at the [codestructure](https://pymzqc.readthedocs.io/en/latest/codestructure.html).
44
+
45
+ If you however just want to get your toes wet, or use it as-is, have a look at the interactive guides (below).
46
+
47
+ ### Interactive pymzqc
48
+ Have a go with our [interactive python notebooks](jupyter/README.md) to explore what is possible.
49
+
50
+ ## Development
51
+ Contributions are welcome! (Just fork, develop, and open PR.)
52
+
53
+ ### Repository structure
54
+ The python package's code is located in the `mzqc` folder, continuous testing code in `tests`, the documentation in `doc`. The libray-**use** container descriptions are in `containers`, if you want a container for library-**development**, you can use the container description within `.devcontainer`, more development presets can be found in `.vscode`. The `jupyter` and `accessories` folders are subprojects making use of the library. See their README in the respective sub-folders.
55
+
56
+ ### Documentation
57
+ The code documentation style convention is of the type `Sphinx/numpy`.
58
+
@@ -0,0 +1,485 @@
1
+ __author__ = 'walzer'
2
+ import json
3
+ import re
4
+ import operator
5
+ from datetime import datetime
6
+ from typing import List,Dict,Union,Any,Tuple
7
+ import numpy as np
8
+ import pandas as pd
9
+ import logging
10
+
11
+ #int
12
+ #str
13
+ #float
14
+ FloatVector = List[float]
15
+ IntVector = List[int]
16
+ StringVector = List[str]
17
+ FloatMatrix = List[FloatVector]
18
+ IntMatrix = List[IntVector]
19
+ StringMatrix = List[StringVector]
20
+ #Table = Dict[str,Union(FloatVector,IntVector,StringVector)]
21
+ Table = Dict[str,List]
22
+
23
+ class JsonSerialisable(object):
24
+ """
25
+ JsonSerialisable Main structure template for mzQC objects
26
+
27
+ Sets the foundation for a mzQC object to be readily (de-)serialisable with standard python json handling code.
28
+ Facilitates reading and writing of complex objects.
29
+
30
+ """
31
+ mappings: Dict[str, Any] = dict()
32
+
33
+ @staticmethod
34
+ def time_helper(da:str) -> datetime:
35
+ """
36
+ time_helper Helper method for ISO8601 string of various length consumption
37
+
38
+ Used on JSON datetime object string representation will handle length and return
39
+ python datetime objects. JSON-schema actually follows
40
+ https://www.rfc-editor.org/rfc/rfc3339.html#section-5.6 which is a little more
41
+ stringent subset of ISO8601.
42
+
43
+ Parameters
44
+ ----------
45
+ da : str
46
+ JSON datetime object string representation
47
+
48
+ Returns
49
+ -------
50
+ datetime
51
+ Python datetime object including the same amount detail provided
52
+ """
53
+ try:
54
+ dt = pd.to_datetime(da)
55
+ except:
56
+ raise ValueError("Unknown string format: {}".format(da))
57
+ return dt
58
+
59
+ @classmethod
60
+ def class_mapper(classself, d):
61
+ """
62
+ class_mapper Maps incoming objects to their respective definition
63
+
64
+ Allows every registered object to 'know' its type map incuding recursing into its attributes.
65
+ Can be used as object_hook in the json load process.
66
+
67
+ Parameters
68
+ ----------
69
+ classself : self
70
+ The objects class self
71
+ d : dict
72
+ The dictionary mapping attributes
73
+
74
+ Returns
75
+ -------
76
+ class object
77
+ Returns an object of the 'outer-most' class
78
+
79
+ Raises
80
+ ------
81
+ ValueError
82
+ If expected date strings are invalid.
83
+ """
84
+ maxcls: Any = None
85
+ exmax: int = 0
86
+ for keys, cls in classself.mappings.items():
87
+ if keys.issuperset(d.keys()):
88
+ nx = len(set(d.keys()).intersection(set(keys)))
89
+ if nx > exmax:
90
+ maxcls = cls
91
+ exmax = nx
92
+
93
+ if maxcls != None:
94
+ return maxcls(**d)
95
+ else:
96
+ if {'creationDate': None}.keys() == d.keys():
97
+ try:
98
+ return JsonSerialisable.time_helper(d['creationDate'])
99
+ except ValueError:
100
+ raise ValueError("It appears the creationDate of your file is not of ISO 8601 format including time to the second: {}".format(d['creationDate']))
101
+ else:
102
+ # raise ValueError('Unable to find a matching class for object: {d} (keys: {k})' .format(d=d,k=d.keys()))
103
+ return d
104
+
105
+ @classmethod
106
+ def complex_handler(classself, obj):
107
+ """
108
+ complex_handler Handles the in-depth serialisations necessary
109
+
110
+ Facilitates the correct serialisation for each type of object (within
111
+ the registered mzQC JsonSerialisable context) through possible
112
+ serialisation specialisation by way of object type. If objects behave
113
+ like dictionaries, but are complex classes (like all pymzqc obj),
114
+ the dict needs to be returned as classical dict in order to serialise.
115
+
116
+ Parameters
117
+ ----------
118
+ classself : self
119
+ The objects class self
120
+ obj : object
121
+ The object to be deserialised
122
+
123
+ Returns
124
+ -------
125
+ obj
126
+ The correct object deconstruction into its deserialisable bits
127
+
128
+ Raises
129
+ ------
130
+ TypeError
131
+ In case a given object cannot be serialised with the given set of functionalities.
132
+ """
133
+ if isinstance(obj, datetime):
134
+ logging.debug("serialisation specialisation dates: "+str(obj))
135
+ if obj.tzinfo:
136
+ return obj.isoformat().replace('+00:00','Z')
137
+ else: #assume local time is UTC, the standard requires RFC3339 after all (see specification)
138
+ return obj.isoformat()+('Z')
139
+
140
+ if 'numpy' in str(type(obj)):
141
+ logging.debug("serialisation specialisation np.dtypes: "+str(obj))
142
+ if isinstance(obj,np.ndarray):
143
+ return obj.tolist()
144
+ return obj.item()
145
+
146
+ # needs to be last
147
+ if hasattr(obj, '__dict__'):
148
+ return {k:v for k,v in obj.__dict__.items() if v != None and v != ""}
149
+
150
+ raise TypeError('Object of type {ty} with value {val} is not JSON (de)serializable'.format(ty=type(obj), val=repr(obj)))
151
+
152
+ @classmethod
153
+ def register(classself, cls):
154
+ """
155
+ register The method for class registration in the class mapping process
156
+
157
+ Each registered class gets mapped.
158
+
159
+ Parameters
160
+ ----------
161
+ classself : self
162
+ the objects class self
163
+ cls : object
164
+ the class type
165
+
166
+ Returns
167
+ -------
168
+ cls
169
+ the class type
170
+ """
171
+ classself.mappings[frozenset(tuple([attr for attr, val in cls().__dict__.items()]))] = cls
172
+ return cls
173
+
174
+ @classmethod
175
+ def ToJson(classself, obj, readability=0, complete=True):
176
+ """
177
+ ToJson Main method for serialisation
178
+
179
+ Parameters
180
+ ----------
181
+ classself : self
182
+ The objects class self
183
+ obj : object
184
+ The object to be serialised
185
+ readability : int, optional
186
+ The indentation level, by default 0 (=no indentation,
187
+ 1=minor indentation on MZQC objects, >1 heavy indentation for max.
188
+ human readability)
189
+ complete: bool, optional
190
+ Flag to indicate if the object is to be left without the
191
+ enclosing `mzQC` key or if the JSON is to be amended to full
192
+ schema compliance (default).
193
+
194
+ Returns
195
+ -------
196
+ str
197
+ The serialisation result
198
+ """
199
+ if readability==0:
200
+ ret = json.dumps(obj.__dict__ if type(obj) == MzQcFile else obj, default=classself.complex_handler)
201
+ elif readability == 1:
202
+ ret = json.dumps(obj.__dict__ if type(obj) == MzQcFile else obj, default=classself.complex_handler, indent=2, cls=MzqcJSONEncoder)
203
+ else:
204
+ ret = json.dumps(obj.__dict__ if type(obj) == MzQcFile else obj, default=classself.complex_handler, indent=4)
205
+ #remove empty run/setQualities and other optinal and empty elements, return with mzqc root,
206
+ ret = re.sub(r'(\"setQualities\"\:\s+\[\s*\][,]*)|(\"runQualities\"\:\s+\[\s*\][,]*)|([,]*\s+\"fileProperties\"\:\s+\[\s*\][,]*)', "", ret)
207
+ ret = ret.replace('"contactName": "",\n', '').replace('"contactAddress": "",\n', '').replace('"description": "",\n', '')
208
+ ret = "{{\"mzQC\": \n{dump} \n}}".format(dump=ret) if complete else ret
209
+ return ret
210
+
211
+ @classmethod
212
+ def FromJson(classself, json_str, complete=False):
213
+ """
214
+ FromJson Main method for deserialisation
215
+
216
+ Accounts for neccessary object rectification due to same-attribute
217
+ class footprints. N.B.: for this to work the class init variables must
218
+ be same name as the corresponding member attributes (self).
219
+
220
+ Parameters
221
+ ----------
222
+ classself : self
223
+ The objects class self
224
+ json_str : str
225
+ The JSON string to be deserialised
226
+ complete : bool, optional
227
+ Flag to indicate if the whole JSON is to be returned deserialised,
228
+ or just the `mzQC` entry (default).
229
+
230
+ Returns
231
+ -------
232
+ MzQcFile object
233
+ The deserialised JSON string
234
+ """
235
+ if isinstance(json_str, str):
236
+ j = json.loads(json_str, object_hook=classself.class_mapper)
237
+ else: # assume it is a IO wrapper
238
+ j = json.load(json_str, object_hook=classself.class_mapper)
239
+ if not(complete) and 'mzQC' in j.keys():
240
+ j = j['mzQC']
241
+ return rectify(j)
242
+
243
+
244
+ def rectify(obj):
245
+ """
246
+ rectify Rectifies objects according to their position in the local hierarchy
247
+
248
+ Carries out the neccessary object rectification due to same-attribute class footprints.
249
+ Rectification depends on the object position in the local object hierarchy.
250
+
251
+ Parameters
252
+ ----------
253
+ obj : object
254
+ The object to be rectified
255
+
256
+ Returns
257
+ -------
258
+ object
259
+ The rectified object
260
+ """
261
+ static_list_typemap = {'runQualities': RunQuality, 'setQualities': SetQuality, 'controlledVocabularies': ControlledVocabulary,
262
+ 'qualityMetrics': QualityMetric, 'inputFiles': InputFile, 'analysisSoftware': AnalysisSoftware, 'fileProperties': CvParameter}
263
+ static_singlet_typemap = {'fileFormat': CvParameter, 'metadata': MetaDataParameters}
264
+ if hasattr(obj, '__dict__'):
265
+ for k,v in obj.__dict__.items():
266
+ if k in static_list_typemap.keys():
267
+ v[:] = [rectify((static_list_typemap[k])(**i.__dict__ if hasattr(i, '__dict__') else i)) for i in v]
268
+ elif k in static_singlet_typemap.keys():
269
+ k = rectify((static_singlet_typemap[k])(**v.__dict__ if hasattr(v, '__dict__') else v))
270
+ else:
271
+ rectify(v)
272
+ elif isinstance(obj, dict):
273
+ for k,v in obj.items():
274
+ rectify(v)
275
+ return obj
276
+
277
+
278
+ class MzqcJSONEncoder(json.JSONEncoder):
279
+ """
280
+ MzqcJSONEncoder The encoder used to facilitate indented encoding
281
+
282
+ Handles the string encoding and formatting of the serialised objects.
283
+
284
+ """
285
+ def iterencode(self, o, _one_shot=False):
286
+ indent_level = 0
287
+ value_scope = False
288
+ for s in super(MzqcJSONEncoder, self).iterencode(o, _one_shot=_one_shot):
289
+ if value_scope and indent_level == 0 and s.startswith('}'):
290
+ value_scope = False
291
+ elif s.startswith('"value"'):
292
+ value_scope = True
293
+ if 0 < indent_level:
294
+ s = s.replace('\n', '').rstrip().lstrip()
295
+ if s.startswith(','):
296
+ s = ',' + s[1:].lstrip()
297
+ if s.startswith('[') and value_scope:
298
+ indent_level += 1
299
+ if s.endswith(']') and value_scope:
300
+ indent_level -= 1
301
+ s = s.replace(']', '\n'+' '*self.indent*6+']').rstrip()
302
+ yield s
303
+
304
+
305
+ class jsonobject(object):
306
+ """
307
+ jsonobject Proxy object for better integration of mzQC objects
308
+
309
+ Useful for testing and validity checks as __eq__ is overridden to compare all attributes as well.
310
+
311
+ """
312
+ def __eq__(self, other):
313
+ """
314
+ __eq__ Overrides the default implementation
315
+
316
+ Compare all attributes as well.
317
+
318
+ Parameters
319
+ ----------
320
+ other : object
321
+
322
+ Returns
323
+ -------
324
+ bool
325
+ False if the two objects are not of the same class or any of the attributes differ
326
+ """
327
+ if isinstance(other, __class__):
328
+ # TODO find difference in keys and check whether they are None or "" in the other or vice versa
329
+ snn = [k for k,v in self.__dict__.items() if (not v == None and not v == "")]
330
+ onn = [k for k,v in other.__dict__.items() if (not v == None and not v == "")]
331
+ if set(snn) == set(onn):
332
+ return all([self.__getattribute__(attr) == other.__getattribute__(attr) for attr in self.__dict__.keys()])
333
+ return False
334
+
335
+ @JsonSerialisable.register
336
+ class ControlledVocabulary(jsonobject):
337
+ """
338
+ ControlledVocabulary Object representation for mzQC schema type ControlledVocabulary
339
+
340
+ """
341
+ def __init__(self, name: str="", uri: str="", version: str=""):
342
+ self.name = name # required
343
+ self.uri = uri # required
344
+ self.version = version # optional
345
+
346
+ @JsonSerialisable.register
347
+ class CvParameter(jsonobject):
348
+ """
349
+ CvParameter Object representation for mzQC schema type CvParameter
350
+
351
+ """
352
+ def __init__(self, accession: str="",
353
+ name: str="",
354
+ description: str="",
355
+ value: Union[int,str,float,IntVector,StringVector,FloatVector,IntMatrix,StringMatrix,FloatMatrix,Table, None]=None,
356
+ unit: str=""):
357
+ self.accession = accession # required "pattern": "^[A-Z]+:[0-9]{7}$"
358
+ self.name = name # required
359
+ self.description = description # optional, "pattern": "^[A-Z]+$"
360
+ self.value = value # optional
361
+ self.unit = unit # optional, IMO this should be accession only, not annother cvParam
362
+
363
+ @JsonSerialisable.register
364
+ class AnalysisSoftware(CvParameter):
365
+ """
366
+ AnalysisSoftware Object representation for mzQC schema type AnalysisSoftware
367
+
368
+ """
369
+ def __init__(self, accession: str="",
370
+ name: str="",
371
+ description: str="",
372
+ value: str="",
373
+ unit: str="",
374
+ version: str = "",
375
+ uri: str = ""):
376
+ super().__init__(accession, name, description, value, unit) # optional, this will set None to optional omitted arguments
377
+ self.version = version # required
378
+ self.uri = uri # required
379
+
380
+ @JsonSerialisable.register
381
+ class InputFile(jsonobject):
382
+ """
383
+ InputFile Object representation for mzQC schema type InputFile
384
+
385
+ """
386
+ def __init__(self, location: str = "",
387
+ name: str = "",
388
+ fileFormat: CvParameter = None,
389
+ fileProperties: List[CvParameter] = None):
390
+ self.location = location # required , uri
391
+ self.name = name # required , string (doubles as internal and external ref anchor?)
392
+ self.fileFormat = fileFormat # required , cvParam
393
+ self.fileProperties = [] if fileProperties is None else fileProperties # optional, cvParam, at least one item
394
+
395
+ @JsonSerialisable.register
396
+ class MetaDataParameters(jsonobject):
397
+ """
398
+ MetaDataParameters Object representation for mzQC schema type MetaDataParameters
399
+
400
+ """
401
+ def __init__(self,
402
+ # fileProvenance: str="",
403
+ # cv_params: List[CvParameter] = None ,
404
+ label: str = "",
405
+ inputFiles: List[InputFile] = None,
406
+ analysisSoftware: List[AnalysisSoftware]=None
407
+ ):
408
+ # self.fileProvenance = fileProvenance # not in schema
409
+ # self.cv_params = [] if cv_params is None else cv_params # not in schema, IMO should be in there
410
+ self.label = label # optional
411
+ self.inputFiles = [] if inputFiles is None else inputFiles # required
412
+ self.analysisSoftware = [] if analysisSoftware is None else analysisSoftware # required
413
+
414
+ # schema: at least one input_file in input_files
415
+ # schema: at least one analysis_software in analysis_software
416
+
417
+ @JsonSerialisable.register
418
+ class QualityMetric(CvParameter):
419
+ """
420
+ QualityMetric Object representation is passed for its more concrete derivatives
421
+
422
+ """
423
+ pass
424
+ # def __init__(self, cvRef: str="",
425
+ # accession: str="",
426
+ # name: str="",
427
+ # description: str="",
428
+ # value: Union[int,str,float,IntVector,StringVector,FloatVector,IntMatrix,StringMatrix,FloatMatrix,Table, None]=None, # here we could clamp down on allowed value types
429
+ # unit: str=""):
430
+ # super().__init__(cvRef, accession, name, description, value, unit) # optional, this will set None to optional omitted arguments
431
+ # schema: is cvParam object
432
+ # schema: do we allow no-value metrics? cvParam value attribute is optional
433
+ # implementation: this is a different object class because we want to make semantical distinctions between pure metrics and generic CvParams
434
+
435
+ @JsonSerialisable.register
436
+ class BaseQuality(jsonobject):
437
+ """
438
+ BaseQuality Object representation for mzQC schema type BaseQuality
439
+
440
+ """
441
+ def __init__(self, metadata: MetaDataParameters=None,
442
+ qualityMetrics: List[QualityMetric]=None):
443
+ self.metadata = metadata # required
444
+ self.qualityMetrics = [] if qualityMetrics is None else qualityMetrics # required,
445
+ # schema: at least one item in quality_metrics
446
+
447
+ @JsonSerialisable.register
448
+ class RunQuality(BaseQuality):
449
+ """
450
+ QualityMetric Object representation is passed for its more general basis
451
+
452
+ """
453
+ pass
454
+
455
+ @JsonSerialisable.register
456
+ class SetQuality(BaseQuality):
457
+ """
458
+ SetQuality Object representation is passed for its more general basis
459
+
460
+ """
461
+ pass
462
+
463
+ @JsonSerialisable.register
464
+ class MzQcFile(jsonobject):
465
+ """
466
+ MzQcFile Object representation for mzQC schema type MzQcFile
467
+
468
+ """
469
+ def __init__(self, creationDate: Union[datetime,str] = datetime.now().replace(microsecond=0), version: str = "1.0.0",
470
+ contactName: str = "", contactAddress: str = "", description: str = "",
471
+ runQualities: List[RunQuality]=None,
472
+ setQualities: List[SetQuality]=None,
473
+ controlledVocabularies: List[ControlledVocabulary]=None
474
+ ):
475
+ self.creationDate = JsonSerialisable.time_helper(creationDate) if isinstance(creationDate, str) else creationDate # required
476
+ self.version = version # required
477
+ self.contactName = contactName # optional
478
+ self.contactAddress = contactAddress # optional
479
+ self.description = description # optional
480
+ self.runQualities = [] if runQualities is None else runQualities # either or set required
481
+ self.setQualities = [] if setQualities is None else setQualities # either or run required
482
+ self.controlledVocabularies = [] if controlledVocabularies is None else controlledVocabularies # required
483
+ # schema: at least one cv in controlled_vocabularies
484
+ # schema: at least one of run_qualities or set_qualities
485
+ # schema: at least one item in run_qualities or set_qualities