roc-film 1.14.1__tar.gz → 1.14.2__tar.gz

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 (50) hide show
  1. {roc_film-1.14.1 → roc_film-1.14.2}/PKG-INFO +3 -3
  2. {roc_film-1.14.1 → roc_film-1.14.2}/pyproject.toml +2 -2
  3. {roc_film-1.14.1 → roc_film-1.14.2}/roc/film/commands.py +0 -18
  4. {roc_film-1.14.1 → roc_film-1.14.2}/roc/film/constants.py +0 -1
  5. {roc_film-1.14.1 → roc_film-1.14.2}/roc/film/descriptor.json +3 -3
  6. {roc_film-1.14.1 → roc_film-1.14.2}/roc/film/tasks/cdf_postpro.py +28 -191
  7. {roc_film-1.14.1 → roc_film-1.14.2}/LICENSE +0 -0
  8. {roc_film-1.14.1 → roc_film-1.14.2}/README.md +0 -0
  9. {roc_film-1.14.1 → roc_film-1.14.2}/roc/__init__.py +0 -0
  10. {roc_film-1.14.1 → roc_film-1.14.2}/roc/film/__init__.py +0 -0
  11. {roc_film-1.14.1 → roc_film-1.14.2}/roc/film/config/__init__.py +0 -0
  12. {roc_film-1.14.1 → roc_film-1.14.2}/roc/film/exceptions.py +0 -0
  13. {roc_film-1.14.1 → roc_film-1.14.2}/roc/film/tasks/__init__.py +0 -0
  14. {roc_film-1.14.1 → roc_film-1.14.2}/roc/film/tasks/cat_solo_hk.py +0 -0
  15. {roc_film-1.14.1 → roc_film-1.14.2}/roc/film/tasks/check_dds.py +0 -0
  16. {roc_film-1.14.1 → roc_film-1.14.2}/roc/film/tasks/db_to_anc_bia_sweep_table.py +0 -0
  17. {roc_film-1.14.1 → roc_film-1.14.2}/roc/film/tasks/dds_to_l0.py +0 -0
  18. {roc_film-1.14.1 → roc_film-1.14.2}/roc/film/tasks/export_solo_coord.py +0 -0
  19. {roc_film-1.14.1 → roc_film-1.14.2}/roc/film/tasks/file_handler.py +0 -0
  20. {roc_film-1.14.1 → roc_film-1.14.2}/roc/film/tasks/l0_to_hk.py +0 -0
  21. {roc_film-1.14.1 → roc_film-1.14.2}/roc/film/tasks/l0_to_l1_bia_current.py +0 -0
  22. {roc_film-1.14.1 → roc_film-1.14.2}/roc/film/tasks/l0_to_l1_bia_sweep.py +0 -0
  23. {roc_film-1.14.1 → roc_film-1.14.2}/roc/film/tasks/l0_to_l1_sbm.py +0 -0
  24. {roc_film-1.14.1 → roc_film-1.14.2}/roc/film/tasks/l0_to_l1_surv.py +0 -0
  25. {roc_film-1.14.1 → roc_film-1.14.2}/roc/film/tasks/make_daily_tm.py +0 -0
  26. {roc_film-1.14.1 → roc_film-1.14.2}/roc/film/tasks/merge_tcreport.py +0 -0
  27. {roc_film-1.14.1 → roc_film-1.14.2}/roc/film/tasks/merge_tmraw.py +0 -0
  28. {roc_film-1.14.1 → roc_film-1.14.2}/roc/film/tasks/parse_dds_xml.py +0 -0
  29. {roc_film-1.14.1 → roc_film-1.14.2}/roc/film/tasks/set_l0_utc.py +0 -0
  30. {roc_film-1.14.1 → roc_film-1.14.2}/roc/film/tests/__init__.py +0 -0
  31. {roc_film-1.14.1 → roc_film-1.14.2}/roc/film/tests/cdf_compare.py +0 -0
  32. {roc_film-1.14.1 → roc_film-1.14.2}/roc/film/tests/hdf5_compare.py +0 -0
  33. {roc_film-1.14.1 → roc_film-1.14.2}/roc/film/tests/test_dds_to_l0.py +0 -0
  34. {roc_film-1.14.1 → roc_film-1.14.2}/roc/film/tests/test_dds_to_tc.py +0 -0
  35. {roc_film-1.14.1 → roc_film-1.14.2}/roc/film/tests/test_dds_to_tm.py +0 -0
  36. {roc_film-1.14.1 → roc_film-1.14.2}/roc/film/tests/test_film.py +0 -0
  37. {roc_film-1.14.1 → roc_film-1.14.2}/roc/film/tests/test_l0_to_hk.py +0 -0
  38. {roc_film-1.14.1 → roc_film-1.14.2}/roc/film/tests/test_l0_to_l1_bia.py +0 -0
  39. {roc_film-1.14.1 → roc_film-1.14.2}/roc/film/tests/test_l0_to_l1_sbm.py +0 -0
  40. {roc_film-1.14.1 → roc_film-1.14.2}/roc/film/tests/test_l0_to_l1_surv.py +0 -0
  41. {roc_film-1.14.1 → roc_film-1.14.2}/roc/film/tests/test_metadata.py +0 -0
  42. {roc_film-1.14.1 → roc_film-1.14.2}/roc/film/tests/tests.py +0 -0
  43. {roc_film-1.14.1 → roc_film-1.14.2}/roc/film/tools/__init__.py +0 -0
  44. {roc_film-1.14.1 → roc_film-1.14.2}/roc/film/tools/dataset_tasks.py +0 -0
  45. {roc_film-1.14.1 → roc_film-1.14.2}/roc/film/tools/file_helpers.py +0 -0
  46. {roc_film-1.14.1 → roc_film-1.14.2}/roc/film/tools/l0.py +0 -0
  47. {roc_film-1.14.1 → roc_film-1.14.2}/roc/film/tools/metadata.py +0 -0
  48. {roc_film-1.14.1 → roc_film-1.14.2}/roc/film/tools/skeleton.py +0 -0
  49. {roc_film-1.14.1 → roc_film-1.14.2}/roc/film/tools/tools.py +0 -0
  50. {roc_film-1.14.1 → roc_film-1.14.2}/roc/film/tools/xlsx2skt.py +0 -0
