-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathutils.py
244 lines (208 loc) · 7.66 KB
/
utils.py
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
# utils.py is a good place to keep a bunch of helper functions
import api_calls
import os
from zipfile import ZipFile
import re
import datetime
import json
import os
def dir_path(string):
'''
Function checks if the path (string) is valid.
Parameters
----------
string : str
String correpsonding to the path.
Returns
-------
None.
'''
if os.path.isdir(string):
return string
else:
raise NotADirectoryError(string)
def read_export(file_descriptor):
"""
Function parses the XML-formatted export file list(passed by reference).
Parameters
----------
file_descriptor : file object
file descriptor of an open XML-formatted file.
Returns
-------
lines : list
List of strings where each element corresponds to a line from the export file.
"""
lines = []
line = file_descriptor.readline().decode('ascii')#we need to decode because we get binary
while line != "":
lines.append(line)
line = file_descriptor.readline().decode('ascii')
del lines[:3]#do not add any meaning
return lines
def unzip_read(src_path):
"""
Function unzips the file and read its lines into lines.
Parameters
----------
src_path : str
String path to the zip file.
Returns
-------
lines : list
List of strings where each element corresponds to a line from the export file.
"""
#The function works by itself.
with ZipFile(src_path, 'r') as zipObject: #Here, we need to unzip the file that was just created
listOfFileNames = zipObject.namelist()
for fileName in listOfFileNames:
if fileName.endswith('.bpm'):
# Extract a single file from zip
with zipObject.open(fileName, 'r') as fd:
return read_export(fd)
return None
def check_bran_logic(record_dict):
"""
Function that delete the fields that are not supposed to be included in the record_dict because their branching logic
is not satisfied. (Modfies record_dict by reference)
Parameters
----------
record_dict : dict
Dictonary with field_name's as keys and field_values as values.
Returns
-------
None.
"""
api = api_calls.API_calls()
branch_dict = api.get_branching_dep_to_indep()
to_delete = []
# print("Here dependnent to independent dict:", branch_dict)
for dependent_field in record_dict:
to_delete_flag = False
if(dependent_field in branch_dict):
for independent_field in branch_dict[dependent_field]:
#if the value that the indep fields takes satisfies the branching logic for the dependent, then do not delete
if(record_dict[independent_field] in branch_dict[dependent_field][independent_field]):
#do not delete
to_delete_flag = False
break#so to_delete = False is set last
else:
to_delete_flag = True
if(to_delete_flag):
to_delete.append(dependent_field)
#Delete the selected keys
for key in to_delete:
del record_dict[key]
def convert_to_numeric(record_dict):
"""
Function converts string choices in to numeric choices according to the REDCAP project specifications.
Parameters
----------
record_dict : dict
Dictonary with field_name's as keys and field_values as values.(modified by reference)
Returns
-------
None.
"""
api = api_calls.API_calls()
metadata = api.get_metadata()
name_choice_type = {field['field_name']:(field['select_choices_or_calculations'], field['field_type']) for field in metadata}#we need field_type for yes/no
regex_full = r"\d+, [A-z0-9\s/%\-]+"#might need to modify the regex
regex_num_choice = r"\d+,"
regex_label_choice = r", [A-z0-9\s/%\-]+"
for name in record_dict:
if(name in name_choice_type and name_choice_type[name][0] != "" and record_dict[name] != ""):#we assume the values are not converted yet
num_choice_lst = re.findall(regex_full, name_choice_type[name][0])#select_choices_or_calculations
num_choice_lst = [choice.strip() for choice in num_choice_lst]#get rid of white spaces
num_choices = [re.match(regex_num_choice, choice)[0].strip(" ,") for choice in num_choice_lst]
label_choices = [re.search(regex_label_choice, choice)[0].strip(", ") for choice in num_choice_lst]
for label_idx in range(len(label_choices)):
if(record_dict[name] == label_choices[label_idx]):
record_dict[name] = num_choices[label_idx]
break
elif(name in name_choice_type and name_choice_type[name][1] =="yesno" and record_dict[name] != ""):#special case of a multiple choice
record_dict[name] = (lambda choice_name: '1' if choice_name == "Yes" else '0')(record_dict[name])
def get_options(field):
"""
Given a field with types: radio or dropdwon function returns the options of the field.
Parameters
----------
field : dict
Dictonary taken from the metadata list of dictonaries.
Returns
-------
None.
"""
regex = r",\s[\w\s/%-]+"
options = [option.strip(", ") for option in re.findall(regex, field['select_choices_or_calculations'])]
return options
def get_date():
"""
Function today's date in the correct format.
Parameters
----------
None.
Returns
-------
None.
"""
today = datetime.date.today()
date = str(today.year) +"-"+ str(today.month) + "-" + str(today.day)
return date
def get_token(name_token):
"""
Funtion reads token.txt file and uses corresponding to name_token token.
Parameters
----------
name_token : str
Key corresponding to a token in token.txt file.
Returns
-------
token : str
Token corresponding to name_token.
"""
token_dict = {}
with open('token.txt','r') as token_file:
token_dict = json.load(token_file)
while True:
try:
return token_dict[name_token]
except KeyError:
print("The token for this user does not exist. Please Try again")
name_token = input()
def getAllImages(folderPath):
"""
Get all .png files in the folder located at folderPath.
Parameters
----------
folderPath : str
Path of the folder where the images are located.
Returns
-------
image_list : list
A list of paths to the images.
"""
image_list = []
for file in os.listdir(folderPath):
if file.endswith(".png"):
image_list.append(os.path.join(folderPath, file))
#make sure images are in the correct order
image_list.sort(key = lambda s: int(s[s.find("layer") + 5:s.find("layer") + 6]))
return image_list
def getNumLayers(field_names, images):
"""
Return number of layers.
Parameters
----------
field_names : List-like iterbale
An iterable that holds the names of the input fields.
images : list
A list of paths to the images.
Returns
-------
min_layers : int
Minimum number of layers that can be added to the experiment record.
"""
layerNums = list(map(lambda elem: int(elem[elem.index("layer_") + 6:]) ,filter(lambda elem: elem.find("im_layer") != -1 , field_names)))
min_layers = min(len(images), max(layerNums))
return min_layers