data_manager.py 29.7 KB
Newer Older
BO ZHANG's avatar
BO ZHANG committed
1
2
3
4
5
6
7
8
"""
Identifier:     KSC-SJ4-csst_common/data_manager.py
Name:           data_manager.py
Description:    file path generator
Author:         Bo Zhang
Created:        2022-09-13
Modified-History:
    2022-09-13, Bo Zhang, created
BO ZHANG's avatar
tweaks    
BO ZHANG committed
9
    2022-09-13, Bo Zhang, added CsstMbiDataManager
BO ZHANG's avatar
BO ZHANG committed
10
    2022-09-29, Bo Zhang, favor CsstMsDataManager instead of CsstMbiDataManager
BO ZHANG's avatar
BO ZHANG committed
11
    2022-10-26, Bo Zhang, reconstruct CsstMsDataManager, deprecate CsstMbiDataManager
BO ZHANG's avatar
BO ZHANG committed
12
    2022-10-28, Bo Zhang, added CsstMsDataManager.query_rc(), dm.use_dfs, dm.node
BO ZHANG's avatar
BO ZHANG committed
13
    2022-11-06, Bo Zhang, deleted CsstMbiDataManager
BO ZHANG's avatar
BO ZHANG committed
14
    2022-11-20, Bo Zhang, added DFS APIs
BO ZHANG's avatar
BO ZHANG committed
15
"""
BO ZHANG's avatar
BO ZHANG committed
16
import _io
BO ZHANG's avatar
BO ZHANG committed
17
import glob
BO ZHANG's avatar
BO ZHANG committed
18
import os
BO ZHANG's avatar
BO ZHANG committed
19
import re
BO ZHANG's avatar
BO ZHANG committed
20
from typing import Union
BO ZHANG's avatar
BO ZHANG committed
21

BO ZHANG's avatar
BO ZHANG committed
22
import numpy as np
BO ZHANG's avatar
BO ZHANG committed
23
from astropy.io import fits
BO ZHANG's avatar
BO ZHANG committed
24
from astropy import time
BO ZHANG's avatar
BO ZHANG committed
25
from astropy.table import Table
BO ZHANG's avatar
BO ZHANG committed
26
27
from csst_dfs_api.facility.level0 import Level0DataApi
from csst_dfs_api.facility.level0prc import Level0PrcApi
BO ZHANG's avatar
BO ZHANG committed
28
29
from csst_dfs_api.facility.level1 import Level1DataApi
from csst_dfs_api.facility.level1prc import Level1PrcApi
BO ZHANG's avatar
BO ZHANG committed
30
from csst_dfs_api.mbi.level2 import Level2DataApi as MbiLevel2DataApi
BO ZHANG's avatar
BO ZHANG committed
31
from csst_dfs_api.sls.level2spectra import Level2SpectraApi as SlsLevel2DataApi
BO ZHANG's avatar
BO ZHANG committed
32
from csst_dfs_api.common.catalog import CatalogApi
BO ZHANG's avatar
BO ZHANG committed
33

BO ZHANG's avatar
BO ZHANG committed
34
from .logger import get_logger
35
from .params import CSST_PARAMS as CP
BO ZHANG's avatar
BO ZHANG committed
36
from .params import DFS_CONF
BO ZHANG's avatar
BO ZHANG committed
37
38


