11# !/usr/bin/python3
22
3- import os
4- import sys
53# from rpy2.robjects.packages import importr
64# from rpy2.robjects import pandas2ri
75import argparse
8- import numpy as np
6+ import os
7+ import sys
98from pathlib import Path
109
10+ import numpy as np
1111import rpy2_api
12- from project import Configs
12+ from arguments import (
13+ batch_ratio_arg ,
14+ cluster_algorithm_arg ,
15+ context_names_arg ,
16+ filtering_technique_arg ,
17+ label_arg ,
18+ min_count_arg ,
19+ min_dist_arg ,
20+ num_neighbors_batch_arg ,
21+ num_neighbors_context_arg ,
22+ num_neighbors_replicate_arg ,
23+ quantile_arg ,
24+ random_seed_arg ,
25+ replicate_ratio_arg ,
26+ )
1327from como_utilities import stringlist_to_list
28+ from project import Configs
1429
1530# enable r to py conversion
1631# pandas2ri.activate()
@@ -36,133 +51,30 @@ def main() -> None:
3651 """
3752 Cluster RNA-seq Data
3853 """
39-
54+
4055 parser = argparse .ArgumentParser (
4156 prog = "cluster_rnaseq.py" ,
4257 description = "Cluster RNA-seq Data using Multiple Correspondence Analysis or UMAP. Clusters at the replicate, "
43- "batch/study, and context levels." ,
58+ "batch/study, and context levels." ,
4459 epilog = "For additional help, please post questions/issues in the MADRID GitHub repo at "
45- "https://github.com/HelikarLab/MADRID or email babessell@gmail.com" ,
46- )
47- parser .add_argument (
48- "-n" ,
49- "--context-names" ,
50- type = str ,
51- required = True ,
52- dest = "context_names" ,
53- help = """Tissue/cell name of models to generate. If making multiple models in a batch, then
54- use the format: \" ['context1', 'context2', ... etc]\" . Note the outer double-quotes and the
55- inner single-quotes are required to be interpreted. This a string, not a python list""" ,
56- )
57- parser .add_argument (
58- "-t" ,
59- "--filt-technique" ,
60- type = str ,
61- required = True ,
62- dest = "technique" ,
63- help = "'zfpkm', 'quantile', or 'cpm'" ,
64- )
65- parser .add_argument (
66- "-a" ,
67- "--cluster-algorithm" ,
68- type = str ,
69- required = False ,
70- default = "umap" ,
71- dest = "clust_algo" ,
72- help = """Clustering algorithm to use. 'mca' or 'umap'.""" ,
73- )
74- parser .add_argument (
75- "-l" ,
76- "--label" ,
77- type = str ,
78- required = False ,
79- default = True ,
80- dest = "label" ,
81- help = """True to label replicate/batch/context names on the plots. May be ugly for large sets""" ,
82- )
83- parser .add_argument (
84- "-d" ,
85- "--min-dist" ,
86- type = float ,
87- required = False ,
88- default = 0.01 ,
89- dest = "min_dist" ,
90- help = """Minimum distance for UMAP clustering. Must be between 0 and 1""" ,
91- )
92- parser .add_argument (
93- "-r" ,
94- "--replicate-ratio" ,
95- type = str ,
96- required = False ,
97- default = 0.9 ,
98- dest = "rep_ratio" ,
99- help = """Ratio of genes active in replicates for a batch/study to be active""" ,
100- )
101- parser .add_argument (
102- "-b" ,
103- "--batch-ratio" ,
104- type = str or float ,
105- required = False ,
106- default = 0.9 ,
107- dest = "batch_ratio" ,
108- help = """Ratio of genes active in a batch/study to be active in the context""" ,
109- )
110- parser .add_argument (
111- "-nr" ,
112- "--n-neighbors-rep" ,
113- type = str or float ,
114- required = False ,
115- default = "default" ,
116- dest = "n_neigh_rep" ,
117- help = """N nearest neighbors for replicate clustering, 'default' is total number of replicates""" ,
118- )
119- parser .add_argument (
120- "-nb" ,
121- "--n-neighbors-batch" ,
122- type = str or float ,
123- required = False ,
124- default = "default" ,
125- dest = "n_neigh_batch" ,
126- help = """N nearest neighbors for batch clustering, 'default' is total number of batches""" ,
127- )
128- parser .add_argument (
129- "-nc" ,
130- "--n-neighbors-context" ,
131- type = str or float ,
132- required = False ,
133- default = "default" ,
134- dest = "n_neigh_cont" ,
135- help = """N nearest neighbors for context clustering, 'default' is total number of contexts""" ,
136- )
137- parser .add_argument (
138- "-c" ,
139- "--min-count" ,
140- type = str or int ,
141- required = False ,
142- default = "default" ,
143- dest = "min_count" ,
144- help = """Ratio of active genes in a batch/study to be active in the context""" ,
145- )
146- parser .add_argument (
147- "-q" ,
148- "--quantile" ,
149- type = str or int ,
150- required = False ,
151- default = 0.5 ,
152- dest = "quantile" ,
153- help = """Ratio of active genes in a batch/study to be active in the context""" ,
154- )
155- parser .add_argument (
156- "-s" ,
157- "--seed" ,
158- type = int ,
159- required = False ,
160- default = - 1 ,
161- dest = "seed" ,
162- help = """Random seed for clustering algorithm initialization""" ,
60+ "https://github.com/HelikarLab/MADRID or email babessell@gmail.com" ,
16361 )
62+
63+ parser .add_argument (** context_names_arg )
64+ parser .add_argument (** filtering_technique_arg )
65+ parser .add_argument (** cluster_algorithm_arg )
66+ parser .add_argument (** label_arg )
67+ parser .add_argument (** min_dist_arg )
68+ parser .add_argument (** replicate_ratio_arg )
69+ parser .add_argument (** batch_ratio_arg )
70+ parser .add_argument (** num_neighbors_replicate_arg )
71+ parser .add_argument (** num_neighbors_batch_arg )
72+ parser .add_argument (** num_neighbors_context_arg )
73+ parser .add_argument (** min_count_arg )
74+ parser .add_argument (** quantile_arg )
75+ parser .add_argument (** random_seed_arg )
16476 args = parser .parse_args ()
165-
77+
16678 wd = os .path .join (configs .data_dir , "results" )
16779 context_names = stringlist_to_list (args .context_names )
16880 technique = args .technique .lower ()
@@ -176,57 +88,63 @@ def main() -> None:
17688 n_neigh_rep = args .n_neigh_rep
17789 n_neigh_batch = args .n_neigh_batch
17890 n_neigh_cont = args .n_neigh_cont
179-
91+
18092 # Set a random seed if none provided
18193 if int (args .seed ) == - 1 :
18294 seed = np .random .randint (0 , 100000 )
18395 else :
18496 seed = args .seed
185-
97+
18698 if isinstance (min_count , str ) and min_count .lower () == "default" :
18799 try :
188100 min_count = int (min_count )
189101 except ValueError :
190102 raise ValueError ("--min-count must be either 'default' or an integer > 0" )
191103 if not isinstance (min_count , str ) and min_count < 0 :
192104 raise ValueError ("--min-count must be either 'default' or an integer > 0" )
193-
105+
194106 if isinstance (quantile , str ) and not quantile .lower () == "default" :
195107 try :
196108 quantile = int (quantile )
197109 except ValueError :
198- raise ValueError ("--quantile must be either 'default' or an integer between 0 and 100" )
110+ raise ValueError (
111+ "--quantile must be either 'default' or an integer between 0 and 100"
112+ )
199113 if not isinstance (quantile , str ) and 0 > quantile > 100 :
200- raise ValueError ("--quantile must be either 'default' or an integer between 0 and 100" )
201-
114+ raise ValueError (
115+ "--quantile must be either 'default' or an integer between 0 and 100"
116+ )
117+
202118 if isinstance (rep_ratio , str ) and not rep_ratio .lower () == "default" :
203119 try :
204120 rep_ratio = float (rep_ratio )
205121 except ValueError :
206122 raise ValueError ("--rep-ratio must be 'default' or a float between 0 and 1" )
207123 if not isinstance (rep_ratio , str ) and 0 > rep_ratio > 1.0 :
208124 raise ValueError ("--rep-ratio must be 'default' or a float between 0 and 1" )
209-
125+
210126 if isinstance (batch_ratio , str ) and not batch_ratio .lower () == "default" :
211127 try :
212128 batch_ratio = float (batch_ratio )
213129 except ValueError :
214- raise ValueError ("--batch-ratio must be 'default' or a float between 0 and 1" )
130+ raise ValueError (
131+ "--batch-ratio must be 'default' or a float between 0 and 1"
132+ )
215133 if not isinstance (batch_ratio , str ) and 0 > batch_ratio > 1.0 :
216134 raise ValueError ("--batch-ratio must be 'default' or a float between 0 and 1" )
217-
135+
218136 if technique .lower () not in ["quantile" , "tpm" , "cpm" , "zfpkm" ]:
219137 raise ValueError ("--technique must be either 'quantile', 'tpm', 'cpm', 'zfpkm'" )
220-
138+
221139 if technique .lower () == "tpm" :
222140 technique = "quantile"
223-
141+
224142 if clust_algo .lower () not in ["mca" , "umap" ]:
225143 raise ValueError ("--clust_algo must be either 'mca', 'umap'" )
226-
144+
227145 if not isinstance (min_dist , str ) and 0 > min_dist > 1.0 :
228146 raise ValueError ("--min_dist must be a float between 0 and 1" )
229-
147+
230148 if isinstance (n_neigh_rep , str ) and not n_neigh_rep .lower () == "default" :
231149 try :
232150 n_neigh_rep = int (n_neigh_rep )
@@ -240,7 +158,7 @@ def main() -> None:
240158 f"--n_neigh_rep must be either 'default' or an integer greater than 1 and less than or equal to "
241159 f"the total number of replicates being clustered across all contexts."
242160 )
243-
161+
244162 if isinstance (n_neigh_batch , str ) and not n_neigh_batch .lower () == "default" :
245163 try :
246164 n_neigh_batch = int (n_neigh_batch )
@@ -254,7 +172,7 @@ def main() -> None:
254172 f"--n_neigh_batch must be either 'default' or an integer greater than 1 and less than or equal to "
255173 f"the total number of batches being clustered across all contexts."
256174 )
257-
175+
258176 if isinstance (n_neigh_cont , str ) and not n_neigh_cont .lower () == "default" :
259177 try :
260178 n_neigh_cont = int (n_neigh_cont )
@@ -268,7 +186,7 @@ def main() -> None:
268186 f"--n_neigh_context must be either 'default' or an integer greater than 1 and less than or equal to "
269187 f"the total number of contexts being clustered."
270188 )
271-
189+
272190 cluster_samples = rpy2_api .Rpy2 (
273191 r_file_path = r_file_path ,
274192 wd = wd ,
0 commit comments