-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathforms.py
More file actions
364 lines (313 loc) · 11.7 KB
/
forms.py
File metadata and controls
364 lines (313 loc) · 11.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
"""Purpose of this script is to create general forms that are programmable with
particular input. Will impliment forms for subsetting the data and
visualisation options in a general way so can be used with any
SingleCellAnalysis dataset.
"""
import sys
from flask_wtf import FlaskForm
# from flask_wtf.file import FileField
from wtforms import SelectMultipleField, SelectField
import wtforms
def createSuperForm(elements, element_fields, element_values, validators=None):
""" Creates a general form; goal is to create a fully programmable form \
that essentially governs all the options the user will select.
Args:
elements (list<str>): Element names to be rendered on the page, in \
order of how they will appear on the page.
element_fields (list<str>): The names of the fields to be rendered. \
Each field is in same order as 'elements'. \
Currently supported are: \
'Title', 'SelectMultipleField', 'SelectField', \
'StringField', 'Text', 'List'.
element_values (list<object>): The information which will be put into \
the field. Changes depending on field: \
'Title' and 'Text': 'object' is a string
containing the title which will be added as \
a heading when rendered on the page.
'SelectMultipleField' and 'SelectField':
'object' is list of options to select from.
'StringField':
The example values to display within the \
fields text area. The 'placeholder' option.
'List':
A list of objects which will be attached \
to the form.
validators (list<FunctionHandles>): A list of functions which take the \
form as input, used to construct the form validator. \
Form validator constructed by calling these \
sequentially with form 'self' as input.
Args:
form (list<WTForm>): A WTForm which has attached as variable all the \
fields mentioned, so then when rendered as input to
'SuperDataDisplay.html' shows the form.
"""
class SuperForm(FlaskForm):
"""A base form on which all of the fields will be added."""
if type(validators) == type(None):
validators = [None] * len(elements)
# Add the information #
SuperForm.elements = elements
SuperForm.element_fields = element_fields
multiSelectLeft = True # Places multi-select field to left, alternatives
# if many multi-selects in row
for i, element in enumerate(elements):
fieldName = element_fields[i]
# Adding each element as the appropriate field to the form #
if fieldName == "SelectMultipleField":
setattr(
SuperForm,
element,
SelectMultipleField(element, choices=element_values[i]),
)
# The point of this number is to give an order for the attributes,
# so that odd numbers get rendered to right of page, even numbers
# left.
setattr(SuperForm, element + "_number", int(multiSelectLeft))
# inverts, so if left, goes right for the next multiSelectField
multiSelectLeft = multiSelectLeft == False
else:
multiSelectLeft = True # Reset the MultiSelectField position
if fieldName in ["Title", "List"]:
setattr(SuperForm, element, element_values[i])
elif fieldName == "SelectField":
setattr(
SuperForm,
element,
SelectField(
element, choices=element_values[i], validators=validators[i]
),
)
# elif fieldName == 'FileField':
# setattr(SuperForm, element, FileField(validators=validators[i]))
# setattr(SuperForm, element + '_placeholder', # Setting default
# element_values[i])
elif fieldName in [
"StringField",
"IntegerField",
"BooleanField",
"FileField",
"FloatField",
]:
FieldClass = getattr(wtforms, fieldName)
setattr(
SuperForm, element, FieldClass(element, validators=validators[i])
)
setattr(
SuperForm,
element + "_placeholder", # Setting default
element_values[i],
)
return SuperForm
def getPreprocessForm():
"""Gets the preprocessing form generated from the superform above.
Returns:
FlaskForm: With attributes that allow for inputs that are related to
pre-processing.
"""
elements = [
"Spot Quality Control Filtering", # Title
"Minimum genes per spot",
"Minimum counts per spot",
"Gene Quality Control Filtering", # Title
"Minimum spots per gene",
"Minimum counts per gene",
"Normalisation, Log-transform, & Scaling", # Title
"Normalize total",
"Log 1P",
"Scale",
]
element_fields = [
"Title",
"IntegerField",
"IntegerField",
"Title",
"IntegerField",
"IntegerField",
"Title",
"BooleanField",
"BooleanField",
"BooleanField",
]
element_values = ["", 200, 300, "", 3, 5, "", True, True, True]
return createSuperForm(elements, element_fields, element_values)
def getLRForm():
"""Gets the LR form generated from the superform above.
Returns:
FlaskForm: With attributes that allow for inputs that are \
related to LR analysis.
"""
elements = [
"Species",
"Spot neighbourhood (-1: smallest neighbourhood, 0: within-spot mode)",
"Minimum spots with LR scores",
"N random gene pairs (permutations)",
"CPUs",
]
element_fields = [
"SelectField",
"IntegerField",
"IntegerField",
"IntegerField",
"IntegerField",
]
element_values = [
[("Human", "Human"), ("Mouse", "Mouse")],
-1,
20,
100,
2,
]
return createSuperForm(elements, element_fields, element_values)
def getCCIForm(adata):
"""Gets the CCI form generated from the superform above.
Returns:
FlaskForm: With attributes that allow for inputs that are
related to CCI analysis.
"""
elements = [
"Cell information (only discrete labels available, unless mixture already in anndata.uns)",
"Minimum spots for LR to be considered",
"Spot mixture (only if the 'Cell Information' label selected available in anndata.uns)",
"Cell proportion cutoff (value above which cell is considered in spot if 'Spot mixture' selected)",
"Permutations (recommend atleast 1000)",
]
element_fields = [
"SelectField",
"IntegerField",
"BooleanField",
"FloatField",
"IntegerField",
]
if type(adata) == type(None):
fields = []
mix = False
else:
fields = [
key for key in adata.obs.keys() if type(adata.obs[key].values[0]) == str
]
mix = fields[0] in adata.uns.keys()
element_values = [fields, 20, mix, 0.2, 100]
return createSuperForm(elements, element_fields, element_values)
def getCCIForm_old():
"""Gets the CCI form generated from the superform above.
Returns:
FlaskForm: With attributes that allow for inputs that are related to
CCI analysis.
"""
elements = [
"* Cell Heterogeneity File",
"Neighbourhood distance (0 indicates within-spot mode)",
"** L-R pair input (e.g. L1_R1, L2_R2, ...)",
"Permutations (0 indicates no permutation testing)",
]
element_fields = ["FileField", "IntegerField", "StringField", "IntegerField"]
element_values = ["", 25, "", 0]
return createSuperForm(elements, element_fields, element_values)
def getClusterForm():
"""Gets the Cluster form generated using superform above.
Returns:
FlaskForm: With attributes that allow input related to clustering.
"""
elements = [
"PCA components",
"stSME normalisation",
"Cluster method",
"K",
"Resolution",
"Neighbours (for Louvain/Leiden)",
]
element_fields = [
"IntegerField",
"BooleanField",
"SelectField",
"IntegerField",
"FloatField",
"IntegerField",
]
element_values = [
50,
True,
[("KMeans", "KMeans"), ("Louvain", "Louvain"), ("Leiden", "Leiden")],
10,
1.0,
15,
]
return createSuperForm(elements, element_fields, element_values)
def getPSTSForm(trajectory, clusts, options):
"""Gets the psts form generated using superform above.
Args:
cluster_set (numpy.array<str>): The clusters which can be selected as
the root for psts analysis.
Returns:
FlaskForm: With attributes that allow input related to psts.
"""
elements = [
"Root cluster",
"Reverse",
"eps (max. dist. spot neighbourhood)",
"Trajectory Select",
"Select distance-based method",
]
element_fields = [
"SelectField",
"BooleanField",
"IntegerField",
"SelectField",
"SelectField",
]
element_values = [clusts, False, 50, trajectory, options]
return createSuperForm(elements, element_fields, element_values)
def getDEAForm(list_labels, methods):
"""Gets the psts form generated using superform above.
Args:
cluster_set (numpy.array<str>): The clusters which can be selected as
the root for psts analysis.
Returns:
FlaskForm: With attributes that allow input related to psts.
"""
elements = ["Use label", "Use method"]
element_fields = [
"SelectField",
"SelectField",
]
element_values = [list_labels, methods]
return createSuperForm(elements, element_fields, element_values)
######################## Junk Code #############################################
# def getCCIForm(step_log):
# """ Gets the CCI form generated from the superform above.
#
# Returns:
# FlaskForm: With attributes that allow for inputs that are related to
# CCI analysis.
# """
# elements, element_fields, element_values = [], [], []
# if type(step_log['cci_het']) == type(None):
# # Analysis type form version #
# analysis_elements = ['Cell Heterogeneity Information', # Title
# 'cci_het',
# 'Permutation Testing', # Title
# 'cci_perm']
# analysis_fields = ['Title', 'SelectField', 'Title', 'SelectField']
# label_transfer_options = ['Upload Cell Label Transfer',
# 'No Cell Label Transfer']
# permutation_options = ['With permutation testing',
# 'Without permutation testing']
# analysis_values = ['', label_transfer_options, '', permutation_options]
# elements += analysis_elements
# element_fields += analysis_fields
# element_values += analysis_values
#
# else:
# # Core elements regardless of CCI mode #
# elements += ['Neighbourhood distance',
# 'L-R pair input (e.g. L1_R1, L2_R2, ...)']
# element_fields += ['IntegerField', 'StringField']
# element_values += [5, '']
#
# if step_log['cci_perm']:
# # Including cell heterogeneity information #
# elements += ['Permutations']
# element_fields += ['IntegerField']
# element_values += [200]
#
# return createSuperForm(elements, element_fields, element_values, None)