CATranS 0.1.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.
@@ -0,0 +1,9 @@
1
+ .venv/
2
+ __pycache__/
3
+ uv.lock
4
+ .antigravitycli/
5
+ .ruff_cache/
6
+ .mypy_cache/
7
+ .pytest_cache/
8
+ dist/
9
+ *.ipynb
catrans-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 ruben-canas-ivi
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
catrans-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,268 @@
1
+ Metadata-Version: 2.4
2
+ Name: CATranS
3
+ Version: 0.1.0
4
+ Summary: Clinical Acute Transcriptomic Stratification
5
+ Project-URL: Homepage, https://github.com/ruben-canas-ivi/CATranS
6
+ Project-URL: Issues, https://github.com/ruben-canas-ivi/CATranS/issues
7
+ Author-email: Patricia Sebastián-León <patricia.sebastian@ivirma.com>, Antonio Parraga-Leo <antonio.parraga@ivirma.com>, Rubén Cañas-Cañas <ruben.canas@ivirma.com>
8
+ License-File: LICENSE
9
+ Keywords: bioinformatics,deseq2,genomics,machine-learning,stratification
10
+ Classifier: Development Status :: 4 - Beta
11
+ Classifier: Intended Audience :: Science/Research
12
+ Classifier: License :: OSI Approved :: MIT License
13
+ Classifier: Operating System :: OS Independent
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.11
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: Topic :: Scientific/Engineering :: Bio-Informatics
18
+ Requires-Python: >=3.11
19
+ Requires-Dist: igraph>=1.0.0
20
+ Requires-Dist: inmoose>=0.9.1
21
+ Requires-Dist: numpy>=2.3.0
22
+ Requires-Dist: pandas>=2.3.3
23
+ Requires-Dist: pydeseq2>=0.5.4
24
+ Requires-Dist: scikit-learn>=1.8.0
25
+ Requires-Dist: scipy>=1.17.1
26
+ Description-Content-Type: text/markdown
27
+
28
+ # CATranS: Clinical Acute Transcriptomic Stratification
29
+
30
+ **CATranS** is a robust bioinformatics and machine learning pipeline written in Python designed to stratify acute clinical cohorts using transcriptomic count data.
31
+
32
+ Through an iterative, semi-supervised learning approach, CATranS combines data normalization, batch correction, correlation-based feature selection, and class prediction to refine classifications of patient cohorts (e.g., separating acute from non-acute states, or predicting survival outcomes).
33
+
34
+ ---
35
+
36
+ ## Key Features
37
+
38
+ - **Iterative Semi-Supervised Relabeling**: Safely expands training cohorts by predicting clinical labels on unclassified/unlabeled samples using high-confidence thresholds.
39
+ - **Generalized Custom Classes**: Supports user-defined positive and negative class labeling (e.g., `Survivor`/`NonSurvivor`, `Mild`/`Severe`, `Responders`/`NonResponders`) with robust Categorical ordering to fix Wald contrast directions in DESeq2.
40
+ - **Batch Correction**: Integrated with `inmoose` for ComBat-seq count batch effect correction.
41
+ - **DESeq2-style Normalization**: Leverages the high-performance `pydeseq2` implementation for median-of-ratios normalization.
42
+ - **Correlation-Based Feature Learning**: Custom graph-theory based gene selection utilizing `igraph`. Filters out highly redundant co-expressed genes and selects optimal representative biomarkers correlating with clinical outcomes.
43
+ - **Flexible Estimator Integration**: Compatible with any Scikit-Learn classifier exposing a `predict_proba` method.
44
+
45
+ ---
46
+
47
+ ## Workflow Overview
48
+
49
+ ```mermaid
50
+ graph TD
51
+ A[Raw Count Matrix & Metadata] --> B[Data Normalization & Optional ComBat-seq Batch Correction]
52
+ B --> C[Feature Selection: Spearman Correlation with Labels]
53
+ C --> D[Graph Construction: Pearson Gene-Gene Network]
54
+ D --> E[Redundant Feature Compression: Connected Components Vertex Selection]
55
+ E --> F[Iterative Semi-Supervised Model Training]
56
+ F --> G[Fit Classifier & Predict Unlabeled Samples]
57
+ G --> H{Meets Threshold?}
58
+ H -- Yes --> I[Relabel Samples & Run DESeq2 Differential Expression Analysis]
59
+ I --> J{Are there new DEGs?}
60
+ J -- Yes --> F
61
+ J -- No --> K[Final Output Classifications & Iteration History]
62
+ H -- No --> K
63
+ ```
64
+
65
+ ---
66
+
67
+ ## Installation
68
+
69
+ We recommend using [uv](https://github.com/astral-sh/uv) or `pip` for rapid virtual environment setup and dependency management.
70
+
71
+ ```bash
72
+ # Clone the repository
73
+ git clone https://github.com/ruben-canas-ivi/CATranS.git
74
+ cd CATranS
75
+
76
+ # Install dependencies and the package using uv
77
+ uv sync
78
+ ```
79
+
80
+ ### Dependencies
81
+ - Python `>=3.11`
82
+ - `numpy>=2.3.0`
83
+ - `pandas>=2.3.3`
84
+ - `scipy>=1.14.0`
85
+ - `scikit-learn>=1.8.0`
86
+ - `pydeseq2>=0.5.4`
87
+ - `igraph>=1.0.0`
88
+ - `inmoose>=0.9.1`
89
+
90
+ ---
91
+
92
+ ## API Reference & Usage Scenarios
93
+
94
+ ### Core Classes & Functions
95
+
96
+ #### 1. `CatransClasses`
97
+ Defines the names of the binary classes.
98
+ - `positive` (default `"Dead"`): The target/case class.
99
+ - `negative` (default `"Alive"`): The reference/control class.
100
+
101
+ #### 2. `correlation_based_feature_selection`
102
+ Identifies representative biomarker genes by correlating expression levels with labels, building a gene-gene correlation network, and selecting one representative gene per connected component.
103
+
104
+ #### 3. `run_catrans`
105
+ Runs the iterative semi-supervised relabeling pipeline.
106
+ - `raw_counts` (pd.DataFrame): Genes (rows) by Samples (columns).
107
+ - `metadata` (pd.DataFrame): Samples (rows) with metadata.
108
+ - `acute_classification` (pd.DataFrame): Samples (rows) with initially known labels under the column `"class"` (unlabeled samples should be `NaN`).
109
+ - `model`: Any Scikit-Learn compatible classifier (e.g. `RandomForestClassifier`, `SVC(probability=True)`).
110
+ - `classes` (CatransClasses, Optional): Custom positive/negative class names.
111
+ - `batch_col` (str, Optional): Metadata column to use for ComBat-seq batch correction.
112
+ - `model_threshold` (float, default `0.8`): Confidence threshold to assign a label.
113
+ - `signature_genes` (list[str], Optional): Genes to use for training the model. If `None`, `correlation_based_feature_selection` runs automatically.
114
+
115
+ ---
116
+
117
+ ### Usage Scenarios
118
+
119
+ #### Scenario 1: Normal Workflow (Two-step Feature Selection + Stratification)
120
+ This is the recommended workflow where you first find a non-redundant gene signature, then pass it to the CATranS pipeline.
121
+
122
+ ```python
123
+ import pandas as pd
124
+ from sklearn.ensemble import RandomForestClassifier
125
+ import catrans
126
+
127
+ # 1. Load your transcriptomics and clinical datasets
128
+ counts = pd.read_csv("data/raw_counts.tsv", sep="\t", index_col=0)
129
+ metadata = pd.read_csv("data/metadata.tsv", sep="\t", index_col=0)
130
+ initial_classes = pd.read_csv("data/initial_classes.tsv", sep="\t", index_col=0)
131
+
132
+ # 2. Define custom labels: "Survivor" (negative) and "NonSurvivor" (positive)
133
+ my_classes = catrans.CatransClasses(positive="NonSurvivor", negative="Survivor")
134
+
135
+ # 3. Perform correlation-based feature selection to identify candidate biomarkers
136
+ signature = catrans.correlation_based_feature_selection(
137
+ data=counts,
138
+ acute_classification=initial_classes,
139
+ classes=my_classes,
140
+ pval=0.05,
141
+ cutoff_corr=0.5,
142
+ cutoff_corr_genes=0.8,
143
+ n_cpus=4
144
+ )
145
+
146
+ # 4. Run the semi-supervised relabeling pipeline using the selected signature
147
+ results = catrans.run_catrans(
148
+ raw_counts=counts,
149
+ metadata=metadata,
150
+ acute_classification=initial_classes,
151
+ classes=my_classes,
152
+ model=RandomForestClassifier(random_state=42),
153
+ model_threshold=0.75,
154
+ signature_genes=signature,
155
+ n_cpus=4
156
+ )
157
+
158
+ print(results.final_classification)
159
+ ```
160
+
161
+ #### Scenario 2: Predefined/Custom Gene Signature (Direct Stratification)
162
+ If you already have a target gene signature (e.g., from literature or a previous experiment), you can bypass the feature selection step entirely and run the stratification pipeline directly.
163
+
164
+ ```python
165
+ import pandas as pd
166
+ from sklearn.svm import SVC
167
+ import catrans
168
+
169
+ counts = pd.read_csv("data/raw_counts.tsv", sep="\t", index_col=0)
170
+ metadata = pd.read_csv("data/metadata.tsv", sep="\t", index_col=0)
171
+ initial_classes = pd.read_csv("data/initial_classes.tsv", sep="\t", index_col=0)
172
+
173
+ # Custom predefined signature from literature
174
+ custom_signature = ["ENSG00000034693.15", "ENSG00000101188.5", "ENSG00000104870.13"]
175
+
176
+ # Run the CATranS pipeline directly with the custom signature
177
+ results = catrans.run_catrans(
178
+ raw_counts=counts,
179
+ metadata=metadata,
180
+ acute_classification=initial_classes,
181
+ model=SVC(probability=True, random_state=42),
182
+ model_threshold=0.8,
183
+ signature_genes=custom_signature,
184
+ n_cpus=4
185
+ )
186
+
187
+ print(f"Completed in {results.number_of_iterations} iterations.")
188
+ ```
189
+
190
+ #### Scenario 3: Implicit Feature Selection (Defaulting Signature Genes)
191
+ If you do not specify a list of `signature_genes`, `run_catrans` will automatically execute `correlation_based_feature_selection` under the hood using default parameters.
192
+
193
+ ```python
194
+ import pandas as pd
195
+ from sklearn.ensemble import RandomForestClassifier
196
+ import catrans
197
+
198
+ counts = pd.read_csv("data/raw_counts.tsv", sep="\t", index_col=0)
199
+ metadata = pd.read_csv("data/metadata.tsv", sep="\t", index_col=0)
200
+ initial_classes = pd.read_csv("data/initial_classes.tsv", sep="\t", index_col=0)
201
+
202
+ # Run CATranS (it will automatically perform feature selection internally)
203
+ results = catrans.run_catrans(
204
+ raw_counts=counts,
205
+ metadata=metadata,
206
+ acute_classification=initial_classes,
207
+ model=RandomForestClassifier(random_state=42),
208
+ model_threshold=0.75,
209
+ n_cpus=4
210
+ )
211
+ ```
212
+
213
+ #### Scenario 4: Default Thresholds & Core Settings
214
+ You can omit optional arguments like `model_threshold` or `classes` if you wish to use the defaults (`model_threshold=0.8`, `classes` defaulting to `"Dead"`/`"Alive"`).
215
+
216
+ ```python
217
+ import pandas as pd
218
+ from sklearn.ensemble import RandomForestClassifier
219
+ import catrans
220
+
221
+ counts = pd.read_csv("data/raw_counts.tsv", sep="\t", index_col=0)
222
+ metadata = pd.read_csv("data/metadata.tsv", sep="\t", index_col=0)
223
+ initial_classes = pd.read_csv("data/initial_classes.tsv", sep="\t", index_col=0)
224
+
225
+ # Minimal parameters
226
+ results = catrans.run_catrans(
227
+ raw_counts=counts,
228
+ metadata=metadata,
229
+ acute_classification=initial_classes,
230
+ model=RandomForestClassifier(random_state=42)
231
+ )
232
+ ```
233
+
234
+ #### Scenario 5: Running with Batch Correction
235
+ To normalize and batch-correct raw counts concurrently, specify the name of the batch column in your metadata dataframe:
236
+
237
+ ```python
238
+ results = catrans.run_catrans(
239
+ raw_counts=counts,
240
+ metadata=metadata,
241
+ acute_classification=initial_classes,
242
+ model=RandomForestClassifier(random_state=42),
243
+ batch_col="batch" # ComBat-seq batch effect correction column
244
+ )
245
+ ```
246
+
247
+ ---
248
+
249
+ ## Testing & Quality Assurance
250
+
251
+ CATranS utilizes `pytest` for automated test suites, `ruff` for code style consistency, and `mypy` for strict type checking.
252
+
253
+ ```bash
254
+ # Run tests
255
+ uv run pytest
256
+
257
+ # Check code format and style
258
+ uv run ruff check .
259
+
260
+ # Perform static type checks
261
+ uv run mypy src/catrans
262
+ ```
263
+
264
+ ---
265
+
266
+ ## License
267
+
268
+ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
@@ -0,0 +1,241 @@
1
+ # CATranS: Clinical Acute Transcriptomic Stratification
2
+
3
+ **CATranS** is a robust bioinformatics and machine learning pipeline written in Python designed to stratify acute clinical cohorts using transcriptomic count data.
4
+
5
+ Through an iterative, semi-supervised learning approach, CATranS combines data normalization, batch correction, correlation-based feature selection, and class prediction to refine classifications of patient cohorts (e.g., separating acute from non-acute states, or predicting survival outcomes).
6
+
7
+ ---
8
+
9
+ ## Key Features
10
+
11
+ - **Iterative Semi-Supervised Relabeling**: Safely expands training cohorts by predicting clinical labels on unclassified/unlabeled samples using high-confidence thresholds.
12
+ - **Generalized Custom Classes**: Supports user-defined positive and negative class labeling (e.g., `Survivor`/`NonSurvivor`, `Mild`/`Severe`, `Responders`/`NonResponders`) with robust Categorical ordering to fix Wald contrast directions in DESeq2.
13
+ - **Batch Correction**: Integrated with `inmoose` for ComBat-seq count batch effect correction.
14
+ - **DESeq2-style Normalization**: Leverages the high-performance `pydeseq2` implementation for median-of-ratios normalization.
15
+ - **Correlation-Based Feature Learning**: Custom graph-theory based gene selection utilizing `igraph`. Filters out highly redundant co-expressed genes and selects optimal representative biomarkers correlating with clinical outcomes.
16
+ - **Flexible Estimator Integration**: Compatible with any Scikit-Learn classifier exposing a `predict_proba` method.
17
+
18
+ ---
19
+
20
+ ## Workflow Overview
21
+
22
+ ```mermaid
23
+ graph TD
24
+ A[Raw Count Matrix & Metadata] --> B[Data Normalization & Optional ComBat-seq Batch Correction]
25
+ B --> C[Feature Selection: Spearman Correlation with Labels]
26
+ C --> D[Graph Construction: Pearson Gene-Gene Network]
27
+ D --> E[Redundant Feature Compression: Connected Components Vertex Selection]
28
+ E --> F[Iterative Semi-Supervised Model Training]
29
+ F --> G[Fit Classifier & Predict Unlabeled Samples]
30
+ G --> H{Meets Threshold?}
31
+ H -- Yes --> I[Relabel Samples & Run DESeq2 Differential Expression Analysis]
32
+ I --> J{Are there new DEGs?}
33
+ J -- Yes --> F
34
+ J -- No --> K[Final Output Classifications & Iteration History]
35
+ H -- No --> K
36
+ ```
37
+
38
+ ---
39
+
40
+ ## Installation
41
+
42
+ We recommend using [uv](https://github.com/astral-sh/uv) or `pip` for rapid virtual environment setup and dependency management.
43
+
44
+ ```bash
45
+ # Clone the repository
46
+ git clone https://github.com/ruben-canas-ivi/CATranS.git
47
+ cd CATranS
48
+
49
+ # Install dependencies and the package using uv
50
+ uv sync
51
+ ```
52
+
53
+ ### Dependencies
54
+ - Python `>=3.11`
55
+ - `numpy>=2.3.0`
56
+ - `pandas>=2.3.3`
57
+ - `scipy>=1.14.0`
58
+ - `scikit-learn>=1.8.0`
59
+ - `pydeseq2>=0.5.4`
60
+ - `igraph>=1.0.0`
61
+ - `inmoose>=0.9.1`
62
+
63
+ ---
64
+
65
+ ## API Reference & Usage Scenarios
66
+
67
+ ### Core Classes & Functions
68
+
69
+ #### 1. `CatransClasses`
70
+ Defines the names of the binary classes.
71
+ - `positive` (default `"Dead"`): The target/case class.
72
+ - `negative` (default `"Alive"`): The reference/control class.
73
+
74
+ #### 2. `correlation_based_feature_selection`
75
+ Identifies representative biomarker genes by correlating expression levels with labels, building a gene-gene correlation network, and selecting one representative gene per connected component.
76
+
77
+ #### 3. `run_catrans`
78
+ Runs the iterative semi-supervised relabeling pipeline.
79
+ - `raw_counts` (pd.DataFrame): Genes (rows) by Samples (columns).
80
+ - `metadata` (pd.DataFrame): Samples (rows) with metadata.
81
+ - `acute_classification` (pd.DataFrame): Samples (rows) with initially known labels under the column `"class"` (unlabeled samples should be `NaN`).
82
+ - `model`: Any Scikit-Learn compatible classifier (e.g. `RandomForestClassifier`, `SVC(probability=True)`).
83
+ - `classes` (CatransClasses, Optional): Custom positive/negative class names.
84
+ - `batch_col` (str, Optional): Metadata column to use for ComBat-seq batch correction.
85
+ - `model_threshold` (float, default `0.8`): Confidence threshold to assign a label.
86
+ - `signature_genes` (list[str], Optional): Genes to use for training the model. If `None`, `correlation_based_feature_selection` runs automatically.
87
+
88
+ ---
89
+
90
+ ### Usage Scenarios
91
+
92
+ #### Scenario 1: Normal Workflow (Two-step Feature Selection + Stratification)
93
+ This is the recommended workflow where you first find a non-redundant gene signature, then pass it to the CATranS pipeline.
94
+
95
+ ```python
96
+ import pandas as pd
97
+ from sklearn.ensemble import RandomForestClassifier
98
+ import catrans
99
+
100
+ # 1. Load your transcriptomics and clinical datasets
101
+ counts = pd.read_csv("data/raw_counts.tsv", sep="\t", index_col=0)
102
+ metadata = pd.read_csv("data/metadata.tsv", sep="\t", index_col=0)
103
+ initial_classes = pd.read_csv("data/initial_classes.tsv", sep="\t", index_col=0)
104
+
105
+ # 2. Define custom labels: "Survivor" (negative) and "NonSurvivor" (positive)
106
+ my_classes = catrans.CatransClasses(positive="NonSurvivor", negative="Survivor")
107
+
108
+ # 3. Perform correlation-based feature selection to identify candidate biomarkers
109
+ signature = catrans.correlation_based_feature_selection(
110
+ data=counts,
111
+ acute_classification=initial_classes,
112
+ classes=my_classes,
113
+ pval=0.05,
114
+ cutoff_corr=0.5,
115
+ cutoff_corr_genes=0.8,
116
+ n_cpus=4
117
+ )
118
+
119
+ # 4. Run the semi-supervised relabeling pipeline using the selected signature
120
+ results = catrans.run_catrans(
121
+ raw_counts=counts,
122
+ metadata=metadata,
123
+ acute_classification=initial_classes,
124
+ classes=my_classes,
125
+ model=RandomForestClassifier(random_state=42),
126
+ model_threshold=0.75,
127
+ signature_genes=signature,
128
+ n_cpus=4
129
+ )
130
+
131
+ print(results.final_classification)
132
+ ```
133
+
134
+ #### Scenario 2: Predefined/Custom Gene Signature (Direct Stratification)
135
+ If you already have a target gene signature (e.g., from literature or a previous experiment), you can bypass the feature selection step entirely and run the stratification pipeline directly.
136
+
137
+ ```python
138
+ import pandas as pd
139
+ from sklearn.svm import SVC
140
+ import catrans
141
+
142
+ counts = pd.read_csv("data/raw_counts.tsv", sep="\t", index_col=0)
143
+ metadata = pd.read_csv("data/metadata.tsv", sep="\t", index_col=0)
144
+ initial_classes = pd.read_csv("data/initial_classes.tsv", sep="\t", index_col=0)
145
+
146
+ # Custom predefined signature from literature
147
+ custom_signature = ["ENSG00000034693.15", "ENSG00000101188.5", "ENSG00000104870.13"]
148
+
149
+ # Run the CATranS pipeline directly with the custom signature
150
+ results = catrans.run_catrans(
151
+ raw_counts=counts,
152
+ metadata=metadata,
153
+ acute_classification=initial_classes,
154
+ model=SVC(probability=True, random_state=42),
155
+ model_threshold=0.8,
156
+ signature_genes=custom_signature,
157
+ n_cpus=4
158
+ )
159
+
160
+ print(f"Completed in {results.number_of_iterations} iterations.")
161
+ ```
162
+
163
+ #### Scenario 3: Implicit Feature Selection (Defaulting Signature Genes)
164
+ If you do not specify a list of `signature_genes`, `run_catrans` will automatically execute `correlation_based_feature_selection` under the hood using default parameters.
165
+
166
+ ```python
167
+ import pandas as pd
168
+ from sklearn.ensemble import RandomForestClassifier
169
+ import catrans
170
+
171
+ counts = pd.read_csv("data/raw_counts.tsv", sep="\t", index_col=0)
172
+ metadata = pd.read_csv("data/metadata.tsv", sep="\t", index_col=0)
173
+ initial_classes = pd.read_csv("data/initial_classes.tsv", sep="\t", index_col=0)
174
+
175
+ # Run CATranS (it will automatically perform feature selection internally)
176
+ results = catrans.run_catrans(
177
+ raw_counts=counts,
178
+ metadata=metadata,
179
+ acute_classification=initial_classes,
180
+ model=RandomForestClassifier(random_state=42),
181
+ model_threshold=0.75,
182
+ n_cpus=4
183
+ )
184
+ ```
185
+
186
+ #### Scenario 4: Default Thresholds & Core Settings
187
+ You can omit optional arguments like `model_threshold` or `classes` if you wish to use the defaults (`model_threshold=0.8`, `classes` defaulting to `"Dead"`/`"Alive"`).
188
+
189
+ ```python
190
+ import pandas as pd
191
+ from sklearn.ensemble import RandomForestClassifier
192
+ import catrans
193
+
194
+ counts = pd.read_csv("data/raw_counts.tsv", sep="\t", index_col=0)
195
+ metadata = pd.read_csv("data/metadata.tsv", sep="\t", index_col=0)
196
+ initial_classes = pd.read_csv("data/initial_classes.tsv", sep="\t", index_col=0)
197
+
198
+ # Minimal parameters
199
+ results = catrans.run_catrans(
200
+ raw_counts=counts,
201
+ metadata=metadata,
202
+ acute_classification=initial_classes,
203
+ model=RandomForestClassifier(random_state=42)
204
+ )
205
+ ```
206
+
207
+ #### Scenario 5: Running with Batch Correction
208
+ To normalize and batch-correct raw counts concurrently, specify the name of the batch column in your metadata dataframe:
209
+
210
+ ```python
211
+ results = catrans.run_catrans(
212
+ raw_counts=counts,
213
+ metadata=metadata,
214
+ acute_classification=initial_classes,
215
+ model=RandomForestClassifier(random_state=42),
216
+ batch_col="batch" # ComBat-seq batch effect correction column
217
+ )
218
+ ```
219
+
220
+ ---
221
+
222
+ ## Testing & Quality Assurance
223
+
224
+ CATranS utilizes `pytest` for automated test suites, `ruff` for code style consistency, and `mypy` for strict type checking.
225
+
226
+ ```bash
227
+ # Run tests
228
+ uv run pytest
229
+
230
+ # Check code format and style
231
+ uv run ruff check .
232
+
233
+ # Perform static type checks
234
+ uv run mypy src/catrans
235
+ ```
236
+
237
+ ---
238
+
239
+ ## License
240
+
241
+ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
@@ -0,0 +1,67 @@
1
+ [project]
2
+ name = "CATranS"
3
+ version = "0.1.0"
4
+ description = "Clinical Acute Transcriptomic Stratification"
5
+ authors = [
6
+ { name = "Patricia Sebastián-León", email = "patricia.sebastian@ivirma.com" },
7
+ { name = "Antonio Parraga-Leo", email = "antonio.parraga@ivirma.com" },
8
+ { name = "Rubén Cañas-Cañas", email = "ruben.canas@ivirma.com" }
9
+ ]
10
+ readme = "README.md"
11
+ requires-python = ">=3.11"
12
+ keywords = ["bioinformatics", "machine-learning", "deseq2", "stratification", "genomics"]
13
+ classifiers = [
14
+ "Development Status :: 4 - Beta",
15
+ "Intended Audience :: Science/Research",
16
+ "Topic :: Scientific/Engineering :: Bio-Informatics",
17
+ "License :: OSI Approved :: MIT License",
18
+ "Programming Language :: Python :: 3",
19
+ "Programming Language :: Python :: 3.11",
20
+ "Programming Language :: Python :: 3.12",
21
+ "Operating System :: OS Independent",
22
+ ]
23
+
24
+ dependencies = [
25
+ "numpy>=2.3.0",
26
+ "pandas>=2.3.3",
27
+ "scikit-learn>=1.8.0",
28
+ "scipy>=1.17.1",
29
+ "pydeseq2>=0.5.4",
30
+ "igraph>=1.0.0",
31
+ "inmoose>=0.9.1",
32
+ ]
33
+
34
+ [project.urls]
35
+ Homepage = "https://github.com/ruben-canas-ivi/CATranS"
36
+ Issues = "https://github.com/ruben-canas-ivi/CATranS/issues"
37
+
38
+ [build-system]
39
+ requires = ["hatchling"]
40
+ build-backend = "hatchling.build"
41
+
42
+ [dependency-groups]
43
+ dev = [
44
+ "pytest>=8.0.0",
45
+ "ruff>=0.9.0",
46
+ "mypy>=1.14.0",
47
+ ]
48
+
49
+ [tool.ruff]
50
+ line-length = 120
51
+ target-version = "py311"
52
+
53
+ [tool.mypy]
54
+ python_version = "3.11"
55
+ strict = true
56
+
57
+ [[tool.mypy.overrides]]
58
+ module = [
59
+ "pydeseq2.*",
60
+ "igraph.*",
61
+ "inmoose.*",
62
+ "statsmodels.*",
63
+ "scipy.*",
64
+ "pandas.*"
65
+ ]
66
+ ignore_missing_imports = true
67
+
@@ -0,0 +1,14 @@
1
+ from catrans.core import (
2
+ correlation_based_feature_selection,
3
+ run_catrans,
4
+ _diffExpAnalysis # recordar quitar esto antes de subir el paquete, que esto es solo para validaciones #TODO
5
+ )
6
+ from catrans.data import CatransClasses, CatransResult
7
+
8
+ __all__ = [
9
+ 'correlation_based_feature_selection',
10
+ 'run_catrans',
11
+ '_diffExpAnalysis', # recordar quitar esto antes de subir el paquete, que esto es solo para validaciones #TODO
12
+ 'CatransClasses',
13
+ 'CatransResult',
14
+ ]
@@ -0,0 +1,38 @@
1
+ import logging
2
+ import sys
3
+
4
+ logger = logging.getLogger(__name__)
5
+ logger.propagate = False
6
+
7
+ class CustomFormatter(logging.Formatter):
8
+ info_format = "[%(asctime)s] | %(levelname)-8s | %(message)s"
9
+ debug_format = "[%(asctime)s] | %(levelname)-8s | STEP: %(funcName)s | %(message)s"
10
+
11
+ def format(self, record: logging.LogRecord) -> str:
12
+ orig_levelname = record.levelname
13
+ record.levelname = orig_levelname.center(8)
14
+
15
+ if record.levelno == logging.DEBUG:
16
+ self._style._fmt = self.debug_format
17
+ else:
18
+ self._style._fmt = self.info_format
19
+ return super().format(record)
20
+
21
+ def _get_logger() -> logging.Logger:
22
+ return logging.getLogger(name=__name__)
23
+
24
+ def _setup_internal_logger(verbose: bool) -> None:
25
+ # Si no hay handlers, creamos uno con el CustomFormatter
26
+ if not logger.handlers:
27
+ handler = logging.StreamHandler(sys.stdout)
28
+ handler.setFormatter(CustomFormatter(datefmt='%y-%m-%d %H:%M:%S'))
29
+ logger.addHandler(handler)
30
+
31
+ # Si el usuario activa verbose, bajamos a INFO
32
+ # Si tú desde fuera pusiste DEBUG, esto no lo sobrescribe (porque DEBUG < INFO)
33
+ if verbose:
34
+ # if logger.level > logging.INFO or logger.level == logging.NOTSET:
35
+ logger.setLevel(logging.INFO)
36
+ else:
37
+ if logger.level == logging.NOTSET or logger.level == logging.INFO:
38
+ logger.setLevel(logging.WARNING)