fred-metadata 0.0.15__py3-none-any.whl

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.
Files changed (44) hide show
  1. fred/__init__.py +0 -0
  2. fred/config/config.yaml +11 -0
  3. fred/config/mamplan_config.yaml +10 -0
  4. fred/images/chicken.png +0 -0
  5. fred/images/human.png +0 -0
  6. fred/images/medaka.png +0 -0
  7. fred/images/mouse.png +0 -0
  8. fred/images/pig.png +0 -0
  9. fred/images/rat.png +0 -0
  10. fred/images/zebrafish.png +0 -0
  11. fred/metaTools.py +399 -0
  12. fred/src/__init__.py +0 -0
  13. fred/src/autogenerate.py +324 -0
  14. fred/src/edit_file.py +368 -0
  15. fred/src/file_reading.py +175 -0
  16. fred/src/find_metafiles.py +553 -0
  17. fred/src/generate.py +356 -0
  18. fred/src/git_whitelists.py +48 -0
  19. fred/src/heatmap/create_heatmap.py +301 -0
  20. fred/src/heatmap/dash_utils.py +461 -0
  21. fred/src/heatmap/heatmap_dash.py +205 -0
  22. fred/src/input_functions.py +816 -0
  23. fred/src/utils.py +1290 -0
  24. fred/src/validate_yaml.py +601 -0
  25. fred/src/web_interface/__init__.py +0 -0
  26. fred/src/web_interface/editing.py +350 -0
  27. fred/src/web_interface/factors_and_conditions.py +829 -0
  28. fred/src/web_interface/file_io.py +43 -0
  29. fred/src/web_interface/html_output.py +198 -0
  30. fred/src/web_interface/searching.py +288 -0
  31. fred/src/web_interface/validation.py +264 -0
  32. fred/src/web_interface/whitelist_parsing.py +184 -0
  33. fred/src/web_interface/wi_object_to_yaml.py +604 -0
  34. fred/src/web_interface/wi_utils.py +274 -0
  35. fred/src/web_interface/yaml_to_wi_object.py +264 -0
  36. fred/src/wi_functions.py +281 -0
  37. fred/structure/keys.yaml +1061 -0
  38. fred/structure/mamplan_keys.yaml +409 -0
  39. fred_metadata-0.0.15.dist-info/METADATA +20 -0
  40. fred_metadata-0.0.15.dist-info/RECORD +44 -0
  41. fred_metadata-0.0.15.dist-info/WHEEL +5 -0
  42. fred_metadata-0.0.15.dist-info/entry_points.txt +2 -0
  43. fred_metadata-0.0.15.dist-info/licenses/LICENSE +21 -0
  44. fred_metadata-0.0.15.dist-info/top_level.txt +1 -0
