roc-film 1.13.4__py3-none-any.whl → 1.14.0__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. roc/__init__.py +2 -1
  2. roc/film/__init__.py +2 -2
  3. roc/film/commands.py +372 -323
  4. roc/film/config/__init__.py +0 -1
  5. roc/film/constants.py +101 -65
  6. roc/film/descriptor.json +126 -95
  7. roc/film/exceptions.py +28 -27
  8. roc/film/tasks/__init__.py +16 -16
  9. roc/film/tasks/cat_solo_hk.py +86 -74
  10. roc/film/tasks/cdf_postpro.py +438 -309
  11. roc/film/tasks/check_dds.py +39 -45
  12. roc/film/tasks/db_to_anc_bia_sweep_table.py +381 -0
  13. roc/film/tasks/dds_to_l0.py +232 -180
  14. roc/film/tasks/export_solo_coord.py +147 -0
  15. roc/film/tasks/file_handler.py +91 -75
  16. roc/film/tasks/l0_to_hk.py +117 -103
  17. roc/film/tasks/l0_to_l1_bia_current.py +38 -30
  18. roc/film/tasks/l0_to_l1_bia_sweep.py +417 -329
  19. roc/film/tasks/l0_to_l1_sbm.py +250 -208
  20. roc/film/tasks/l0_to_l1_surv.py +185 -130
  21. roc/film/tasks/make_daily_tm.py +40 -37
  22. roc/film/tasks/merge_tcreport.py +77 -71
  23. roc/film/tasks/merge_tmraw.py +102 -89
  24. roc/film/tasks/parse_dds_xml.py +21 -20
  25. roc/film/tasks/set_l0_utc.py +51 -49
  26. roc/film/tests/cdf_compare.py +565 -0
  27. roc/film/tests/hdf5_compare.py +84 -62
  28. roc/film/tests/test_dds_to_l0.py +93 -51
  29. roc/film/tests/test_dds_to_tc.py +8 -11
  30. roc/film/tests/test_dds_to_tm.py +8 -10
  31. roc/film/tests/test_film.py +161 -116
  32. roc/film/tests/test_l0_to_hk.py +64 -36
  33. roc/film/tests/test_l0_to_l1_bia.py +10 -14
  34. roc/film/tests/test_l0_to_l1_sbm.py +14 -19
  35. roc/film/tests/test_l0_to_l1_surv.py +68 -41
  36. roc/film/tests/test_metadata.py +21 -20
  37. roc/film/tests/tests.py +743 -396
  38. roc/film/tools/__init__.py +5 -5
  39. roc/film/tools/dataset_tasks.py +34 -2
  40. roc/film/tools/file_helpers.py +390 -269
  41. roc/film/tools/l0.py +402 -324
  42. roc/film/tools/metadata.py +147 -127
  43. roc/film/tools/skeleton.py +12 -17
  44. roc/film/tools/tools.py +109 -92
  45. roc/film/tools/xlsx2skt.py +161 -139
  46. {roc_film-1.13.4.dist-info → roc_film-1.14.0.dist-info}/LICENSE +127 -125
  47. roc_film-1.14.0.dist-info/METADATA +60 -0
  48. roc_film-1.14.0.dist-info/RECORD +50 -0
  49. {roc_film-1.13.4.dist-info → roc_film-1.14.0.dist-info}/WHEEL +1 -1
  50. roc/film/tasks/l0_to_anc_bia_sweep_table.py +0 -348
  51. roc_film-1.13.4.dist-info/METADATA +0 -120
  52. roc_film-1.13.4.dist-info/RECORD +0 -48
roc/film/tools/tools.py CHANGED
@@ -17,32 +17,38 @@ from poppy.core.generic.metaclasses import Singleton
17
17
  from poppy.core.configuration import Configuration
18
18
  from poppy.core.generic.paths import Paths
19
19
  from poppy.core.logger import logger
20
- from roc.film.constants import _ROOT_DIRECTORY, INPUT_DATETIME_STRFTIME, \
21
- DATA_VERSION, TIME_DAILY_STRFORMAT
20
+ from roc.film.constants import (
21
+ _ROOT_DIRECTORY,
22
+ INPUT_DATETIME_STRFTIME,
23
+ DATA_VERSION,
24
+ TIME_DAILY_STRFORMAT,
25
+ )
22
26
 
23
27
  from roc.film.exceptions import FilmException, HandlingFileError
24
28
 
