Skip to content

Commit

Permalink
Merge pull request #87 from wilhelm-lab/patch/0.5.1
Browse files Browse the repository at this point in the history
Patch/0.5.1
  • Loading branch information
picciama authored Apr 12, 2024
2 parents 1fbddfa + 715d638 commit 8a64572
Show file tree
Hide file tree
Showing 18 changed files with 1,064 additions and 692 deletions.
2 changes: 1 addition & 1 deletion .cookietemple.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,5 @@ full_name: Victor Giurcoiu
email: [email protected]
project_name: spectrum_fundamentals
project_short_description: Fundamentals public repo
version: 0.5.0
version: 0.5.1
license: MIT
4 changes: 2 additions & 2 deletions .github/release-drafter.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name-template: "0.5.0 🌈" # <<COOKIETEMPLE_FORCE_BUMP>>
tag-template: 0.5.0 # <<COOKIETEMPLE_FORCE_BUMP>>
name-template: "0.5.1 🌈" # <<COOKIETEMPLE_FORCE_BUMP>>
tag-template: 0.5.1 # <<COOKIETEMPLE_FORCE_BUMP>>
exclude-labels:
- "skip-changelog"

Expand Down
10 changes: 8 additions & 2 deletions .github/workflows/run_tests.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
name: Run spectrum_fundamentals Tests

on:
- push
- pull_request
push:
branches:
- development
- main
- "release/*"
pull_request:
branches:
- "*"

jobs:
tests:
Expand Down
2 changes: 1 addition & 1 deletion cookietemple.cfg
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[bumpversion]
current_version = 0.5.0
current_version = 0.5.1

[bumpversion_files_whitelisted]
init_file = spectrum_fundamentals/__init__.py
Expand Down
4 changes: 2 additions & 2 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,9 @@
# the built documents.
#
# The short X.Y version.
version = "0.5.0"
version = "0.5.1"
# The full version, including alpha/beta/rc tags.
release = "0.5.0"
release = "0.5.1"

# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
Expand Down
1 change: 1 addition & 0 deletions noxfile.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
"""Nox sessions."""

import os
import shlex
import shutil
Expand Down
1,532 changes: 882 additions & 650 deletions poetry.lock

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "spectrum_fundamentals"
version = "0.5.0" # <<COOKIETEMPLE_FORCE_BUMP>>
version = "0.5.1" # <<COOKIETEMPLE_FORCE_BUMP>>
description = "Fundamental functions, annotation pipeline and constants for oktoberfest"
authors = ["Wilhelmlab at Technical University of Munich"]
license = "MIT"
Expand Down
37 changes: 29 additions & 8 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,8 +1,29 @@
click>=8.0.0
rich>=10.3.0
PyYAML>=5.4.1
numpy>=1.24.1
pandas>=1.3.0
scikit-learn>=1.0
joblib>=1.0.1
moepy>=1.1.4
click==8.1.7 ; python_full_version >= "3.8.0" and python_full_version < "3.11.0"
colorama==0.4.6 ; python_full_version >= "3.8.0" and python_full_version < "3.11.0" and platform_system == "Windows"
contourpy==1.1.1 ; python_version >= "3.8" and python_full_version < "3.11.0"
cycler==0.12.1 ; python_version >= "3.8" and python_full_version < "3.11.0"
fonttools==4.51.0 ; python_version >= "3.8" and python_full_version < "3.11.0"
importlib-resources==6.4.0 ; python_version >= "3.8" and python_version < "3.10"
joblib==1.4.0 ; python_version >= "3.8" and python_full_version < "3.11.0"
kiwisolver==1.4.5 ; python_version >= "3.8" and python_full_version < "3.11.0"
markdown-it-py==3.0.0 ; python_version >= "3.8" and python_full_version < "3.11.0"
matplotlib==3.7.5 ; python_version >= "3.8" and python_full_version < "3.11.0"
mdurl==0.1.2 ; python_version >= "3.8" and python_full_version < "3.11.0"
moepy==1.1.4 ; python_full_version >= "3.8.0" and python_full_version < "3.11.0"
numpy==1.24.4 ; python_version >= "3.8" and python_full_version < "3.11.0"
packaging==24.0 ; python_version >= "3.8" and python_full_version < "3.11.0"
pandas==1.5.3 ; python_version >= "3.8" and python_full_version < "3.11.0"
pillow==10.3.0 ; python_version >= "3.8" and python_full_version < "3.11.0"
pygments==2.17.2 ; python_full_version >= "3.8.0" and python_full_version < "3.11.0"
pyparsing==3.1.2 ; python_version >= "3.8" and python_full_version < "3.11.0"
python-dateutil==2.9.0.post0 ; python_version >= "3.8" and python_full_version < "3.11.0"
pytz==2024.1 ; python_version >= "3.8" and python_full_version < "3.11.0"
pyyaml==6.0.1 ; python_full_version >= "3.8.0" and python_full_version < "3.11.0"
rich==13.7.1 ; python_full_version >= "3.8.0" and python_full_version < "3.11.0"
scikit-learn==1.3.2 ; python_version >= "3.8" and python_full_version < "3.11.0"
scipy==1.10.1 ; python_version >= "3.8" and python_full_version < "3.11.0"
six==1.16.0 ; python_version >= "3.8" and python_full_version < "3.11.0"
threadpoolctl==3.4.0 ; python_version >= "3.8" and python_full_version < "3.11.0"
tqdm==4.66.2 ; python_full_version >= "3.8.0" and python_full_version < "3.11.0"
typing-extensions==4.11.0 ; python_version >= "3.8" and python_version < "3.9"
zipp==3.18.1 ; python_version >= "3.8" and python_version < "3.10"
3 changes: 2 additions & 1 deletion spectrum_fundamentals/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
"""Initialize fundamentals."""