BO ZHANG's avatar
BO ZHANG committed
39
class CsstMsDataManager:
BO ZHANG's avatar
BO ZHANG committed
40
41
    """
    CSST MS data manager, including MBI and SLS.
BO ZHANG's avatar
tweaks    
BO ZHANG committed
42

BO ZHANG's avatar
tweaks    
BO ZHANG committed
43
44
45
46
    ``CsstMsDataManager`` provides an interface to switch between DFS and local file system.
    To initialize ``CsstMsDataManager`` from local directory, use ``CsstMsDataManager.from_dir()``
    To initialize ``CsstMsDataManager`` on ``dandelion`` or ``PM node``, ``CsstMsDataManager.quickstart()``.
    To initialize ``CsstMsDataManager`` from DFS, use ``CsstMsDataManager.from_dfs()``.
BO ZHANG's avatar
tweaks    
BO ZHANG committed
47
    To generate L0 and L1 file paths, use ``CsstMsDataManager.l0_detector()``, ``CsstMsDataManager.l1_detector()``, etc.
BO ZHANG's avatar
BO ZHANG committed
48
    Here are some examples for simulation with different versions.
BO ZHANG's avatar
BO ZHANG committed
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
    C3:
        MSC_MS_210525220000_100000020_06_raw.fits
        MSC_CRS_210525220000_100000020_06_raw.fits
        MSC_210525120000_0000020_06.cat
    C5.1:
        CSST_MSC_MS_SCI_20270810081950_20270810082220_100000100_06_L0_1.fits
        CSST_MSC_MS_CRS_20270810081950_20270810082220_100000100_06_L0_1.fits
        MSC_10000100_chip_06_filt_y.cat
        MSC_10000100_chip_06_filt_y.log
    C5.2
        CSST_MSC_MS_SCI_20270810081950_20270810082220_100000100_06_L0_1.fits
        CSST_MSC_MS_CRS_20270810081950_20270810082220_100000100_06_L0_1.fits
        MSC_100000100_chip_06_filt_y.cat
        MSC_100000100_chip_06_filt_y.log

BO ZHANG's avatar
BO ZHANG committed
64
65
66
    Parameters
    ----------
    ver_sim : str
BO ZHANG's avatar
BO ZHANG committed
67
68
69
70
71
72
73
74
75
        The version of simulation data, see ``csst_common.params.CP``.
    datatype : str
        The options are {"mbi", "sls", "all"}.
        The "all" option is used for QC in particular.
        Note that in this case methods like ``get_bias`` are unavailable.
    available_detectors : list
        The list of available detector serial numbers of available images.
    target_detectors : list
        The list of target detector serial numbers of available images.
BO ZHANG's avatar
BO ZHANG committed
76
77
78
79
    dir_l0 : str
        The L0 directory.
    dir_l1 : str
        The L1 directory.
BO ZHANG's avatar
BO ZHANG committed
80
81
    path_aux : str
        The aux data directory (bias, flat, dark).
BO ZHANG's avatar
BO ZHANG committed
82
83
    use_dfs : bool
        If True, use DFS. In case some modules may have other options such as astroquery.
BO ZHANG's avatar
BO ZHANG committed
84
    dfs_node : str
BO ZHANG's avatar
BO ZHANG committed
85
86
        The environment in which the pipeline will run.
        Use "pml" for Purple Mountain Lab cluster and "local" for others.
BO ZHANG's avatar
BO ZHANG committed
87
88
    dfs_root : str
        The DFS root path.
BO ZHANG's avatar
BO ZHANG committed
89
    obs_id : str
BO ZHANG's avatar
BO ZHANG committed
90
        The exposure ID.
BO ZHANG's avatar
BO ZHANG committed
91
    exp_start : int
BO ZHANG's avatar
BO ZHANG committed
92
        The exposure start time in ``yyyymmddhhmmss`` format.
BO ZHANG's avatar
BO ZHANG committed
93
    exp_stop : int
BO ZHANG's avatar
BO ZHANG committed
94
95
96
97
98
99
100
        The exposure start time in ``yyyymmddhhmmss`` format.
    _telescope : str
        The telescope name. Defaults to ``CSST`` for C5.2 simulation.
    _instrument : str
        The instrument name. Defaults to ``MSC`` for C5.2 simulation.
    _survey : str
        The survey name. Defaults to ``MS`` for C5.2 simulation.
BO ZHANG's avatar
BO ZHANG committed
101
    obs_type : str
BO ZHANG's avatar
BO ZHANG committed
102
        The image type signature for science images. Defualts to ``SCI`` for C5.2 simulation.
BO ZHANG's avatar
BO ZHANG committed
103
    l0_post : str
BO ZHANG's avatar
BO ZHANG committed
104
        The postfix. Defaults to ``L0_1`` for C5.2 simulation.
BO ZHANG's avatar
BO ZHANG committed
105
106
107
108
    log_ppl : str
        The pipeline log file name.
    log_mod : str
        The module log file name.
109
110
    clear_dir : bool
        If True, clear ``dm.dir_l1`` directory.
BO ZHANG's avatar
BO ZHANG committed
111
112
    verbose : bool
        If True, print verbose info.
BO ZHANG's avatar
BO ZHANG committed
113
114
115
116
    n_jobs : int
        The number of jobs.
    backend : str
        The joblib backend.
BO ZHANG's avatar
BO ZHANG committed
117
118
    device : str
        The device for neural network. "CPU" or "GPU".
BO ZHANG's avatar
BO ZHANG committed
119
120
121

    Examples
    --------
BO ZHANG's avatar
BO ZHANG committed
122
    >>> dm_mbi = CsstMsDataManager(...)
BO ZHANG's avatar
BO ZHANG committed
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
    >>> # access L0 directory
    >>> dm_mbi.dir_l0
    >>> # access L1 directory
    >>> dm_mbi.dir_l1
    >>> # access path_aux
    >>> dm_mbi.path_aux
    >>> # access ver_sim
    >>> dm_mbi.ver_sim
    >>> # access target detectors
    >>> dm_mbi.target_detectors
    >>> # access available detectors
    >>> dm_mbi.available_detectors
    >>> # define an L1 file (detector-specified)
    >>> dm_mbi.l1_detector(detector=6)
    >>> # define an L1 file (non-detector-specified)
    >>> dm_mbi.l1_file("flipped_image.fits")
BO ZHANG's avatar
BO ZHANG committed
139
140
    """

BO ZHANG's avatar
BO ZHANG committed
141
    def __init__(self,
BO ZHANG's avatar
tweaks    
BO ZHANG committed
142
143
144
                 ver_sim: str = "C5.2",
                 datatype: str = "mbi",
                 available_detectors: Union[None, list] = None,
BO ZHANG's avatar
BO ZHANG committed
145
                 target_detectors: Union[None, list, int] = None,
BO ZHANG's avatar
tweaks    
BO ZHANG committed
146
147
                 dir_l0: str = ".",
                 dir_l1: str = ".",
BO ZHANG's avatar
BO ZHANG committed
148
                 path_aux: str = "/L1Pipeline/aux",  # aux dir
BO ZHANG's avatar
BO ZHANG committed
149
                 use_dfs: bool = False,
BO ZHANG's avatar
BO ZHANG committed
150
                 dfs_node: str = "kmust",
BO ZHANG's avatar
BO ZHANG committed
151
                 dfs_root: str = "/share/dfs",
BO ZHANG's avatar
BO ZHANG committed
152
153
154
                 obs_id: str = "100000100",
                 exp_start: int = "20270810081950",
                 exp_stop: int = "20270810082220",
BO ZHANG's avatar
tweaks    
BO ZHANG committed
155
156
157
                 _telescope: str = "CSST",
                 _instrument: str = "MSC",
                 _survey: str = "MS",
BO ZHANG's avatar
BO ZHANG committed
158
159
                 obs_type: str = "SCI",
                 l0_post: str = "L0_1",
BO ZHANG's avatar
BO ZHANG committed
160
161
                 log_ppl="",
                 log_mod="",
162
                 clear_dir=False,
BO ZHANG's avatar
BO ZHANG committed
163
                 verbose=True,
BO ZHANG's avatar
BO ZHANG committed
164
                 n_jobs=18,
BO ZHANG's avatar
BO ZHANG committed
165
                 backend="multiprocessing",
BO ZHANG's avatar
BO ZHANG committed
166
167
                 device="CPU",
                 stamps="",
BO ZHANG's avatar
BO ZHANG committed
168
169
                 ):

BO ZHANG's avatar
BO ZHANG committed
170
171
172
        # set DFS log dir
        os.environ["CSST_DFS_LOGS_DIR"] = "."

BO ZHANG's avatar
BO ZHANG committed
173
        # version
BO ZHANG's avatar
BO ZHANG committed
174
        assert ver_sim in CP["sim"]["versions"]
BO ZHANG's avatar
tweaks    
BO ZHANG committed
175
        self.ver_sim = ver_sim
BO ZHANG's avatar
BO ZHANG committed
176

BO ZHANG's avatar
BO ZHANG committed
177
        # datatype, valid_detectors, detector2filter
178
        assert datatype in ["mbi", "sls", "all"]
BO ZHANG's avatar
tweaks    
BO ZHANG committed
179
        self.datatype = datatype
BO ZHANG's avatar
BO ZHANG committed
180
181
182
183
        if datatype == "mbi":
            # MBI
            self.valid_detectors = CP["mbi"]["detectors"]
            self.detector2filter = CP["mbi"]["detector2filter"]
184
        elif datatype == "sls":
