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.
- {roc_film-1.14.1 → roc_film-1.14.2}/PKG-INFO +3 -3
- {roc_film-1.14.1 → roc_film-1.14.2}/pyproject.toml +2 -2
- {roc_film-1.14.1 → roc_film-1.14.2}/roc/film/commands.py +0 -18
- {roc_film-1.14.1 → roc_film-1.14.2}/roc/film/constants.py +0 -1
- {roc_film-1.14.1 → roc_film-1.14.2}/roc/film/descriptor.json +3 -3
- {roc_film-1.14.1 → roc_film-1.14.2}/roc/film/tasks/cdf_postpro.py +28 -191
- {roc_film-1.14.1 → roc_film-1.14.2}/LICENSE +0 -0
- {roc_film-1.14.1 → roc_film-1.14.2}/README.md +0 -0
- {roc_film-1.14.1 → roc_film-1.14.2}/roc/__init__.py +0 -0
- {roc_film-1.14.1 → roc_film-1.14.2}/roc/film/__init__.py +0 -0
- {roc_film-1.14.1 → roc_film-1.14.2}/roc/film/config/__init__.py +0 -0
- {roc_film-1.14.1 → roc_film-1.14.2}/roc/film/exceptions.py +0 -0
- {roc_film-1.14.1 → roc_film-1.14.2}/roc/film/tasks/__init__.py +0 -0
- {roc_film-1.14.1 → roc_film-1.14.2}/roc/film/tasks/cat_solo_hk.py +0 -0
- {roc_film-1.14.1 → roc_film-1.14.2}/roc/film/tasks/check_dds.py +0 -0
- {roc_film-1.14.1 → roc_film-1.14.2}/roc/film/tasks/db_to_anc_bia_sweep_table.py +0 -0
- {roc_film-1.14.1 → roc_film-1.14.2}/roc/film/tasks/dds_to_l0.py +0 -0
- {roc_film-1.14.1 → roc_film-1.14.2}/roc/film/tasks/export_solo_coord.py +0 -0
- {roc_film-1.14.1 → roc_film-1.14.2}/roc/film/tasks/file_handler.py +0 -0
- {roc_film-1.14.1 → roc_film-1.14.2}/roc/film/tasks/l0_to_hk.py +0 -0
- {roc_film-1.14.1 → roc_film-1.14.2}/roc/film/tasks/l0_to_l1_bia_current.py +0 -0
- {roc_film-1.14.1 → roc_film-1.14.2}/roc/film/tasks/l0_to_l1_bia_sweep.py +0 -0
- {roc_film-1.14.1 → roc_film-1.14.2}/roc/film/tasks/l0_to_l1_sbm.py +0 -0
- {roc_film-1.14.1 → roc_film-1.14.2}/roc/film/tasks/l0_to_l1_surv.py +0 -0
- {roc_film-1.14.1 → roc_film-1.14.2}/roc/film/tasks/make_daily_tm.py +0 -0
- {roc_film-1.14.1 → roc_film-1.14.2}/roc/film/tasks/merge_tcreport.py +0 -0
- {roc_film-1.14.1 → roc_film-1.14.2}/roc/film/tasks/merge_tmraw.py +0 -0
- {roc_film-1.14.1 → roc_film-1.14.2}/roc/film/tasks/parse_dds_xml.py +0 -0
- {roc_film-1.14.1 → roc_film-1.14.2}/roc/film/tasks/set_l0_utc.py +0 -0
- {roc_film-1.14.1 → roc_film-1.14.2}/roc/film/tests/__init__.py +0 -0
- {roc_film-1.14.1 → roc_film-1.14.2}/roc/film/tests/cdf_compare.py +0 -0
- {roc_film-1.14.1 → roc_film-1.14.2}/roc/film/tests/hdf5_compare.py +0 -0
- {roc_film-1.14.1 → roc_film-1.14.2}/roc/film/tests/test_dds_to_l0.py +0 -0
- {roc_film-1.14.1 → roc_film-1.14.2}/roc/film/tests/test_dds_to_tc.py +0 -0
- {roc_film-1.14.1 → roc_film-1.14.2}/roc/film/tests/test_dds_to_tm.py +0 -0
- {roc_film-1.14.1 → roc_film-1.14.2}/roc/film/tests/test_film.py +0 -0
- {roc_film-1.14.1 → roc_film-1.14.2}/roc/film/tests/test_l0_to_hk.py +0 -0
- {roc_film-1.14.1 → roc_film-1.14.2}/roc/film/tests/test_l0_to_l1_bia.py +0 -0
- {roc_film-1.14.1 → roc_film-1.14.2}/roc/film/tests/test_l0_to_l1_sbm.py +0 -0
- {roc_film-1.14.1 → roc_film-1.14.2}/roc/film/tests/test_l0_to_l1_surv.py +0 -0
- {roc_film-1.14.1 → roc_film-1.14.2}/roc/film/tests/test_metadata.py +0 -0
- {roc_film-1.14.1 → roc_film-1.14.2}/roc/film/tests/tests.py +0 -0
- {roc_film-1.14.1 → roc_film-1.14.2}/roc/film/tools/__init__.py +0 -0
- {roc_film-1.14.1 → roc_film-1.14.2}/roc/film/tools/dataset_tasks.py +0 -0
- {roc_film-1.14.1 → roc_film-1.14.2}/roc/film/tools/file_helpers.py +0 -0
- {roc_film-1.14.1 → roc_film-1.14.2}/roc/film/tools/l0.py +0 -0
- {roc_film-1.14.1 → roc_film-1.14.2}/roc/film/tools/metadata.py +0 -0
- {roc_film-1.14.1 → roc_film-1.14.2}/roc/film/tools/skeleton.py +0 -0
- {roc_film-1.14.1 → roc_film-1.14.2}/roc/film/tools/tools.py +0 -0
- {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.
|
3
|
+
Version: 1.14.2
|
4
4
|
Summary: RPW FILe Maker (FILM): Plugin to make RPW L0, L1 and HK data files
|
5
|
-
License:
|
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 ::
|
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.
|
7
|
+
version = "1.14.2"
|
8
8
|
readme = "README.md"
|
9
|
-
license = "
|
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"""
|
@@ -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.
|
10
|
-
"date": "2025-01-
|
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": "
|
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
|
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
|
231
|
-
self.time_max = self.epoch
|
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
|
239
|
-
#
|
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.
|
511
|
-
f"
|
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 =
|
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[
|
421
|
+
current_tc["unique_id"]
|
521
422
|
for current_tc in self.obs_id_list
|
522
|
-
if
|
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
|
-
|
550
|
-
def get_ior_obs_id(rpw_ior_xml_list):
|
451
|
+
def get_tc_log_data(self):
|
551
452
|
"""
|
552
|
-
Return list of
|
553
|
-
|
453
|
+
Return list of [unique_id, utc_time] entries from
|
454
|
+
pipeline.tc_log database table.
|
554
455
|
|
555
|
-
:
|
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
|
-
|
576
|
-
|
577
|
-
|
578
|
-
|
579
|
-
|
580
|
-
|
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
|
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
|
-
|
828
|
-
|
829
|
-
|
830
|
-
|
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
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|