msreport 0.0.27__py3-none-any.whl → 0.0.29__py3-none-any.whl

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.
msreport/isobar.py CHANGED
@@ -1,4 +1,5 @@
1
1
  from __future__ import annotations
2
+
2
3
  import functools
3
4
  from typing import Protocol
4
5
 
@@ -27,7 +28,7 @@ class IsotopeImpurityCorrecter:
27
28
  def __init__(self):
28
29
  self._impurity_matrix = None
29
30
 
30
- def fit(self, impurity_matrix: np.array) -> IsotopeImpurityCorrecter:
31
+ def fit(self, impurity_matrix: np.ndarray) -> IsotopeImpurityCorrecter:
31
32
  """Fits the isotope impurity correcter to a given impurity matrix.
32
33
 
33
34
  Args:
@@ -51,7 +52,7 @@ class IsotopeImpurityCorrecter:
51
52
  """Returns True if the IsotopeImpurityCorrecter has been fitted."""
52
53
  return self._impurity_matrix is not None
53
54
 
54
- def get_fits(self) -> np.array:
55
+ def get_fits(self) -> np.ndarray:
55
56
  """Returns a copy of the fitted impurity matrix.
56
57
 
57
58
  returns:
@@ -89,9 +90,9 @@ class IsotopeImpurityCorrecter:
89
90
 
90
91
 
91
92
  def correct_isobaric_reporter_impurities(
92
- intensity_table: np.array,
93
- diagonal_impurity_matrix: np.array,
94
- ) -> np.array:
93
+ intensity_table: np.ndarray,
94
+ diagonal_impurity_matrix: np.ndarray,
95
+ ) -> np.ndarray:
95
96
  """Performs isotope impurity correction on isobaric reporter expression values.
96
97
 
97
98
  Args:
@@ -122,8 +123,8 @@ def correct_isobaric_reporter_impurities(
122
123
 
123
124
 
124
125
  def _apply_impurity_contamination(
125
- intensities: np.array, impurity_matrix: np.array
126
- ) -> np.array:
126
+ intensities: np.ndarray, impurity_matrix: np.ndarray
127
+ ) -> np.ndarray:
127
128
  """Applies reporter isotope impurity interference to an intensity array.
128
129
 
129
130
  Args:
@@ -141,8 +142,8 @@ def _apply_impurity_contamination(
141
142
 
142
143
 
143
144
  def _correct_impurity_contamination(
144
- intensities: np.array, impurity_matrix: np.array
145
- ) -> np.array:
145
+ intensities: np.ndarray, impurity_matrix: np.ndarray
146
+ ) -> np.ndarray:
146
147
  """Applies reporter isotope impurity interference correction to an intensity array.
147
148
 
148
149
  Args:
msreport/normalize.py CHANGED
@@ -1,10 +1,11 @@
1
1
  from __future__ import annotations
2
+
2
3
  from typing import Callable, Iterable, Optional, Protocol
3
- from typing_extensions import Self
4
4
 
5
5
  import numpy as np
6
6
  import pandas as pd
7
7
  import statsmodels.nonparametric.smoothers_lowess
8
+ from typing_extensions import Self
8
9
 
9
10
  import msreport.helper
10
11
  import msreport.helper.maxlfq as MAXLFQ
msreport/peptidoform.py CHANGED
@@ -67,7 +67,9 @@ class Peptide:
67
67
  probabilities = []
68
68
  for site in self.list_modified_peptide_sites(modification):
69
69
  probabilities.append(self.get_peptide_site_probability(site))
70
- return np.prod(probabilities)
70
+ if None in probabilities:
71
+ return None
72
+ return float(np.prod(probabilities))
71
73
 
72
74
  def get_peptide_site_probability(self, position: int) -> Optional[float]:
73
75
  """Return the modification localization probability of the peptide position.
@@ -161,7 +163,7 @@ def parse_modified_sequence(
161
163
  modified_sequence: str,
162
164
  tag_open: str,
163
165
  tag_close: str,
164
- ) -> tuple[str, list]:
166
+ ) -> tuple[str, list[tuple[int, str]]]:
165
167
  """Returns the plain sequence and a list of modification positions and tags.
166
168
 
167
169
  Args:
@@ -253,7 +255,7 @@ def make_localization_string(
253
255
  return localization_string
254
256
 
255
257
 
256
- def read_localization_string(localization_string: str) -> dict:
258
+ def read_localization_string(localization_string: str) -> dict[str, dict[int, float]]:
257
259
  """Converts a site localization probability string into a dictionary.