25
- __all__ = ['paths', 'DESCRIPTOR',
26
- 'raise_error',
27
- 'valid_time',
28
- 'valid_date',
29
- 'valid_data_version',
30
- 'valid_single_file',
31
- 'valid_dir',
32
- 'extract_datetime',
33
- 'extract_file_fields',
34
- 'get_datasets',
35
- 'sort_indices',
36
- 'unique_dict_list',
37
- 'sort_dict_list',
38
- 'safe_move',
39
- 'setup_lock',
40
- 'get_latest_file',
41
- 'Map',
42
- 'glob_list',
43
- 'move_to_trash',
44
- 'decode',
45
- ]
29
+ __all__ = [
30
+ "paths",
31
+ "DESCRIPTOR",
32
+ "raise_error",
33
+ "valid_time",
34
+ "valid_date",
35
+ "valid_data_version",
36
+ "valid_single_file",
37
+ "valid_dir",
38
+ "extract_datetime",
39
+ "extract_file_fields",
40
+ "get_datasets",
41
+ "sort_indices",
42
+ "unique_dict_list",
43
+ "sort_dict_list",
44
+ "safe_move",
45
+ "setup_lock",
46
+ "get_latest_file",
47
+ "Map",
48
+ "glob_list",
49
+ "move_to_trash",
50
+ "decode",
51
+ ]
46
52
 
47
53
  # ________________ Global Variables _____________
48
54
  # (define here the global variables)
@@ -65,20 +71,18 @@ def get_descriptor():
65
71
  """
66
72
 
67
73
  class Descriptor(object, metaclass=Singleton):
68
-
69
74
  def __init__(self):
70
-
71
- descriptor = paths.from_root('descriptor.json')
75
+ descriptor = paths.from_root("descriptor.json")
72
76
 
73
77
  # Get descriptor content
74
- with open(descriptor, 'r') as file_buffer:
78
+ with open(descriptor, "r") as file_buffer:
75
79
  for key, val in json.load(file_buffer).items():
76
80
  setattr(self, key, val)
77
81
 
78
82
  # Re-organize task section
79
83
  tasks = dict()
80
84
  for task in self.tasks:
81
- tasks[task['name']] = task
85
+ tasks[task["name"]] = task
82
86
 
83
87
  self.tasks = tasks
84
88
 
@@ -107,8 +111,9 @@ def valid_time(t, format=INPUT_DATETIME_STRFTIME):
107
111
  try:
108
112
  return datetime.strptime(t, format)
109
113
  except ValueError:
110
- raise_error(f"Not a valid datetime: '{t}'.",
111
- exception=argparse.ArgumentTypeError)
114
+ raise_error(
115
+ f"Not a valid datetime: '{t}'.", exception=argparse.ArgumentTypeError
116
+ )
112
117
 
113
118
 
114
119
  def valid_date(t, format=TIME_DAILY_STRFORMAT):
@@ -123,8 +128,9 @@ def valid_date(t, format=TIME_DAILY_STRFORMAT):
123
128
  try:
124
129
  return datetime.strptime(t, format)
125
130
  except ValueError:
126
- raise_error(f"Not a valid date: '{t}'.",
127
- exception=argparse.ArgumentTypeError)
131
+ raise_error(
132
+ f"Not a valid date: '{t}'.", exception=argparse.ArgumentTypeError
133
+ )
128
134
 
129
135
 
130
136
  def valid_data_version(data_version):
@@ -138,9 +144,9 @@ def valid_data_version(data_version):
138
144
  if isinstance(data_version, list):
139
145
  data_version = data_version[0]
140
146
  data_version = int(data_version)
141
- return f'{data_version:02d}'
147
+ return f"{data_version:02d}"
142
148
  except ValueError:
143
- raise_error(f'Input value for --data-version is not valid! ({data_version})')
149
+ raise_error(f"Input value for --data-version is not valid! ({data_version})")
144
150
 
145
151
 
146
152
  def valid_single_file(file):
@@ -158,11 +164,11 @@ def valid_single_file(file):
158
164
  else:
159
165
  raise FileNotFoundError
160
166
  except FileNotFoundError:
161
- raise_error(f'Input file not found! ({file})', exception=FileNotFoundError)
167
+ raise_error(f"Input file not found! ({file})", exception=FileNotFoundError)
162
168
  except ValueError:
163
- raise_error(f'Input file is not valid! ({file})', exception=ValueError)
169
+ raise_error(f"Input file is not valid! ({file})", exception=ValueError)
164
170
  except Exception as e:
165
- raise_error(f'Problem with input file! ({file})', exception=e)
171
+ raise_error(f"Problem with input file! ({file})", exception=e)
166
172
 
167
173
 
168
174
  def valid_dir(dir):
@@ -180,11 +186,11 @@ def valid_dir(dir):
180
186
  else:
181
187
  raise IsADirectoryError
182
188
  except IsADirectoryError:
183
- raise_error(f'Input directory not found! ({dir})', exception=IsADirectoryError)
189
+ raise_error(f"Input directory not found! ({dir})", exception=IsADirectoryError)
184
190
  except ValueError:
185
- raise_error(f'Input directory is not valid! ({dir})', exception=ValueError)
191
+ raise_error(f"Input directory is not valid! ({dir})", exception=ValueError)
186
192
  except Exception as e:
187
- raise_error(f'Problem with input directory! ({dir})', exception=e)
193
+ raise_error(f"Problem with input directory! ({dir})", exception=e)
188
194
 
189
195
 
190
196
  def unique_dates(utc_times):
@@ -212,14 +218,15 @@ def extract_datetime(str_datetime):
212
218
  :return: 2-elements list containing Datetime start/end time (if input Datetime has a daily format, return the day twice).
213
219
  """