BO ZHANG's avatar
BO ZHANG committed
185
186
187
            # SLS
            self.valid_detectors = CP["sls"]["detectors"]
            self.detector2filter = CP["sls"]["detector2filter"]
188
189
        else:
            # ALL
BO ZHANG's avatar
BO ZHANG committed
190
191
            self.valid_detectors = CP["all"]["detectors"]
            self.detector2filter = CP["all"]["detector2filter"]
BO ZHANG's avatar
BO ZHANG committed
192
193
194
        if verbose:
            print("Data type is: ", self.datatype)
            print("Valid detectors are: ", self.valid_detectors)
BO ZHANG's avatar
BO ZHANG committed
195
196

        # available_detectors
197
        self.available_detectors = available_detectors if available_detectors is not None else list()
BO ZHANG's avatar
BO ZHANG committed
198
199
        if verbose:
            print("Available detectors are:", self.available_detectors)
BO ZHANG's avatar
BO ZHANG committed
200
        # set all available detectors by default
201
        self.target_detectors = target_detectors
BO ZHANG's avatar
BO ZHANG committed
202
203
        if verbose:
            print("Target detectors are: ", self._target_detectors)
BO ZHANG's avatar
BO ZHANG committed
204
205

        # exposure info
BO ZHANG's avatar
BO ZHANG committed
206
207
208
        self.obs_id = obs_id
        self.exp_start = exp_start
        self.exp_stop = exp_stop
BO ZHANG's avatar
BO ZHANG committed
209

BO ZHANG's avatar
BO ZHANG committed
210
211
212
213
        # file name components
        self._telescope = _telescope
        self._instrument = _instrument
        self._survey = _survey
BO ZHANG's avatar
BO ZHANG committed
214
215
        self.obs_type = obs_type
        self.l0_post = l0_post
BO ZHANG's avatar
BO ZHANG committed
216

BO ZHANG's avatar
BO ZHANG committed
217
218
        # DFS configuration
        self.use_dfs = use_dfs
219
        self.dfs_node = dfs_node
BO ZHANG's avatar
BO ZHANG committed
220
        self.dfs_root = dfs_root
BO ZHANG's avatar
BO ZHANG committed
221
222

        # data directory
BO ZHANG's avatar
BO ZHANG committed
223
224
225
        self.dir_l0 = dir_l0
        self.dir_l1 = dir_l1
        self.path_aux = path_aux
BO ZHANG's avatar
BO ZHANG committed
226
        self.ref_version = None
BO ZHANG's avatar
BO ZHANG committed
227

BO ZHANG's avatar
BO ZHANG committed
228
        # record hard code names in history
BO ZHANG's avatar
BO ZHANG committed
229
230
        self.hardcode_history = []

BO ZHANG's avatar
BO ZHANG committed
231
232
        self.n_jobs = n_jobs
        self.backend = backend
BO ZHANG's avatar
BO ZHANG committed
233
        self.device = device
BO ZHANG's avatar
BO ZHANG committed
234

BO ZHANG's avatar
BO ZHANG committed
235
        # aXe
BO ZHANG's avatar
BO ZHANG committed
236
        self.set_env()
BO ZHANG's avatar
BO ZHANG committed
237

BO ZHANG's avatar
BO ZHANG committed
238
239
        # change to working directory
        os.chdir(self.dir_l1)
240
241
242
        # clear dir_l1
        if clear_dir:
            self.clear_dir(self.dir_l1)
BO ZHANG's avatar
BO ZHANG committed
243

BO ZHANG's avatar
BO ZHANG committed
244
        # pipeline logger
BO ZHANG's avatar
BO ZHANG committed
245
246
247
        if log_ppl == "":
            self.logger_ppl = get_logger(name="CSST L1 Pipeline Logger", filename="")
        else:
BO ZHANG's avatar
BO ZHANG committed
248
            self.logger_ppl = get_logger(name="CSST L1 Pipeline Logger", filename=os.path.join(dir_l1, log_ppl))
BO ZHANG's avatar
BO ZHANG committed
249
        # module logger
BO ZHANG's avatar
BO ZHANG committed
250
251
252
        if log_mod == "":
            self.logger_mod = get_logger(name="CSST L1 Module Logger", filename="")
        else:
BO ZHANG's avatar
BO ZHANG committed
253
            self.logger_mod = get_logger(name="CSST L1 Module Logger", filename=os.path.join(dir_l1, log_mod))
BO ZHANG's avatar
BO ZHANG committed
254

255
256
257
258
        self.custom_bias = None
        self.custom_dark = None
        self.custom_flat = None

BO ZHANG's avatar
BO ZHANG committed
259
260
261
262
263
264
265
266
267
268
        if stamps == "" or stamps is None:
            self.stamps = None
        else:
            self.stamps = open(stamps, "w+")
            self.write_stamp()

    def write_stamp(self):
        if self.stamps is not None:
            self.stamps.write(f"{time.Time.now().isot}\n")

269
270
271
272
273
274
    # DFS APIs
    @property
    def dfs_L0DataApi(self):
        return Level0DataApi()

    @property
BO ZHANG's avatar
BO ZHANG committed
275
276
    def dfs_L0PrcApi(self):
        return Level0PrcApi()
277
278

    @property
BO ZHANG's avatar
BO ZHANG committed
279
280
    def dfs_L1DataApi(self):
        return Level1DataApi()
281
282

    @property
BO ZHANG's avatar
BO ZHANG committed
283
284
    def dfs_L1PrcApi(self):
        return Level1PrcApi()
BO ZHANG's avatar
BO ZHANG committed
285
286
287
288

    @property
    def dfs_MbiL2DataApi(self):
        return MbiLevel2DataApi()
289

BO ZHANG's avatar
BO ZHANG committed
290
291
292
293
    @property
    def dfs_SlsL2DataApi(self):
        return SlsLevel2DataApi()

BO ZHANG's avatar
BO ZHANG committed
294
295
296
297
    @property
    def dfs_CatApi(self):
        return CatalogApi()

BO ZHANG's avatar
BO ZHANG committed
298
299
300
    def set_env(self):
        """ set environment variables """
        if os.uname()[1] == "dandelion":
BO ZHANG's avatar
BO ZHANG committed
301
302
            os.environ["LD_LIBRARY_PATH"] = "/home/csstpipeline/anaconda3/lib"
            os.environ["AXE_BINDIR"] = "/home/csstpipeline/PycharmProjects/axe/cextern/src"