258
260
 
259
261
  Args:
@@ -269,7 +271,7 @@ def read_localization_string(localization_string: str) -> dict:
269
271
  A dictionary in the form {"modification tag": {position: probability}}, where
270
272
  positions are integers and probabilitiesa are floats ranging from 0 to 1.
271
273
  """
272
- localization = {}
274
+ localization: dict[str, dict[int, float]] = {}
273
275
  if localization_string == "":
274
276
  return localization
275
277
 
@@ -0,0 +1,41 @@
1
+ """This module provides various plotting functions for visualizing data within a Qtable.
2
+
3
+ The functions in this module generate a wide range of plots, including heatmaps, PCA
4
+ plots, volcano plots, and histograms, to analyze and compare expression values,
5
+ missingness, contaminants, and other features in proteomics datasets. The plots are
6
+ designed to work with the Qtable class as input, which provides structured access to
7
+ proteomics data and experimental design information.
8
+
9
+ The style of the plots can be customized using the `set_active_style` function, which
10
+ allows applying style sheets from the msreport library or those available in matplotlib.
11
+ """
12
+
13
+ from .comparison import expression_comparison, pvalue_histogram, volcano_ma
14
+ from .distribution import experiment_ratios, replicate_ratios
15
+ from .multivariate import expression_clustermap, sample_pca
16
+ from .quality import (
17
+ contaminants,
18
+ missing_values_horizontal,
19
+ missing_values_vertical,
20
+ sample_correlation,
21
+ sample_intensities,
22
+ )
23
+ from .style import ColorWheelDict, set_active_style, set_dpi
24
+
25
+ __all__ = [
26
+ "ColorWheelDict",
27
+ "set_dpi",
28
+ "set_active_style",
29
+ "missing_values_vertical",
30
+ "missing_values_horizontal",
31
+ "contaminants",
32
+ "sample_intensities",
33
+ "replicate_ratios",
34
+ "experiment_ratios",
35
+ "sample_pca",
36
+ "volcano_ma",
37
+ "expression_comparison",
38
+ "expression_clustermap",
39
+ "pvalue_histogram",
40
+ "sample_correlation",
41
+ ]
@@ -0,0 +1,159 @@
1
+ from collections.abc import Iterable, Sequence
2
+ from typing import Optional
3
+
4
+ import adjustText
5
+ import matplotlib.pyplot as plt
6
+ import seaborn as sns
7
+
8
+ from .style import with_active_style
9
+
10
+
11
+ @with_active_style
12
+ def annotated_scatter(
13
+ x_values,
14
+ y_values,
15
+ labels,
16
+ ax=None,
17
+ scatter_kws=None,
18
+ text_kws=None,
19
+ ) -> None:
20
+ ax = plt.gca() if ax is None else ax
21
+ if scatter_kws is None:
22
+ scatter_kws = {}
23
+ if text_kws is None:
24
+ text_kws = {}
25
+ text_params = {
26
+ "force_text": 0.15,
27
+ "arrowprops": {
28
+ "arrowstyle": "-",
29
+ "color": scatter_kws["color"],
30
+ "lw": 0.75,
31
+ "alpha": 0.5,
32
+ },
33
+ "lim": 100,
34
+ }
35
+
36
+ texts = []
37
+ for x, y, text in zip(x_values, y_values, labels, strict=True):
38
+ texts.append(ax.text(x, y, text, **text_kws))
39
+
40
+ if texts:
41
+ adjustText.adjust_text(texts, ax=ax, **text_params) # type: ignore
42
+ ax.scatter(x_values, y_values, **scatter_kws)
43
+
44
+
45
+ @with_active_style
46
+ def box_and_bars(
47
+ box_values: Sequence[Iterable[float]],
48
+ bar_values: Sequence[float],
49
+ group_names: Sequence[str],
50
+ colors: Optional[Sequence[str]] = None,
51
+ edge_colors: Optional[Sequence[str]] = None,
52
+ ) -> tuple[plt.Figure, list[plt.Axes]]:
53
+ """Generates a figure with horizontally aligned box and bar subplots.
54
+
55
+ In the top subplot the 'box_values' are displayed as box plots, in lower subplot the
56
+ 'bar_values' are displayed as bar plots. The figure width is automatically adjusted
57
+ to the number of groups that will be plotted. The length of group_names must be the
58
+ same as the length of the of the 'bar_values' and the number of iterables from
59
+ 'box_values'. Each group from 'box_values' and 'bar_values' is horizontally aligned
60
+ between the two subplots.
61
+
62
+ Args:
63
+ box_values: A sequence of sequences that each contain y values for generating a
64
+ box plot.
65
+ bar_values: A sequence of y values for generating bar plots.
66
+ group_names: Used to label groups from box and bar plots.
67
+ colors: Sequence of hex color codes for each group that is used for the boxes of
68
+ the box and bar plots. Must be the same length as group names. If 'colors'
69
+ is None, boxes are colored in light grey.
70
+ edge_colors: Sequence of hex color codes for each group that is used for the
71
+ edges of the boxes and bars. Must be the same length as group names. If
72
+ None, black is used as edge color.
73
+
74
+ Raises:
75
+ ValueError: If the length of box_values, bar_values and group_names is not the
76
+ same or if the length of colors is not the same as group_names.
77
+
78
+ Returns:
79
+ A matplotlib Figure and a list of Axes objects containing the box and bar plots.
80
+ """
81
+ if not (len(box_values) == len(bar_values) == len(group_names)):
82
+ raise ValueError(
83
+ "The length of 'box_values', 'bar_values' and 'group_names' must be the "
84
+ "same."
85
+ )
86
+ if colors is not None and len(colors) != len(group_names):
87
+ raise ValueError(
88
+ "The length of 'colors' must be the same as the length of 'group_names'."
89
+ )
90
+ if edge_colors is not None and len(edge_colors) != len(group_names):
91
+ raise ValueError(
92
+ "The length of 'edge_colors' must be the same as the length of "
93
+ "'group_names'."
94
+ )
95
+
96
+ if colors is None:
97
+ colors = ["#D0D0D0" for _ in group_names]
98
+ if edge_colors is None:
99
+ edge_colors = ["#000000" for _ in group_names]
100
+
101
+ num_samples = len(group_names)
102
+ x_values = range(num_samples)
103
+ bar_width = 0.8
104
+
105
+ suptitle_space_inch = 0.4
106
+ ax_height_inch = 1.6
107
+ ax_hspace_inch = 0.35
108
+ bar_width_inches = 0.24
109
+ x_padding = 0.24
110
+ fig_height = suptitle_space_inch + ax_height_inch * 2 + ax_hspace_inch
111
+
112
+ fig_width = (num_samples + (2 * x_padding)) * bar_width_inches
113
+ fig_size = (fig_width, fig_height)
114
+
115
+ subplot_top = 1 - (suptitle_space_inch / fig_height)
116
+ subplot_hspace = ax_hspace_inch / ax_height_inch
117
+
118
+ bar_half_width = 0.5
119
+ lower_xbound = (0 - bar_half_width) - x_padding
120
+ upper_xbound = (num_samples - 1) + bar_half_width + x_padding
121
+
122
+ fig, axes = plt.subplots(2, figsize=fig_size, sharex=True)
123
+ fig.subplots_adjust(
124
+ bottom=0, top=subplot_top, left=0, right=1, hspace=subplot_hspace
125
+ )
126
+ fig.suptitle("A box and bars plot", y=1)
127
+
128
+ # Plot boxplots using the box_values
129
+ ax = axes[0]
130
+ ax.axhline(0, color="#999999", lw=1, zorder=2)
131
+ boxplots = ax.boxplot(
132
+ box_values,
133
+ positions=x_values,
134
+ vert=True,
135
+ showfliers=False,
136
+ patch_artist=True,
137
+ widths=bar_width,
138
+ medianprops={"color": "#000000"},
139
+ )
140
+ for color, edge_color, box in zip(
141
+ colors, edge_colors, boxplots["boxes"], strict=True
142
+ ):
143
+ box.set(facecolor=color)
144
+ box.set(edgecolor=edge_color)
145
+ ylim = ax.get_ylim()
146
+ ax.set_ylim(min(-0.4, ylim[0]), max(0.401, ylim[1]))
147
+
148
+ # Plot barplots using the bar_values
149
+ ax = axes[1]
150
+ ax.bar(x_values, bar_values, width=bar_width, color=colors, edgecolor=edge_colors)
151
+ ax.set_xticklabels(
152
+ group_names, fontsize=plt.rcParams["axes.labelsize"], rotation=90
153
+ )
154
+ for ax in axes:
155
+ ax.grid(False, axis="x")
156
+ sns.despine(top=True, right=True)
157
+
158
+ ax.set_xlim(lower_xbound, upper_xbound)
159
+ return fig, axes