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/l0_to_l1_sbm.py
    CHANGED
    
    | @@ -2,6 +2,7 @@ | |
| 2 2 | 
             
            # -*- coding: utf-8 -*-
         | 
| 3 3 |  | 
| 4 4 | 
             
            """Module to create the RPW L1 SBM1/SBM2 CDF files."""
         | 
| 5 | 
            +
             | 
| 5 6 | 
             
            import os
         | 
| 6 7 | 
             
            from datetime import timedelta
         | 
| 7 8 | 
             
            import uuid
         | 
| @@ -16,146 +17,142 @@ from roc.film.tools.l0 import L0 | |
| 16 17 | 
             
            from roc.rpl.time import Time
         | 
| 17 18 | 
             
            from roc.rpl.packet_parser import raw_to_eng
         | 
| 18 19 |  | 
| 19 | 
            -
            from roc.film.tools.file_helpers import  | 
| 20 | 
            +
            from roc.film.tools.file_helpers import (
         | 
| 21 | 
            +
                get_l0_files,
         | 
| 22 | 
            +
                l0_to_trange_cdf,
         | 
| 23 | 
            +
                get_output_dir,
         | 
| 24 | 
            +
                is_output_dir,
         | 
| 25 | 
            +
                get_l0_trange,
         | 
| 26 | 
            +
            )
         | 
| 20 27 |  | 
| 21 28 | 
             
            from roc.film.constants import TIME_JSON_STRFORMAT
         | 