BO ZHANG's avatar
BO ZHANG committed
303
304
        else:
            os.environ["LD_LIBRARY_PATH"] = ""
BO ZHANG's avatar
BO ZHANG committed
305
            os.environ["AXE_BINDIR"] = ""
BO ZHANG's avatar
BO ZHANG committed
306

307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
    @property
    def target_detectors(self):
        return self._target_detectors

    @target_detectors.setter
    def target_detectors(self, detectors: Union[None, list, int] = None):
        assert detectors is None or type(detectors) in [list, int]
        if detectors is None:
            self._target_detectors = list(set(self.available_detectors) & set(self.valid_detectors))
        elif isinstance(detectors, list):
            self._target_detectors = list(set(self.available_detectors) & set(self.valid_detectors) & set(detectors))
        elif isinstance(detectors, int):
            self._target_detectors = list(set(self.available_detectors) & set(self.valid_detectors) & {detectors})

    def set_detectors(self, detectors=None):
        raise DeprecationWarning("This method is deprecated, please directly use dm.target_detectors = detectors!")

BO ZHANG's avatar
BO ZHANG committed
324
    @staticmethod
BO ZHANG's avatar
BO ZHANG committed
325
326
327
328
329
330
331
332
    def from_dir(
            ver_sim="C5.2",
            datatype="mbi",
            dir_l0=".",
            dir_l1=".",
            path_aux="",
            use_dfs=False,
            dfs_node="kmust",
BO ZHANG's avatar
BO ZHANG committed
333
334
            log_ppl="csst-l1ppl.log",
            log_mod="csst-l1mod.log",
BO ZHANG's avatar
BO ZHANG committed
335
            n_jobs=18,
BO ZHANG's avatar
BO ZHANG committed
336
            backend="multiprocessing",
BO ZHANG's avatar
BO ZHANG committed
337
338
            device="CPU",
            **kwargs
BO ZHANG's avatar
BO ZHANG committed
339
    ):
BO ZHANG's avatar
BO ZHANG committed
340
        """ initialize the multi-band imaging data manager """
BO ZHANG's avatar
BO ZHANG committed
341

BO ZHANG's avatar
BO ZHANG committed
342
        assert ver_sim in CP["sim"]["versions"]
BO ZHANG's avatar
BO ZHANG committed
343
344
345
346
347
348
349
350
351
352
353

        # glob files
        fps_img = CsstMsDataManager.glob_image(dir_l0, ver_sim=ver_sim)
        if len(fps_img) == 0:
            raise FileNotFoundError(f"No file found in dir_l0: {dir_l0}")

        # available detectors
        available_detectors = [int(re.split(r"[_.]", fp)[7]) for fp in fps_img]
        available_detectors.sort()

        # parse info
BO ZHANG's avatar
BO ZHANG committed
354
355
356
        (_telescope, _instrument, _survey, obs_type,
         exp_start, exp_stop, obs_id,
         _detector, *l0_post, _ext) = re.split(r"[_.]", fps_img[0])
BO ZHANG's avatar
BO ZHANG committed
357

BO ZHANG's avatar
BO ZHANG committed
358
359
360
        # exp_start = int(exp_start)
        # exp_stop = int(exp_stop)
        # obs_id = int(obs_id)
BO ZHANG's avatar
BO ZHANG committed
361

BO ZHANG's avatar
BO ZHANG committed
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
        return CsstMsDataManager(
            ver_sim=ver_sim,
            datatype=datatype,
            available_detectors=available_detectors,
            target_detectors=None,
            dir_l0=dir_l0,
            dir_l1=dir_l1,
            path_aux=path_aux,  # bias dark flat
            use_dfs=use_dfs,
            dfs_node=dfs_node,
            obs_id=obs_id,
            exp_start=exp_start,
            exp_stop=exp_stop,
            _telescope=_telescope,
            _instrument=_instrument,
            _survey=_survey,
            obs_type=obs_type,
            l0_post="_".join(l0_post),
BO ZHANG's avatar
BO ZHANG committed
380
381
            log_ppl=log_ppl,
            log_mod=log_mod,
BO ZHANG's avatar
BO ZHANG committed
382
            n_jobs=n_jobs,
BO ZHANG's avatar
BO ZHANG committed
383
            backend=backend,
BO ZHANG's avatar
BO ZHANG committed
384
385
            device=device,
            **kwargs
BO ZHANG's avatar
BO ZHANG committed
386
        )
BO ZHANG's avatar
BO ZHANG committed
387

BO ZHANG's avatar
BO ZHANG committed
388
    @staticmethod
BO ZHANG's avatar
BO ZHANG committed
389
    def glob_image(dir_l0, ver_sim="C5.2"):
BO ZHANG's avatar
BO ZHANG committed
390
        """ glob files in L0 data directory """
BO ZHANG's avatar
BO ZHANG committed
391
392
        assert ver_sim in CP["sim"]["versions"]
        pattern = os.path.join(dir_l0, "CSST_MSC_MS_SCI_*.fits")
BO ZHANG's avatar
BO ZHANG committed
393
394
395
396
        fps = glob.glob(pattern)
        fps = [os.path.basename(fp) for fp in fps]
        fps.sort()

397
        print("{} files found with pattern: {}".format(len(fps), pattern))
BO ZHANG's avatar
BO ZHANG committed
398
399
400
401
402
        return fps

    @staticmethod
    def glob_cat(dir_l0, ver_sim="C5"):
        """ glob input catalogs in L0 data directory """
BO ZHANG's avatar
BO ZHANG committed
403
        assert ver_sim in CP["sim"]["versions"]
BO ZHANG's avatar
BO ZHANG committed
404
        pattern = os.path.join(dir_l0, "MSC_*.cat")
BO ZHANG's avatar
BO ZHANG committed
405
406
407
408
409
410
411
        fps = glob.glob(pattern)
        fps = [os.path.basename(fp) for fp in fps]
        fps.sort()

        print("@DM.glob_dir: {} files found with pattern: {}".format(len(fps), pattern))
        return fps

BO ZHANG's avatar
BO ZHANG committed
412
413
414
415
    def l0_id(self, detector=6):
        """ Level0 ID, consistent with DFS. """
        return f"{self.obs_id}{detector:02d}"

BO ZHANG's avatar
BO ZHANG committed
416
417
    def l0_cat(self, detector=6):
        """ the L0 cat file path"""
BO ZHANG's avatar
BO ZHANG committed
418
        assert self.ver_sim in CP["sim"]["versions"]