@@ -1,12 +1,12 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: roc-film
3
- Version: 1.14.1
3
+ Version: 1.14.2
4
4
  Summary: RPW FILe Maker (FILM): Plugin to make RPW L0, L1 and HK data files
5
- License: CeCILL
5
+ License: CECILL-2.1
6
6
  Author: Xavier Bonnin
7
7
  Author-email: xavier.bonnin@obspm.fr
8
8
  Requires-Python: >=3.9,<4
9
- Classifier: License :: Other/Proprietary License
9
+ Classifier: License :: OSI Approved :: CEA CNRS Inria Logiciel Libre License, version 2.1 (CeCILL-2.1)
10
10
  Classifier: Programming Language :: Python :: 3
11
11
  Classifier: Programming Language :: Python :: 3.9
12
12
  Classifier: Programming Language :: Python :: 3.10
@@ -4,9 +4,9 @@ build-backend = "poetry.core.masonry.api"
4
4
 
5
5
  [tool.poetry]
6
6
  name = "roc-film"
7
- version = "1.14.1"
7
+ version = "1.14.2"
8
8
  readme = "README.md"
9
- license = "CeCILL"
9
+ license = "CECILL-2.1"
10
10
  repository = "https://gitlab.obspm.fr/ROC/Pipelines/Plugins/FILM"
11
11
  description = "RPW FILe Maker (FILM): Plugin to make RPW L0, L1 and HK data files"
12
12
  authors = [ "Xavier Bonnin <xavier.bonnin@obspm.fr>", "ROC Team <roc.support@sympa.obspm.fr>",]
@@ -1142,24 +1142,6 @@ class CdfPostProCommand(Command):
1142
1142
  required=True,
1143
1143
  )
1144
1144
 
