pyaging 0.0.1__tar.gz → 0.0.4__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.

Potentially problematic release.


This version of pyaging might be problematic. Click here for more details.

@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pyaging
3
- Version: 0.0.1
3
+ Version: 0.0.4
4
4
  Summary: A Python-based compendium of GPU-optimized aging clocks.
5
5
  License: BSD
6
6
  Author: Lucas Paulo de Lima Camillo
@@ -13,12 +13,12 @@ Classifier: Programming Language :: Python :: 3.10
13
13
  Classifier: Programming Language :: Python :: 3.11
14
14
  Classifier: Programming Language :: Python :: 3.12
15
15
  Provides-Extra: docs
16
- Requires-Dist: anndata (>=0.10.0,<0.11.0)
17
- Requires-Dist: numpy (>=1.26.0,<2.0.0)
18
- Requires-Dist: pandas (>=2.0.0,<3.0.0)
16
+ Requires-Dist: anndata (>=0.10.3,<0.11.0)
17
+ Requires-Dist: numpy (>=1.26.2,<2.0.0)
18
+ Requires-Dist: pandas (>=2.1.3,<3.0.0)
19
19
  Requires-Dist: pyBigWig (>=0.3.22,<0.4.0)
20
- Requires-Dist: scikit-learn (>=1.3.0,<2.0.0)
21
- Requires-Dist: torch (>=2.0.0,<3.0.0)
20
+ Requires-Dist: scikit-learn (>=1.3.2,<2.0.0)
21
+ Requires-Dist: torch (>=2.1.1,<3.0.0)
22
22
  Project-URL: homepage, https://github.com/rsinghlab/pyaging
23
23
  Project-URL: repository, https://github.com/rsinghlab/pyaging
24
24
  Description-Content-Type: text/markdown
@@ -43,29 +43,18 @@ Description-Content-Type: text/markdown
43
43
 
44
44
  `pyaging` is a cutting-edge Python package designed for the longevity research community, offering a comprehensive suite of GPU-optimized biological aging clocks.
45
45
 