BO ZHANG's avatar
BO ZHANG committed
419
        fn = "{}_{}_chip_{:02d}_filt_{}.cat".format(
BO ZHANG's avatar
BO ZHANG committed
420
            self._instrument, self.obs_id, detector, self.detector2filter[detector])
BO ZHANG's avatar
BO ZHANG committed
421
422
423
424
        return os.path.join(self.dir_l0, fn)

    def l0_log(self, detector=6):
        """ L0 log file path """
BO ZHANG's avatar
BO ZHANG committed
425
        assert self.ver_sim in CP["sim"]["versions"]
BO ZHANG's avatar
BO ZHANG committed
426
        fn = "{}_{}_chip_{:02d}_filt_{}.log".format(
BO ZHANG's avatar
BO ZHANG committed
427
            self._instrument, self.obs_id, detector, self.detector2filter[detector])
BO ZHANG's avatar
BO ZHANG committed
428
429
430
431
        return os.path.join(self.dir_l0, fn)

    def l0_detector(self, detector=6):
        """ L0 detector-specific image file path """
BO ZHANG's avatar
BO ZHANG committed
432
        assert self.ver_sim in CP["sim"]["versions"]
BO ZHANG's avatar
BO ZHANG committed
433
434
        fn = "{}_{}_{}_SCI_{}_{}_{}_{:02d}_L0_1.fits".format(
            self._telescope, self._instrument, self._survey,
BO ZHANG's avatar
BO ZHANG committed
435
            self.exp_start, self.exp_stop, self.obs_id, detector)
BO ZHANG's avatar
BO ZHANG committed
436
437
438
439
        return os.path.join(self.dir_l0, fn)

    def l0_crs(self, detector=6):
        """ L0 cosmic ray file path """
BO ZHANG's avatar
BO ZHANG committed
440
        assert self.ver_sim in CP["sim"]["versions"]
BO ZHANG's avatar
BO ZHANG committed
441
442
        fn = "{}_{}_{}_CRS_{}_{}_{}_{:02d}_L0_1.fits".format(
            self._telescope, self._instrument, self._survey,
BO ZHANG's avatar
BO ZHANG committed
443
            self.exp_start, self.exp_stop, self.obs_id, detector)
BO ZHANG's avatar
BO ZHANG committed
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
        return os.path.join(self.dir_l0, fn)

    def l1_detector(self, detector=6, post="img.fits"):
        """ generate L1 file path

        Parameters
        ----------
        detector:
            detector ID
        post:
            postfix
            e.g, {"img.fits", "wht.fits", "flg.fits", "img_L1.fits", "wht_L1.fits", "flg_L1.fits"}

        Returns
        -------
        L1 file path

        """
BO ZHANG's avatar
BO ZHANG committed
462
        assert self.ver_sim in CP["sim"]["versions"]
BO ZHANG's avatar
BO ZHANG committed
463
464
        fn = "{}_{}_{}_SCI_{}_{}_{}_{:02d}_{}".format(
            self._telescope, self._instrument, self._survey,
BO ZHANG's avatar
BO ZHANG committed
465
            self.exp_start, self.exp_stop, self.obs_id, detector, post)
BO ZHANG's avatar
BO ZHANG committed
466
467
        return os.path.join(self.dir_l1, fn)

BO ZHANG's avatar
BO ZHANG committed
468
    def get_bias(self, detector=6):
BO ZHANG's avatar
tweaks    
BO ZHANG committed
469
        """ get bias data """
470
        if self.custom_bias is None:
BO ZHANG's avatar
BO ZHANG committed
471
472
473
474
475
476
477
            return os.path.join(
                self.path_aux,
                "C6.1_ref_crds",
                "csst_msc_{}_{:02d}_{:04d}.fits".format(
                    "bias", detector, 1 if self.ref_version is None else self.ref_version
                )
            )
BO ZHANG's avatar
BO ZHANG committed
478
        else:
479
            return self.custom_bias.format("bias", detector)
BO ZHANG's avatar
BO ZHANG committed
480

BO ZHANG's avatar
BO ZHANG committed
481
    def get_dark(self, detector=6):
BO ZHANG's avatar
tweaks    
BO ZHANG committed
482
        """ get dark data """
483
        if self.custom_dark is None:
BO ZHANG's avatar
BO ZHANG committed
484
485
486
487
488
489
490
            return os.path.join(
                self.path_aux,
                "C6.1_ref_crds",
                "csst_msc_{}_{:02d}_{:04d}.fits".format(
                    "dark", detector, 1 if self.ref_version is None else self.ref_version
                )
            )
BO ZHANG's avatar
BO ZHANG committed
491
        else:
492
            return self.custom_dark.format("dark", detector)
BO ZHANG's avatar
BO ZHANG committed
493

BO ZHANG's avatar
BO ZHANG committed
494
    def get_flat(self, detector=6):
BO ZHANG's avatar
tweaks    
BO ZHANG committed
495
        """ get flat data """
496
        if self.custom_flat is None:
BO ZHANG's avatar
BO ZHANG committed
497
498
499
500
501
502
503
            return os.path.join(
                self.path_aux,
                "C6.1_ref_crds",
                "csst_msc_{}_{:02d}_{:04d}.fits".format(
                    "flat", detector, 1 if self.ref_version is None else self.ref_version
                )
            )
BO ZHANG's avatar
BO ZHANG committed
504
        else:
505
            return self.custom_flat.format("flat", detector)
BO ZHANG's avatar
BO ZHANG committed
506

BO ZHANG's avatar
BO ZHANG committed
507
    def get_axeconf(self):
BO ZHANG's avatar
BO ZHANG committed
508
        return os.path.join(self.path_aux, "axeconf")  # "/home/csstpipeline/L1Pipeline/aux/axeconf"
BO ZHANG's avatar
BO ZHANG committed
509

BO ZHANG's avatar
BO ZHANG committed
510
511
512
513
514
    def l1_file(self, name="", comment=""):
        """ L1 file path

        Parameters
        ----------
BO ZHANG's avatar
BO ZHANG committed
515
        name : str
BO ZHANG's avatar
BO ZHANG committed
516
            file name
BO ZHANG's avatar
BO ZHANG committed
517
        comment : str
BO ZHANG's avatar
BO ZHANG committed
518
519
520
521
522
523
524
525
526
527
528
529
530
            use the function name plz

        Returns
        -------
        fp: str
            the synthetic file path

        """
        fp = os.path.join(self.dir_l1, name)
        # record hardcode history
        self.hardcode_history.append(dict(hdcd=fp, comment=comment))
        return fp