fred/__init__.py ADDED
File without changes
@@ -0,0 +1,11 @@
1
+ structure: fred # fred, mampok or path to yaml file
2
+ whitelist_repository: https://gitlab.gwdg.de/loosolab/software/metadata_whitelists.git
3
+ private_access:
4
+ name: # github: username for access token; gitlab: oauth2 for project access token
5
+ token: # personal (github) or project (gitlab) access token
6
+ branch: v1.2.*
7
+ whitelist_path: fred
8
+ update_whitelists: True
9
+ output_path: .
10
+ filename: '_metadata' # example_metadata.yaml
11
+ email: bcu.support@mpi-bn.mpg.de
@@ -0,0 +1,10 @@
1
+ structure: mampok
2
+ whitelist_repository: https://gitlab.gwdg.de/loosolab/software/metadata_whitelists.git
3
+ private_access:
4
+ name: # github: username for access token; gitlab: oauth2 for project access token
5
+ token: # personal (github) or project (gitlab) access token
6
+ branch: v1.2.*
7
+ whitelist_path: fred
8
+ update_whitelists: True
9
+ output_path: .
10
+ filename: 'mamplan' # example_metadata.yaml
Binary file
fred/images/human.png ADDED
Binary file
fred/images/medaka.png ADDED
Binary file
fred/images/mouse.png ADDED
Binary file
fred/images/pig.png ADDED
Binary file
fred/images/rat.png ADDED
Binary file
Binary file
fred/metaTools.py ADDED
@@ -0,0 +1,399 @@
1
+ import argparse
2
+ import copy
3
+ import pathlib
4
+ import sys
5
+ import os
6
+ import time
7
+
8
+ sys.path.append(os.path.dirname(__file__))
9
+ from src.generate import Generate
10
+ from src import find_metafiles
11
+ from src import validate_yaml
12
+ from src import file_reading
13
+ from src import utils
14
+ from src import git_whitelists
15
+ from src.heatmap import create_heatmap
16
+
17
+
18
+
19
+ class FRED:
20
+
21
+ def __init__(self, config):
22
+ self.whitelist_repo, self.whitelist_branch, self.whitelist_path, \
23
+ self.username, self.password, structure, self.update_whitelists, \
24
+ self.output_path, self.filename, self.email = utils.parse_config(config)
25
+ if self.whitelist_path == 'fred':
26
+ self.whitelist_path = os.path.join(os.path.dirname(__file__), 'FRED_whitelists')
27
+ else:
28
+ self.whitelist_path = os.path.join(self.whitelist_path, 'FRED_whitelists')
29
+ self.fetch_whitelists()
30
+ self.structure = utils.read_in_yaml(structure)
31
+
32
+ def fetch_whitelists(self):
33
+ git_whitelists.get_whitelists(self.whitelist_path, self.whitelist_repo, self.whitelist_branch, self.update_whitelists)
34
+
35
+ def find(self, search_path, search, output, output_filename, skip_validation):
36
+ result = find_metafiles.find_projects(self.structure, search_path,
37
+ search, True, skip_validation)
38
+ if output == 'print':
39
+ if len(result) > 0:
40
+
41
+ # print summary of matching files
42
+ print(find_metafiles.print_summary(result, output))
43
+
44
+ else:
45
+
46
+ # print information that there are no matching files
47
+ print('No matches found')
48
+ elif output == 'json':
49
+ if not output_filename:
50
+ output_filename = 'search_result'
51
+ json_filename = f'{output_filename}.json'
52
+ utils.save_as_json({'data': find_metafiles.print_summary(result, output)}, json_filename)
53
+ print(
54
+ f'The report was saved to the file \'{json_filename}\'.')
55
+
56
+ def generate(self, path, project_id, mandatory_only):
57
+ gen = Generate(path, project_id, mandatory_only, self.filename, self.structure, self.email)
58
+ gen.generate()
59
+
60
+ def validate(self, logical_validation, path, output, output_filename, save_empty=False):
61
+ validation_reports = {'all_files': 1,
62
+ 'corrupt_files': {'count': 0, 'report': []},
63
+ 'error_count': 0, 'warning_count': 0}
64
+ if os.path.isdir(path):
65
+ metafiles, validation_reports = file_reading.iterate_dir_metafiles(
66
+ self.structure, [path], filename=self.filename,
67
+ logical_validation=logical_validation, yaml=copy.deepcopy(self.structure),
68
+ whitelist_path=self.whitelist_path)
69
+ else:
70
+ metafile = utils.read_in_yaml(path)
71
+ file_reports = {'file': metafile, 'error': None, 'warning': None}
72
+ valid, missing_mandatory_keys, invalid_keys, \
73
+ invalid_entries, invalid_values, logical_warn = validate_yaml.validate_file(
74
+ metafile, self.structure, self.filename,
75
+ logical_validation=logical_validation, yaml=copy.deepcopy(self.structure),
76
+ whitelist_path=self.whitelist_path)
77
+ metafile['path'] = path
78
+ if not valid:
79
+ validation_reports['corrupt_files']['count'] = 1
80
+ validation_reports['error_count'] += (
81
+ len(missing_mandatory_keys) + len(
82
+ invalid_keys) + len(invalid_entries) + len(
83
+ invalid_values))
84
+ file_reports['error'] = (
85
+ missing_mandatory_keys, invalid_keys, invalid_entries,
86
+ invalid_values)
87
+ if len(logical_warn) > 0:
88
+ validation_reports['corrupt_files']['count'] = 1
89
+ validation_reports['warning_count'] += len(logical_warn)
90
+ file_reports['warning'] = logical_warn
91
+ validation_reports['corrupt_files']['report'].append(file_reports)
92
+
93
+ print(f'{validation_reports["all_files"]} files were validated.')
94
+ print(
95
+ f'Found {validation_reports["error_count"]} errors and {validation_reports["warning_count"]} warnings in {validation_reports["corrupt_files"]["count"]} of those files.')
96
+
97
+ if validation_reports['corrupt_files']['count'] > 0 or save_empty is True:
98
+
99
+ res = None
100
+ if output is not None:
101
+ if output == 'print':
102
+ res = ['print report']
103
+ elif output == 'txt':
104
+ res = ['save report to txt file']
105
+ elif output == 'json':
106
+ res = ['save report to json file']
107
+ elif output == 'yaml':
108
+ res = ['save report to yaml file']
109
+ else:
110
+ options = ['print report', 'save report to txt file',
111
+ 'save report to json file',
112
+ 'save report to yaml file']
113
+ print(
114
+ f'Do you want to see a report? Choose from the following options (1,...,{len(options)} or n)')
115
+ ask = Generate('', '', False, self.filename, self.structure, self.email)
116
+ ask.print_option_list(options, '')
117
+ res = ask.parse_input_list(options, True)
118
+
119
+ try:
120
+ output_report = {
121
+ 'report': copy.deepcopy(validation_reports)['corrupt_files']['report']}
122
+ except KeyError:
123
+ output_report = {'report': []}
124
+ for elem in output_report['report']:
125
+ id = list(utils.find_keys(elem['file'], 'id'))
126
+ if len(id) > 0:
127
+ elem['id'] = id[0]
128
+ else:
129
+ elem['id'] = 'missing'
130
+ elem['path'] = elem['file']['path']
131
+ errors = list(elem['error']) if 'error' in elem and elem[
132
+ 'error'] is not None else []
133
+ elem['error'] = {}
134
+ elem.pop('file')
135
+ for i in range(len(errors)):
136
+
137
+ if len(errors[i]) > 0:
138
+ if i == 0:
139
+ elem['error']['missing_mandatory_keys'] = errors[i]
140
+ elif i == 1:
141
+ elem['error']['invalid_keys'] = errors[i]
142
+ elif i == 2:
143
+ whitelist_values = []
144
+ for v in errors[i]:
145
+ key = ':'.join(v.split(':')[:-1])
146
+ entry = v.split(':')[-1]
147
+ whitelist_values.append(
148
+ entry + ' in ' + key + '\n')
149
+ elem['error']['invalid_entries'] = whitelist_values
150
+ elif i == 3:
151
+ value = []
152
+ for v in errors[i]:
153
+ value.append(f'{v[0]}: {v[1]} -> {v[2]}')
154
+ elem['error']['invalid_values'] = value
155
+
156
+ if 'warning' in elem:
157
+ if elem['warning'] is not None:
158
+ for i in range(len(elem['warning'])):
159
+ elem['warning'][
160
+ i] = f'{elem["warning"][i][0]}: {elem["warning"][i][1]}'
161
+ else:
162
+ elem.pop('warning')
163
+
164
+ if res is not None:
165
+ if output_filename is None:
166
+ timestamp = time.time()
167
+ output_filename = f'validation_report_{str(timestamp).split(".")[0]}'
168
+
169
+ rep = ''
170
+ for report in validation_reports['corrupt_files']['report']:
171
+ rep += f'{"".center(80, "_")}\n\n'
172
+ rep += validate_yaml.print_full_report(report['file'],
173
+ report['error'],
174
+ report['warning'])
175
+ rep += f'{"".center(80, "_")}\n\n'
176
+
177
+ if 'save report to txt file' in res:
178
+ txt_filename = f'{output_filename}.txt'
179
+ txt_f = open(txt_filename, 'w')
180
+ txt_f.write(rep)
181
+ print(
182
+ f'The report was saved to the file \'{txt_filename}\'.')
183
+ txt_f.close()
184
+
185
+ if 'save report to json file' in res:
186
+ json_filename = f'{output_filename}.json'
187
+ utils.save_as_json(output_report, json_filename)
188
+ print(
189
+ f'The report was saved to the file \'{json_filename}\'.')
190
+
191
+ if 'save report to yaml file' in res:
192
+ yaml_filename = f'{output_filename}.yaml'
193
+ utils.save_as_yaml(output_report, yaml_filename)
194
+ print(
195
+ f'The report was saved to the file \'{yaml_filename}\'.')
196
+
197
+ if 'print report' in res:
198
+ print(rep)
199
+
200
+ return validation_reports["error_count"], validation_reports["warning_count"]
201
+
202
+ #def edit(self, path, mandatory_only):
203
+ # try:
204
+ # size = os.get_terminal_size()
205
+ # size = size.columns
206
+ # except OSError:
207
+ # size = 80
208
+
209
+ # edit_file.edit_file(path, self.filename, mandatory_only, size)
210
+
211
+ def add_value(self, path, position, value, edit_existing):
212
+ files, errors = file_reading.iterate_dir_metafiles(self.structure,
213
+ [path],
214
+ self.filename, False,
215
+ return_false=True,
216
+ whitelist_path=
217
+ self.whitelist_path)
218
+ position = position.split(':')
219
+ # TODO: type
220
+ for file in files:
221
+ file = utils.add_value_at_pos(self.structure, file, position, value,
222
+ edit_existing)
223
+ save_path = file['path']
224
+ file.pop('path')
225
+ print(f'edited file {save_path}')
226
+ utils.save_as_yaml(file, save_path)
227
+
228
+ def find(args):
229
+ """
230
+ calls script find_metafiles to find matching files and print results
231
+ :param args:
232
+ path: a path of a folder that should be searched for metadata files
233
+ search: a string specifying search parameters linked via 'and', 'or'
234
+ and 'not'
235
+ """
236
+ finding = FRED(args.config)
237
+ finding.find(args.path, args.search, args.output, args.filename,
238
+ args.skip_validation)
239
+
240
+
241
+ def generate(args):
242
+ """
243
+ calls script generate_metafile to start dialog
244
+ :param args:
245
+ """
246
+ generating = FRED(args.config)
247
+ generating.generate(args.path, args.id, args.mandatory_only)
248
+
249
+
250
+ def validate(args):
251
+ validating = FRED(args.config)
252
+ errors, warnings = validating.validate(not args.skip_logic, args.path, args.output, args.filename)
253
+
254
+
255
+ def plot(args):
256
+ fred_object = FRED(args.config)
257
+ input_file = utils.read_in_yaml(args.path)
258
+ plots = create_heatmap.get_heatmap(input_file, fred_object.structure, mode=args.mode, labels=args.labels, background=args.background, sample_labels=args.sample_labels, condition_labels=args.condition_labels, transpose=args.transpose, drop_defaults=args.drop_defaults)
259
+ output_filename = args.filename if args.filename is not None else 'fig1'
260
+ if len(plots) > 0:
261
+ try:
262
+ plot = plots[args.setting-1][1]
263
+ except IndexError:
264
+ print(f'Setting exp{args.setting} does not exist. Defaulting to exp1.')
265
+ plot = plots[0][1]
266
+
267
+ if plot is not None:
268
+ if args.output == 'png':
269
+ plot.write_image(f'{output_filename}.{args.output}', format='png')
270
+ print(f'Plot was saved to {output_filename}.{args.output}')
271
+ elif args.output == 'html':
272
+ with open(f'{output_filename}.{args.output}', 'w') as file:
273
+ file.write(plot.to_html(full_html=False, include_plotlyjs='cdn'))
274
+ print(f'Plot was saved to {output_filename}.{args.output}')
275
+ else:
276
+ plot.show()
277
+ else:
278
+ print('Plot could not be created due to missing samples or conditions.')
279
+ else:
280
+ print('No settings found.')
281
+
282
+ #def edit(args):
283
+ # editing = FRED(args.config)
284
+ # editing.edit(args.path, args.mandatory_only)
285
+
286
+ def add_value(args):
287
+ adding = FRED(args.config)
288
+ adding.add_value(args.path, args.position, args.value, args.edit_existing)
289
+
290
+ def main():
291
+
292
+ parser = argparse.ArgumentParser(prog='metaTools.py')
293
+ subparsers = parser.add_subparsers(title='commands')
294
+
295
+ find_function = subparsers.add_parser('find',
296
+ help='This command is used to find '
297
+ 'projects by searching the '
298
+ 'metadata files.')
299
+
300
+ find_group = find_function.add_argument_group('mandatory arguments')
301
+ find_group.add_argument('-p', '--path', type=pathlib.Path, required=True,
302
+ help='The path to be searched')
303
+ find_group.add_argument('-s', '--search', type=str, required=True,
304
+ help='The search parameters')
305
+ find_group.add_argument('-c', '--config', type=pathlib.Path,
306
+ help='Config file', default=os.path.join(os.path.dirname(__file__), 'config', 'config.yaml'))
307
+ find_group.add_argument('-o', '--output', default='print', choices=['json', 'print'])
308
+ find_group.add_argument('-f', '--filename', default=None)
309
+ find_group.add_argument('-sv', '--skip_validation', default=False,
310
+ action='store_true')
311
+ find_function.set_defaults(func=find)
312
+
313
+ create_function = subparsers.add_parser('generate',
314
+ help='This command is used to '
315
+ 'create a metadata file.')
316
+ create_group = create_function.add_argument_group('mandatory arguments')
317
+ create_group.add_argument('-p', '--path', type=pathlib.Path,
318
+ required=True,
319
+ help='The path to save the yaml')
320
+ create_group.add_argument('-c', '--config', type=pathlib.Path,
321
+ help='Config file', default=os.path.join(os.path.dirname(__file__), 'config', 'config.yaml'))
322
+ create_group.add_argument('-id', '--id', type=str,
323
+ required=True,
324
+ help='The ID of the experiment')
325
+ create_function.add_argument('-mo', '--mandatory_only', default=False,
326
+ action='store_true',
327
+ help='If True, only mandatory keys will '
328
+ 'be filled out')
329
+ create_function.add_argument('-m', '--mode', default='metadata', choices=['metadata', 'mamplan'])
330
+ create_function.set_defaults(func=generate)
331
+
332
+ validate_function = subparsers.add_parser('validate',
333
+ help='')
334
+ validate_group = validate_function.add_argument_group('mandatory arguments')
335
+ validate_group.add_argument('-p', '--path', type=pathlib.Path, required=True)
336
+ validate_function.add_argument('-l', '--skip_logic', default=False,
337
+ action='store_true')
338
+ validate_function.add_argument('-m', '--mode', default='metadata', choices=['metadata', 'mamplan'])
339
+ validate_function.add_argument('-o', '--output', default=None, choices=['json', 'txt', 'print', 'yaml'])
340
+ validate_function.add_argument('-f', '--filename', default=None)
341
+ validate_function.add_argument('-c', '--config', type=pathlib.Path,
342
+ help='Config file', default=os.path.join(os.path.dirname(__file__), 'config', 'config.yaml'))
343
+ validate_function.set_defaults(func=validate)
344
+
345
+ #edit_function = subparsers.add_parser('edit', help='')
346
+ #edit_group = edit_function.add_argument_group('mandatory_arguments')
347
+ #edit_group.add_argument('-p', '--path', type=pathlib.Path, required=True)
348
+ #edit_function.add_argument('-mo', '--mandatory_only', default=False,
349
+ # action='store_true',
350
+ # help='If True, only mandatory keys will '
351
+ # 'be filled out')
352
+ #edit_function.add_argument('-c', '--config', type=pathlib.Path,
353
+ # help='Config file', default='config.yaml')
354
+ #edit_function.add_argument('-m', '--mode', default='metadata', choices=['metadata', 'mamplan'])
355
+ #edit_function.set_defaults(func=edit)
356
+
357
+ add_value_function = subparsers.add_parser('add_value', help='')
358
+ add_value_function.add_argument('-m', '--mode', default='metadata', choices=['metadata', 'mamplan'])
359
+ add_value_function.add_argument('-pos', '--position', required=True)
360
+ add_value_function.add_argument('-v', '--value', required=True)
361
+ add_value_function.add_argument('-t', '--type', default='str', choices=['str', 'int', 'float', 'bool'])
362
+ add_value_function.add_argument('-p', '--path', type=pathlib.Path, required=True)
363
+ add_value_function.add_argument('-e', '--edit_existing', default=False, action='store_true')
364
+ add_value_function.add_argument('-c', '--config', type=pathlib.Path,
365
+ help='Config file', default=os.path.join(os.path.dirname(__file__), 'config', 'config.yaml'))
366
+ add_value_function.set_defaults(func=add_value)
367
+
368
+ plot_function = subparsers.add_parser('plot', help='')
369
+ plot_function.add_argument('-p', '--path', type=pathlib.Path, required=True)
370
+ plot_function.add_argument('-c', '--config', type=pathlib.Path,
371
+ help='Config file', default=os.path.join(os.path.dirname(__file__), 'config', 'config.yaml'))
372
+ plot_function.add_argument('-m', '--mode', default='samples', choices=['samples', 'conditions'])
373
+ plot_function.add_argument('-s', '--setting', type=int, default=1)
374
+ plot_function.add_argument('-l', '--labels', default='factors', choices=['factors', 'all', 'none'])
375
+ plot_function.add_argument('-o', '--output', default='show', choices=['show', 'png', 'html', 'dash'])
376
+ plot_function.add_argument('-f', '--filename', type=pathlib.Path)
377
+ plot_function.add_argument('-b', '--background', default=False, action='store_true',
378
+ help='If stated, the background will be displayed in white. Per default it is transparent.')
379
+ plot_function.add_argument('-cl', '--condition_labels', default=False, action='store_true',
380
+ help='If stated, the label of the condition will be displayed as a name. Per default an index is stated. ')
381
+ plot_function.add_argument('-sl', '--sample_labels', default=False, action='store_true',
382
+ help='If stated, the label of the sample will be displayed as a name. Per default an index is stated. ')
383
+ plot_function.add_argument('-t', '--transpose', default=False, action='store_true',
384
+ )
385
+ plot_function.add_argument('-d', '--drop_defaults', default=False, action='store_true',
386
+ )
387
+ plot_function.set_defaults(func=plot)
388
+
389
+ args = parser.parse_args()
390
+
391
+ try:
392
+ args.func(args)
393
+ except AttributeError:
394
+ parser.print_help()
395
+
396
+
397
+ if __name__ == "__main__":
398
+
399
+ main()
fred/src/__init__.py ADDED
File without changes