214
220
 
215
- str_datetime_list = str_datetime.split('-')
221
+ str_datetime_list = str_datetime.split("-")
216
222
  if len(str_datetime_list) == 1:
217
- out_datetime = [datetime.strptime(str_datetime, '%Y%m%d')] * 2
223
+ out_datetime = [datetime.strptime(str_datetime, "%Y%m%d")] * 2
218
224
  elif len(str_datetime_list) == 2:
219
- out_datetime = [datetime.strptime(
220
- dt, '%Y%m%dT%H%M%S') for dt in str_datetime_list]
225
+ out_datetime = [
226
+ datetime.strptime(dt, "%Y%m%dT%H%M%S") for dt in str_datetime_list
227
+ ]
221
228
  else:
222
- logger.error(f'Wrong input datetime format: {str_datetime}')
229
+ logger.error(f"Wrong input datetime format: {str_datetime}")
223
230
  return None
224
231
 
225
232
  return out_datetime
@@ -251,30 +258,29 @@ def get_datasets(task, task_name):
251
258
  """
252
259
 
253
260
  # Get dataset JSON file provided as an input argument (if any)
254
- dataset_file = task.pipeline.get(
255
- 'dataset_file', default=[None], args=True)[0]
261
+ dataset_file = task.pipeline.get("dataset_file", default=[None], args=True)[0]
256
262
  # Get --dataset input keyword value (if any)
257
- dataset_names = task.pipeline.get('dataset', default=[None], args=True)
263
+ dataset_names = task.pipeline.get("dataset", default=[None], args=True)
258
264
  # Get --data-version input keyword value (if any)
259
- data_version = task.pipeline.get('data_version', default=[
260
- DATA_VERSION], args=True)[0]
265
+ data_version = task.pipeline.get("data_version", default=[DATA_VERSION], args=True)[
266
+ 0
267
+ ]
261
268
 
262
269
  # Get task output dataset description list from the descriptor.json file
263
- task_output_list = DESCRIPTOR.tasks[task_name]['outputs']
270
+ task_output_list = DESCRIPTOR.tasks[task_name]["outputs"]
264
271
 
265
272
  # If dataset JSON file passed as an value of the --dataset_file input
266
273
  # keyword, load list of datasets to create and related data_version
267
274
  # (optional)
268
275
  if dataset_file and os.path.isfile(dataset_file):
269
- with open(dataset_file, 'r') as file_buff:
276
+ with open(dataset_file, "r") as file_buff:
270
277
  # Loop over dataset array in the JSON file to get the name and
271
278
  # optionally the version of the output file
272
279
  dataset_to_create = []
273
280
  data_versions = []
274
- for current_dataset_obj in json.load(file_buff)['dataset']:
275
- dataset_to_create.append(current_dataset_obj['name'])
276
- data_versions.append(
277
- current_dataset_obj.get('version', data_version))
281
+ for current_dataset_obj in json.load(file_buff)["dataset"]:
282
+ dataset_to_create.append(current_dataset_obj["name"])
283
+ data_versions.append(current_dataset_obj.get("version", data_version))
278
284
  elif dataset_names[0]:
279
285
  # Else if dataset list passed as values of the --dataset input keyword
280
286
  dataset_to_create = dataset_names
@@ -282,22 +288,25 @@ def get_datasets(task, task_name):
282
288
  else:
283
289
  # Else load all the output datasets listed in descriptor for the given
284
290
  # task by default
285
- dataset_to_create = list(DESCRIPTOR.tasks[task_name]['outputs'].keys())
291
+ dataset_to_create = list(DESCRIPTOR.tasks[task_name]["outputs"].keys())
286
292
  data_versions = [data_version] * len(dataset_to_create)
287
293
 
288
294
  # Retrieve dataset info from descriptor.json
289
295
  dataset_list = []
290
296
  for i, dataset_name in enumerate(dataset_to_create):
291
-
292
297
  # Check if current dataset is indeed a output dataset of the task (as
293
298
  # described in the descriptor.json file)
294
299
  if dataset_name not in task_output_list:
295
- logger.warning(f'{dataset_name} is not a valid dataset of the task {task_name}!')
300
+ logger.warning(
301
+ f"{dataset_name} is not a valid dataset of the task {task_name}!"
302
+ )
296
303
  else:
297
304
  # if yes, get description and store info in the dataset_list list
298
- current_dataset = {'name': dataset_name,
299
- 'version': data_versions[i],
300
- 'descr': task_output_list[dataset_name]}
305
+ current_dataset = {
306
+ "name": dataset_name,
307
+ "version": data_versions[i],
308
+ "descr": task_output_list[dataset_name],
309
+ }
301
310
  dataset_list.append(current_dataset)
302
311
 
303
312
  return dataset_list
@@ -310,7 +319,7 @@ def unique_dict_list(list_of_dict):
310
319
  :param list_of_dict: List of dict to unify
311
320
  :return: return list inside which each dict is unique
312
321
  """