BO ZHANG's avatar
tweaks    
BO ZHANG committed
531
532
    def get_sls_info(self):
        """ Get the target SLS image header info and return. """
BO ZHANG's avatar
BO ZHANG committed
533
        # if self.use_dfs:
BO ZHANG's avatar
BO ZHANG committed
534
535
536
537
        #     raise NotImplementedError()
        # else:
        assert len(self.target_detectors) == 1
        header = fits.getheader(self.l0_detector(self.target_detectors[0]), ext=1)
BO ZHANG's avatar
BO ZHANG committed
538
539
        return header

BO ZHANG's avatar
tweaks    
BO ZHANG committed
540
541
    def get_mbi_info(self):
        """ Get all MBI image header info and return as a table. """
BO ZHANG's avatar
BO ZHANG committed
542
        # if self.use_dfs:
BO ZHANG's avatar
BO ZHANG committed
543
544
545
        #     raise NotImplementedError()
        # else:
        info = Table.read("/nfsdata/share/csst_simulation_data/Cycle-5-SimuData/slitlessSpectroscopy/t_mbi_l1.fits")
BO ZHANG's avatar
BO ZHANG committed
546
547
        return info

BO ZHANG's avatar
BO ZHANG committed
548
    @staticmethod
549
    def quickstart(ver_sim="C5.2", datatype="mbi", dir_l1=".", exposure_id=100,
550
                   use_dfs=False, dfs_node="kmust", clear_l1=False, n_jobs=18, backend="multiprocessing"):
551
552
        """
        Quick dataset generator for tests on dandelion or PML
BO ZHANG's avatar
BO ZHANG committed
553
554
555

        Parameters
        ----------
BO ZHANG's avatar
BO ZHANG committed
556
        ver_sim : str
BO ZHANG's avatar
BO ZHANG committed
557
            {"C5.2"}
BO ZHANG's avatar
BO ZHANG committed
558
        datatype : str
BO ZHANG's avatar
BO ZHANG committed
559
            {"mbi", "sls"}
BO ZHANG's avatar
BO ZHANG committed
560
        dir_l1 : str
BO ZHANG's avatar
BO ZHANG committed
561
            output directory
BO ZHANG's avatar
BO ZHANG committed
562
        exposure_id : int
BO ZHANG's avatar
BO ZHANG committed
563
            The serial number of the exposure. 20-154 for C5.2.
BO ZHANG's avatar
BO ZHANG committed
564
        use_dfs : bool
BO ZHANG's avatar
BO ZHANG committed
565
            If True, use DFS.
BO ZHANG's avatar
BO ZHANG committed
566
567
        dfs_node : str
            The DFS node. Defaults to "kmust", could be "pml".
568
        clear_l1 : bool
569
            If True, clear dir_l1.
570
571
572
573
        n_jobs : int
            The number of jobs.
        backend : str
            The joblib backend.
BO ZHANG's avatar
BO ZHANG committed
574
575
576

        Returns
        -------
BO ZHANG's avatar
tweaks    
BO ZHANG committed
577
        CsstMsDataManager
BO ZHANG's avatar
BO ZHANG committed
578
            The Main Survey Data Manager instance.
BO ZHANG's avatar
BO ZHANG committed
579
580
581
582
583
584
585
586
587
588
        """
        assert datatype in ["mbi", "sls"]
        # auto identify node name
        hostname = os.uname()[1]
        assert hostname in ["dandelion", "ubuntu"]

        # dandelion
        if hostname == "dandelion" and datatype == "mbi":
            dir_l0 = "/nfsdata/share/csst_simulation_data/Cycle-5-SimuData/multipleBandsImaging/" \
                     "NGP_AstrometryON_shearOFF/MSC_{:07d}/".format(exposure_id)
BO ZHANG's avatar
BO ZHANG committed
589
            path_aux = "/nfsdata/users/csstpipeline/L1Pipeline/aux"
BO ZHANG's avatar
BO ZHANG committed
590
        elif hostname == "dandelion" and datatype == "sls":
BO ZHANG's avatar
BO ZHANG committed
591
            dir_l0 = "/nfsdata/share/csst_simulation_data/Cycle-5-SimuData/slitlessSpectroscopy/" \
BO ZHANG's avatar
BO ZHANG committed
592
                     "NGP_AstrometryON_shearOFF_Spec/MSC_{:07d}/".format(exposure_id)
BO ZHANG's avatar
BO ZHANG committed
593
            path_aux = "/nfsdata/users/csstpipeline/L1Pipeline/aux"
BO ZHANG's avatar
BO ZHANG committed
594
595
596
597
598

        # PMO
        elif hostname == "ubuntu" and datatype == "mbi":
            dir_l0 = "/share/simudata/CSSOSDataProductsSims/data/CSSTSimImage_C5/" \
                     "NGP_AstrometryON_shearOFF/MSC_{:07d}/".format(exposure_id)
BO ZHANG's avatar
BO ZHANG committed
599
            path_aux = "/L1Pipeline/aux"
BO ZHANG's avatar
BO ZHANG committed
600
601
602
        elif hostname == "ubuntu" and datatype == "sls":
            dir_l0 = "/share/simudata/CSSOSDataProductsSims/data/CSSTSimImage_C5/" \
                     "NGP_AstrometryON_shearOFF_Spec/MSC_{:07d}/".format(exposure_id)
BO ZHANG's avatar
BO ZHANG committed
603
            path_aux = "/L1Pipeline/aux"
BO ZHANG's avatar
BO ZHANG committed
604
        else:
BO ZHANG's avatar
tweaks    
BO ZHANG committed
605
            raise ValueError("@DM: invalid hostname {} or datatype {}!".format(hostname, datatype))
BO ZHANG's avatar
BO ZHANG committed
606

BO ZHANG's avatar
BO ZHANG committed
607
        return CsstMsDataManager.from_dir(
BO ZHANG's avatar
BO ZHANG committed
608
            ver_sim=ver_sim, datatype=datatype, dir_l0=dir_l0, dir_l1=dir_l1, path_aux=path_aux,
BO ZHANG's avatar
BO ZHANG committed
609
610
            use_dfs=use_dfs, dfs_node=dfs_node, n_jobs=n_jobs, backend=backend
        )
BO ZHANG's avatar
BO ZHANG committed
611