46
- [Installation](https://pyaging.readthedocs.io/en/latest/installation.html) - [Search, cite, and get metadata](https://pyaging.readthedocs.io/en/latest/tutorial_utils.html) - [Bulk DNA methylation](https://pyaging.readthedocs.io/en/latest/tutorial_dnam.html) - [Bulk histone mark ChIP-Seq](https://pyaging.readthedocs.io/en/latest/tutorial_histonemarkchipseq.html) - [Bulk ATAC-Seq](https://pyaging.readthedocs.io/en/latest/tutorial_atacseq.html) - [Bulk RNA-Seq](https://pyaging.readthedocs.io/en/latest/tutorial_rnaseq.html) - [API Reference](https://pyaging.readthedocs.io/en/latest/pyaging.html)
46
+ [Installation](https://pyaging.readthedocs.io/en/latest/installation.html) - [Search, cite, and get metadata](https://pyaging.readthedocs.io/en/latest/tutorial_utils.html) - [Bulk DNA methylation](https://pyaging.readthedocs.io/en/latest/tutorial_dnam.html) - [Bulk histone mark ChIP-Seq](https://pyaging.readthedocs.io/en/latest/tutorial_histonemarkchipseq.html) - [Bulk ATAC-Seq](https://pyaging.readthedocs.io/en/latest/tutorial_atacseq.html) - [Bulk RNA-Seq](https://pyaging.readthedocs.io/en/latest/tutorial_rnaseq.html) - [Blood chemistry](https://pyaging.readthedocs.io/en/latest/tutorial_bloodchemistry.html) - [API Reference](https://pyaging.readthedocs.io/en/latest/pyaging.html)
47
47
 
48
48
  With a growing number of aging clocks, comparing and analyzing them can be challenging. `pyaging` simplifies this process, allowing researchers to input various molecular layers (DNA methylation, histone ChIP-Seq, ATAC-seq, transcriptomics, etc.) and quickly analyze them using multiple aging clocks, thanks to its GPU-backed infrastructure. This makes it an ideal tool for large datasets and multi-layered analysis.
49
49
 
50
50
  ## 📝 To-Do List
51
51
 
52
- - [X] Integrate `black` for PEP8 compliant code formatting
53
- - [X] Improve and expand `readthedocs` documentation
54
- - [X] Add option to specify download directory for datasets
55
- - [X] Rename datasets to reflect source publications
56
- - [X] Include mammalian array example datasets
57
- - [X] Add feature to control logging verbosity
58
- - [ ] Publish to PyPi
59
- - [ ] Add percentage of missing features in anndata after age prediction for each clock
60
- - [ ] Add table in readthedocs with all clock metadata
61
- - [ ] Add and populate "Notes" tab in metadata
62
52
  - [ ] Integrate scAge and scRNAseq clocks (and datasets)
63
53
  - [ ] Incorporate murine DNA methylation and proteomic clocks (and datasets)
64
- - [ ] Add PhenoAge based on blood chemistry analysis (and datasets)
65
54
 
66
55
  ## ❓ Can't find an aging clock?
67
56
 
68
- If you have recently developed an aging clock and would like it to be integrated into `pyaging`, please [email us](lucas_camillo@alumni.brown.edu). We aim to incorporate it within two weeks!
57
+ If you have recently developed an aging clock and would like it to be integrated into `pyaging`, please [email us](lucas_camillo@alumni.brown.edu). We aim to incorporate it within two weeks! We are also happy to adapt to any licensing terms for commercial entities.
69
58
 
70
59
  ## 💬 Community Discussion
71
60
  For coding-related queries, feedback, and discussions, please visit our [GitHub Issues](https://github.com/rsinghlab/pyaging/issues) page.
@@ -18,29 +18,18 @@
18
18
 
19
19
  `pyaging` is a cutting-edge Python package designed for the longevity research community, offering a comprehensive suite of GPU-optimized biological aging clocks.
20
20
 
21
- [Installation](https://pyaging.readthedocs.io/en/latest/installation.html) - [Search, cite, and get metadata](https://pyaging.readthedocs.io/en/latest/tutorial_utils.html) - [Bulk DNA methylation](https://pyaging.readthedocs.io/en/latest/tutorial_dnam.html) - [Bulk histone mark ChIP-Seq](https://pyaging.readthedocs.io/en/latest/tutorial_histonemarkchipseq.html) - [Bulk ATAC-Seq](https://pyaging.readthedocs.io/en/latest/tutorial_atacseq.html) - [Bulk RNA-Seq](https://pyaging.readthedocs.io/en/latest/tutorial_rnaseq.html) - [API Reference](https://pyaging.readthedocs.io/en/latest/pyaging.html)
21
+ [Installation](https://pyaging.readthedocs.io/en/latest/installation.html) - [Search, cite, and get metadata](https://pyaging.readthedocs.io/en/latest/tutorial_utils.html) - [Bulk DNA methylation](https://pyaging.readthedocs.io/en/latest/tutorial_dnam.html) - [Bulk histone mark ChIP-Seq](https://pyaging.readthedocs.io/en/latest/tutorial_histonemarkchipseq.html) - [Bulk ATAC-Seq](https://pyaging.readthedocs.io/en/latest/tutorial_atacseq.html) - [Bulk RNA-Seq](https://pyaging.readthedocs.io/en/latest/tutorial_rnaseq.html) - [Blood chemistry](https://pyaging.readthedocs.io/en/latest/tutorial_bloodchemistry.html) - [API Reference](https://pyaging.readthedocs.io/en/latest/pyaging.html)
22
22
 
23
23
  With a growing number of aging clocks, comparing and analyzing them can be challenging. `pyaging` simplifies this process, allowing researchers to input various molecular layers (DNA methylation, histone ChIP-Seq, ATAC-seq, transcriptomics, etc.) and quickly analyze them using multiple aging clocks, thanks to its GPU-backed infrastructure. This makes it an ideal tool for large datasets and multi-layered analysis.
24
24
 
25
25
  ## 📝 To-Do List
26
26
 
27
- - [X] Integrate `black` for PEP8 compliant code formatting
28
- - [X] Improve and expand `readthedocs` documentation
29
- - [X] Add option to specify download directory for datasets
30
- - [X] Rename datasets to reflect source publications
31
- - [X] Include mammalian array example datasets
32
- - [X] Add feature to control logging verbosity
33
- - [ ] Publish to PyPi
34
- - [ ] Add percentage of missing features in anndata after age prediction for each clock
35
- - [ ] Add table in readthedocs with all clock metadata
36
- - [ ] Add and populate "Notes" tab in metadata
37
27
  - [ ] Integrate scAge and scRNAseq clocks (and datasets)
38
28
  - [ ] Incorporate murine DNA methylation and proteomic clocks (and datasets)
39
- - [ ] Add PhenoAge based on blood chemistry analysis (and datasets)
40
29
 
41
30
  ## ❓ Can't find an aging clock?
42
31
 
43
- If you have recently developed an aging clock and would like it to be integrated into `pyaging`, please [email us](lucas_camillo@alumni.brown.edu). We aim to incorporate it within two weeks!
32
+ If you have recently developed an aging clock and would like it to be integrated into `pyaging`, please [email us](lucas_camillo@alumni.brown.edu). We aim to incorporate it within two weeks! We are also happy to adapt to any licensing terms for commercial entities.
44
33
 
45
34
  ## 💬 Community Discussion
46
35
  For coding-related queries, feedback, and discussions, please visit our [GitHub Issues](https://github.com/rsinghlab/pyaging/issues) page.
@@ -4,6 +4,7 @@ import ntpath
4
4
  import os
5
5
  from urllib.request import urlretrieve
6
6
  from functools import wraps
7
+
7
8
  from ..utils import progress, download
8
9
  from ..logger import LoggerManager, main_tqdm, silence_logger
9
10
 
@@ -21,7 +22,9 @@ def download_example_data(
21
22
  Parameters
22
23
  ----------
23
24
  data_type : str
24
- The type of data to download. Valid options are 'methylation', 'histone_mark', 'rnaseq', and 'atac'.
25
+ The type of data to download. Valid options are 'GSE139307' (human methylation),
26
+ 'GSE223748' (mammalian methylation), 'ENCFF386QWG' (histone mark),
27
+ 'GSE65765' (C. elegans RNA-seq), 'atac_example' (ATAC-Seq), 'blood_chemistry_example' (blood chemistry).
25
28
 
26
29
  dir : str
27
30
  The directory to deposit the downloaded file. Defaults to "pyaging_data".
@@ -61,6 +64,7 @@ def download_example_data(
61
64
  "ENCFF386QWG": "https://pyaging.s3.amazonaws.com/example_data/ENCFF386QWG.bigWig",
62
65
  "GSE65765": "https://pyaging.s3.amazonaws.com/example_data/GSE65765_CPM.pkl",
63
66
  "atac_example": "https://pyaging.s3.amazonaws.com/example_data/atac_example.pkl",
67
+ "blood_chemistry_example": "https://pyaging.s3.amazonaws.com/example_data/blood_chemistry_example.pkl",
64
68
  }
65
69
 
66
70
  if data_type not in list(data_type_to_url.keys()):
@@ -273,7 +273,8 @@ class Logger:
273
273
  self.logger_stream_handler.terminator = saved_terminator
274
274
 
275
275
  def start_progress(self, message, indent_level=1, *args, **kwargs):
276
- self.log_time()
276
+ now = time.time()
277
+ self.previous_timestamp = now
277
278
  message = format_logging_message(
278
279
  "⚙️ " + message, logging.INFO, indent_level=indent_level
279
280
  )
@@ -281,8 +282,8 @@ class Logger:
281
282
  self.logger_stream_handler.flush()
282
283
 
283
284
  def finish_progress(self, progress_name="", time_unit="s", indent_level=1):
284
- # self.log_time()
285
- # self.report_progress(percent=100, progress_name=progress_name)#
285
+ now = time.time()
286
+ self.time_passed = now - self.previous_timestamp
286
287
 
287
288
  saved_terminator = self.logger_stream_handler.terminator
288
289
  self.logger_stream_handler.terminator = ""
@@ -1,5 +1,6 @@
1
1
  # pyaging/predict/__init__.py
2
2
 
3
3
  from ._pred import *
4
+ from ._pred_utils import *
4
5
  from ._preprocessing import *
5
6
  from ._postprocessing import *
@@ -35,3 +35,15 @@ def anti_log_log(x):
35
35
  """
36
36
  # Double transformation: logarithmic followed by anti-logarithmic
37
37
  return math.exp(-math.exp(-x))
38
+
39
+
40
+ def mortality_to_phenoage(x):
41
+ """
42
+ Applies a convertion from a CDF of the mortality score from a Gompertz
43
+ distribution to phenotypic age.
44
+ """
45
+ # lambda
46
+ l = 0.0192
47
+ mortality_score = 1 - math.exp(-math.exp(x) * (math.exp(120 * l) - 1) / l)
48
+ age = 141.50225 + math.log(-0.00553 * math.log(1 - mortality_score)) / 0.090165
49
+ return age
@@ -0,0 +1,137 @@
1
+ import anndata
2
+
3
+ from ._pred_utils import *
4
+
5
+
6
+ def predict_age(
7
+ adata: anndata.AnnData,
8
+ clock_names: str = "horvath2013",
9
+ dir: str = "pyaging_data",
10
+ verbose: bool = True,
11
+ ) -> anndata.AnnData:
12
+ """
13
+ Predicts biological age using specified aging clocks.
14
+
15
+ This function takes an AnnData object and applies one or more specified aging
16
+ clock models to predict the biological age of the samples. It handles the entire pipeline from data
17
+ preprocessing, model loading, prediction, to postprocessing. It also enriches the input AnnData
18
+ object with the predicted ages and relevant clock metadata.
19
+
20
+ Parameters
21
+ ----------
22
+ adata: AnnData
23
+ An AnnData object. The object should have .X attribute for the
24
+ data matrix and .var_names for feature names.
25
+
26
+ clock_names: str or list of str, optional
27
+ Names of the aging clocks to be applied. It can be a single clock name as a string or a list
28
+ of clock names, by default "horvath2013".
29
+
30
+ dir: str
31
+ The directory to deposit the downloaded file. Defaults to "pyaging_data".
32
+
33
+ verbose: bool
34
+ Whether to log the output to console with the logger. Defaults to True.
35
+
36
+ Returns
37
+ -------
38
+ AnnData
39
+ The input AnnData object enriched with the predicted ages and clock metadata in the .obs and
40
+ .uns attributes, respectively.
41
+
42
+ Notes
43
+ -----
44
+ The function is designed to be flexible and can handle both single and multiple clock predictions.
45
+ The predicted ages are appended to the .obs attribute of the AnnData object with the clock name as
46
+ the key. The metadata of each clock used in the prediction is stored in the .uns attribute.
47
+
48
+ It is important that the input AnnData object's .X attribute contains data suitable for age
49
+ prediction.
50
+
51
+ The function automatically handles the transfer of data and models to the appropriate compute
52
+ device (CPU or GPU) based on system configuration.
53
+
54
+ Examples
55
+ --------
56
+ >>> adata = anndata.read_h5ad("sample_data.h5ad")
57
+ >>> adata = predict_age(adata, clock_names=["horvath2013", "hannum"])
58
+ >>> adata.obs["horvath2013"] # Access predicted ages by clock name
59
+
60
+ """
61
+ logger = LoggerManager.gen_logger("predict_age")
62
+ if not verbose:
63
+ silence_logger("predict_age")
64
+ logger.first_info("Starting predict_age function")
65
+
66
+ # Ensure clock_names is a list
67
+ if isinstance(clock_names, str):
68
+ clock_names = [clock_names]
69
+
70
+ # Set device for PyTorch operations
71
+ device = set_torch_device(logger)
72
+
73
+ for clock_name in clock_names:
74
+ logger.info(f"🕒 Processing clock: {clock_name}", indent_level=1)
75
+
76
+ # Load and prepare the clock
77
+ clock_name = clock_name.lower()
78
+ features, weight_dict, preprocessing, postprocessing, preprocessing_helper, postprocessing_helper = load_clock(
79
+ clock_name, dir, logger, indent_level=2
80
+ )
81
+
82
+ # Check and update adata for missing features
83
+ adata = check_features_in_adata(
84
+ adata, clock_name, features, logger, indent_level=2
85
+ )
86
+
87
+ # Apply preprocessing
88
+ if preprocessing:
89
+ adata = preprocess_data(
90
+ adata, preprocessing, preprocessing_helper, features, logger, indent_level=2
91
+ )
92
+
93
+ # Filter features and then extract data matrix
94
+ x_numpy = filter_features_and_extract_data(
95
+ adata, preprocessing, features, logger, indent_level=2
96
+ )
97
+
98
+ # Convert numpy array to tensor
99
+ x_tensor = convert_numpy_array_to_tensor(
100
+ x_numpy, device, logger, indent_level=2
101
+ )
102
+
103
+ # Initialize and configure the model
104
+ clock_model = initialize_model(
105
+ clock_name, features, weight_dict, device, logger, indent_level=2
106
+ )
107
+
108
+ # Perform age prediction using the model
109
+ predicted_ages_tensor = predict_ages_with_model(
110
+ clock_model, x_tensor, logger, indent_level=2
111
+ )
112
+
113
+ # Convert adata tensor to numpy array
114
+ predicted_ages = convert_tensor_to_numpy_array(
115
+ predicted_ages_tensor, logger, indent_level=2
116
+ )
117
+
118
+ # Apply postprocessing if specified
119
+ if postprocessing:
120
+ predicted_ages = postprocess_data(
121
+ predicted_ages, postprocessing, postprocessing_helper, logger, indent_level=2
122
+ )
123
+
124
+ # Add predicted ages to adata
125
+ add_pred_ages_adata(adata, predicted_ages, clock_name, logger, indent_level=2)
126
+
127
+ # Load all clocks metadata
128
+ all_clock_metadata = load_clock_metadata(dir, logger, indent_level=2)
129
+
130
+ # Add clock metadata to adata object
131
+ add_clock_metadata_adata(
132
+ adata, clock_name, all_clock_metadata, logger, indent_level=2
133
+ )
134
+
135
+
136
+ logger.done()
137
+ return adata