313
- return [i for n, i in enumerate(list_of_dict) if i not in list_of_dict[n + 1:]]
322
+ return [i for n, i in enumerate(list_of_dict) if i not in list_of_dict[n + 1 :]]
314
323
 
315
324
 
316
325
  def sort_dict_list(list_of_dict, key):
@@ -333,8 +342,7 @@ def sort_indices(list_to_sort):
333
342
  :return: list of sorted indices
334
343
  """
335
344
 
336
- return sorted(range(len(list_to_sort)),
337
- key=lambda k: list_to_sort[k])
345
+ return sorted(range(len(list_to_sort)), key=lambda k: list_to_sort[k])
338
346
 
339
347
 
340
348
  def safe_move(src, dst, ignore_patterns=[]):
@@ -355,11 +363,14 @@ def safe_move(src, dst, ignore_patterns=[]):
355
363
  if os.path.isfile(src):
356
364
  shutil.copy(src, dst, follow_symlinks=True)
357
365
  elif os.path.isdir(src):
358
- shutil.copytree(src, dst,
359
- ignore=shutil.ignore_patterns(ignore_patterns),
360
- dirs_exist_ok=True)
366
+ shutil.copytree(
367
+ src,
368
+ dst,
369
+ ignore=shutil.ignore_patterns(ignore_patterns),
370
+ dirs_exist_ok=True,
371
+ )
361
372
  except Exception:
362
- raise HandlingFileError(f'Cannot move {src} into {dst}!')
373
+ raise HandlingFileError(f"Cannot move {src} into {dst}!")
363
374
  else:
364
375
  # then delete if the file has well copied
365
376
  if os.path.exists(dst):
@@ -382,10 +393,11 @@ def setup_lock(pipeline):
382
393
  """
383
394
 
384
395
  # Retrieve lock_file input argument value
385
- lock_file = pipeline.get('lock_file', default=[None], args=True)[0]
396
+ lock_file = pipeline.get("lock_file", default=[None], args=True)[0]
386
397
  if lock_file is not None:
387
398
  # Retrieve output directory path
388
399
  from roc.film.tools.file_helpers import get_output_dir
400
+
389
401
  output_dir = get_output_dir(pipeline)
390
402
 
391
403
  # Set the value of Pipeline.lock attribute filename
@@ -403,9 +415,9 @@ def sort_cdf_by_epoch(cdf, descending=False, zvar_list=[]):
403
415
  """
404
416
 
405
417
  try:
406
- epoch = cdf['Epoch']
418
+ epoch = cdf["Epoch"]
407
419
  except Exception:
408
- logger.error('Cannot get Epoch zVariable from input CDF!')
420
+ logger.error("Cannot get Epoch zVariable from input CDF!")
409
421
  return cdf
410
422
 
411
423
  sorted_idx = np.argsort(epoch[...])
@@ -417,18 +429,20 @@ def sort_cdf_by_epoch(cdf, descending=False, zvar_list=[]):
417
429
 
418
430
  for zvar in zvar_list:
419
431
  current_zvar = cdf[zvar][...]
420
- current_zvar = current_zvar[sorted_idx, ]
432
+ current_zvar = current_zvar[sorted_idx,]
421
433
  cdf[zvar] = current_zvar
422
434
 
423
435
  return cdf
424
436
 
425
437
 
426
- def extract_file_fields(rpw_file,
427
- get_source=False,
428
- get_level=False,
429
- get_descriptor=False,
430
- get_datetime=False,
431
- get_version=False):
438
+ def extract_file_fields(
439
+ rpw_file,
440
+ get_source=False,
441
+ get_level=False,
442
+ get_descriptor=False,
443
+ get_datetime=False,
444
+ get_version=False,
445
+ ):
432
446
  """