612
613
614
    def __repr__(self):
        lines = ""
        lines += "<CsstMsDataManager>\n"
615
616
617
618
619
620
        lines += f"- Data type = {self.datatype}\n"
        lines += f"- Valid detectors = {self.valid_detectors}\n"
        lines += f"- Available detectors = {self.available_detectors}\n"
        lines += f"- Target detectors = {self.target_detectors}\n"
        lines += f"- dir_l0 = {self.dir_l0}\n"
        lines += f"- dir_l1 = {self.dir_l1}\n"
BO ZHANG's avatar
BO ZHANG committed
621
        lines += f"- use_dfs = {self.use_dfs}\n"
622
623
        lines += f"- dfs_node = {self.dfs_node}\n"
        lines += f"- CSST_DFS_GATEWAY = " + os.getenv("CSST_DFS_GATEWAY") + "\n"
624
625
        return lines

626
    def remove_files(self, fmt="*.fits"):
BO ZHANG's avatar
BO ZHANG committed
627
        """ Remove L1 files conforming the format. """
628
        os.system(f"rm -rf {os.path.join(self.dir_l1, fmt)}")
629

BO ZHANG's avatar
BO ZHANG committed
630
631
632
633
    def remove_dir(self, dir_name):
        """ Remove L1 (sub-)directory. """
        os.system(f"rm -rf {os.path.join(self.dir_l1, dir_name)}")

634
635
636
637
    @staticmethod
    def clear_dir(dir_path):
        os.system(f"rm -rf {dir_path}/*")

BO ZHANG's avatar
BO ZHANG committed
638
639
640
641
642
643
644
645
646
647
648
649
    # DFS interfaces
    @property
    def dfs_node(self):
        return self._dfs_node

    @dfs_node.setter
    def dfs_node(self, dfs_node):
        # for DFS configuration, defaults to "local", could be "pml"
        assert dfs_node in DFS_CONF.keys()
        self._dfs_node = dfs_node
        for k, v in DFS_CONF[dfs_node].items():
            os.environ[k] = v
650

651
652
    @staticmethod
    def dfs_is_available():
BO ZHANG's avatar
BO ZHANG committed
653
654
        """ Test if DFS works. """
        try:
BO ZHANG's avatar
BO ZHANG committed
655
            tbl = CatalogApi().catalog_query(
BO ZHANG's avatar
tweaks    
BO ZHANG committed
656
657
658
659
660
661
662
663
664
                catalog_name="gaia3",
                ra=180,
                dec=0,
                radius=.1,
                columns=("ra", "dec"),
                min_mag=0,
                max_mag=30,
                obstime=-1,
                limit=-1
BO ZHANG's avatar
BO ZHANG committed
665
666
            )
            return len(tbl) > 0
BO ZHANG's avatar
BO ZHANG committed
667
668
669
        except:
            return False

670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
    def get_coord(self):
        """ Get pointing coordinate. """
        header = fits.getheader(self.l0_detector(detector=self.target_detectors[0]))
        pointing_ra = header["RA_OBJ"]
        pointing_dec = header["DEC_OBJ"]
        return pointing_ra, pointing_dec

    def dfs_rc_auto(self):
        """ Download RC. """
        assert self.dfs_is_available()
        assert len(self.target_detectors) >= 1
        pointing_ra, pointing_dec = self.get_coord()
        refcat = self.dfs_rc_query(
            ra=pointing_ra,
            dec=pointing_dec,
            columns=(
                    'ref_epoch',
                    'ra',
                    'ra_error',
                    'dec',
                    'dec_error',
                    'parallax',
                    'parallax_error',
                    'pmra',
                    'pmra_error',
                    'pmdec',
                    'pmdec_error',
                    'phot_g_mean_mag',
                    'source_id'
            ),
            radius=2,
            min_mag=0,
            max_mag=30,
            obstime=-1,
            limit=-1
        )
        print(
            f"RA, Dec = [{pointing_ra}, {pointing_dec}], "
            f"Status = {isinstance(refcat, Table)}, "
            f"N_entries = {len(refcat)}"
        )
        return refcat

BO ZHANG's avatar
BO ZHANG committed
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
    def dfs_rc_query(
            self,
            ra=180,
            dec=0,
            radius=2,
            columns=(
                    'ref_epoch',
                    'ra',
                    'ra_error',
                    'dec',
                    'dec_error',
                    'parallax',
                    'parallax_error',
                    'pmra',
                    'pmra_error',
                    'pmdec',
                    'pmdec_error',
                    'phot_g_mean_mag',
                    'source_id'
            ),
            min_mag=0,
            max_mag=30,
            obstime=-1,
            limit=-1
    ):
BO ZHANG's avatar
BO ZHANG committed
738
739
740
741
742
        """ Query Reference Catalog (RC) from DFS.
        Ref.
        https://gea.esac.esa.int/archive/documentation/GDR3/Gaia_archive/chap_datamodel/
        sec_dm_main_source_catalogue/ssec_dm_gaia_source.html
        """
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
        cat = self.dfs_CatApi.catalog_query(
            catalog_name="gaia3",
            ra=ra,
            dec=dec,
            columns=columns,
            radius=radius,
            min_mag=min_mag,
            max_mag=max_mag,
            obstime=obstime,
            limit=limit
        )
        self.logger_ppl.info(f"Results from DFS CATAPI: code = {cat['code']}, message = {cat['message']}")
        if cat["code"] == 0:
            return self.dfs_CatApi.to_table(cat)
        else:
            raise ValueError("Bad results!")
BO ZHANG's avatar
BO ZHANG committed
759
760
761
762
763

    def dfs_l1_push(self):
        """ Push MBI/SLS L1 data to DFS. """
        # l1api = get_l1api()
        # l1api.write()
764
        return
BO ZHANG's avatar
BO ZHANG committed
765
766
767
768
769

    def dfs_l2_push(self):
        """ Push SLS spectra to DFS. """
        pass

BO ZHANG's avatar
BO ZHANG committed
770
771
772
773
774
775
776
777
778
779
780
781
782
    @staticmethod
    def from_l1id(
            l1_id="1000000001",
            datatype="sls",
            dir_l0="/L1Pipeline/L0",
            dir_l1="/L1Pipeline/L1",
            use_dfs=True,
            dfs_node="pml",
            clear_l1=False,
            dfs_root="/share/dfs"
    ):
        pass

BO ZHANG's avatar
BO ZHANG committed
783
    @staticmethod
