Commits (14)
# edited from Gitlab template
image: python:3.7.7
# Change pip's cache directory to be inside the project directory since we can
# only cache local items.
variables:
PIP_CACHE_DIR: "$CI_PROJECT_DIR/.cache/pip"
# Pip's cache doesn't store the python packages
# https://pip.pypa.io/en/stable/reference/pip_install/#caching
#
# If you want to also cache the installed packages, you have to install
# them in a virtualenv and cache it as well.
cache:
paths:
- .cache/pip
- venv/
before_script:
- python -V # Print out python version for debugging
- pip install virtualenv
- virtualenv venv
- source venv/bin/activate
test:
script:
- python setup.py test
run:
script:
- python setup.py bdist_wheel
- python setup.py sdist
artifacts:
paths:
- dist/*.whl
- dist/*.tar.gz
# pages:
# script:
# - pip install sphinx sphinx-rtd-theme
# - cd doc ; make html
# - mv build/html/ ../public/
# artifacts:
# paths:
# - public
# only:
# - master
publish:
stage: deploy
variables:
TWINE_USERNAME: $PYPI_USERNAME
TWINE_PASSWORD: $PYPI_PASSWORD
script:
- pip install twine==2.0.0
- twine upload dist/*
only:
- tags
......@@ -43,10 +43,10 @@ from pythoms.molecule import IPMolecule
from pythoms.xlsx import XLSX
# input *.raw filename
filename = 'validation_files\\LY-2015-09-15 06.mzML.gz'
filename = 'tests/LY-2015-09-15 06.mzML.gz'
# Excel file to read from and output to (in *.xlsx format)
xlsx = 'validation_files\\LY-2015-09-15 06 processing.xlsx'
xlsx = 'tests/LY-2015-09-15 06 processing.xlsx'
# set number of scans to sum (integer or list of integers)
n = [3]
......
__version__ = '1.6.3'
__version__ = '1.6.4'
......@@ -1127,6 +1127,14 @@ class Molecule(object):
self.verbose,
)
def _get_kwargs(self) -> dict:
"""gets the kwargs associated with the instance for reinstantiation"""
return {
'charge': self.charge,
'mass_key': self.mass_key,
'verbose': self.verbose,
}
def __reduce__(self):
"""pickle support"""
return (
......@@ -1158,7 +1166,7 @@ class Molecule(object):
new[key] = other[key]
return self.__class__(
new,
charge=f'{self.charge}{self.sign}'
**self._get_kwargs(),
)
def __radd__(self, other):
......@@ -1205,7 +1213,7 @@ class Molecule(object):
new[key] -= other[key]
return self.__class__(
new,
charge=f'{self.charge}{self.sign}'
**self._get_kwargs(),
)
def __rsub__(self, other):
......@@ -1239,7 +1247,7 @@ class Molecule(object):
new[key] = new[key] * other
return self.__class__(
new,
charge=f'{self.charge}{self.sign}'
**self._get_kwargs(),
)
def __rmul__(self, other):
......@@ -1266,7 +1274,7 @@ class Molecule(object):
new[key] = int(newval)
return self.__class__(
new,
charge=f'{self.charge}{self.sign}'
**self._get_kwargs(),
)
def __itruediv__(self, other):
......@@ -1474,6 +1482,7 @@ class IPMolecule(Molecule):
save=False,
verbose=VERBOSE,
precalculated=None,
mass_key: str = 'nist_mass',
):
"""
A class with many mass-spectrometric properties such as estimated exact masses, isotope patterns, error
......@@ -1528,7 +1537,9 @@ class IPMolecule(Molecule):
*dropmethod* is not ``None``. See *dropmethod* for more details.
:param bool verbose: Verbose output. Mostly useful when calculating for large molecules or while debugging.
:param str mass_key: The mass dictionary to use for calculations. Default is nist_mass, but additional mass
dictionaries may be defined in the mass_dictionary file and retrieved using the dictionary name
used to define them.
"""
# todo implement apply_threshold method for trimming resulting spectrum
self.ipmethod = ipmethod
......@@ -1557,7 +1568,8 @@ class IPMolecule(Molecule):
Molecule.__init__(
self,
string,
charge,
charge=charge,
mass_key=mass_key,
verbose=verbose,
)
......@@ -1596,6 +1608,26 @@ class IPMolecule(Molecule):
},
)
def _get_kwargs(self) -> dict:
"""gets the kwargs associated with the instance for reinstantiation"""
return {
'charge': self.charge,
'mass_key': self.mass_key,
'verbose': self.verbose,
'consolidate': self.consolidate,
'criticalerror': self.criticalerror,
'decpl': self.decpl,
'dropmethod': self.dropmethod,
'emptyspec': self.emptyspec,
'groupmethod': self.groupmethod,
'ipmethod': self.ipmethod,
'keepall': self.keepall,
'npeaks': self.npeaks,
'resolution': self.resolution,
'threshold': self.threshold,
'save': self.save,
}
@property
def ipmethod(self):
return self._ipmethod
......
......@@ -13,8 +13,10 @@ KEYWORDS = ', '.join([
'HUPO PSI-MS',
])
with open('README.MD') as f:
long_description = f.read()
long_description = """
Contains classes and methods for processing mzML files, determining isotope patterns and physicochemical properties,
and combining spectra of dissimilar shape.
"""
setup(
name=NAME,
......@@ -23,7 +25,7 @@ setup(
long_description=long_description,
long_description_content_type='text/markdown',
author=AUTHOR,
url='https://github.com/larsyunker/PythoMS',
url='https://gitlab.com/larsyunker/PythoMS',
packages=PACKAGES,
license='MIT',
classifiers=[
......
"""
a script for validating the functionality of the commonly used scripts
"""
import unittest
if __name__ == '__main__':
unittest.main(verbosity=2)
import unittest
from pythoms.molecule import Molecule, IPMolecule, VALID_IPMETHODS, VALID_DROPMETHODS
class TestMolecule(unittest.TestCase):
def setUp(self):
self.mol = Molecule('L2PdAr+I')
self.ipmol = IPMolecule(
'L2PdAr+I',
ipmethod='multiplicative',
dropmethod='threshold',
threshold=0.01,
)
def test_molecule(self):
self.assertEqual(
self.mol.molecular_formula,
'C61H51IP3Pd'
)
self.assertEqual(
self.mol.composition,
{'C': 61, 'H': 51, 'P': 3, 'Pd': 1, 'I': 1}
)
self.assertEqual(
self.mol.molecular_weight,
1110.300954404405
)
self.assertEqual(
self.mol.monoisotopic_mass,
1109.12832
)
def test_ipmolecule_methods(self):
for ipmethod in VALID_IPMETHODS:
for dropmethod in VALID_DROPMETHODS:
mol = IPMolecule(
'Pd2C10H5',
ipmethod=ipmethod,
dropmethod=dropmethod,
)
test = mol.gaussian_isotope_pattern # test gaussian isotope pattern generation
def test_ipmolecule(self):
self.assertEqual(
self.ipmol.estimated_exact_mass,
1109.1303706381723,
)
self.assertEqual(
self.ipmol.barip,
[[1105.130443, 1106.133823749481, 1107.1290292337153, 1108.1305157201678, 1109.1303706381723,
1110.1328590930914, 1111.1301978511672, 1112.1325950611867, 1113.1318575059308, 1114.134086933976,
1115.1370272665604, 1116.140052, 1117.143407],
[2.287794397621507, 1.5228133756325326, 25.476059354316945, 66.8193866193291, 100.0, 52.65050639843156,
74.88108058795096, 42.5730473226288, 39.36707265932168, 20.17253048748261, 5.990476280101723,
1.1848920932846654, 0.16082254122736006]]
)
self.ipmol - 'PPh3' # test subtraction
self.ipmol + 'PPh3' # test addition
mol2 = IPMolecule('N(Et)2(CH2(13C)H2(2H))2')
self.ipmol + mol2 # test class addition
import unittest
import os
from pythoms.mzml import mzML, branch_attributes, branch_cvparams
class TestmzML(unittest.TestCase):
def test_mzml(self):
mzml = mzML(
os.path.join(os.path.dirname(__file__), 'MultiTest.mzML.gz'),
verbose=False
)
self.assertEqual( # check that the correct function keys were pulled
mzml.functions.keys(),
{1, 3, 4},
)
@mzml.foreachchrom
def testperchrom(chromatogram):
attr = branch_attributes(chromatogram)
return attr['id']
self.assertEqual( # test chromatogram decorator
testperchrom(),
[u'TIC', u'SRM SIC Q1=200 Q3=100 function=2 offset=0']
)
@mzml.foreachscan
def testperspec(spectrum):
p = branch_cvparams(spectrum)
return p["MS:1000016"].value
self.assertEqual( # test spectrum decorator
testperspec(),
[0.0171000008, 0.135733336, 0.254333347, 0.372983336, 0.491699994, 0.0510833338, 0.169750005,
0.288383335, 0.407000005, 0.525833309, 0.0847499967, 0.20341666, 0.322033346, 0.440683335]
)
self.assertEqual( # test intensity summing
sum(mzml.sum_scans()[1]),
162804754.0
)
self.assertEqual( # test scan indexing
sum((mzml[2])[1]),
6742121
)
self.assertEqual( # test time indexing
sum((mzml[0.01])[1]),
56270834
)
import os
import shutil
import unittest
from PyRSIR import pyrsir
class TestPyRSIR(unittest.TestCase):
def setUp(self) -> None:
# target xlsx and mzml pairings
self.targets = [
[
os.path.join(os.path.dirname(__file__), 'multitest_pyrsir_validation.xlsx'),
os.path.join(os.path.dirname(__file__), 'MultiTest.mzML.gz')
],
[
os.path.join(os.path.dirname(__file__), 'LY-2015-09-15 06 pyrsir example.xlsx'),
os.path.join(os.path.dirname(__file__), 'LY-2015-09-15 06.mzML.gz'),
]
]
# create backups
for xlfile, _ in self.targets:
shutil.copy(
xlfile,
f'{xlfile}.bak'
)
def test(self):
for xlfile, msfile in self.targets:
pyrsir(
msfile,
xlfile,
3,
plot=False,
verbose=False,
)
def tearDown(self) -> None:
for xlfile, _ in self.targets:
shutil.copy(
f'{xlfile}.bak',
xlfile,
)
os.remove(f'{xlfile}.bak')
"""
a script for validating the functionality of the commonly used scripts
"""
import unittest
import os
import pathlib
import shutil
from random import random
from pythoms.mzml import mzML, branch_cvparams, branch_attributes
from pythoms.molecule import Molecule, IPMolecule, VALID_DROPMETHODS, VALID_IPMETHODS, element_intensity_list
from pythoms.spectrum import Spectrum
from pythoms.xlsx import XLSX
from PyRSIR import pyrsir
validation_path = pathlib.Path(os.getcwd()) / 'validation_files'
class TestPyRSIR(unittest.TestCase):
def setUp(self) -> None:
# target xlsx and mzml pairings
self.targets = [
[
'multitest_pyrsir_validation.xlsx',
'MultiTest'
],
[
'LY-2015-09-15 06 pyrsir example.xlsx',
'LY-2015-09-15 06',
]
]
# create backups
for xlfile, _ in self.targets:
shutil.copy(
validation_path / xlfile,
validation_path / f'{xlfile}.bak'
)
def test(self):
for xlfile, msfile in self.targets:
pyrsir(
validation_path / msfile,
validation_path / xlfile,
3,
plot=False,
verbose=False,
)
def tearDown(self) -> None:
for xlfile, _ in self.targets:
shutil.copy(
validation_path / f'{xlfile}.bak',
validation_path / xlfile,
)
os.remove(validation_path / f'{xlfile}.bak')
class TestMolecule(unittest.TestCase):
def setUp(self):
self.mol = Molecule('L2PdAr+I')
self.ipmol = IPMolecule(
'L2PdAr+I',
ipmethod='multiplicative',
dropmethod='threshold',
threshold=0.01,
)
def test_molecule(self):
self.assertEqual(
self.mol.molecular_formula,
'C61H51IP3Pd'
)
self.assertEqual(
self.mol.composition,
{'C': 61, 'H': 51, 'P': 3, 'Pd': 1, 'I': 1}
)
self.assertEqual(
self.mol.molecular_weight,
1110.300954404405
)
self.assertEqual(
self.mol.monoisotopic_mass,
1109.12832
)
def test_ipmolecule_methods(self):
for ipmethod in VALID_IPMETHODS:
for dropmethod in VALID_DROPMETHODS:
mol = IPMolecule(
'Pd2C10H5',
ipmethod=ipmethod,
dropmethod=dropmethod,
)
test = mol.gaussian_isotope_pattern # test gaussian isotope pattern generation
def test_ipmolecule(self):
self.assertEqual(
self.ipmol.estimated_exact_mass,
1109.1303706381723,
)
self.assertEqual(
self.ipmol.barip,
[[1105.130443, 1106.133823749481, 1107.1290292337153, 1108.1305157201678, 1109.1303706381723,
1110.1328590930914, 1111.1301978511672, 1112.1325950611867, 1113.1318575059308, 1114.134086933976,
1115.1370272665604, 1116.140052, 1117.143407],
[2.287794397621507, 1.5228133756325326, 25.476059354316945, 66.8193866193291, 100.0, 52.65050639843156,
74.88108058795096, 42.5730473226288, 39.36707265932168, 20.17253048748261, 5.990476280101723,
1.1848920932846654, 0.16082254122736006]]
)
self.ipmol - 'PPh3' # test subtraction
self.ipmol + 'PPh3' # test addition
mol2 = IPMolecule('N(Et)2(CH2(13C)H2(2H))2')
self.ipmol + mol2 # test class addition
class TestmzML(unittest.TestCase):
def test_mzml(self):
mzml = mzML(
validation_path / 'MultiTest',
verbose=False
)
self.assertEqual( # check that the correct function keys were pulled
mzml.functions.keys(),
{1, 3, 4},
)
@mzml.foreachchrom
def testperchrom(chromatogram):
attr = branch_attributes(chromatogram)
return attr['id']
self.assertEqual( # test chromatogram decorator
testperchrom(),
[u'TIC', u'SRM SIC Q1=200 Q3=100 function=2 offset=0']
)
@mzml.foreachscan
def testperspec(spectrum):
p = branch_cvparams(spectrum)
return p["MS:1000016"].value
self.assertEqual( # test spectrum decorator
testperspec(),
[0.0171000008, 0.135733336, 0.254333347, 0.372983336, 0.491699994, 0.0510833338, 0.169750005,
0.288383335, 0.407000005, 0.525833309, 0.0847499967, 0.20341666, 0.322033346, 0.440683335]
)
self.assertEqual( # test intensity summing
sum(mzml.sum_scans()[1]),
162804754.0
)
self.assertEqual( # test scan indexing
sum((mzml[2])[1]),
6742121
)
self.assertEqual( # test time indexing
sum((mzml[0.01])[1]),
56270834
)
class TestXLSX(unittest.TestCase):
def test_xlsx(self):
xlfile = XLSX(
validation_path / 'xlsx_validation',
verbose=False
)
spec, xunit, yunit = xlfile.pullspectrum('example MS spectrum')
multispec = xlfile.pullmultispectrum('example multi-spectrum')
rsimparams = xlfile.pullrsimparams()
xlout = XLSX(
validation_path / 'xlsxtestout.xlsx',
create=True,
verbose=False
)
xlout.writespectrum(spec[0], spec[1], 'test single spectrum out', xunit, yunit)
for key, val in sorted(multispec.items()):
xlout.writemultispectrum(
multispec[key]['x'],
multispec[key]['y'],
multispec[key]['xunit'],
multispec[key]['yunit'],
'Function Chromatograms',
key
)
xlout.save()
os.remove(
validation_path / 'xlsxtestout.xlsx'
)
from pythoms.molecule import element_intensity_list
from pythoms.spectrum import Spectrum
class TestSpectrum(unittest.TestCase):
......@@ -287,7 +101,3 @@ class TestSpectrum(unittest.TestCase):
round(mz, 3),
round(spec.x[index], 3)
)
if __name__ == '__main__':
unittest.main(verbosity=2)
import os
import unittest
from pythoms.xlsx import XLSX
class TestXLSX(unittest.TestCase):
def test_xlsx(self):
xlfile = XLSX(
os.path.join(os.path.dirname(__file__), 'xlsx_validation'),
verbose=False
)
spec, xunit, yunit = xlfile.pullspectrum('example MS spectrum')
multispec = xlfile.pullmultispectrum('example multi-spectrum')
rsimparams = xlfile.pullrsimparams()
xlout = XLSX(
'xlsxtestout.xlsx',
create=True,
verbose=False
)
xlout.writespectrum(spec[0], spec[1], 'test single spectrum out', xunit, yunit)
for key, val in sorted(multispec.items()):
xlout.writemultispectrum(
multispec[key]['x'],
multispec[key]['y'],
multispec[key]['xunit'],
multispec[key]['yunit'],
'Function Chromatograms',
key
)
xlout.save()
os.remove(
'xlsxtestout.xlsx'
)
......@@ -21,7 +21,7 @@ import sys
import os
# input *.raw filename
filename = os.path.join(os.getcwd(), 'validation_files', 'LY-2015-09-15 06.mzML.gz')
filename = os.path.join(os.getcwd(), 'tests', 'LY-2015-09-15 06.mzML.gz')
# species to track and plot
# sub and superscripts can be denoted by TeX formatting
......