| 22 29 |  | 
| 23 | 
            -
            __all__ = [ | 
| 30 | 
            +
            __all__ = ["L0ToL1Sbm"]
         | 
| 24 31 |  | 
| 25 32 | 
             
            # SBM1 QF TF ID
         | 
| 26 | 
            -
            TF_PA_DPU_0038 =  | 
| 33 | 
            +
            TF_PA_DPU_0038 = "CIWP0028TM"
         | 
| 27 34 | 
             
            # SBM2 QF TF ID
         | 
| 28 | 
            -
            TF_PA_DPU_0039 =  | 
| 35 | 
            +
            TF_PA_DPU_0039 = "CIWP0029TM"
         | 
| 29 36 |  | 
| 30 37 |  | 
| 31 38 | 
             
            class L0ToL1Sbm(Task):
         | 
| 32 39 | 
             
                """
         | 
| 33 40 | 
             
                Task to generate l1 sbm CDF from l0 file(s)
         | 
| 34 41 | 
             
                """
         | 
| 35 | 
            -
                plugin_name = 'roc.film'
         | 
| 36 | 
            -
                name = 'l0_to_l1_sbm'
         | 
| 37 42 |  | 
| 38 | 
            -
                 | 
| 43 | 
            +
                plugin_name = "roc.film"
         | 
| 44 | 
            +
                name = "l0_to_l1_sbm"
         | 
| 39 45 |  | 
| 40 | 
            -
             | 
| 41 | 
            -
             | 
| 42 | 
            -
             | 
| 43 | 
            -
             | 
| 46 | 
            +
                def add_targets(self):
         | 
| 47 | 
            +
                    self.add_input(
         | 
| 48 | 
            +
                        target_class=FileTarget,
         | 
| 49 | 
            +
                        identifier="l0_file",
         | 
| 50 | 
            +
                        filepath=get_l0_files,
         | 
| 51 | 
            +
                        many=True,
         | 
| 52 | 
            +
                    )
         | 
| 44 53 |  | 
| 45 | 
            -
                    self.add_output(target_class=FileTarget,
         | 
| 46 | 
            -
                                    identifier='l1_sbm1_rswf')
         | 
| 54 | 
            +
                    self.add_output(target_class=FileTarget, identifier="l1_sbm1_rswf")
         | 
| 47 55 |  | 
| 48 | 
            -
                    self.add_output(target_class=FileTarget,
         | 
| 49 | 
            -
                                    identifier='l1_sbm2_tswf')
         | 
| 56 | 
            +
                    self.add_output(target_class=FileTarget, identifier="l1_sbm2_tswf")
         | 
| 50 57 |  | 
| 51 | 
            -
                    self.add_output(target_class=FileTarget,
         | 
| 52 | 
            -
                                    identifier='l1_sbm1_cwf')
         | 
| 58 | 
            +
                    self.add_output(target_class=FileTarget, identifier="l1_sbm1_cwf")
         | 
| 53 59 |  | 
| 54 | 
            -
                    self.add_output(target_class=FileTarget,
         | 
| 55 | 
            -
                                    identifier='l1_sbm1_bp1')
         | 
| 60 | 
            +
                    self.add_output(target_class=FileTarget, identifier="l1_sbm1_bp1")
         | 
| 56 61 |  | 
| 57 | 
            -
                    self.add_output(target_class=FileTarget,
         | 
| 58 | 
            -
                                    identifier='l1_sbm1_bp2')
         | 
| 62 | 
            +
                    self.add_output(target_class=FileTarget, identifier="l1_sbm1_bp2")
         | 
| 59 63 |  | 
| 60 | 
            -
                    self.add_output(target_class=FileTarget,
         | 
| 61 | 
            -
                                    identifier='l1_sbm2_cwf')
         | 
| 64 | 
            +
                    self.add_output(target_class=FileTarget, identifier="l1_sbm2_cwf")
         | 
| 62 65 |  | 
| 63 | 
            -
                    self.add_output(target_class=FileTarget,
         | 
| 64 | 
            -
                                    identifier='l1_sbm2_bp1')
         | 
| 66 | 
            +
                    self.add_output(target_class=FileTarget, identifier="l1_sbm2_bp1")
         | 
| 65 67 |  | 
| 66 | 
            -
                    self.add_output(target_class=FileTarget,
         | 
| 67 | 
            -
                                    identifier='l1_sbm2_bp2')
         | 
| 68 | 
            +
                    self.add_output(target_class=FileTarget, identifier="l1_sbm2_bp2")
         | 
| 68 69 |  | 
| 69 70 | 
             
                def setup_inputs(self):
         | 
| 70 | 
            -
             | 
| 71 71 | 
             
                    # Get products directory (folder where final output files will be
         | 
| 72 72 | 
             
                    # moved)
         | 
| 73 | 
            -
                    self.products_dir = self.pipeline.get( | 
| 74 | 
            -
             | 
| 73 | 
            +
                    self.products_dir = self.pipeline.get(
         | 
| 74 | 
            +
                        "products_dir", default=[None], args=True
         | 
| 75 | 
            +
                    )[0]
         | 
| 75 76 |  | 
| 76 77 | 
             
                    # Get output dir
         | 
| 77 78 | 
             
                    self.output_dir = get_output_dir(self.pipeline)
         | 
| 78 | 
            -
                    if not is_output_dir(self.output_dir,
         | 
| 79 | 
            -
             | 
| 80 | 
            -
                        logger.info(f'Making {self.output_dir}')
         | 
| 79 | 
            +
                    if not is_output_dir(self.output_dir, products_dir=self.products_dir):
         | 
| 80 | 
            +
                        logger.info(f"Making {self.output_dir}")
         | 
| 81 81 | 
             
                        os.makedirs(self.output_dir)
         | 
| 82 82 | 
             
                    else:
         | 
| 83 | 
            -
                        logger.debug(f | 
| 84 | 
            -
                                     f'saved into folder {self.output_dir}')
         | 
| 83 | 
            +
                        logger.debug(f"Output files will be saved into folder {self.output_dir}")
         | 
| 85 84 |  | 
| 86 85 | 
             
                    # Get (optional) arguments for SPICE
         | 
| 87 | 
            -
                    predictive = self.pipeline.get( | 
| 88 | 
            -
                    kernel_date = self.pipeline.get( | 
| 89 | 
            -
                    no_spice = self.pipeline.get( | 
| 86 | 
            +
                    predictive = self.pipeline.get("predictive", default=False, args=True)
         | 
| 87 | 
            +
                    kernel_date = self.pipeline.get("kernel_date", default=None, args=True)
         | 
| 88 | 
            +
                    no_spice = self.pipeline.get("no_spice", default=False, args=True)
         | 
| 90 89 |  | 
| 91 90 | 
             
                    # Get/create Time singleton
         | 
| 92 | 
            -
                    self.time = Time( | 
| 93 | 
            -
             | 
| 94 | 
            -
             | 
| 91 | 
            +
                    self.time = Time(
         | 
| 92 | 
            +
                        predictive=predictive, kernel_date=kernel_date, no_spice=no_spice
         | 
| 93 | 
            +
                    )
         | 
| 95 94 |  | 
| 96 95 | 
             
                    # Get list of input l0 file(s)
         | 
| 97 | 
            -
                    self.l0_file_list = self.inputs[ | 
| 96 | 
            +
                    self.l0_file_list = self.inputs["l0_file"].filepath
         | 
| 98 97 |  | 
| 99 98 | 
             
                    # Get or create failed_files list from pipeline properties
         | 
| 100 | 
            -
                    self.failed_files = self.pipeline.get(
         | 
| 101 | 
            -
                        'failed_files', default=[], create=True)
         | 
| 99 | 
            +
                    self.failed_files = self.pipeline.get("failed_files", default=[], create=True)
         | 
| 102 100 |  | 
| 103 101 | 
             
                    # Get or create processed_files list from pipeline properties
         | 
| 104 102 | 
             
                    self.processed_files = self.pipeline.get(
         | 
| 105 | 
            -
                         | 
| 103 | 
            +
                        "processed_files", default=[], create=True
         | 
| 104 | 
            +
                    )
         | 
| 106 105 |  | 
| 107 106 | 
             
                    # Get overwrite argument
         | 
| 108 | 
            -
                    self.overwrite = self.pipeline.get(
         | 
| 109 | 
            -
                        'overwrite', default=False, args=True)
         | 
| 107 | 
            +
                    self.overwrite = self.pipeline.get("overwrite", default=False, args=True)
         | 
| 110 108 |  | 
| 111 109 | 
             
                    # Get force optional keyword
         | 
| 112 | 
            -
                    self.force = self.pipeline.get( | 
| 110 | 
            +
                    self.force = self.pipeline.get("force", default=False, args=True)
         | 
| 113 111 |  | 
| 114 112 | 
             
                    # Get --cdag keyword
         | 
| 115 | 
            -
                    self.is_cdag = self.pipeline.get( | 
| 113 | 
            +
                    self.is_cdag = self.pipeline.get("cdag", default=False, args=True)
         | 
| 116 114 |  | 
| 117 115 | 
             
                    # Get --no-sbm1/2 ans --as-is keywords
         | 
| 118 | 
            -
                    self.no_sbm1 = self.pipeline.get( | 
| 119 | 
            -
                    self.no_sbm2 = self.pipeline.get( | 
| 120 | 
            -
                    self.manual = self.pipeline.get( | 
| 116 | 
            +
                    self.no_sbm1 = self.pipeline.get("no_sbm1", default=False, args=True)
         | 
| 117 | 
            +
                    self.no_sbm2 = self.pipeline.get("no_sbm2", default=False, args=True)
         | 
| 118 | 
            +
                    self.manual = self.pipeline.get("manual", default=False, args=True)
         | 
| 121 119 |  | 
| 122 120 | 
             
                    # Define output file start time
         | 
| 123 | 
            -
                    self.start_time = self.pipeline.get( | 
| 124 | 
            -
                    logger.debug(f | 
| 121 | 
            +
                    self.start_time = self.pipeline.get("start_time", default=[None])[0]
         | 
| 122 | 
            +
                    logger.debug(f"start_time value is {self.start_time}")
         | 
| 125 123 |  | 
| 126 124 | 
             
                    # Define output file end time
         | 
| 127 | 
            -
                    self.end_time = self.pipeline.get( | 
| 128 | 
            -
                    logger.debug(f | 
| 125 | 
            +
                    self.end_time = self.pipeline.get("end_time", default=[None])[0]
         | 
| 126 | 
            +
                    logger.debug(f"end_time value is {self.end_time}")
         | 
| 129 127 |  | 
| 130 128 | 
             
                    # Define SBM type (only used with --as-is optional keyword)
         | 
| 131 | 
            -
                    self.sbm_type = self.pipeline.get( | 
| 132 | 
            -
                    logger.debug(f | 
| 129 | 
            +
                    self.sbm_type = self.pipeline.get("sbm_type", default=[None])[0]
         | 
| 130 | 
            +
                    logger.debug(f"sbm_type value is {self.sbm_type}")
         | 
| 133 131 |  | 
| 134 132 | 
             
                    return True
         | 
| 135 133 |  | 
| 136 134 | 
             
                def run(self):
         | 
| 137 | 
            -
             | 
| 138 135 | 
             
                    # Define task job ID (long and short)
         | 
| 139 136 | 
             
                    self.job_uuid = str(uuid.uuid4())
         | 
| 140 | 
            -
                    self.job_id =  | 
| 141 | 
            -
                    logger.info(f | 
| 137 | 
            +
                    self.job_id = self.job_uuid[:8]
         | 
| 138 | 
            +
                    logger.info(f"Task job {self.job_id} is starting")
         | 
| 142 139 | 
             
                    try:
         | 
| 143 140 | 
             
                        self.setup_inputs()
         | 
| 144 | 
            -
                    except:
         | 
| 145 | 
            -
                        logger.exception(
         | 
| 146 | 
            -
                            f'Initializing inputs has failed for {self.job_id}!')
         | 
| 141 | 
            +
                    except Exception:
         | 
| 142 | 
            +
                        logger.exception(f"Initializing inputs has failed for job {self.job_id}!")
         | 
| 147 143 | 
             
                        try:
         | 
| 148 | 
            -
                            os.makedirs(os.path.join(self.output_dir,  | 
| 149 | 
            -
                        except:
         | 
| 150 | 
            -
                            logger.error( | 
| 144 | 
            +
                            os.makedirs(os.path.join(self.output_dir, "failed"))
         | 
| 145 | 
            +
                        except Exception:
         | 
| 146 | 
            +
                            logger.error(
         | 
| 147 | 
            +
                                f"output_dir argument is not defined for job {self.job_id}!"
         | 
| 148 | 
            +
                            )
         | 
| 151 149 | 
             
                        self.pipeline.exit()
         | 
| 152 150 | 
             
                        return
         | 
| 153 151 |  | 
| 154 152 | 
             
                    if self.manual:
         | 
| 155 153 | 
             
                        # If 'manual' option is passed, then try to
         | 
| 156 154 | 
             
                        # process straightly the SBM packet data found in the input L0 files
         | 
| 157 | 
            -
                        logger.info(
         | 
| 158 | 
            -
                            f'Try to process data manually    [{self.job_id}]')
         | 
| 155 | 
            +
                        logger.info(f"Try to process data manually    [{self.job_id}]")
         | 
| 159 156 |  | 
| 160 157 | 
             
                        # Define time range to process
         | 
| 161 158 | 
             
                        if not self.start_time and not self.end_time:
         | 
| @@ -168,72 +165,89 @@ class L0ToL1Sbm(Task): | |
| 168 165 | 
             
                            end_time = self.end_time
         | 
| 169 166 |  | 
| 170 167 | 
             
                        if not self.sbm_type:
         | 
| 171 | 
            -
                            logger.warning( | 
| 172 | 
            -
                        elif self.sbm_type and self.sbm_type not in [1,2]:
         | 
| 173 | 
            -
                            logger.error( | 
| 168 | 
            +
                            logger.warning("--sbm-type argument value is not passed!")
         | 
| 169 | 
            +
                        elif self.sbm_type and self.sbm_type not in [1, 2]:
         | 
| 170 | 
            +
                            logger.error("--sbm-type argument value is not valid: must be 1 or 2!")
         | 
| 174 171 | 
             
                            self.pipeline.exit()
         | 
| 175 172 |  | 
| 176 | 
            -
                        sbm_list = [ | 
| 177 | 
            -
             | 
| 178 | 
            -
             | 
| 179 | 
            -
             | 
| 180 | 
            -
             | 
| 181 | 
            -
             | 
| 182 | 
            -
             | 
| 173 | 
            +
                        sbm_list = [
         | 
| 174 | 
            +
                            {
         | 
| 175 | 
            +
                                "start_time": start_time,
         | 
| 176 | 
            +
                                "end_time": end_time,
         | 
| 177 | 
            +
                                # We do not know DT?_SBM? parameters here, so assume
         | 
| 178 | 
            +
                                # that SBM event occurrence time is in the center of the window
         | 
| 179 | 
            +
                                "sbm_time": start_time + 0.5 * (end_time - start_time),
         | 
| 180 | 
            +
                                "sbm_l0": self.l0_file_list,
         | 
| 181 | 
            +
                                "sbm_type": self.sbm_type,
         | 
| 182 | 
            +
                            }
         | 
| 183 | 
            +
                        ]
         | 
| 183 184 | 
             
                        sbm_num = 1
         | 
| 184 185 | 
             
                    else:
         | 
| 185 | 
            -
             | 
| 186 186 | 
             
                        # Build list of sbm events by looking for
         | 
| 187 187 | 
             
                        # TM_DPU_EVENT_PR_DPU_SBM1 or TM_DPU_EVENT_PR_DPU_SBM2 packets in input L0 files
         | 
| 188 | 
            -
                        logger.info(f | 
| 189 | 
            -
                        sbm_list = self._build_sbm_list( | 
| 190 | 
            -
             | 
| 191 | 
            -
             | 
| 192 | 
            -
             | 
| 193 | 
            -
             | 
| 188 | 
            +
                        logger.info(f"Building list of SBM events to process...    [{self.job_id}]")
         | 
| 189 | 
            +
                        sbm_list = self._build_sbm_list(
         | 
| 190 | 
            +
                            self.l0_file_list,
         | 
| 191 | 
            +
                            start_time=self.start_time,
         | 
| 192 | 
            +
                            end_time=self.end_time,
         | 
| 193 | 
            +
                            no_sbm1=self.no_sbm1,
         | 
| 194 | 
            +
                            no_sbm2=self.no_sbm2,
         | 
| 195 | 
            +
                        )
         | 
| 194 196 |  | 
| 195 197 | 
             
                        sbm_num = len(sbm_list)
         | 
| 196 198 | 
             
                        if sbm_num == 0:
         | 
| 197 | 
            -
                            logger.info( | 
| 199 | 
            +
                            logger.info(
         | 
| 200 | 
            +
                                "No SBM detection event found in input L0 files    [{self.job_id}]"
         | 
| 201 | 
            +
                            )
         | 
| 198 202 | 
             
                            return
         | 
| 199 203 | 
             
                        else:
         | 
| 200 | 
            -
                            logger.info(f | 
| 204 | 
            +
                            logger.info(f"{sbm_num} SBM events to process    [{self.job_id}]")
         | 
| 201 205 |  | 
| 202 206 | 
             
                    # Initialize loop variables
         | 
| 203 207 | 
             
                    l1_cdf_path = None
         | 
| 204 208 |  | 
| 205 209 | 
             
                    # Loop over each SBM event in the list
         | 
| 206 210 | 
             
                    for i, current_sbm in enumerate(sbm_list):
         | 
| 207 | 
            -
             | 
| 208 211 | 
             
                        # Get info of current sbm event
         | 
| 209 | 
            -
                        sbm_start_time = current_sbm[ | 
| 210 | 
            -
                        sbm_end_time = current_sbm[ | 
| 211 | 
            -
                        sbm_time = current_sbm[ | 
| 212 | 
            -
                         | 
| 213 | 
            -
                         | 
| 214 | 
            -
                         | 
| 215 | 
            -
                         | 
| 216 | 
            -
                         | 
| 217 | 
            -
                         | 
| 218 | 
            -
             | 
| 219 | 
            -
             | 
| 220 | 
            -
             | 
| 212 | 
            +
                        sbm_start_time = current_sbm["start_time"]
         | 
| 213 | 
            +
                        sbm_end_time = current_sbm["end_time"]
         | 
| 214 | 
            +
                        sbm_time = current_sbm["sbm_time"]
         | 
| 215 | 
            +
                        sbm_obt = current_sbm["sbm_obt"]
         | 
| 216 | 
            +
                        sbm_l0_list = current_sbm["sbm_l0"]
         | 
| 217 | 
            +
                        sbm_type = current_sbm.get("sbm_type", "UNKNOWN")
         | 
| 218 | 
            +
                        sbm_qf = current_sbm.get("sbm_qf", "UNKNOWN")
         | 
| 219 | 
            +
                        sbm_algo = current_sbm.get("sbm_algo", "UNKNOWN")
         | 
| 220 | 
            +
                        sbm_duration = current_sbm.get("sbm_duration", "UNKNOWN")
         | 
| 221 | 
            +
                        if sbm_type != "UNKNOWN":
         | 
| 222 | 
            +
                            logger.info(
         | 
| 223 | 
            +
                                f"Processing SBM{sbm_type} event detected "
         | 
| 224 | 
            +
                                f"between {current_sbm['start_time']} and "
         | 
| 225 | 
            +
                                f"{current_sbm['end_time']}... ({sbm_num - i} events remaining)    [{self.job_id}]"
         | 
| 226 | 
            +
                            )
         | 
| 221 227 |  | 
| 222 228 | 
             
                        try:
         | 
| 223 229 | 
             
                            # Generate L1 CDF from L0 files
         | 
| 224 | 
            -
                            l1_cdf_path = l0_to_trange_cdf( | 
| 225 | 
            -
             | 
| 226 | 
            -
             | 
| 227 | 
            -
             | 
| 228 | 
            -
             | 
| 229 | 
            -
             | 
| 230 | 
            -
             | 
| 231 | 
            -
             | 
| 232 | 
            -
             | 
| 233 | 
            -
             | 
| 230 | 
            +
                            l1_cdf_path = l0_to_trange_cdf(
         | 
| 231 | 
            +
                                self,
         | 
| 232 | 
            +
                                "l0_to_l1_sbm",
         | 
| 233 | 
            +
                                sbm_l0_list,
         | 
| 234 | 
            +
                                self.output_dir,
         | 
| 235 | 
            +
                                time_instance=self.time,
         | 
| 236 | 
            +
                                start_time=sbm_start_time,
         | 
| 237 | 
            +
                                end_time=sbm_end_time,
         | 
| 238 | 
            +
                                failed_files=self.failed_files,
         | 
| 239 | 
            +
                                processed_files=self.processed_files,
         | 
| 240 | 
            +
                                is_cdag=self.is_cdag,
         | 
| 241 | 
            +
                                overwrite=self.overwrite,
         | 
| 242 | 
            +
                            )
         | 
| 243 | 
            +
                        except Exception as e:
         | 
| 244 | 
            +
                            logger.exception(
         | 
| 245 | 
            +
                                f"L1 SBM CDF production has failed!    [{self.job_id}]:\n{e}"
         | 
| 246 | 
            +
                            )
         | 
| 234 247 | 
             
                            if not l1_cdf_path:
         | 
| 235 | 
            -
                                l1_cdf_path = [ | 
| 236 | 
            -
                                    self.output_dir,  | 
| 248 | 
            +
                                l1_cdf_path = [
         | 
| 249 | 
            +
                                    os.path.join(self.output_dir, ".l0_to_l1_sbm_failed")
         | 
| 250 | 
            +
                                ]
         | 
| 237 251 | 
             
                            if l1_cdf_path[0] not in self.failed_files:
         | 
| 238 252 | 
             
                                self.failed_files.append(l1_cdf_path[0])
         | 
| 239 253 | 
             
                            return
         | 
| @@ -241,41 +255,43 @@ class L0ToL1Sbm(Task): | |
| 241 255 | 
             
                        if l1_cdf_path and os.path.isfile(l1_cdf_path[0]):
         | 
| 242 256 | 
             
                            # Open CDF and add some extra information about SBM event
         | 
| 243 257 | 
             
                            # parameters
         | 
| 244 | 
            -
                            logger.info( | 
| 258 | 
            +
                            logger.info(
         | 
| 259 | 
            +
                                f"Filling {l1_cdf_path[0]} file with SBM event parameters...    [{self.job_id}]"
         | 
| 260 | 
            +
                            )
         | 
| 245 261 | 
             
                            cdf = None
         | 
| 246 262 | 
             
                            try:
         | 
| 247 | 
            -
                                 | 
| 248 | 
            -
             | 
| 249 | 
            -
             | 
| 250 | 
            -
             | 
| 251 | 
            -
             | 
| 252 | 
            -
             | 
| 253 | 
            -
             | 
| 254 | 
            -
             | 
| 255 | 
            -
             | 
| 256 | 
            -
             | 
| 257 | 
            -
                                     | 
| 258 | 
            -
             | 
| 259 | 
            -
                            except:
         | 
| 263 | 
            +
                                with CDF(l1_cdf_path[0]) as cdf:
         | 
| 264 | 
            +
                                    cdf.readonly(False)
         | 
| 265 | 
            +
             | 
| 266 | 
            +
                                    # Add QF, detection time, duration and algo type
         | 
| 267 | 
            +
                                    # as g. attributes
         | 
| 268 | 
            +
                                    # TODO - Add also in CDF skeletons
         | 
| 269 | 
            +
                                    cdf.attrs["SBM_QUALITY_FACTOR"] = str(sbm_qf)
         | 
| 270 | 
            +
                                    cdf.attrs["SBM_DURATION"] = str(sbm_duration)
         | 
| 271 | 
            +
                                    cdf.attrs["SBM_ALGO_TYPE"] = str(sbm_algo)
         | 
| 272 | 
            +
                                    cdf.attrs["SBM_TIME"] = sbm_time.strftime(TIME_JSON_STRFORMAT)
         | 
| 273 | 
            +
                                    cdf.attrs["SBM_OBT"] = f"{sbm_obt[0]}:{sbm_obt[1]}"
         | 
| 274 | 
            +
                            except Exception as e:
         | 
| 260 275 | 
             
                                logger.exception(
         | 
| 261 | 
            -
                                     | 
| 276 | 
            +
                                    f"Filling L1 SBM CDF with SBM parameter has failed!    [{self.job_id}]:\n{e}"
         | 
| 277 | 
            +
                                )
         | 
| 262 278 | 
             
                                if l1_cdf_path[0] not in self.failed_files:
         | 
| 263 279 | 
             
                                    self.failed_files.append(l1_cdf_path[0])
         | 
| 264 | 
            -
             | 
| 265 280 | 
             
                            else:
         | 
| 266 | 
            -
                                logger.info( | 
| 281 | 
            +
                                logger.info(
         | 
| 282 | 
            +
                                    f"{l1_cdf_path[0]} filled with SBM parameters    [{self.job_id}]"
         | 
| 283 | 
            +
                                )
         | 
| 267 284 | 
             
                                if l1_cdf_path[0] not in self.processed_files:
         | 
| 268 285 | 
             
                                    self.processed_files.append(l1_cdf_path[0])
         | 
| 269 | 
            -
             | 
| 270 | 
            -
             | 
| 271 | 
            -
             | 
| 272 | 
            -
             | 
| 273 | 
            -
             | 
| 274 | 
            -
             | 
| 275 | 
            -
             | 
| 276 | 
            -
             | 
| 277 | 
            -
             | 
| 278 | 
            -
                                    ):
         | 
| 286 | 
            +
             | 
| 287 | 
            +
                @staticmethod
         | 
| 288 | 
            +
                def _build_sbm_list(
         | 
| 289 | 
            +
                    l0_file_list,
         | 
| 290 | 
            +
                    start_time=None,
         | 
| 291 | 
            +
                    end_time=None,
         | 
| 292 | 
            +
                    no_sbm1=False,
         | 
| 293 | 
            +
                    no_sbm2=False,
         | 
| 294 | 
            +
                ):
         | 
| 279 295 | 
             
                    """
         | 
| 280 296 | 
             
                    Build list of SBM events to process
         | 
| 281 297 | 
             
                    from an input set of l0 files.
         | 
| @@ -285,7 +301,7 @@ class L0ToL1Sbm(Task): | |
| 285 301 | 
             
                    :param end_time: Filter data by end_time
         | 
| 286 302 | 
             
                    :param no_sbm1: If True, do not include SBM1 event in the output list
         | 
| 287 303 | 
             
                    :param no_sbm2: If True, do not include SBM1 event in the output list
         | 
| 288 | 
            -
                    :return:  | 
| 304 | 
            +
                    :return: sbm events to process
         | 
| 289 305 | 
             
                    """
         | 
| 290 306 |  | 
| 291 307 | 
             
                    # Initialize output list
         | 
| @@ -293,91 +309,109 @@ class L0ToL1Sbm(Task): | |
| 293 309 |  | 
| 294 310 | 
             
                    expected_packet_list = []
         | 
| 295 311 | 
             
                    if not no_sbm1:
         | 
| 296 | 
            -
                        expected_packet_list.append( | 
| 312 | 
            +
                        expected_packet_list.append("TM_DPU_EVENT_PR_DPU_SBM1")
         | 
| 297 313 | 
             
                    if not no_sbm2:
         | 
| 298 | 
            -
                        expected_packet_list.append( | 
| 314 | 
            +
                        expected_packet_list.append("TM_DPU_EVENT_PR_DPU_SBM2")
         | 
| 299 315 |  | 
| 300 316 | 
             
                    if not expected_packet_list:
         | 
| 301 | 
            -
                        logger.warning( | 
| 302 | 
            -
             | 
| 317 | 
            +
                        logger.warning(
         | 
| 318 | 
            +
                            "--no-sbm1 and --no-sbm2 keywords should not be passed together!"
         | 
| 319 | 
            +
                        )
         | 
| 303 320 | 
             
                    else:
         | 
| 304 321 | 
             
                        # Extract wanted packets and re-order by increasing time
         | 
| 305 | 
            -
                        sbm_packet_list = L0.l0_to_raw( | 
| 306 | 
            -
             | 
| 307 | 
            -
             | 
| 308 | 
            -
             | 
| 309 | 
            -
             | 
| 310 | 
            -
             | 
| 322 | 
            +
                        sbm_packet_list = L0.l0_to_raw(
         | 
| 323 | 
            +
                            l0_file_list,
         | 
| 324 | 
            +
                            expected_packet_list=expected_packet_list,
         | 
| 325 | 
            +
                            start_time=start_time,
         | 
| 326 | 
            +
                            end_time=end_time,
         | 
| 327 | 
            +
                            increasing_time=True,
         | 
| 328 | 
            +
                        )["packet_list"]
         | 
| 311 329 | 
             
                        if sbm_packet_list:
         | 
| 312 | 
            -
             | 
| 313 330 | 
             
                            for current_packet in sbm_packet_list:
         | 
| 331 | 
            +
                                # current_time = current_packet['utc_time']
         | 
| 332 | 
            +
                                current_name = current_packet["palisade_id"]
         | 
| 333 | 
            +
                                current_data = current_packet["data"]
         | 
| 314 334 |  | 
| 315 | 
            -
                                 | 
| 316 | 
            -
                                 | 
| 317 | 
            -
                                current_data = current_packet['data']
         | 
| 318 | 
            -
             | 
| 319 | 
            -
                                current_idb_source = current_packet['idb_source']
         | 
| 320 | 
            -
                                current_idb_version = current_packet['idb_version']
         | 
| 335 | 
            +
                                current_idb_source = current_packet["idb_source"]
         | 
| 336 | 
            +
                                current_idb_version = current_packet["idb_version"]
         | 
| 321 337 |  | 
| 322 338 | 
             
                                # Get SBM event parameters
         | 
| 323 339 | 
             
                                current_sbm_type = int(current_name[-1])
         | 
| 340 | 
            +
             | 
| 341 | 
            +
                                # Get SBM detection time (Onboard time in CCSDS CUC format)
         | 
| 342 | 
            +
                                current_sbm_obt = current_data[
         | 
| 343 | 
            +
                                    f"HK_RPW_S20_SBM{current_sbm_type}_TIME_D"
         | 
| 344 | 
            +
                                ][:2].reshape([1, 2])[0]
         | 
| 345 | 
            +
             | 
| 324 346 | 
             
                                # Get SBM detection time (UTC)
         | 
| 325 347 | 
             
                                current_sbm_time = Time().obt_to_utc(
         | 
| 326 | 
            -
                                     | 
| 327 | 
            -
             | 
| 348 | 
            +
                                    current_sbm_obt, to_datetime=True
         | 
| 349 | 
            +
                                )[0]
         | 
| 328 350 |  | 
| 329 351 | 
             
                                # Get algo
         | 
| 330 | 
            -
                                current_sbm_algo = current_data[ | 
| 352 | 
            +
                                current_sbm_algo = current_data[
         | 
| 353 | 
            +
                                    f"SY_DPU_SBM{current_sbm_type}_ALGO"
         | 
| 354 | 
            +
                                ]
         | 
| 331 355 |  | 
| 332 356 | 
             
                                # Get SBM duration
         | 
| 333 357 | 
             
                                # (see SSS or DAS User manual for details)
         | 
| 334 358 | 
             
                                if current_sbm_type == 1:
         | 
| 335 | 
            -
                                    current_sbm_dt1_sbm1 = current_data[
         | 
| 336 | 
            -
             | 
| 337 | 
            -
                                     | 
| 338 | 
            -
             | 
| 339 | 
            -
             | 
| 340 | 
            -
                                         | 
| 341 | 
            -
             | 
| 342 | 
            -
             | 
| 343 | 
            -
                                                                 idb_version=current_idb_version)
         | 
| 359 | 
            +
                                    current_sbm_dt1_sbm1 = current_data["SY_DPU_SBM1_DT1_SBM1_D"]
         | 
| 360 | 
            +
                                    current_sbm_dt2_sbm1 = current_data["SY_DPU_SBM1_DT2_SBM1_D"]
         | 
| 361 | 
            +
                                    current_sbm_dt3_sbm1 = current_data["SY_DPU_SBM1_DT3_SBM1_D"]
         | 
| 362 | 
            +
                                    current_sbm_qf = sbm1_qf_eng(
         | 
| 363 | 
            +
                                        current_data["HK_RPW_S20_SBM1_QF_D"],
         | 
| 364 | 
            +
                                        idb_source=current_idb_source,
         | 
| 365 | 
            +
                                        idb_version=current_idb_version,
         | 
| 366 | 
            +
                                    )
         | 
| 344 367 | 
             
                                    logger.debug(
         | 
| 345 | 
            -
                                        f | 
| 368 | 
            +
                                        f"Current SBM1 event parameters: [{current_sbm_dt1_sbm1}, {current_sbm_dt2_sbm1}, {current_sbm_dt3_sbm1}, {current_sbm_qf}]"
         | 
| 369 | 
            +
                                    )
         | 
| 346 370 | 
             
                                    # Set SBM1 duration
         | 
| 347 371 | 
             
                                    current_sbm_duration = int(current_sbm_dt2_sbm1)
         | 
| 348 372 | 
             
                                    # Get SBM1 start/end time (UTC)
         | 
| 349 373 | 
             
                                    if current_sbm_dt2_sbm1 < 2 * current_sbm_dt1_sbm1:
         | 
| 350 | 
            -
                                        current_sbm_end = current_sbm_time +  | 
| 351 | 
            -
             | 
| 352 | 
            -
             | 
| 353 | 
            -
                                        current_sbm_start = current_sbm_end -  | 
| 354 | 
            -
             | 
| 374 | 
            +
                                        current_sbm_end = current_sbm_time + timedelta(
         | 
| 375 | 
            +
                                            seconds=int(current_sbm_dt1_sbm1)
         | 
| 376 | 
            +
                                        )
         | 
| 377 | 
            +
                                        current_sbm_start = current_sbm_end - timedelta(
         | 
| 378 | 
            +
                                            seconds=int(current_sbm_duration)
         | 
| 379 | 
            +
                                        )
         | 
| 355 380 | 
             
                                    elif current_sbm_dt2_sbm1 > 2 * current_sbm_dt1_sbm1:
         | 
| 356 | 
            -
                                        current_sbm_end = current_sbm_time +  | 
| 357 | 
            -
             | 
| 358 | 
            -
             | 
| 359 | 
            -
                                        current_sbm_start = current_sbm_end -  | 
| 360 | 
            -
             | 
| 381 | 
            +
                                        current_sbm_end = current_sbm_time + timedelta(
         | 
| 382 | 
            +
                                            seconds=int(current_sbm_dt1_sbm1 + current_sbm_dt3_sbm1)
         | 
| 383 | 
            +
                                        )
         | 
| 384 | 
            +
                                        current_sbm_start = current_sbm_end - timedelta(
         | 
| 385 | 
            +
                                            seconds=current_sbm_duration
         | 
| 386 | 
            +
                                        )
         | 
| 361 387 | 
             
                                    else:
         | 
| 362 388 | 
             
                                        current_sbm_start = current_sbm_time - timedelta(
         | 
| 363 | 
            -
                                            seconds=(current_sbm_duration / 2) | 
| 389 | 
            +
                                            seconds=(current_sbm_duration / 2)
         | 
| 390 | 
            +
                                        )
         | 
| 364 391 | 
             
                                        current_sbm_end = current_sbm_time + timedelta(
         | 
| 365 | 
            -
                                            seconds=(current_sbm_duration / 2) | 
| 392 | 
            +
                                            seconds=(current_sbm_duration / 2)
         | 
| 393 | 
            +
                                        )
         | 
| 366 394 |  | 
| 367 395 | 
             
                                elif current_sbm_type == 2:
         | 
| 368 | 
            -
                                    current_sbm_duration = current_data[
         | 
| 369 | 
            -
             | 
| 370 | 
            -
             | 
| 371 | 
            -
             | 
| 372 | 
            -
             | 
| 396 | 
            +
                                    current_sbm_duration = current_data["HK_DPU_SBM2_DT_SBM2"]
         | 
| 397 | 
            +
                                    current_sbm_qf = sbm2_qf_eng(
         | 
| 398 | 
            +
                                        current_data["HK_RPW_S20_SBM2_QF_D"],
         | 
| 399 | 
            +
                                        idb_source=current_idb_source,
         | 
| 400 | 
            +
                                        idb_version=current_idb_version,
         | 
| 401 | 
            +
                                    )
         | 
| 373 402 | 
             
                                    # Get SBM2 start/end time (UTC)
         | 
| 374 403 | 
             
                                    current_sbm_start = current_sbm_time
         | 
| 375 404 | 
             
                                    current_sbm_end = current_sbm_time + timedelta(
         | 
| 376 | 
            -
                                        seconds=(int(current_sbm_duration) + 1) | 
| 405 | 
            +
                                        seconds=(int(current_sbm_duration) + 1)
         | 
| 406 | 
            +
                                    )
         | 
| 377 407 |  | 
| 378 | 
            -
                                    logger.debug( | 
| 408 | 
            +
                                    logger.debug(
         | 
| 409 | 
            +
                                        f"Current SBM2 event parameters: [{current_sbm_duration}, {current_sbm_qf}]"
         | 
| 410 | 
            +
                                    )
         | 
| 379 411 | 
             
                                else:
         | 
| 380 | 
            -
                                    logger.error( | 
| 412 | 
            +
                                    logger.error(
         | 
| 413 | 
            +
                                        f"Wrong SBM type: {current_sbm_type}! (should be 1 or 2)"
         | 
| 414 | 
            +
                                    )
         | 
| 381 415 | 
             
                                    continue
         | 
| 382 416 |  | 
| 383 417 | 
             
                                # Extend start_time/end_time by 1 minutes
         | 
| @@ -389,25 +423,30 @@ class L0ToL1Sbm(Task): | |
| 389 423 | 
             
                                current_sbm_l0 = L0.filter_l0_files(
         | 
| 390 424 | 
             
                                    l0_file_list,
         | 
| 391 425 | 
             
                                    start_time=current_sbm_start,
         | 
| 392 | 
            -
                                    end_time=current_sbm_end | 
| 426 | 
            +
                                    end_time=current_sbm_end,
         | 
| 427 | 
            +
                                )
         | 
| 393 428 |  | 
| 394 429 | 
             
                                # add current event to the list of events to return
         | 
| 395 430 | 
             
                                sbm_event_list.append(
         | 
| 396 | 
            -
                                    { | 
| 397 | 
            -
             | 
| 398 | 
            -
             | 
| 399 | 
            -
             | 
| 400 | 
            -
             | 
| 401 | 
            -
             | 
| 402 | 
            -
             | 
| 403 | 
            -
             | 
| 431 | 
            +
                                    {
         | 
| 432 | 
            +
                                        "start_time": current_sbm_start,
         | 
| 433 | 
            +
                                        "end_time": current_sbm_end,
         | 
| 434 | 
            +
                                        "sbm_time": current_sbm_time,
         | 
| 435 | 
            +
                                        "sbm_obt": current_sbm_obt,
         | 
| 436 | 
            +
                                        "sbm_type": current_sbm_type,
         | 
| 437 | 
            +
                                        "sbm_duration": current_sbm_duration,
         | 
| 438 | 
            +
                                        "sbm_algo": current_sbm_algo,
         | 
| 439 | 
            +
                                        "sbm_qf": current_sbm_qf,
         | 
| 440 | 
            +
                                        "sbm_l0": current_sbm_l0,
         | 
| 441 | 
            +
                                    }
         | 
| 404 442 | 
             
                                )
         | 
| 405 443 |  | 
| 406 444 | 
             
                    return sbm_event_list
         | 
| 407 445 |  | 
| 408 446 |  | 
| 409 | 
            -
            def sbm1_qf_eng( | 
| 410 | 
            -
             | 
| 447 | 
            +
            def sbm1_qf_eng(
         | 
| 448 | 
            +
                raw_values, tf_srdb_id=TF_PA_DPU_0038, idb_source="MIB", idb_version=None
         | 
| 449 | 
            +
            ):
         | 
| 411 450 | 
             
                """
         | 
| 412 451 | 
             
                Retrieve engineering values of the SBM1 event quality factor
         | 
| 413 452 |  | 
| @@ -417,12 +456,14 @@ def sbm1_qf_eng(raw_values, tf_srdb_id=TF_PA_DPU_0038, | |
| 417 456 | 
             
                :param idb_version:
         | 
| 418 457 | 
             
                :return: engineering values of SBM1 QF
         | 
| 419 458 | 
             
                """
         | 
| 420 | 
            -
                return raw_to_eng( | 
| 421 | 
            -
             | 
| 459 | 
            +
                return raw_to_eng(
         | 
| 460 | 
            +
                    raw_values, tf_srdb_id, idb_source=idb_source, idb_version=idb_version
         | 
| 461 | 
            +
                )
         | 
| 422 462 |  | 
| 423 463 |  | 
| 424 | 
            -
            def sbm2_qf_eng( | 
| 425 | 
            -
             | 
| 464 | 
            +
            def sbm2_qf_eng(
         | 
| 465 | 
            +
                raw_values, tf_srdb_id=TF_PA_DPU_0039, idb_source="MIB", idb_version=None
         | 
| 466 | 
            +
            ):
         | 
| 426 467 | 
             
                """
         | 
| 427 468 | 
             
                 Retrieve engineering values of the SBM2 event quality factor
         | 
| 428 469 |  | 
| @@ -432,5 +473,6 @@ def sbm2_qf_eng(raw_values, tf_srdb_id=TF_PA_DPU_0039, | |
| 432 473 | 
             
                :param idb_version:
         | 
| 433 474 | 
             
                :return: engineering values of SBM1 QF
         | 
| 434 475 | 
             
                """
         | 
| 435 | 
            -
                return raw_to_eng( | 
| 436 | 
            -
             | 
| 476 | 
            +
                return raw_to_eng(
         | 
| 477 | 
            +
                    raw_values, tf_srdb_id, idb_source=idb_source, idb_version=idb_version
         | 
| 478 | 
            +
                )
         |