__author__ = "Mario Picciani"
__email__ = "[email protected]"
__version__ = "0.5.0"
__version__ = "0.5.1"

import logging
import logging.handlers
Expand Down
2 changes: 1 addition & 1 deletion spectrum_fundamentals/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@


@click.command()
@click.version_option(version="0.5.0", message=click.style("spectrum_fundamentals Version: 0.5.0"))
@click.version_option(version="0.5.1", message=click.style("spectrum_fundamentals Version: 0.5.1"))
def main() -> None:
"""spectrum_fundamentals."""

Expand Down
2 changes: 1 addition & 1 deletion spectrum_fundamentals/charge.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ def indices_to_one_hot(labels: Union[int, List[int], np.ndarray], classes: Optio
f"Type of labels not understood. Only int, List[int] and np.ndarray are supported. Given: {type(labels)}."
)

max_label = labels.max()
max_label = int(labels.max())
if classes is None:
classes = max_label
if max_label > classes:
Expand Down
11 changes: 11 additions & 0 deletions spectrum_fundamentals/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,17 @@
"n[214]": "[UNIMOD:214]-",
}

#######################
# Xisearch constants #
#######################

XISEARCH_VAR_MODS = {
"ox": "[UNIMOD:35]",
"cm": "[UNIMOD:4]",
"dsso": "[UNIMOD:1896]",
"dsbu": "[UNIMOD:1884]",
}

####################
# MASS CALCULATION #
####################
Expand Down
4 changes: 1 addition & 3 deletions spectrum_fundamentals/metrics/fragments_ratio.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ class FragmentsRatio(Metric):

@staticmethod
def count_with_ion_mask(
boolean_array: scipy.sparse.csr_matrix, ion_mask: Optional[Union[np.ndarray, scipy.sparse.csr_matrix]] = None
boolean_array: scipy.sparse.csr_matrix, ion_mask: Optional[Union[np.ndarray, scipy.sparse.spmatrix]] = None
) -> np.ndarray:
"""
Count the number of ions.
Expand All @@ -43,8 +43,6 @@ def count_with_ion_mask(
:return: number of observed/predicted peaks not masked by ion_mask
"""
if ion_mask is None:
ion_mask = []
if len(ion_mask) == 0:
ion_mask = scipy.sparse.csr_matrix(np.ones((174, 1)))
else:
ion_mask = scipy.sparse.csr_matrix(ion_mask).T
Expand Down
78 changes: 73 additions & 5 deletions spectrum_fundamentals/mod_string.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,20 @@
import difflib
import re
from itertools import repeat
from typing import Dict, List, Optional, Tuple
from typing import Dict, List, Optional, Tuple, Union