433
447
  Extract RPW file fields (assuming SolO file naming standards)
434
448
 
@@ -440,7 +454,7 @@ def extract_file_fields(rpw_file,
440
454
  :param get_version: return only data version field
441
455
  :return: list of file fields (or a scalar with expected field)
442
456
  """
443
- fields = os.path.splitext(os.path.basename(rpw_file))[0].split('_')
457
+ fields = os.path.splitext(os.path.basename(rpw_file))[0].split("_")
444
458
 
445
459
  if len(fields) < 5:
446
460
  logger.warning(f'Cannot extract file fields: invalid input file "{rpw_file}"!')
@@ -497,12 +511,14 @@ class Map(dict):
497
511
  del self.__dict__[key]
498
512
 
499
513
 
500
- def glob_list(list_of_files):
514
+ def glob_list(list_of_files: list) -> list:
501
515
  """
502
516
  Perform glob.glob on a list of input files.
503
517
 
504
- :param list_of_files: List of input files (passed as strings)
518
+ :param list_of_files: List of input files (strings)
519
+ :type:list
505
520
  :return: list of files globbed
521
+ :rtype: list
506
522
  """
507
523
  output_list = []
508
524
  for current_file in list_of_files:
@@ -526,7 +542,7 @@ def move_to_trash(file_or_dir):
526
542
  is_file = False
527
543
 
528
544
  try:
529
- logger.debug(f'Moving {file_or_dir} into {trash_dir}')
545
+ logger.debug(f"Moving {file_or_dir} into {trash_dir}")
530
546
  target_path = os.path.join(trash_dir, os.path.basename(file_or_dir))
531
547
  shutil.copyfile(file_or_dir, target_path)
532
548
  if os.path.exists(target_path):
@@ -536,7 +552,7 @@ def move_to_trash(file_or_dir):
536
552
  else:
537
553
  shutil.rmtree(file_or_dir)
538
554
  except Exception:
539
- logger.exception(f'Moving {file_or_dir} into {trash_dir} has failed!')
555
+ logger.exception(f"Moving {file_or_dir} into {trash_dir} has failed!")
540
556
  target_path = None
541
557
 
542
558
  return target_path
@@ -551,18 +567,17 @@ def get_trash_dir():
551
567
  """
552
568
 
553
569
  # Get trash folder path
554
- if 'ROC_PIP_TRASH_DIR' in Configuration.manager['pipeline']['environment']:
555
- trash_dir = Configuration.manager['pipeline'][
556
- 'environment.ROC_PIP_TRASH_DIR']
557
- elif 'ROC_PIP_TRASH_DIR' in os.environ:
558
- trash_dir = os.environ['ROC_PIP_TRASH_DIR']
570
+ if "ROC_PIP_TRASH_DIR" in Configuration.manager["pipeline"]["environment"]:
571
+ trash_dir = Configuration.manager["pipeline"]["environment.ROC_PIP_TRASH_DIR"]
572
+ elif "ROC_PIP_TRASH_DIR" in os.environ:
573
+ trash_dir = os.environ["ROC_PIP_TRASH_DIR"]
559
574
  else:
560
- raise MissingProperty('ROC_PIP_TRASH_DIR variable is not defined!')
575
+ raise MissingProperty("ROC_PIP_TRASH_DIR variable is not defined!")
561
576
 
562
577
  return trash_dir
563
578
 
564
579
 
565
- def decode(binary, encoding='UTF-8'):
580
+ def decode(binary, encoding="UTF-8"):
566
581
  """
567
582
  Decode input binary into string.
568
583
 
@@ -575,10 +590,12 @@ def decode(binary, encoding='UTF-8'):
575
590
  elif isinstance(binary, list):
576
591
  return [element.decode(encoding) for element in binary]
577
592
  elif isinstance(binary, np.ndarray):
593
+
578
594
  def f(x):
579
595
  return x.decode(encoding)
596
+
580
597
  return np.vectorize(f)(binary)
581
598
  elif isinstance(binary, bytes):
582
599
  return binary.decode(encoding)
583
600
  else:
584
- raise ValueError(f'Input binary type ({type(binary)}) is not valid!')
601
+ raise ValueError(f"Input binary type ({type(binary)}) is not valid!")