plot-misc 2.2.2__py3-none-any.whl → 2.3.1__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.
- plot_misc/__init__.py +17 -0
- plot_misc/_version.py +1 -1
- plot_misc/example_data/example_datasets/string_data.txt +1 -0
- plot_misc/example_data/examples.py +30 -30
- plot_misc/forest.py +0 -14
- plot_misc/heatmap.py +2 -3
- plot_misc/machine_learning.py +10 -14
- plot_misc/survival.py +1 -0
- plot_misc/utils/formatting.py +1 -1
- plot_misc/utils/utils.py +83 -54
- plot_misc/volcano.py +26 -7
- {plot_misc-2.2.2.dist-info → plot_misc-2.3.1.dist-info}/METADATA +32 -7
- {plot_misc-2.2.2.dist-info → plot_misc-2.3.1.dist-info}/RECORD +16 -15
- {plot_misc-2.2.2.dist-info → plot_misc-2.3.1.dist-info}/WHEEL +1 -1
- {plot_misc-2.2.2.dist-info → plot_misc-2.3.1.dist-info}/licenses/LICENSE +0 -0
- {plot_misc-2.2.2.dist-info → plot_misc-2.3.1.dist-info}/top_level.txt +0 -0
plot_misc/__init__.py
CHANGED
|
@@ -1 +1,18 @@
|
|
|
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 reuse.
|
|
11
|
+
"""
|
|
1
12
|
from ._version import __version__
|
|
13
|
+
|
|
14
|
+
__citation__ = (
|
|
15
|
+
"Schmidt AF, Hukerikar N, Finan C, van Vugt M. Effective visualization "
|
|
16
|
+
"of biomedical data using plot-misc. Bioinformatics Advances. "
|
|
17
|
+
"2026;6(1):vbag184. https://doi.org/10.1093/bioadv/vbag184"
|
|
18
|
+
)
|
plot_misc/_version.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
__version__ = '2.
|
|
1
|
+
__version__ = '2.3.1'
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
hi!
|
|
@@ -229,12 +229,12 @@ def help(name):
|
|
|
229
229
|
@dataset
|
|
230
230
|
def dummy_data():
|
|
231
231
|
"""A dummy dataset function that returns a small list.
|
|
232
|
-
|
|
232
|
+
|
|
233
233
|
Returns
|
|
234
234
|
-------
|
|
235
235
|
data : `list`
|
|
236
236
|
A list of length 3 with ``['A', 'B', 'C']``
|
|
237
|
-
|
|
237
|
+
|
|
238
238
|
Notes
|
|
239
239
|
-----
|
|
240
240
|
This function is called ``dummy_data`` and has been decorated with a
|
|
@@ -253,7 +253,7 @@ def dummy_load_data():
|
|
|
253
253
|
-------
|
|
254
254
|
str_data : `str`
|
|
255
255
|
A string of data loaded from an example data file.
|
|
256
|
-
|
|
256
|
+
|
|
257
257
|
Notes
|
|
258
258
|
-----
|
|
259
259
|
This function is called ``dummy_data`` and has been decorated with a
|
|
@@ -774,34 +774,34 @@ def load_survival_table(**kwargs):
|
|
|
774
774
|
return table
|
|
775
775
|
|
|
776
776
|
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
777
|
-
@dataset
|
|
778
|
-
def load_forest_preprocessed(**kwargs):
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
777
|
+
# @dataset
|
|
778
|
+
# def load_forest_preprocessed(**kwargs):
|
|
779
|
+
# """
|
|
780
|
+
# Loads the forest example data with subgroup colour and model shape
|
|
781
|
+
# columns attached, ready for direct use by the forest plot.
|
|
782
782
|
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
783
|
+
# Returns
|
|
784
|
+
# -------
|
|
785
|
+
# pd.DataFrame
|
|
786
|
+
# """
|
|
787
|
+
# # mapping literals (mirrors resources/examples/forestplot.ipynb cell 2)
|
|
788
|
+
# col_dict = {
|
|
789
|
+
# 'wo T2DM/CVD': 'orangered',
|
|
790
|
+
# 'w T2DM': 'blueviolet',
|
|
791
|
+
# 'w T2DM & CVD': 'limegreen',
|
|
792
|
+
# }
|
|
793
|
+
# shape_dict = {
|
|
794
|
+
# 'PGS only': 'o',
|
|
795
|
+
# 'PGS plus': 's',
|
|
796
|
+
# 'PGS extended': 'H',
|
|
797
|
+
# }
|
|
798
|
+
# # base data (already carries the hardcoded ForestNames.y_col)
|
|
799
|
+
# df = load_forest_data(**kwargs)
|
|
800
|
+
# # attach colour and shape columns
|
|
801
|
+
# df['col'] = df['subgroup_name'].map(col_dict)
|
|
802
|
+
# df['shape'] = df['model'].map(shape_dict)
|
|
803
|
+
# # return
|
|
804
|
+
# return df
|
|
805
805
|
|
|
806
806
|
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
807
807
|
@dataset
|
plot_misc/forest.py
CHANGED
|
@@ -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
|
plot_misc/heatmap.py
CHANGED
|
@@ -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
|
-
|
|
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
|
plot_misc/machine_learning.py
CHANGED
|
@@ -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
|
-
`
|
|
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
|
-
`
|
|
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
|
"""
|
plot_misc/survival.py
CHANGED
|
@@ -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
|
plot_misc/utils/formatting.py
CHANGED
|
@@ -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,
|
|
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)
|
plot_misc/utils/utils.py
CHANGED
|
@@ -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,
|
|
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,
|
|
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
|
-
|
|
288
|
-
|
|
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(
|
|
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,
|
|
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.
|
|
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
|
-
|
|
492
|
-
Name of the column representing
|
|
493
|
-
|
|
494
|
-
Name of the column representing
|
|
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,
|
|
519
|
-
pvalue = data[[pvalue_col,
|
|
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=[
|
|
522
|
-
columns =
|
|
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=[
|
|
528
|
-
columns =
|
|
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
|
-
|
|
663
|
-
|
|
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=
|
|
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
|
|
685
|
-
|
|
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
|
|
693
|
-
and p-value columns
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
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 `
|
|
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(
|
|
751
|
-
is_type(
|
|
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
|
-
|
|
803
|
-
|
|
828
|
+
columns=columns,
|
|
829
|
+
rows=rows,
|
|
804
830
|
point_col=point_col,
|
|
805
831
|
pvalue_col=pvalue_col,
|
|
806
|
-
**
|
|
832
|
+
**new_kwargs,
|
|
807
833
|
)
|
|
808
|
-
### formatting data (convert the raw-p `alpha` to a -log10 threshold
|
|
809
|
-
|
|
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
|
|
843
|
+
ptrun=trun, digits=str(sig_numbers),
|
|
815
844
|
symbol=symbol, pval_mode=pval_mode,
|
|
816
845
|
)
|
|
817
846
|
### selecting the annotation to use
|
plot_misc/volcano.py
CHANGED
|
@@ -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
|
|
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
|
|
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
|
-
|
|
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.
|
|
4
|
-
Summary: Various plotting
|
|
3
|
+
Version: 2.3.1
|
|
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,17 +11,19 @@ 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.
|
|
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
|
|
19
20
|
Requires-Dist: numpy>=1.21
|
|
20
21
|
Requires-Dist: matplotlib>=3.5
|
|
21
22
|
Requires-Dist: scipy>=1.5
|
|
22
|
-
Requires-Dist: statsmodels>=0.
|
|
23
|
+
Requires-Dist: statsmodels>=0.12
|
|
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"
|
|
@@ -45,10 +47,10 @@ Requires-Dist: numpydoc; extra == "dev"
|
|
|
45
47
|
Requires-Dist: docutils<0.21; extra == "dev"
|
|
46
48
|
Dynamic: license-file
|
|
47
49
|
|
|
48
|
-
<img src="https://schmidtaf.gitlab.io/plot-misc/_images/
|
|
50
|
+
<img src="https://schmidtaf.gitlab.io/plot-misc/_images/fish.png" alt="plot-misc icon" width="250"/>
|
|
49
51
|
|
|
50
52
|
# A collection of plotting functions
|
|
51
|
-
__version__: `2.
|
|
53
|
+
__version__: `2.3.1`
|
|
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,
|
|
@@ -75,6 +77,25 @@ research:
|
|
|
75
77
|
Please consult the **[documentation](https://SchmidtAF.gitlab.io/plot-misc/)**
|
|
76
78
|
for plot-misc.
|
|
77
79
|
|
|
80
|
+
## Citation
|
|
81
|
+
|
|
82
|
+
If you use this package in your research please cite the
|
|
83
|
+
**[paper](https://academic.oup.com/bioinformaticsadvances/article/6/1/vbag184/8721292)**:
|
|
84
|
+
|
|
85
|
+
```bibtex
|
|
86
|
+
@article{Schmidt:2026,
|
|
87
|
+
author = {Schmidt, Amand Floriaan and Hukerikar, Nikita and
|
|
88
|
+
Finan, Chris and van Vugt, Marion},
|
|
89
|
+
title = {Effective visualization of biomedical data using plot-misc},
|
|
90
|
+
journal = {Bioinformatics Advances},
|
|
91
|
+
volume = {6},
|
|
92
|
+
number = {1},
|
|
93
|
+
pages = {vbag184},
|
|
94
|
+
doi = {10.1093/bioadv/vbag184},
|
|
95
|
+
year = {2026}
|
|
96
|
+
}
|
|
97
|
+
```
|
|
98
|
+
|
|
78
99
|
## Installation
|
|
79
100
|
The package is available on PyPI, and conda, with the latest source code
|
|
80
101
|
available on gitlab.
|
|
@@ -144,7 +165,7 @@ branches without reinstalling.
|
|
|
144
165
|
Alternatively, you can install manually:
|
|
145
166
|
```bash
|
|
146
167
|
python -m pip install -e .
|
|
147
|
-
python .setup_git_hooks.py
|
|
168
|
+
python .githooks/.setup_git_hooks.py
|
|
148
169
|
```
|
|
149
170
|
|
|
150
171
|
#### Git Hooks Configuration
|
|
@@ -200,4 +221,8 @@ Please have a look at the examples in
|
|
|
200
221
|
[resources](https://gitlab.com/SchmidtAF/plot-misc/-/tree/master/resources/examples)
|
|
201
222
|
for some possible recipes.
|
|
202
223
|
|
|
224
|
+
## Icon
|
|
225
|
+
|
|
226
|
+
The icon at the top of this README is a _mandarinfish_, widely regarded as one of
|
|
227
|
+
the most colourful animals on the planet.
|
|
203
228
|
|
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
plot_misc/__init__.py,sha256=
|
|
2
|
-
plot_misc/_version.py,sha256=
|
|
1
|
+
plot_misc/__init__.py,sha256=9gmOKQn4BlRPhrNelBhlcHUeUg-RruLhHhO0UaUjRtA,807
|
|
2
|
+
plot_misc/_version.py,sha256=0Ns5BhVD3XOEWhtSUJ76K319NapPiQfZKsWZRt-kZOk,22
|
|
3
3
|
plot_misc/barchart.py,sha256=_4Fj8ypYi6Aehgv4b13Lh1zS1ee4z7OXrGo1P5QBshw,21925
|
|
4
4
|
plot_misc/constants.py,sha256=SABaNQpTRXm4pMF_F6sdsBUvNVyb-WXQLT_YAmUgtuo,4530
|
|
5
5
|
plot_misc/errors.py,sha256=ZbOZg1TbY-7dtPAsJNxIRsjlUfJg0vrx8kRPFsMClaQ,9637
|
|
6
|
-
plot_misc/forest.py,sha256=
|
|
7
|
-
plot_misc/heatmap.py,sha256=
|
|
6
|
+
plot_misc/forest.py,sha256=baQVlX4LLnb7AsNw_UPvOLt1eFqVKU0Ov_EM4vb2c9U,61988
|
|
7
|
+
plot_misc/heatmap.py,sha256=EmsVXrDX80rI3IErqBFFYAIbSHnYAWCwtgmurkc8i7U,19855
|
|
8
8
|
plot_misc/incidencematrix.py,sha256=BFDLQZT0nEhd8XzCtVVo7mR3s70DwzAMG4-ut7zLal8,18832
|
|
9
|
-
plot_misc/machine_learning.py,sha256=
|
|
9
|
+
plot_misc/machine_learning.py,sha256=8KgOKI1ukTEOgdIqEMpeIjR8IhQ3ubz-nbi6Uy7DJQ4,48679
|
|
10
10
|
plot_misc/piechart.py,sha256=nKT9Xr-rP9t8hv6ITb_0594AlzgfnAEdqkyCslLriLc,8613
|
|
11
|
-
plot_misc/survival.py,sha256
|
|
12
|
-
plot_misc/volcano.py,sha256=
|
|
11
|
+
plot_misc/survival.py,sha256=_fKxaHSLjLU1Pq9KsxVqby5kXhl6QIsTM4sqq3hv6ak,25410
|
|
12
|
+
plot_misc/volcano.py,sha256=4zAC4GH-sC5jJyDeHOTq9-3N-UgSldMKgutFs35KE4g,10298
|
|
13
13
|
plot_misc/example_data/__init__.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
|
|
14
|
-
plot_misc/example_data/examples.py,sha256=
|
|
14
|
+
plot_misc/example_data/examples.py,sha256=9F7xuJQGBu0WweoG719NdHPaOJaj5Dd1TzrqJXVC040,31564
|
|
15
15
|
plot_misc/example_data/example_datasets/bar_points.tsv.gz,sha256=ppYQY01DXz77GzSANpwZ9N4zZvxQN5AiHmLsOhZ6cbk,255
|
|
16
16
|
plot_misc/example_data/example_datasets/barchart.tsv.gz,sha256=9TVBaC7yuDuNzOQivTm-UxjmB_jyCfbv1twiL13WpOs,123
|
|
17
17
|
plot_misc/example_data/example_datasets/calibration_bins.tsv.gz,sha256=7BQdx7Tx5zF6wSyyCTwjkSaELKywoykUpelWvxe5pxA,332
|
|
@@ -23,13 +23,14 @@ plot_misc/example_data/example_datasets/incidence_matrix_data.tsv.gz,sha256=A5IQ
|
|
|
23
23
|
plot_misc/example_data/example_datasets/lollipop_data.tsv.gz,sha256=2EivSWOoYOxLKjFHgB86k9ln9xm3elTHd3eUI2tEwpg,820
|
|
24
24
|
plot_misc/example_data/example_datasets/mace_associations.tsv.gz,sha256=oTtSzrOUbOqXap-wmA5QhJxKgj4O5nbpZ964J7AXBcw,1732
|
|
25
25
|
plot_misc/example_data/example_datasets/net_benefit.tsv.gz,sha256=eW9ltgCj0smsq1_rGFbI0bujw4GkECfP89jIMk461iM,1323
|
|
26
|
+
plot_misc/example_data/example_datasets/string_data.txt,sha256=GttBz476DDdb9k0IvA_gJ6cg_vDXrAUUDCof4SABVaI,4
|
|
26
27
|
plot_misc/example_data/example_datasets/volcano.tsv.gz,sha256=Cd0J-VeiVPruUqdbPoMOCqDpOKZthITfKEKybsZ0qU8,41139
|
|
27
28
|
plot_misc/utils/__init__.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
|
|
28
29
|
plot_misc/utils/colour.py,sha256=SfhjFcnvTQ-_zfstMqb0vMPyW3-pdPO4G3KJ7-BtQ4E,7715
|
|
29
|
-
plot_misc/utils/formatting.py,sha256=
|
|
30
|
-
plot_misc/utils/utils.py,sha256=
|
|
31
|
-
plot_misc-2.
|
|
32
|
-
plot_misc-2.
|
|
33
|
-
plot_misc-2.
|
|
34
|
-
plot_misc-2.
|
|
35
|
-
plot_misc-2.
|
|
30
|
+
plot_misc/utils/formatting.py,sha256=RRXCSlGBv5SkshfZPnURcYy_QV9Zyu_ApbMdWxWRkAE,14018
|
|
31
|
+
plot_misc/utils/utils.py,sha256=Ydu3TVwz48K6FhqSjFg0CbagJp0WRQbTRVgn6BQetfA,52113
|
|
32
|
+
plot_misc-2.3.1.dist-info/licenses/LICENSE,sha256=TAKLZop-WRQ03q1liEZVOMPZOrVwR2ndHSdxC7j1YeU,779
|
|
33
|
+
plot_misc-2.3.1.dist-info/METADATA,sha256=ZAlUxBejWaIsGMzbQW5szU_pzuBSWWFZ32OQkzJ7WR8,6498
|
|
34
|
+
plot_misc-2.3.1.dist-info/WHEEL,sha256=YVMoNqKzERt-wjUZwJ33xBGAwnFl-4cqbYkTtWa4itE,91
|
|
35
|
+
plot_misc-2.3.1.dist-info/top_level.txt,sha256=WyOYx7sloAXvlDvWfFf57ZAf9PnKTWb0zqenkcZKkAE,10
|
|
36
|
+
plot_misc-2.3.1.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|