roc-film 1.13.4__py3-none-any.whl → 1.14.0__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.
- roc/__init__.py +2 -1
- roc/film/__init__.py +2 -2
- roc/film/commands.py +372 -323
- roc/film/config/__init__.py +0 -1
- roc/film/constants.py +101 -65
- roc/film/descriptor.json +126 -95
- roc/film/exceptions.py +28 -27
- roc/film/tasks/__init__.py +16 -16
- roc/film/tasks/cat_solo_hk.py +86 -74
- roc/film/tasks/cdf_postpro.py +438 -309
- roc/film/tasks/check_dds.py +39 -45
- roc/film/tasks/db_to_anc_bia_sweep_table.py +381 -0
- roc/film/tasks/dds_to_l0.py +232 -180
- roc/film/tasks/export_solo_coord.py +147 -0
- roc/film/tasks/file_handler.py +91 -75
- roc/film/tasks/l0_to_hk.py +117 -103
- roc/film/tasks/l0_to_l1_bia_current.py +38 -30
- roc/film/tasks/l0_to_l1_bia_sweep.py +417 -329
- roc/film/tasks/l0_to_l1_sbm.py +250 -208
- roc/film/tasks/l0_to_l1_surv.py +185 -130
- roc/film/tasks/make_daily_tm.py +40 -37
- roc/film/tasks/merge_tcreport.py +77 -71
- roc/film/tasks/merge_tmraw.py +102 -89
- roc/film/tasks/parse_dds_xml.py +21 -20
- roc/film/tasks/set_l0_utc.py +51 -49
- roc/film/tests/cdf_compare.py +565 -0
- roc/film/tests/hdf5_compare.py +84 -62
- roc/film/tests/test_dds_to_l0.py +93 -51
- roc/film/tests/test_dds_to_tc.py +8 -11
- roc/film/tests/test_dds_to_tm.py +8 -10
- roc/film/tests/test_film.py +161 -116
- roc/film/tests/test_l0_to_hk.py +64 -36
- roc/film/tests/test_l0_to_l1_bia.py +10 -14
- roc/film/tests/test_l0_to_l1_sbm.py +14 -19
- roc/film/tests/test_l0_to_l1_surv.py +68 -41
- roc/film/tests/test_metadata.py +21 -20
- roc/film/tests/tests.py +743 -396
- roc/film/tools/__init__.py +5 -5
- roc/film/tools/dataset_tasks.py +34 -2
- roc/film/tools/file_helpers.py +390 -269
- roc/film/tools/l0.py +402 -324
- roc/film/tools/metadata.py +147 -127
- roc/film/tools/skeleton.py +12 -17
- roc/film/tools/tools.py +109 -92
- roc/film/tools/xlsx2skt.py +161 -139
- {roc_film-1.13.4.dist-info → roc_film-1.14.0.dist-info}/LICENSE +127 -125
- roc_film-1.14.0.dist-info/METADATA +60 -0
- roc_film-1.14.0.dist-info/RECORD +50 -0
- {roc_film-1.13.4.dist-info → roc_film-1.14.0.dist-info}/WHEEL +1 -1
- roc/film/tasks/l0_to_anc_bia_sweep_table.py +0 -348
- roc_film-1.13.4.dist-info/METADATA +0 -120
- roc_film-1.13.4.dist-info/RECORD +0 -48
roc/film/tasks/parse_dds_xml.py
CHANGED
@@ -13,61 +13,62 @@ from poppy.core.target import FileTarget, PyObjectTarget
|
|
13
13
|
|
14
14
|
from edds_process.response import xml_to_dict
|
15
15
|
|
16
|
-
__all__ = [
|
16
|
+
__all__ = ["ParseDdsXml"]
|
17
|
+
|
17
18
|
|
18
19
|
class ParseDdsXml(Task):
|
19
20
|
"""
|
20
21
|
Task to parse an input DDS TmRaw XML file
|
21
22
|
and return content as a dictionary.
|
22
23
|
"""
|
23
|
-
|
24
|
-
|
24
|
+
|
25
|
+
plugin_name = "roc.film"
|
26
|
+
name = "parse_dds_xml"
|
25
27
|
|
26
28
|
def add_targets(self):
|
27
|
-
self.add_input(
|
28
|
-
|
29
|
-
|
30
|
-
self.add_output(identifier=
|
31
|
-
target_class=PyObjectTarget)
|
29
|
+
self.add_input(
|
30
|
+
identifier="dds_xml", filepath=self.get_dds_xml(), target_class=FileTarget
|
31
|
+
)
|
32
|
+
self.add_output(identifier="dds_data", target_class=PyObjectTarget)
|
32
33
|
|
33
34
|
def get_dds_xml(self):
|
34
|
-
return self.pipeline.get(
|
35
|
+
return self.pipeline.get("dds_xml", default=[])
|
35
36
|
|
36
37
|
def setup_inputs(self):
|
37
|
-
|
38
38
|
# Get input DDS XML file
|
39
39
|
dds_file = None
|
40
40
|
try:
|
41
|
-
dds_file = self.inputs[
|
41
|
+
dds_file = self.inputs["dds_xml"].filepath
|
42
42
|
if not os.path.isfile(dds_file):
|
43
43
|
raise FileNotFoundError
|
44
|
-
except:
|
45
|
-
logger.exception(f"Cannot load input DDS XML file
|
44
|
+
except Exception as e:
|
45
|
+
logger.exception(f"Cannot load input DDS XML file {dds_file}:\n{e}")
|
46
46
|
return False
|
47
47
|
else:
|
48
48
|
self.dds_file = dds_file
|
49
49
|
|
50
50
|
# Get/create list of well processed DDS files
|
51
51
|
self.processed_dds_files = self.pipeline.get(
|
52
|
-
|
52
|
+
"processed_dds_files", default=[], create=True
|
53
|
+
)
|
53
54
|
# Get/create list of failed DDS files
|
54
55
|
self.failed_dds_files = self.pipeline.get(
|
55
|
-
|
56
|
+
"failed_dds_files", default=[], create=True
|
57
|
+
)
|
56
58
|
|
57
59
|
return True
|
58
60
|
|
59
61
|
def run(self):
|
60
|
-
|
61
62
|
if not self.setup_inputs():
|
62
63
|
return
|
63
64
|
|
64
65
|
try:
|
65
|
-
logger.info(f
|
66
|
+
logger.info(f"Parsing {self.dds_file}...")
|
66
67
|
dds_data = xml_to_dict(self.dds_file)
|
67
|
-
except:
|
68
|
-
logger.exception(f"Cannot parse input DDS XML file
|
68
|
+
except Exception as e:
|
69
|
+
logger.exception(f"Cannot parse input DDS XML file {self.dds_file}:\n{e}")
|
69
70
|
self.failed_dds_files.append(self.dds_file)
|
70
71
|
return
|
71
72
|
else:
|
72
|
-
self.outputs[
|
73
|
+
self.outputs["dds_data"].value = dds_data
|
73
74
|
self.processed_dds_files.append(self.dds_file)
|
roc/film/tasks/set_l0_utc.py
CHANGED
@@ -3,7 +3,6 @@
|
|
3
3
|
|
4
4
|
"""Contains task to set the utc_time values of L0 TM/TC packets."""
|
5
5
|
|
6
|
-
|
7
6
|
import os
|
8
7
|
import shutil
|
9
8
|
from datetime import datetime
|
@@ -18,29 +17,30 @@ from roc.film import TIME_ISO_STRFORMAT
|
|
18
17
|
from roc.film.tools.file_helpers import get_output_dir
|
19
18
|
from roc.film.tools.l0 import L0
|
20
19
|
|
21
|
-
__all__ = [
|
20
|
+
__all__ = ["SetL0Utc"]
|
21
|
+
|
22
22
|
|
23
23
|
class SetL0Utc(Task):
|
24
24
|
"""
|
25
25
|
Set the UTC times of the input L0 file using SolO SPICE kernels.
|
26
26
|
"""
|
27
|
-
|
28
|
-
|
27
|
+
|
28
|
+
plugin_name = "roc.film"
|
29
|
+
name = "set_l0_utc"
|
29
30
|
|
30
31
|
def add_targets(self):
|
31
|
-
self.add_input(
|
32
|
-
|
33
|
-
|
34
|
-
self.add_output(target_class=FileTarget,
|
35
|
-
identifier='l0_file')
|
32
|
+
self.add_input(
|
33
|
+
target_class=FileTarget, identifier="l0_file", filepath=self.get_l0_file()
|
34
|
+
)
|
35
|
+
self.add_output(target_class=FileTarget, identifier="l0_file")
|
36
36
|
|
37
37
|
def get_l0_file(self):
|
38
|
-
return self.pipeline.get(
|
38
|
+
return self.pipeline.get("l0_file", default=[None])[0]
|
39
39
|
|
40
40
|
def setup_inputs(self):
|
41
|
-
self.l0_file = self.inputs[
|
41
|
+
self.l0_file = self.inputs["l0_file"].filepath
|
42
42
|
if not os.path.isfile(self.l0_file):
|
43
|
-
logger.error(f
|
43
|
+
logger.error(f"Input file {self.l0_file} not found!")
|
44
44
|
return False
|
45
45
|
|
46
46
|
# Get time instance
|
@@ -48,49 +48,47 @@ class SetL0Utc(Task):
|
|
48
48
|
|
49
49
|
# Pass input arguments for the Time instance
|
50
50
|
self.time.kernel_date = self.pipeline.get(
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
self.time.no_spice = self.pipeline.get(
|
55
|
-
'no_spice', default=False, args=True)
|
51
|
+
"kernel_date", default=None, args=True
|
52
|
+
)
|
53
|
+
self.time.predictive = self.pipeline.get("predictive", default=True, args=True)
|
54
|
+
self.time.no_spice = self.pipeline.get("no_spice", default=False, args=True)
|
56
55
|
|
57
56
|
# Get/create list of well processed L0 files
|
58
57
|
self.processed_files = self.pipeline.get(
|
59
|
-
|
58
|
+
"processed_files", default=[], create=True
|
59
|
+
)
|
60
60
|
# Get/create list of failed DDS files
|
61
|
-
self.failed_files = self.pipeline.get(
|
62
|
-
'failed_files', default=[], create=True)
|
61
|
+
self.failed_files = self.pipeline.get("failed_files", default=[], create=True)
|
63
62
|
|
64
63
|
# If output directory not found, create it
|
65
64
|
self.output_dir = get_output_dir(self.pipeline)
|
66
65
|
if not os.path.isdir(self.output_dir):
|
67
|
-
logger.debug(f
|
66
|
+
logger.debug(f"Making {self.output_dir}...")
|
68
67
|
os.makedirs(self.output_dir)
|
69
68
|
|
70
69
|
return True
|
71
70
|
|
72
71
|
def run(self):
|
73
|
-
|
74
72
|
# Load/Initialize task inputs
|
75
73
|
if not self.setup_inputs():
|
76
74
|
return
|
77
75
|
|
78
76
|
# Make a copy of the input L0 file
|
79
|
-
l0_copy = os.path.join(self.output_dir,
|
80
|
-
os.path.basename(self.l0_file))
|
77
|
+
l0_copy = os.path.join(self.output_dir, os.path.basename(self.l0_file))
|
81
78
|
shutil.copyfile(self.l0_file, l0_copy)
|
82
79
|
|
83
80
|
if not self._set_utc_time(l0_copy):
|
84
|
-
logger.info(
|
85
|
-
|
81
|
+
logger.info(
|
82
|
+
f"{self.l0_file} does not need to be updated "
|
83
|
+
f"(delete copy in {self.output_dir})"
|
84
|
+
)
|
86
85
|
os.remove(l0_copy)
|
87
86
|
else:
|
88
|
-
logger.debug(
|
87
|
+
logger.debug("Make sure to have sorted/unique utc time values")
|
89
88
|
L0.order_by_utc(l0_copy, unique=True, update_time_minmax=True)
|
90
|
-
logger.info(f
|
89
|
+
logger.info(f"{l0_copy} updated")
|
91
90
|
|
92
91
|
def _set_utc_time(self, l0_file):
|
93
|
-
|
94
92
|
# Flag to indicate if the L0 file content has been changed at the end
|
95
93
|
# (or if the L0 already uses the latest SPICE kernels to compute time).
|
96
94
|
# If has_changed = False, then do not need to update the L0, if True then
|
@@ -98,62 +96,66 @@ class SetL0Utc(Task):
|
|
98
96
|
has_changed = False
|
99
97
|
|
100
98
|
# SPICE SCLK kernel name prefix
|
101
|
-
sclk_prefix =
|
99
|
+
sclk_prefix = "solo_ANC_soc-sclk"
|
102
100
|
|
103
101
|
# Get loaded SPICE kernels
|
104
102
|
loaded_kernel_list = self.time.spice.kall()
|
105
103
|
if not loaded_kernel_list:
|
106
|
-
logger.warning(
|
104
|
+
logger.warning("No SPICE kernel loaded, exiting")
|
107
105
|
return has_changed
|
108
106
|
else:
|
109
107
|
# Keep only SCLK kernels
|
110
|
-
loaded_sclk_list = [
|
111
|
-
|
112
|
-
|
108
|
+
loaded_sclk_list = [
|
109
|
+
kfile for kfile in loaded_kernel_list.keys() if sclk_prefix in kfile
|
110
|
+
]
|
113
111
|
loaded_sclk_num = len(loaded_sclk_list)
|
114
112
|
if loaded_sclk_num == 0:
|
115
|
-
logger.warning(
|
113
|
+
logger.warning("No SPICE SCLK kernel loaded, exiting")
|
116
114
|
return has_changed
|
117
115
|
else:
|
118
116
|
# Get loaded SCLK (latest)
|
119
117
|
loaded_sclk = os.path.basename(loaded_sclk_list[-1])
|
120
118
|
|
121
119
|
# Open L0 file
|
122
|
-
with h5py.File(l0_file,
|
123
|
-
|
120
|
+
with h5py.File(l0_file, "a") as l0:
|
124
121
|
# Check if utc time values need to be updated
|
125
122
|
# To achieve it, re-compute UTC times with loaded kernels
|
126
123
|
# and compare with current values in the L0
|
127
|
-
cat =
|
124
|
+
cat = "TM"
|
128
125
|
if cat in l0.keys():
|
129
126
|
# Loop over each TM packet in L0
|
130
127
|
for packet_name in l0[cat].keys():
|
131
128
|
# Get packet UTC times
|
132
|
-
utc_time = [
|
133
|
-
|
129
|
+
utc_time = [
|
130
|
+
datetime.strptime(current_time[:-4] + "Z", TIME_ISO_STRFORMAT)
|
131
|
+
for current_time in l0[cat][packet_name]["utc_time"][()]
|
132
|
+
]
|
134
133
|
|
135
134
|
# Compute UTC times with current SPICE kernels from
|
136
135
|
# array of time in packet data_field_header
|
137
|
-
new_utc_time = self.time.obt_to_utc(
|
138
|
-
|
139
|
-
|
136
|
+
new_utc_time = self.time.obt_to_utc(
|
137
|
+
(l0[cat][packet_name]["data_field_header"]["time"][()])[:, :2],
|
138
|
+
to_datetime=True,
|
139
|
+
)
|
140
140
|
try:
|
141
141
|
# Compare current L0 utc time values with new ones
|
142
142
|
assert utc_time == new_utc_time
|
143
143
|
except AssertionError:
|
144
144
|
# If not equal, then update L0 UTC Times with loaded
|
145
145
|
# SCLK kernel
|
146
|
-
l0[cat][packet_name][
|
147
|
-
logger.debug(
|
148
|
-
|
146
|
+
l0[cat][packet_name]["utc_time"][...] = new_utc_time
|
147
|
+
logger.debug(
|
148
|
+
f"UTC time values updated for {packet_name} in {l0_file}"
|
149
|
+
)
|
149
150
|
has_changed = True
|
150
151
|
else:
|
151
|
-
logger.debug(
|
152
|
-
|
152
|
+
logger.debug(
|
153
|
+
f"Same UTC time values found for {packet_name} in {l0_file}"
|
154
|
+
)
|
153
155
|
|
154
156
|
# If UTC times have been updated, set the new SCLK filename
|
155
157
|
# in the SPICE_KERNELS attribute
|
156
158
|
if has_changed:
|
157
|
-
l0.attrs[
|
159
|
+
l0.attrs["SPICE_KERNELS"] = loaded_sclk
|
158
160
|
|
159
161
|
return has_changed
|