from .constants import MAXQUANT_VAR_MODS, MOD_MASSES, MOD_MASSES_SAGE, MOD_NAMES, MSFRAGGER_VAR_MODS, SPECTRONAUT_MODS
import numpy as np
import pandas as pd

from .constants import (
MAXQUANT_VAR_MODS,
MOD_MASSES,
MOD_MASSES_SAGE,
MOD_NAMES,
MSFRAGGER_VAR_MODS,
SPECTRONAUT_MODS,
XISEARCH_VAR_MODS,
)


def sage_to_internal(sequences: List[str]) -> List[str]:
Expand Down Expand Up @@ -54,7 +65,60 @@ def replace(match):
return modified_strings


def internal_to_spectronaut(sequences: List[str]) -> List[str]:
def xisearch_to_internal(
xl: str,
seq: str,
mod: str,
crosslinker_position: int,
mod_positions: str,
):
"""
Function to translate a xisearch modstring to the XL-Prosit format.
:param xl: type of crosslinker used. Can be 'DSSO' or 'DSBU'.
:param seq: unmodified peptide sequence
:param mod: all modifications of pep
:param crosslinker_position: crosslinker position of peptide
:param mod_positions: position of all modifications of peptide
:raises ValueError: if suplied type of crosslinker is unknown
:return: modified sequence
"""

def add_mod_sequence(split_seq: List[str], mods: str, mod_positions: str):
"""
Apply modifications.
:param split_seq: List containing the sequence characters
:param mods: String containing modifications
:param mod_positions: String containing positions of modifications
"""
if mod_positions.lower() in ["", "nan", "null"]:
return

split_mod = mods.split(";")
split_mod_positions = mod_positions.split(";")

for mod, pos in zip(split_mod, split_mod_positions):
modification = XISEARCH_VAR_MODS.get(mod)
pos_mod = int(pos)
if modification:
split_seq[pos_mod - 1] += modification
else:
split_seq[pos_mod - 1] += f"({mod})"

# Check the crosslinker type and apply modification accordingly
modification = XISEARCH_VAR_MODS.get(xl.lower())
if modification is None:
raise ValueError(f"Unknown crosslinker type provided: {xl}. Only 'DSSO' and 'DSBU' are supported.")

split_seq = [x for x in seq]
add_mod_sequence(split_seq, mod, mod_positions)
split_seq[crosslinker_position - 1] += modification
return "".join(split_seq)


def internal_to_spectronaut(sequences: Union[np.ndarray, pd.Series, List[str]]) -> List[str]:
"""
Function to translate a modstring from the internal format to the spectronaut format.
Expand All @@ -65,7 +129,9 @@ def internal_to_spectronaut(sequences: List[str]) -> List[str]:
return [regex.sub(lambda mo: SPECTRONAUT_MODS[mo.string[mo.start() : mo.end()]], seq) for seq in sequences]


def maxquant_to_internal(sequences: List[str], fixed_mods: Optional[Dict[str, str]] = None) -> List[str]:
def maxquant_to_internal(
sequences: Union[np.ndarray, pd.Series, List[str]], fixed_mods: Optional[Dict[str, str]] = None
) -> List[str]:
"""
Function to translate a MaxQuant modstring to the Prosit format.
Expand Down Expand Up @@ -116,7 +182,9 @@ def find_replacement(match: re.Match) -> str:
return [regex.sub(find_replacement, seq).replace("_", "") for seq in sequences]