BO ZHANG's avatar
BO ZHANG committed
784
785
    def from_dfs(
            obs_id="100000100",
BO ZHANG's avatar
BO ZHANG committed
786
            ver_sim="C5.2",
BO ZHANG's avatar
BO ZHANG committed
787
788
789
            datatype="mbi",
            dir_l0="/L1Pipeline/L0",
            dir_l1="/L1Pipeline/L1",
BO ZHANG's avatar
tweaks    
BO ZHANG committed
790
            path_aux="/L1Pipeline/aux",
BO ZHANG's avatar
BO ZHANG committed
791
            use_dfs=True,
BO ZHANG's avatar
BO ZHANG committed
792
793
            dfs_node="pml",
            clear_l1=False,
BO ZHANG's avatar
BO ZHANG committed
794
795
            dfs_root="/share/dfs",
            n_jobs=18,
BO ZHANG's avatar
BO ZHANG committed
796
            backend="multiprocessing",
BO ZHANG's avatar
BO ZHANG committed
797
798
            device="CPU",
            **kwargs
BO ZHANG's avatar
BO ZHANG committed
799
    ):
BO ZHANG's avatar
BO ZHANG committed
800
        """ Initialize CsstMsDataManager from DFS. """
801
802
803
804
805
        # (clear and) make directories
        if os.path.exists(dir_l0):
            os.system(f"rm -rf {dir_l0}/*")
        else:
            os.mkdir(dir_l0)
BO ZHANG's avatar
BO ZHANG committed
806
807
808
809
        # if os.path.exists(dir_l1):
        #     os.system(f"rm -rf {dir_l1}/*")
        # else:
        #     os.mkdir(dir_l1)
BO ZHANG's avatar
BO ZHANG committed
810
811
812
        # os.chdir(dir_l1)
        if not os.path.exists(dir_l1):
            os.mkdir(dir_l1)
BO ZHANG's avatar
BO ZHANG committed
813
814
        elif clear_l1:
            os.system(f"rm -rf {dir_l1}/*")
815
816
        os.chdir(dir_l1)

BO ZHANG's avatar
BO ZHANG committed
817
        print(f"Query obs_id={obs_id} ...", end="")
BO ZHANG's avatar
BO ZHANG committed
818
        records = CsstMsDataManager(dfs_node=dfs_node, verbose=False).dfs_L0DataApi.find(obs_id=obs_id)
BO ZHANG's avatar
tweaks    
BO ZHANG committed
819
        print(f"{records['totalCount']} records obtained!")
BO ZHANG's avatar
BO ZHANG committed
820
821
822
        tbl = Table([_.__dict__ for _ in records["data"]])
        tbl.sort(["detector_no", "obs_type"])

BO ZHANG's avatar
tweaks    
BO ZHANG committed
823
824
        print("Making symbolic links ...")
        for i_rec in range(len(tbl)):
BO ZHANG's avatar
BO ZHANG committed
825
            os.symlink(
BO ZHANG's avatar
tweaks    
BO ZHANG committed
826
827
                src=os.path.join(dfs_root, tbl["file_path"][i_rec]),
                dst=os.path.join(dir_l0, os.path.basename(tbl["file_path"][i_rec])),
BO ZHANG's avatar
BO ZHANG committed
828
829
830
831
            )

        # initialize dm
        dm = CsstMsDataManager.from_dir(
BO ZHANG's avatar
BO ZHANG committed
832
            ver_sim=ver_sim,
BO ZHANG's avatar
BO ZHANG committed
833
834
835
836
837
838
839
            datatype=datatype,
            dir_l0=dir_l0,
            dir_l1=dir_l1,
            path_aux=path_aux,
            use_dfs=use_dfs,
            dfs_node=dfs_node,
            n_jobs=n_jobs,
BO ZHANG's avatar
BO ZHANG committed
840
            backend=backend,
BO ZHANG's avatar
BO ZHANG committed
841
842
            device=device,
            **kwargs
BO ZHANG's avatar
BO ZHANG committed
843
        )
BO ZHANG's avatar
BO ZHANG committed
844
        assert dm.obs_id == obs_id
BO ZHANG's avatar
BO ZHANG committed
845
846
847

        return dm

BO ZHANG's avatar
BO ZHANG committed
848
    def dfs_l0_query(self, obs_id: str = "100000100"):
BO ZHANG's avatar
BO ZHANG committed
849
        """ Query L0 data from DFS. """
BO ZHANG's avatar
BO ZHANG committed
850
        result = self.dfs_L0DataApi.find(obs_id=str(obs_id))
BO ZHANG's avatar
BO ZHANG committed
851
        print(f"{result['totalCount']} records returned from DFS.")
BO ZHANG's avatar
tweaks    
BO ZHANG committed
852
853
854
        if not result["code"] == 0:
            raise ValueError(f"DFS returns non-zero code! ({result['code']})")
        tbl = Table([_.__dict__ for _ in result["data"]])
BO ZHANG's avatar
BO ZHANG committed
855
856
857
858
859
860
861
        tbl.sort(["detector_no", "obs_type"])
        # Check if all 30 detectors are available
        for detector in CP["all"]["detectors"]:
            for obs_type in ["sci", "cosmic_ray"]:
                if np.sum((tbl["detector_no"] == f"{detector:02d}") & (tbl["obs_type"] == obs_type)) == 0:
                    self.logger_ppl.warning(f"Record not found for detector {detector:02d} and obs_type {obs_type}")
        return tbl
BO ZHANG's avatar
BO ZHANG committed
862

BO ZHANG's avatar
BO ZHANG committed
863
864
865
866
867
868
869
870
871
872
873
874
    def dfs_l0_check_all(self):
        """ Check all C5.2 L0 data is available in DFS. """
        is_good = True
        for obs_id in range(100000020, 100000155):
            tbl = self.dfs_l0_query(obs_id=f"{obs_id}")
            if len(tbl) == 60:
                self.logger_ppl.info(f"DFS returns {len(tbl)} records for obs_id={obs_id}")
            else:
                is_good = False
                self.logger_ppl.warning(f"DFS returns {len(tbl)} records for obs_id={obs_id}")
        return is_good

875
    def dfs_l1_query(self, obs_id, detector):
BO ZHANG's avatar
BO ZHANG committed
876
877
        """ Query L1 data from DFS. """
        pass
878
879
880
881


# temporarily compatible with old interface
CsstMbiDataManager = CsstMsDataManager