plot-misc 2.2.2__tar.gz → 2.3.0__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.
Files changed (45) hide show
  1. {plot_misc-2.2.2/plot_misc.egg-info → plot_misc-2.3.0}/PKG-INFO +6 -4
  2. {plot_misc-2.2.2 → plot_misc-2.3.0}/README.md +1 -1
  3. plot_misc-2.3.0/plot_misc/__init__.py +12 -0
  4. plot_misc-2.3.0/plot_misc/_version.py +1 -0
  5. {plot_misc-2.2.2 → plot_misc-2.3.0}/plot_misc/forest.py +0 -14
  6. {plot_misc-2.2.2 → plot_misc-2.3.0}/plot_misc/heatmap.py +2 -3
  7. {plot_misc-2.2.2 → plot_misc-2.3.0}/plot_misc/machine_learning.py +10 -14
  8. {plot_misc-2.2.2 → plot_misc-2.3.0}/plot_misc/survival.py +1 -0
  9. {plot_misc-2.2.2 → plot_misc-2.3.0}/plot_misc/utils/formatting.py +1 -1
  10. {plot_misc-2.2.2 → plot_misc-2.3.0}/plot_misc/utils/utils.py +83 -54
  11. {plot_misc-2.2.2 → plot_misc-2.3.0}/plot_misc/volcano.py +26 -7
  12. {plot_misc-2.2.2 → plot_misc-2.3.0/plot_misc.egg-info}/PKG-INFO +6 -4
  13. {plot_misc-2.2.2 → plot_misc-2.3.0}/plot_misc.egg-info/requires.txt +3 -0
  14. {plot_misc-2.2.2 → plot_misc-2.3.0}/pyproject.toml +4 -3
  15. {plot_misc-2.2.2 → plot_misc-2.3.0}/requirements.txt +1 -0
  16. plot_misc-2.2.2/plot_misc/__init__.py +0 -1
  17. plot_misc-2.2.2/plot_misc/_version.py +0 -1
  18. {plot_misc-2.2.2 → plot_misc-2.3.0}/LICENSE +0 -0
  19. {plot_misc-2.2.2 → plot_misc-2.3.0}/MANIFEST.in +0 -0
  20. {plot_misc-2.2.2 → plot_misc-2.3.0}/plot_misc/barchart.py +0 -0
  21. {plot_misc-2.2.2 → plot_misc-2.3.0}/plot_misc/constants.py +0 -0
  22. {plot_misc-2.2.2 → plot_misc-2.3.0}/plot_misc/errors.py +0 -0
  23. {plot_misc-2.2.2 → plot_misc-2.3.0}/plot_misc/example_data/__init__.py +0 -0
  24. {plot_misc-2.2.2 → plot_misc-2.3.0}/plot_misc/example_data/example_datasets/bar_points.tsv.gz +0 -0
  25. {plot_misc-2.2.2 → plot_misc-2.3.0}/plot_misc/example_data/example_datasets/barchart.tsv.gz +0 -0
  26. {plot_misc-2.2.2 → plot_misc-2.3.0}/plot_misc/example_data/example_datasets/calibration_bins.tsv.gz +0 -0
  27. {plot_misc-2.2.2 → plot_misc-2.3.0}/plot_misc/example_data/example_datasets/calibration_data.tsv.gz +0 -0
  28. {plot_misc-2.2.2 → plot_misc-2.3.0}/plot_misc/example_data/example_datasets/forest_data.tsv.gz +0 -0
  29. {plot_misc-2.2.2 → plot_misc-2.3.0}/plot_misc/example_data/example_datasets/group_bar.tsv.gz +0 -0
  30. {plot_misc-2.2.2 → plot_misc-2.3.0}/plot_misc/example_data/example_datasets/heatmap_data.tsv.gz +0 -0
  31. {plot_misc-2.2.2 → plot_misc-2.3.0}/plot_misc/example_data/example_datasets/incidence_matrix_data.tsv.gz +0 -0
  32. {plot_misc-2.2.2 → plot_misc-2.3.0}/plot_misc/example_data/example_datasets/lollipop_data.tsv.gz +0 -0
  33. {plot_misc-2.2.2 → plot_misc-2.3.0}/plot_misc/example_data/example_datasets/mace_associations.tsv.gz +0 -0
  34. {plot_misc-2.2.2 → plot_misc-2.3.0}/plot_misc/example_data/example_datasets/net_benefit.tsv.gz +0 -0
  35. {plot_misc-2.2.2 → plot_misc-2.3.0}/plot_misc/example_data/example_datasets/volcano.tsv.gz +0 -0
  36. {plot_misc-2.2.2 → plot_misc-2.3.0}/plot_misc/example_data/examples.py +0 -0
  37. {plot_misc-2.2.2 → plot_misc-2.3.0}/plot_misc/incidencematrix.py +0 -0
  38. {plot_misc-2.2.2 → plot_misc-2.3.0}/plot_misc/piechart.py +0 -0
  39. {plot_misc-2.2.2 → plot_misc-2.3.0}/plot_misc/utils/__init__.py +0 -0
  40. {plot_misc-2.2.2 → plot_misc-2.3.0}/plot_misc/utils/colour.py +0 -0
  41. {plot_misc-2.2.2 → plot_misc-2.3.0}/plot_misc.egg-info/SOURCES.txt +0 -0
  42. {plot_misc-2.2.2 → plot_misc-2.3.0}/plot_misc.egg-info/dependency_links.txt +0 -0
  43. {plot_misc-2.2.2 → plot_misc-2.3.0}/plot_misc.egg-info/top_level.txt +0 -0
  44. {plot_misc-2.2.2 → plot_misc-2.3.0}/requirements-dev.txt +0 -0
  45. {plot_misc-2.2.2 → plot_misc-2.3.0}/setup.cfg +0 -0