def msfragger_to_internal(sequences: List[str], fixed_mods: Optional[Dict[str, str]] = None) -> List[str]:
def msfragger_to_internal(
sequences: Union[np.ndarray, pd.Series, List[str]], fixed_mods: Optional[Dict[str, str]] = None
) -> List[str]:
"""
Function to translate a MSFragger modstring to the Prosit format.
Expand Down
1 change: 1 addition & 0 deletions tests/test_main.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
"""Test cases for the __main__ module."""

import pytest
from click.testing import CliRunner

Expand Down
14 changes: 0 additions & 14 deletions tests/unit_tests/test_charge.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,6 @@
class TestCharge(unittest.TestCase):
"""Class to test charge."""

def test_indices_to_one_hot(self):
"""Test get_mask_observed_valid."""

def test_indices_to_one_hot_with_classes(self):
"""Test indices_to_one_hot with given number of classes."""
labels = np.array([1, 2, 3])
Expand Down Expand Up @@ -38,17 +35,6 @@ def test_indices_to_one_hot_with_list_and_class(self):
expected_output = np.array([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0]])
np.testing.assert_equal(charge.indices_to_one_hot(labels, classes), expected_output)

"""
def test_indices_to_one_hot_with_wrong_input_type(self):
# Test indices_to_one_hot correctly raises TypeError on wrong input type.
try:
labels = None
self.assertRaises(TypeError, charge.indices_to_one_hot, labels)
except Exception as e: # explicitly silence typeguard.TypeCheckError here without importing TypeGuard
if e.__class__.__name__ != "TypeCheckError":
raise
"""

def test_indices_to_one_hot_with_incompatible_classes(self):
"""Test indices_to_one_hot correctly raises TypeError on wrong input type."""
labels = [1, 2, 3]
Expand Down
47 changes: 47 additions & 0 deletions tests/unit_tests/test_mod_string.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,53 @@ def test_sage_to_internal_tmt(self):
)


class TestXisearchToInternal(unittest.TestCase):
"""Class to test Internal to Xisearch."""

def test_internal_to_xisearch_carbamidomethylation_oxidation_dsso(self):
"""Test internal_to_xisearch_carbamidomethylation and oxidation along with DSSO as crosslinker ."""
self.assertEqual(
mod.xisearch_to_internal(
xl="DSSO", seq="SNVPALEACPQKR", mod="cm", crosslinker_position=12, mod_positions="9"
),
("SNVPALEAC[UNIMOD:4]PQK[UNIMOD:1896]R"),
)

def test_internal_to_xisearch_no_modification_dsso(self):
"""Test internal_to_xisearch_no_variable along with DSSO as crosslinker."""
self.assertEqual(
mod.xisearch_to_internal(
xl="DSSO", seq="SNVPALEACPQKR", mod="NaN", crosslinker_position=12, mod_positions="NaN"
),
("SNVPALEACPQK[UNIMOD:1896]R"),
)

def test_internal_to_xisearch_carbamidomethylation_oxidation_dsbu(self):
"""Test internal_to_xisearch_carbamidomethylation and oxidation along with DSBU as crosslinker."""
self.assertEqual(
mod.xisearch_to_internal(
xl="DSBU", seq="SNVPALEACPQKR", mod="cm", crosslinker_position=12, mod_positions="9"
),
("SNVPALEAC[UNIMOD:4]PQK[UNIMOD:1884]R"),
)

def test_internal_to_xisearch_no_modification_dsbu(self):
"""Test internal_to_xisearch_no_variable along with DSBU as crosslinker."""
self.assertEqual(
mod.xisearch_to_internal(
xl="DSBU", seq="SNVPALEACPQKR", mod="NaN", crosslinker_position=12, mod_positions="NaN"
),
("SNVPALEACPQK[UNIMOD:1884]R"),
)

def test_internal_to_xisearch_double_modifications(self):
"""Test internal_to_xisearch_double_variable."""
self.assertEqual(
mod.xisearch_to_internal(xl="DSSO", seq="MKRM", mod="ox;ox", crosslinker_position=2, mod_positions="1;4"),
("M[UNIMOD:35]K[UNIMOD:1896]RM[UNIMOD:35]"),
)


class TestMaxQuantToInternal(unittest.TestCase):
"""Class to test MaxQuant to internal."""

Expand Down

0 comments on commit 8a64572

Please sign in to comment.