1145
- parser.add_argument(
1146
- "--rpw-obs-json",
1147
- help="""
1148
- List of RPW SoopKitchen export JSON files. Pattern can also be passed.
1149
- """,
1150
- type=str,
1151
- nargs="+",
1152
- )
1153
-
1154
- parser.add_argument(
1155
- "--rpw-ior-xml",
1156
- help="""
1157
- List of RPW IOR XML files. Pattern or ZIP archive can be also passed.
1158
- """,
1159
- type=str,
1160
- nargs="+",
1161
- )
1162
-
1163
1145
  parser.add_argument(
1164
1146
  "--options",
1165
1147
  help=f"""
@@ -141,7 +141,6 @@ TIMEOUT = 14400
141
141
 
142
142
  # Allowed values for keyword --options in l1_post_pro command
143
143
  CDF_POST_PRO_OPTS_ARGS = [
144
- "soop_type",
145
144
  "obs_id",
146
145
  "resize_wf",
147
146
  "update_cdf",
@@ -6,10 +6,10 @@
6
6
  "description": "RPW FILe Maker (FILM): Plugin to make RPW L0, L1 and HK data files"
7
7
  },
8
8
  "release": {
9
- "version": "1.14.1",
10
- "date": "2025-01-29",
9
+ "version": "1.14.2",
10
+ "date": "2025-01-30",
11
11
  "author": "Xavier Bonnin <xavier.bonnin@obspm.fr>, ROC Team <roc.support@sympa.obspm.fr>",
12
- "modification": "Hotfix in file_helper + minor updates",
12
+ "modification": "Update cdf_postpro",
13
13
  "url": "https://gitlab.obspm.fr/ROC/Pipelines/Plugins/FILM"
14
14
  },
15
15
  "tasks": [
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env python
2
2
  # -*- coding: utf-8 -*-
3
3
 
4
- """Module to create the RPW L1 SBM1/SBM2 CDF files."""
4
+ """Module to perform some post-processing on the RPW CDF files."""
5
5
 
6
6
  import json
7
7
  import os
@@ -22,13 +22,11 @@ from poppy.core.target import FileTarget
22
22
 
23
23
  from roc.rpl.time import Time
24
24
  from roc.dingo.models.data import EventLog
25
+ from roc.dingo.models.packet import TcLog
25
26
  from roc.dingo.tools import query_db
26
27
  from roc.dingo.constants import PIPELINE_DATABASE
27
28
 
28
29
  from roc.film import (
29
- TIME_JSON_STRFORMAT,
30
- TIME_DOY1_STRFORMAT,
31
- TIME_DOY2_STRFORMAT,
32
30
  INPUT_DATETIME_STRFTIME,
33
31
  )
34
32
  from roc.film.tools.file_helpers import is_output_dir, get_output_dir
@@ -80,14 +78,6 @@ class CdfPostPro(Task):
80
78
  self.pipeline.exit()
81
79
  return
82
80
 
83
- # Get list of RPW Soopkitchen Observations JSON files
84
- self.rpw_obs_json_list = glob_list(
85
- self.pipeline.get("rpw_obs_json", default=[])
86
- )
87
-
88
- # Get list of RPW IOR XML files
89
- self.rpw_ior_xml_list = glob_list(self.pipeline.get("rpw_ior_xml", default=[]))
90
-
91
81
  # Get post-processing options
92
82
  self.options = [
93
83
  opt.lower()
@@ -167,7 +157,6 @@ class CdfPostPro(Task):
167
157
  self.session = Connector.manager[PIPELINE_DATABASE].session
168
158
 
169
159
  # Initialize some class variables
170
- self.soop_type_list = []
171
160
  self.obs_id_list = []
172
161
  self.event_log = None
173
162
 
@@ -227,21 +216,16 @@ class CdfPostPro(Task):
227
216
  # Get time range of the input L1 CDF
228
217
  self.epoch = cdf["Epoch"][...]
229
218
  self.nrec = self.epoch.shape[0]
230
- self.time_min = self.epoch[0]
231
- self.time_max = self.epoch[-1]
219
+ self.time_min = min(self.epoch)
220
+ self.time_max = max(self.epoch)
232
221
  logger.info(
233
222
  f"{self.current_file} has {self.nrec} records "
234
223
  f"between {self.time_min} "
235
224
  f"and {self.time_max}\t[{self.job_id}]"
236
225
  )
237
226
 
238
- # Set SOOP_TYPE global attribute from RPW SOOPKitchen
239
- # export observation JSON files
240
- if "soop_type" in self.options:
241
- self._set_soop_type(cdf)
242
-
243
- # Set OBS_ID global attribute from IOR XML files (get
244
- # observationID)
227
+ # Set OBS_ID global attribute
228
+ # from unique_id entries in pipeline.tc_log database table
245
229
  if "obs_id" in self.options:
246
230
  self._set_obs_id(cdf)
247
231
 
@@ -410,88 +394,6 @@ class CdfPostPro(Task):
410
394
 
411
395
  return is_succeeded
412
396
 
413
- def _set_soop_type(self, cdf_obj):
414
- """
415
- Set input CDF file with expected value for SOOP_TYPE g.attribute.
416
-
417
- :param cdf_obj: CDF to update (passed as a spacepy.pycdf.CDF class instance)
418
- :return: True if SOOP_TYPE has been set, False otherwise
419
- """
420
-
421
- logger.info(
422
- "Setting SOOP_TYPE global attribute "
423
- f"in {self.current_file} ...\t[{self.job_id}]"
424
- )
425
-
426
- # Get list of SOOP type from RPW soopkitchen observation json files
427
- if not self.soop_type_list:
428
- logger.info(
429
- "Extracting soopType elements from input "
430
- f"list of {len(self.rpw_obs_json_list)} RPW SoopKitchen JSON files...\t[{self.job_id}]"
431
- )
432
- self.soop_type_list = CdfPostPro.get_soop_type(self.rpw_obs_json_list)
433
-
434
- # Only keep list of soop type betwen time_min and time_max
435
- soop_type_list = [
436
- current_soop_type["soopType"]
437
- for current_soop_type in self.soop_type_list
438
- if (
439
- datetime.strptime(current_soop_type["startDate"], TIME_JSON_STRFORMAT)
440
- <= self.time_max
441
- and datetime.strptime(current_soop_type["endDate"], TIME_JSON_STRFORMAT)
442
- >= self.time_min
443
- )
444
- ]
445
-
446
- soop_type_len = len(soop_type_list)
447
- if soop_type_len == 0:
448
- logger.info(
449
- "No Soop Type value found "
450
- f"between {self.time_min} and {self.time_max}\t[{self.job_id}]"
451
- )
452
- cdf_obj.attrs["SOOP_TYPE"] = "none"
453
- return False
454
- else:
455
- cdf_obj.attrs["SOOP_TYPE"] = list(set(soop_type_list))
456
- logger.debug(f"SOOP_TYPE = {soop_type_list} in {self.current_file}")
457
- logger.info(
458
- f"{soop_type_len} entries set for "
459
- f"SOOP_TYPE in {self.current_file}\t[{self.job_id}]"
460
- )
461
-
462
- # make sure to save the change
463
- cdf_obj.save()
464
-
465
- return True
466
-
467
- @staticmethod
468
- def get_soop_type(rpw_obs_json_list):
469
- """
470
- Return list of SOOP_TYPE values for a given set of input RPW SoopKitchen observation JSON files
471
-
472
- :param rpw_obs_json_list: List of input RPW SK JSON files
473
- :return: list of SOOP_TYPE values found
474
- """
475
-
476
- # Define sub-method
477
- def extract_soop_type(json_file):
478
- """Extract soopType from input JSON"""
479
-
480
- # Open JSON file
481
- with open(json_file, "r") as json_buff:
482
- data = json.load(json_buff)
483
-
484
- # Retrieve all "soopType" field from file
485
- return data["soops"]
486
-
487
- # Initialize output list
488
- soop_type_list = []
489
-
490
- for current_json in rpw_obs_json_list:
491
- soop_type_list.extend(extract_soop_type(current_json))
492
-
493
- return soop_type_list
494
-
495
397
  def _set_obs_id(self, cdf_obj):
496
398
  """
497
399
  Set input CDF file with expected value for OBS_ID g.attribute.
@@ -507,19 +409,19 @@ class CdfPostPro(Task):
507
409
 
508
410
  # Get list of RPW TC obs id values
509
411
  if not self.obs_id_list:
510
- logger.info(
511
- f"Extracting uniqueID elements from "
512
- f"input list of {len(self.rpw_ior_xml_list)} RPW IOR files...\t[{self.job_id}]"
412
+ logger.debug(
413
+ f"Requesting pipeline.tc_log table entries from database...\t[{self.job_id}]"
513
414
  )
514
- self.obs_id_list = CdfPostPro.get_ior_obs_id(self.rpw_ior_xml_list)
415
+ self.obs_id_list = self.get_tc_log_data()
515
416
 
516
417
  # Keep only obs_id between time_min and time_max
517
418
  obs_id_list = list(
518
419
  set(
519
420
  [
520
- current_tc[1]
421
+ current_tc["unique_id"]
521
422
  for current_tc in self.obs_id_list
522
- if self.time_max >= current_tc[0] >= self.time_min and current_tc[1]
423
+ if current_tc["unique_id"]
424
+ and self.time_max >= current_tc["utc_time"] >= self.time_min
523
425
  ]
524
426
  )
525
427
  )
@@ -546,87 +448,22 @@ class CdfPostPro(Task):
546
448
 
547
449
  return True
548
450
 
549
- @staticmethod
550
- def get_ior_obs_id(rpw_ior_xml_list):
451
+ def get_tc_log_data(self):
551
452
  """
552
- Return list of OBS_ID values from
553
- an input list of RPW IOR XML files
453
+ Return list of [unique_id, utc_time] entries from
454
+ pipeline.tc_log database table.
554
455
 
555
- :param rpw_ior_xml_list: List of input RPW TC XML files.
556
- (ZIP files containing IOR XML can be also passed).
557
- :return: list of OBS_ID values found
456
+ :return: tc_log data entries found
558
457
  """
559
- import zipfile
560
-
561
- # Define sub-method
562
- def extract_obs_id(xml):
563
- """
564
- Extract OBS_ID from input XML
565
-
566
- :param xml: input IOR XML stream
567
- :return: List of (time, observationID) values extracted from IOR
568
- """
569
- import xmltodict
570
-
571
- # Convert input IOR XML stream into dictionary
572
- logger.debug(f"Parsing {xml.name} ...")
573
- data = xmltodict.parse(xml.read())
574
458
 
575
- # Extract list of sequences
576
- sequence_list = data["planningData"]["commandRequests"]["occurrenceList"][
577
- "sequence"
578
- ]
579
-
580
- # Make sure that returned sequence_list is a list
581
- # (If only one sequence tag is found in the XML
582
- # the xml_to_dict method returns a collections.OrderedDict()
583
- # instance).
584
- if not isinstance(sequence_list, list):
585
- sequence_list = [sequence_list]
586
-
587
- # Retrieve all "observationID" field from input TC XML file
588
- # Return as a list of tuple (ExecutionTime, observationID)
589
- ior_seq_list = []
590
- for current_seq in sequence_list:
591
- # Make sure to retrieve executionTime with the
592
- # right time format (two are possible)
593
- for current_strtformat in [TIME_DOY1_STRFORMAT, TIME_DOY2_STRFORMAT]:
594
- current_time = cast_ior_seq_datetime(
595
- current_seq, current_strtformat
596
- )
597
- if current_time is not None:
598
- break
599
- current_obsid = current_seq["observationID"]
600
-
601
- ior_seq_list.append((current_time, current_obsid))
602
-
603
- return ior_seq_list
604
-
605
- # Initialize output list
606
- obs_id_list = []
607
-
608
- for current_file in rpw_ior_xml_list:
609
- if not os.path.basename(current_file).startswith("IOR"):
610
- logger.debug(f"{current_file} not a valid RPW IOR file, skip it")
611
- continue
612
-
613
- if zipfile.is_zipfile(current_file):
614
- with zipfile.ZipFile(current_file, "r") as zip_stream:
615
- for current_xml in zip_stream.namelist():
616
- with zip_stream.open(current_xml, "r") as ior_xml:
617
- if ior_xml.name.startswith("IOR") and ior_xml.name.endswith(
618
- ".SOL"
619
- ):
620
- obs_id_list.extend(extract_obs_id(ior_xml))
621
- else:
622
- logger.debug(
623
- f"{current_xml} is not a valid RPW IOR XML file, skip it"
624
- )
625
- else:
626
- with open(current_file, "r") as ior_xml:
627
- obs_id_list.extend(extract_obs_id(ior_xml))
459
+ tc_log_data = query_db(
460
+ self.session,
461
+ [TcLog.unique_id, TcLog.utc_time],
462
+ filters=(TcLog.tc_exe_state == "PASSED"),
463
+ to_dict="records",
464
+ )
628
465
 
629
- return obs_id_list
466
+ return tc_log_data
630
467
 
631
468
  def _update_cdf(self, cdf_obj):
632
469
  """
@@ -824,11 +661,11 @@ class CdfPostPro(Task):
824
661
  # Set 7th bit (X000000)
825
662
  bitmask[w] = bitmask[w] | 64
826
663
 
827
- logger.debug(
828
- f"Set {len(w)} QUALITY_BITMASK records for {row['label']} "
829
- f"between {row['start_time']} "
830
- f"and {row['end_time']}\t[{self.job_id}]"
831
- )
664
+ logger.debug(
665
+ f"Set {len(w)} QUALITY_BITMASK records for {row['label']} "
666
+ f"between {row['start_time']} "
667
+ f"and {row['end_time']}\t[{self.job_id}]"
668
+ )
832
669
 
833
670
  # Save quality_bitmask
834
671
  cdf_obj["QUALITY_BITMASK"] = bitmask[...]
File without changes
File without changes
File without changes