@@ -1,7 +1,7 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: plot-misc
3
- Version: 2.2.2
4
- Summary: Various plotting templates built on top of matplotlib
3
+ Version: 2.3.0
4
+ Summary: Various plotting archetypes built on top of matplotlib
5
5
  Author-email: A Floriaan Schmidt <floriaanschmidt@gmail.com>
6
6
  License-Expression: GPL-3.0-or-later
7
7
  Project-URL: Homepage, https://gitlab.com/SchmidtAF/plot-misc
@@ -11,8 +11,9 @@ Classifier: Programming Language :: Python :: 3
11
11
  Classifier: Programming Language :: Python :: 3.10
12
12
  Classifier: Programming Language :: Python :: 3.11
13
13
  Classifier: Programming Language :: Python :: 3.12
14
+ Classifier: Programming Language :: Python :: 3.13
14
15
  Classifier: Programming Language :: Python :: Implementation :: PyPy
15
- Requires-Python: <3.13,>=3.10
16
+ Requires-Python: <3.14,>=3.10
16
17
  Description-Content-Type: text/markdown
17
18
  License-File: LICENSE
18
19
  Requires-Dist: pandas>=1.3
@@ -22,6 +23,7 @@ Requires-Dist: scipy>=1.5
22
23
  Requires-Dist: statsmodels>=0.1
23
24
  Requires-Dist: scikit-learn>=1.4
24
25
  Requires-Dist: adjustText>=1.3
26
+ Requires-Dist: typing_extensions>=4; python_version < "3.11"
25
27
  Provides-Extra: dev
26
28
  Requires-Dist: python-build; extra == "dev"
27
29
  Requires-Dist: twine; extra == "dev"
@@ -48,7 +50,7 @@ Dynamic: license-file
48
50
  <img src="https://schmidtaf.gitlab.io/plot-misc/_images/icon.png" alt="plot-misc icon" width="250"/>
49
51
 
50
52
  # A collection of plotting functions
51
- __version__: `2.2.2`
53
+ __version__: `2.3.0`
52
54
 
53
55
  This repository collects plotting modules written on top of `matplotlib`.
54
56
  The functions describe plotting archetypes intended to set up light-touch,
@@ -1,7 +1,7 @@
1
1
  <img src="https://schmidtaf.gitlab.io/plot-misc/_images/icon.png" alt="plot-misc icon" width="250"/>
2
2
 
3
3
  # A collection of plotting functions
4
- __version__: `2.2.2`
4
+ __version__: `2.3.0`
5
5
 
6
6
  This repository collects plotting modules written on top of `matplotlib`.
7
7
  The functions describe plotting archetypes intended to set up light-touch,
@@ -0,0 +1,12 @@
1
+ """
2
+ plot-misc: matplotlib-based plotting archetypes for scientific figures.
3
+
4
+ A curated collection of user-oriented plotting functions and
5
+ classes built on top of `matplotlib`. Each function returns standard
6
+ matplotlib `Figure`/`Axes` objects, so results can be further customised
7
+ with familiar matplotlib methods. Per the package design callables are limited
8
+ to creating illustrations, and should data be internally calculated this is
9
+ done with options for user overwrites, while making the derived data available
10
+ for inspection and re-use.
11
+ """
12
+ from ._version import __version__
@@ -0,0 +1 @@
1
+ __version__ = '2.3.0'
@@ -982,20 +982,6 @@ class EmpiricalSupport(object):
982
982
  results_ : `EmpiricalSupportResults`
983
983
  An EmpiricalSupportResults instance.
984
984
 
985
- Methods
986
- -------
987
- calc_empirical_support(estimate, standard_error, alpha)
988
- Computes the range of confidence intervals and compatibility metrics
989
- over the supplied alpha values.
990
-
991
- plot_tree(...)
992
- Creates a 'tree plot' summarising the parameter space supported by
993
- the data, with options for CI and estimate annotations.
994
-
995
- _plot_empirical_support(...)
996
- Generates a visualisation of confidence intervals and their overlap
997
- across varying alpha values.
998
-
999
985
  Notes
1000
986
  -----
1001
987
  This implementation is based on the concept of compatibility (or
@@ -26,9 +26,8 @@ from the example published in the official matplotlib gallery [1]_.
26
26
 
27
27
  References
28
28
  ----------
29
- .. [1] Matplotlib contributors. "Creating annotated heatmaps."
30
- Matplotlib Gallery.
31
- https://matplotlib.org/stable/gallery/images_contours_and_fields/image_annotated_heatmap.html
29
+ .. [1] Matplotlib contributors. "Creating annotated heatmaps." Matplotlib
30
+ Gallery. https://matplotlib.org/stable/gallery/images_contours_and_fields/image_annotated_heatmap.html
32
31
  """
33
32
 
34
33
  # modules
@@ -55,8 +55,13 @@ from typing import (
55
55
  Any,
56
56
  Callable,
57
57
  Union,
58
- Self,
59
58
  )
59
+ # `typing.Self` was added in Python 3.11; fall back to typing_extensions on 3.10
60
+ # (the minimum supported version per pyproject `requires-python`).
61
+ if sys.version_info >= (3, 11):
62
+ from typing import Self
63
+ else:
64
+ from typing_extensions import Self
60
65
  from statsmodels.nonparametric.smoothers_lowess import lowess
61
66
  # from packaging import version
62
67
  # if version.parse('3.4.0') < version.parse(mpl._version.version):
@@ -665,15 +670,6 @@ class DecisionCurve(object):
665
670
  include at least one predicted risk score (between 0 and 1) and a
666
671
  binary outcome variable.
667
672
 
668
- Methods
669
- -------
670
- calc_net_benefit(...)
671
- Computes the net benefit across a range of thresholds for one or more
672
- models.
673
- plot(...)
674
- Visualises the decision curves, with optional smoothing and style
675
- customisation.
676
-
677
673
  Notes
678
674
  -----
679
675
  This implementation is adapted from the `dcurves` Python package
@@ -763,8 +759,8 @@ class DecisionCurve(object):
763
759
  These rates are scaled by the assumed prevalence to allow valid
764
760
  comparisons across populations with different case/control ratios.
765
761
 
766
- Code adapted from
767
- `here <https://github.com/MSKCC-Epi-Bio/dcurves/blob/main/dcurves/dca.py>`_.
762
+ Code adapted from the
763
+ `dcurves true/false rate calculation <https://github.com/MSKCC-Epi-Bio/dcurves/blob/main/dcurves/dca.py>`_.
768
764
 
769
765
  Hash: 007c64b
770
766
  """
@@ -861,8 +857,8 @@ class DecisionCurve(object):
861
857
 
862
858
  The resulting table can be visualised using the `plot()` method.
863
859
 
864
- Code adapted from:
865
- `here <https://github.com/MSKCC-Epi-Bio/dcurves/blob/main/dcurves/dca.py>`_
860
+ Code adapted from the
861
+ `dcurves net benefit calculation <https://github.com/MSKCC-Epi-Bio/dcurves/blob/main/dcurves/dca.py>`_
866
862
 
867
863
  Hash: 007c64b
868
864
  """
@@ -292,6 +292,7 @@ def extract_follow_up(data: pd.DataFrame,
292
292
  -------
293
293
  pd.DataFrame
294
294
  DataFrame with the following columns:
295
+
295
296
  - 'time': Requested time points (as integers)
296
297
  - '{output_col}_at_risk': Number at risk at each time point
297
298
  - '{output_col}_at_risk_format': Formatted at-risk numbers with
@@ -16,7 +16,7 @@ format_estimates(point, se=None, lower=None, upper=None, alpha=0.05, ...)
16
16
  sci_notation(number, sig_fig=2, ...)
17
17
  Converts a float into scientific notation with superscript exponents.
18
18
 
19
- format_roc(observed, predicted, **kwargs)
19
+ format_roc(observed, predicted, ...)
20
20
  Computes ROC curve data and returns it as a tidy DataFrame.
21
21
 
22
22
  string_interval(limits, int_notation, middle, lower_lim, inq_space, sep)
@@ -24,7 +24,7 @@ annotate_axis_midpoints(ax, labels, axis='y', gap=6, offset=None, ...)
24
24
  calc_angle_points(x, y, radians=False)
25
25
  Calculates the angle between two points in degrees or radians.
26
26
 
27
- calc_matrices(data, exposure_col, outcome_col, point_col='point',
27
+ calc_matrices(data, columns, rows, point_col='point',
28
28
  pvalue_col='pvalue', ...)
29
29
  Creates effect and p-value matrices for heatmap plotting, including
30
30
  optional annotation styles and NA masking.
@@ -38,7 +38,7 @@ change_ticks(ax, ticks, labels=None, axis='x', log=False)
38
38
  adjust_labels(annotations, axis, min_distance=0.1)
39
39
  Adjusts overlapping annotation text to improve legibility.
40
40
 
41
- plot_span(start_span, stop_span, ax, horizontal=True, **kwargs)
41
+ plot_span(start_span, stop_span, ax, horizontal=True, ...)
42
42
  Adds a vertical or horizontal span to a matplotlib axis.
43
43
 
44
44
  segment_labelled(x, y, ax, label=None, ...)
@@ -261,12 +261,6 @@ class MidpointNormalize(mpl.colors.Normalize):
261
261
  Central value that maps to 0.5 on the colour scale.
262
262
  clip : `bool`, default False
263
263
  If True, data outside vmin/vmax is clipped to the endpoints.
264
-
265
- Methods
266
- -------
267
- inverse(value)
268
- Inverts a normalised value from the [0, 1] scale back to the original
269
- data scale.
270
264
  """
271
265
  def __init__(self, vmin:float | None = None, vmax:float | None = None,
272
266
  vcenter:float | None = None, clip:bool=False):
@@ -284,8 +278,12 @@ class MidpointNormalize(mpl.colors.Normalize):
284
278
  else:
285
279
  value = np.clip(value, self.vmin, self.vmax)
286
280
  x, y = [self.vmin, self.vcenter, self.vmax], [0, 0.5, 1.]
287
- return np.ma.masked_array(np.interp(value, x, y,
288
- left=-np.inf, right=np.inf))
281
+ # capturing potential mask, and applying to interp
282
+ value = np.ma.asarray(value, dtype=float)
283
+ mask = np.ma.getmaskarray(value)
284
+ result = np.interp(value.filled(np.nan), x, y,
285
+ left=-np.inf, right=np.inf)
286
+ return np.ma.masked_array(result, mask=mask)
289
287
  # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
290
288
  def inverse(self, value):
291
289
  y, x = [self.vmin, self.vcenter, self.vmax], [0, 0.5, 1]
@@ -326,6 +324,7 @@ def _update_kwargs(update_dict:dict[Any, Any], **kwargs:Any,
326
324
  return new_dict
327
325
 
328
326
  # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
327
+ # NOTE this is not used anymore can be removed
329
328
  def _dict_string_argument(partial_match:str, dict_string:dict[Any, str],
330
329
  context:dict[Any,Any],
331
330
  ) -> dict[Any,Any]:
@@ -364,7 +363,11 @@ def _dict_string_argument(partial_match:str, dict_string:dict[Any, str],
364
363
  # evaluating object
365
364
  for key, value in dict_string.items():
366
365
  if isinstance(value, str) and re.match(partial_match, value):
367
- dict_string[key] = eval(value, context)
366
+ dict_string[key] = eval(
367
+ value,
368
+ {"__builtins__": {}},
369
+ context,
370
+ )
368
371
  # return stuff
369
372
  return dict_string
370
373
 
@@ -473,7 +476,7 @@ def change_ticks(ax:plt.Axes, ticks:list[str], labels:list[str] | None = None,
473
476
  # done
474
477
 
475
478
  # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
476
- def _extract(data:pd.DataFrame, exposure_col:str, outcome_col:str,
479
+ def _extract(data:pd.DataFrame, columns:str, rows:str,
477
480
  point_col:str, pvalue_col:str, dropna:bool=False,
478
481
  **kwargs:Any,
479
482
  ) -> tuple[pd.DataFrame, pd.DataFrame]:
@@ -481,17 +484,16 @@ def _extract(data:pd.DataFrame, exposure_col:str, outcome_col:str,
481
484
  Extract point estimate and p-value matrices from long-format data.
482
485
 
483
486
  This function takes a long-format DataFrame and returns two pivot tables:
484
- one for point estimates and one for p-values. These are indexed by
485
- outcome and columned by exposure.
487
+ one for point estimates and one for p-values.
486
488
 
487
489
  Parameters
488
490
  ----------
489
491
  data : `pd.DataFrame`
490
492
  Input data in long format with the required columns.
491
- exposure_col : `str`
492
- Name of the column representing exposure variables.
493
- outcome_col : `str`
494
- Name of the column representing outcome variables.
493
+ columns : `str`
494
+ Name of the column representing column labels.
495
+ rows : `str`
496
+ Name of the column representing row labels.
495
497
  point_col : `str`
496
498
  Name of the column containing point estimates.
497
499
  pvalue_col : `str`
@@ -510,22 +512,28 @@ def _extract(data:pd.DataFrame, exposure_col:str, outcome_col:str,
510
512
  ------
511
513
  ValueError
512
514
  If the point and p-value matrices have mismatched shapes.
515
+
516
+ Notes
517
+ -----
518
+ Both matrices are sorted alphabetically on the index and on the columns.
519
+ To retain input order instead, pass ``sort=False``, which is forwarded
520
+ through `**kwargs` to `pd.DataFrame.pivot_table`
513
521
  """
514
522
  ### subsetting
515
523
  # making sure we do not change the original `data`
516
524
  data = data.copy()
517
525
  ### getting estimates
518
- point = data[[point_col, exposure_col, outcome_col]].copy()
519
- pvalue = data[[pvalue_col, exposure_col, outcome_col]].copy()
526
+ point = data[[point_col, columns, rows]].copy()
527
+ pvalue = data[[pvalue_col, columns, rows]].copy()
520
528
  ### matrix
521
- point_mat = point.pivot_table(index=[outcome_col],
522
- columns = exposure_col,
529
+ point_mat = point.pivot_table(index=[rows],
530
+ columns = columns,
523
531
  values = point_col,
524
532
  dropna=dropna,
525
533
  **kwargs,
526
534
  )
527
- pvalue_mat = pvalue.pivot_table(index=[outcome_col],
528
- columns = exposure_col,
535
+ pvalue_mat = pvalue.pivot_table(index=[rows],
536
+ columns = columns,
529
537
  values = pvalue_col,
530
538
  dropna=dropna,
531
539
  **kwargs,
@@ -567,9 +575,11 @@ def _format_matrices(effect:pd.DataFrame, pval:pd.DataFrame, sig:float,
567
575
  Matrix of p-values as floats (in [0, 1]).
568
576
  sig : `float`
569
577
  Significance cut-off expressed as a `-log10` threshold (a cell is
570
- significant when `-log10(p) >= sig`).
578
+ significant when `-log10(p) >= sig`). Use `-inf` to disable the
579
+ significance filter (every non-missing cell is significant).
571
580
  ptrun : `float` or `int`, default 16
572
- P-values smaller than `10^(-ptrun)` are truncated.
581
+ P-values smaller than `10^(-ptrun)` are truncated. Use `+inf` to
582
+ disable truncation (a p-value of exactly 0 maps to `+inf`).
573
583
  digits : `str`, default `3`
574
584
  Number of decimals the numeric tables and effect strings are rounded
575
585
  to (a single integer character).
@@ -659,13 +669,13 @@ def _format_matrices(effect:pd.DataFrame, pval:pd.DataFrame, sig:float,
659
669
 
660
670
  # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
661
671
  def calc_matrices(data:pd.DataFrame,
662
- exposure_col:str,
663
- outcome_col:str,
672
+ columns:str,
673
+ rows:str,
664
674
  point_col:str='point',
665
675
  pvalue_col:str='pvalue',
666
- alpha:Real=0.05,
676
+ alpha:Real | None =0.05,
667
677
  sig_numbers:int=2,
668
- ptrun:Real=1e-16,
678
+ ptrun:Real | None = None,
669
679
  annotate:Literal['symbol',
670
680
  'star',
671
681
  'pvalues',
@@ -681,36 +691,43 @@ def calc_matrices(data:pd.DataFrame,
681
691
  """
682
692
  Generate value and annotation matrices for clustered heatmap visualisation.
683
693
 
684
- This function transforms a long-format DataFrame into heatmap-ready matrices
685
- based on statistical results. The output includes both numeric matrices
694
+ This function transforms a long-format DataFrame into heatmap-ready
695
+ matrices. The output includes both numeric matrices
686
696
  (e.g. signed -log10(p-values)) and string annotations (e.g. significance
687
697
  stars, p-values, or effect sizes).
688
698
 
689
699
  Arguments
690
700
  ---------
691
701
  data : `pd.DataFrame`
692
- Long-format dataframe containing exposure, outcome, point estimate,
693
- and p-value columns.
694
- exposure_col : `str`
695
- Column name indicating the exposure variable.
696
- outcome_col : `str`
697
- Column name indicating the outcome variable.
702
+ Long-format dataframe containing the column and row groups, as
703
+ well as point estimate and p-value columns (representing the matrix
704
+ values).
705
+ columns : `str`
706
+ Column name indicating the column labels.
707
+ rows : `str`
708
+ Column name indicating the row labels.
698
709
  point_col : `str`, default `point`
699
710
  Column name with point estimates.
700
711
  pvalue_col : `str`, default 'pvalue'
701
712
  Column name with p-values. Note p-values are expected to range between
702
713
  0 and 1.
703
- alpha : `float`, default `0.05`
714
+ alpha : `float` or `None`, default `0.05`
704
715
  The significance cut-off as a raw p-value in (0, 1] (consistent with
705
716
  `volcano`). Converted internally to a -log10 threshold. Values outside
706
- (0, 1] raise `InputValidationError`.
717
+ (0, 1] raise `InputValidationError`. Set to `None` to disable the
718
+ significance filter: every non-missing cell is treated as significant
719
+ and annotated.
707
720
  sig_numbers : `int`, default 2
708
721
  The number of significant numbers the cell annotations should have.
709
- ptrun : `float` or `int`, default 1e-16
722
+ ptrun : `float`, `int` or `None`, default `None`
710
723
  The truncation threshold as a raw p-value in (0, 1]: p-values smaller
711
- than `ptrun` are floored to `ptrun` before the -log10 transform.
724
+ than `ptrun` are floored to `ptrun` before the -log10 transform. When
725
+ `None` (the default) no truncation is applied and a p-value of exactly
726
+ 0 maps to `+inf` in the -log10 value tables, which can affect heatmap
727
+ colour scaling.
712
728
  annotate : `str`, default 'symbol'
713
729
  Annotation style to return. Options:
730
+
714
731
  - 'symbol': significance markers using `symbol`.
715
732
  - 'star': **Deprecated** alias for 'symbol' — use 'symbol' instead.
716
733
  - 'pvalues': signed -log10(p-values). **Deprecated** — use
@@ -720,6 +737,7 @@ def calc_matrices(data:pd.DataFrame,
720
737
  - 'pvalues_raw': the untransformed p-values (in [0, 1]).
721
738
  - 'point_estimates': formatted effect estimates
722
739
  - None: returns only numeric matrix without annotations
740
+
723
741
  The numeric value matrix is always signed -log10(p-values); only the
724
742
  annotation representation changes with the 'pvalues*' options.
725
743
  symbol : `str`, default `★`
@@ -744,27 +762,32 @@ def calc_matrices(data:pd.DataFrame,
744
762
  If `annotate` is not one of the supported values.
745
763
  InputValidationError
746
764
  If `alpha` is not a raw p-value in (0, 1].
765
+
766
+ Notes
767
+ -----
768
+ The rows and columns of the returned matrices retain the order in which
769
+ they first appear in `data`. Pass ``sort=True`` to sort alphabetically.
747
770
  """
748
771
  #### check input
749
772
  is_type(data, pd.DataFrame)
750
- is_type(exposure_col, str)
751
- is_type(outcome_col, str)
773
+ is_type(columns, str)
774
+ is_type(rows, str)
752
775
  is_type(point_col, str)
753
776
  is_type(pvalue_col, str)
754
- is_type(alpha, (int, float))
755
- is_type(ptrun, (int, float))
777
+ is_type(alpha, (type(None), int, float))
778
+ is_type(ptrun, (type(None), int, float))
756
779
  is_type(sig_numbers, int)
757
780
  is_type(symbol, str)
758
781
  is_type(without_log, bool)
759
782
  is_type(mask_na, bool)
760
783
  ### `alpha` is a raw p-value threshold in (0, 1]
761
- if not (0 < alpha <= 1):
784
+ if (alpha is not None) and not (0 < alpha <= 1):
762
785
  raise InputValidationError(
763
786
  "`alpha` must be a raw p-value in (0, 1] (e.g. 0.05); got: "
764
787
  f"{alpha}. The -log10 convention was removed in v2.3."
765
788
  )
766
789
  ### `ptrun` is a raw p-value truncation threshold in (0, 1]
767
- if not (0 < ptrun <= 1):
790
+ if (ptrun is not None) and not (0 < ptrun <= 1):
768
791
  raise InputValidationError(
769
792
  "`ptrun` must be a raw p-value in (0, 1] (e.g. 1e-16); got: "
770
793
  f"{ptrun}. The exponent convention was removed in v2.3."
@@ -798,20 +821,26 @@ def calc_matrices(data:pd.DataFrame,
798
821
  else:
799
822
  pval_mode = 'signed_log'
800
823
  ### subsetting data
824
+ new_kwargs = _update_kwargs(update_dict=kwargs,
825
+ sort=False,
826
+ )
801
827
  point_mat, pvalue_mat = _extract(data,
802
- exposure_col=exposure_col,
803
- outcome_col=outcome_col,
828
+ columns=columns,
829
+ rows=rows,
804
830
  point_col=point_col,
805
831
  pvalue_col=pvalue_col,
806
- **kwargs,
832
+ **new_kwargs,
807
833
  )
808
- ### formatting data (convert the raw-p `alpha` to a -log10 threshold)
809
- sig = -1 * np.log10(alpha)
834
+ ### formatting data (convert the raw-p `alpha` to a -log10 threshold;
835
+ ### `alpha=None` disables the significance filter entirely)
836
+ sig = -np.inf if alpha is None else -1 * np.log10(alpha)
837
+ ### `ptrun=None` disables truncation (p == 0 maps to +inf)
838
+ trun = np.inf if ptrun is None else -1 * np.log10(ptrun)
810
839
  (values, values_unsigned, values_raw, annot_effect, annot_star,
811
840
  annot_pval, values_point) =\
812
841
  _format_matrices(
813
842
  point_mat, pvalue_mat, sig=sig,
814
- ptrun=-np.log10(ptrun), digits=str(sig_numbers),
843
+ ptrun=trun, digits=str(sig_numbers),
815
844
  symbol=symbol, pval_mode=pval_mode,
816
845
  )
817
846
  ### selecting the annotation to use
@@ -41,8 +41,10 @@ from typing import Any
41
41
  def plot_volcano(data:DataFrame, y_column:str, x_column:str,
42
42
  point_label:str | None = None, adjust:bool=False,
43
43
  lim:int=1000, vline:Real=0, alpha:float=1e-5,
44
- col_sgnd: str = 'orangered', col_nsgnd: str = 'dimgrey',
44
+ col_sgnd: str | None = 'orangered',
45
+ col_nsgnd: str | None = 'dimgrey',
45
46
  col_vline: str = 'lightcoral',
47
+ c_col: str | None = None,
46
48
  xlab:str='Point estimate', ylab:str=r'$-log_{10}(pvalue)$',
47
49
  ylim:tuple[float, float] | None = None, msize:Real=10,
48
50
  lsize:Real=5, transparency_ns:Real=0.6,
@@ -79,12 +81,16 @@ def plot_volcano(data:DataFrame, y_column:str, x_column:str,
79
81
  The x-position of the vertical line
80
82
  alpha : `float`, default 1e-5
81
83
  P-value threshold for significance (used on –log10 scale).
82
- col_sgnd : `str`, default `orangered`
84
+ col_sgnd : `str` or `None`, default `orangered`
83
85
  The colour for the dots above the significance threshold.
84
- col_nsgnd : `str`, default `dimgrey`
86
+ col_nsgnd : `str` or `None`, default `dimgrey`
85
87
  The colour for the dots below the significance threshold.
86
88
  col_vline ; `str`, default `lightcoral`
87
89
  The colour of the vertical line.
90
+ c_col : `str` or `None`, default `None`
91
+ The column name of the colour indicator. Allows for per-point
92
+ colouring based on a data column. Will internally overrule
93
+ `col_sgnd` and `col_nsgnd`.
88
94
  xlab : `str`, default 'Point estimate'
89
95
  x-axis label.
90
96
  ylab : `str`, default '-log10(pvalue)'
@@ -131,7 +137,7 @@ def plot_volcano(data:DataFrame, y_column:str, x_column:str,
131
137
  points are labelled in a crowded region. Additional options can be passed
132
138
  to `adjustText` via `label_kwargs_dict`.
133
139
 
134
- Please see the module documentation `here <https://pypi.org/project/adjustText/>`_.
140
+ Please see the `adjustText documentation <https://pypi.org/project/adjustText/>`_.
135
141
  """
136
142
  FT_FAM = 'font.family'
137
143
  # ###### Check input
@@ -140,9 +146,12 @@ def plot_volcano(data:DataFrame, y_column:str, x_column:str,
140
146
  is_type(x_column, str)
141
147
  is_type(point_label, (str, type(None)))
142
148
  is_type(font_label, (type(None), str))
143
- is_type(col_sgnd, str)
144
- is_type(col_nsgnd, str)
149
+ is_type(col_sgnd, (type(None), str))
150
+ is_type(col_nsgnd,(type(None), str))
151
+ is_type(c_col,(type(None), str))
145
152
  is_type(col_vline, str)
153
+ if c_col is not None and c_col not in data.columns:
154
+ raise IndexError('`c_col` is not present in data.columns.')
146
155
  # map None to dict
147
156
  label_kwargs_dict = label_kwargs_dict or {}
148
157
  scatter_sig_kwargs_dict = scatter_sig_kwargs_dict or {}
@@ -151,7 +160,11 @@ def plot_volcano(data:DataFrame, y_column:str, x_column:str,
151
160
  # raise warning
152
161
  if adjust and point_label is None:
153
162
  warnings.warn('`adjust` is ignored if `point_label` is None',
154
- SyntaxWarning)
163
+ UserWarning, stacklevel=2,)
164
+ if (col_sgnd is not None or col_nsgnd is not None) and (c_col is not None):
165
+ warnings.warn('`c_col` overrules `col_sgnd` and `col_nsgnd`. Set these '
166
+ 'to None to silence this warning.',
167
+ UserWarning, stacklevel=2,)
155
168
  ### getting figure
156
169
  # should we create a figure and axis
157
170
  if ax is None:
@@ -170,6 +183,9 @@ def plot_volcano(data:DataFrame, y_column:str, x_column:str,
170
183
  above = data[data[y_column] >= threshold]
171
184
  xs = above[x_column]
172
185
  ys = above[y_column]
186
+ # update col if needed
187
+ if c_col is not None:
188
+ col_sgnd = above[c_col]
173
189
  # kwargs
174
190
  new_sig_kwargs = _update_kwargs(
175
191
  update_dict=scatter_sig_kwargs_dict,
@@ -180,6 +196,9 @@ def plot_volcano(data:DataFrame, y_column:str, x_column:str,
180
196
  below = data[data[y_column] < threshold]
181
197
  xns = below[x_column]
182
198
  yns = below[y_column]
199
+ # update col if needed
200
+ if c_col is not None:
201
+ col_nsgnd = below[c_col]
183
202
  # kwargs
184
203
  new_nonsig_kwargs = _update_kwargs(
185
204
  update_dict=scatter_nonsig_kwargs_dict,
@@ -1,7 +1,7 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: plot-misc
3
- Version: 2.2.2
4
- Summary: Various plotting templates built on top of matplotlib
3
+ Version: 2.3.0
4
+ Summary: Various plotting archetypes built on top of matplotlib
5
5
  Author-email: A Floriaan Schmidt <floriaanschmidt@gmail.com>
6
6
  License-Expression: GPL-3.0-or-later
7
7
  Project-URL: Homepage, https://gitlab.com/SchmidtAF/plot-misc
@@ -11,8 +11,9 @@ Classifier: Programming Language :: Python :: 3
11
11
  Classifier: Programming Language :: Python :: 3.10
12
12
  Classifier: Programming Language :: Python :: 3.11
13
13
  Classifier: Programming Language :: Python :: 3.12
14
+ Classifier: Programming Language :: Python :: 3.13
14
15
  Classifier: Programming Language :: Python :: Implementation :: PyPy
15
- Requires-Python: <3.13,>=3.10
16
+ Requires-Python: <3.14,>=3.10
16
17
  Description-Content-Type: text/markdown
17
18
  License-File: LICENSE
18
19
  Requires-Dist: pandas>=1.3
@@ -22,6 +23,7 @@ Requires-Dist: scipy>=1.5
22
23
  Requires-Dist: statsmodels>=0.1
23
24
  Requires-Dist: scikit-learn>=1.4
24
25
  Requires-Dist: adjustText>=1.3
26
+ Requires-Dist: typing_extensions>=4; python_version < "3.11"
25
27
  Provides-Extra: dev
26
28
  Requires-Dist: python-build; extra == "dev"
27
29
  Requires-Dist: twine; extra == "dev"
@@ -48,7 +50,7 @@ Dynamic: license-file
48
50
  <img src="https://schmidtaf.gitlab.io/plot-misc/_images/icon.png" alt="plot-misc icon" width="250"/>
49
51
 
50
52
  # A collection of plotting functions
51
- __version__: `2.2.2`
53
+ __version__: `2.3.0`
52
54
 
53
55
  This repository collects plotting modules written on top of `matplotlib`.
54
56
  The functions describe plotting archetypes intended to set up light-touch,
@@ -6,6 +6,9 @@ statsmodels>=0.1
6
6
  scikit-learn>=1.4
7
7
  adjustText>=1.3
8
8
 
9
+ [:python_version < "3.11"]
10
+ typing_extensions>=4
11
+
9
12
  [dev]
10
13
  python-build
11
14
  twine
@@ -4,13 +4,13 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "plot-misc"
7
- version = "2.2.2"
8
- description = "Various plotting templates built on top of matplotlib"
7
+ version = "2.3.0"
8
+ description = "Various plotting archetypes built on top of matplotlib"
9
9
  readme = "README.md"
10
10
  authors = [{ name = "A Floriaan Schmidt", email = "floriaanschmidt@gmail.com" }]
11
11
  license = "GPL-3.0-or-later"
12
12
  license-files = ["LICENSE"]
13
- requires-python = ">=3.10, <3.13"
13
+ requires-python = ">=3.10, <3.14"
14
14
  dynamic = ["dependencies", "optional-dependencies"]
15
15
  classifiers = [
16
16
  "Programming Language :: Python",
@@ -18,6 +18,7 @@ classifiers = [
18
18
  "Programming Language :: Python :: 3.10",
19
19
  "Programming Language :: Python :: 3.11",
20
20
  "Programming Language :: Python :: 3.12",
21
+ "Programming Language :: Python :: 3.13",
21
22
  "Programming Language :: Python :: Implementation :: PyPy"
22
23
  ]
23
24
 
@@ -5,4 +5,5 @@ scipy>=1.5
5
5
  statsmodels>=0.1
6
6
  scikit-learn>=1.4
7
7
  adjustText>=1.3
8
+ typing_extensions>=4; python_version < "3.11"
8
9
 
@@ -1 +0,0 @@
1
- from ._version import __version__
@@ -1 +0,0 @@
1
- __version__ = '2.2.2'
File without changes
File without changes
File without changes
File without changes