Esempio n. 1
0
def test_deltatime_sub():
    t1 = SCETime(100, 2)
    dt1 = SCETimeDelta(100, 1)
    dt2 = SCETimeDelta(200, 2)

    with pytest.raises(TypeError, match=r'Unsupported operation for types SCETimeDelta and int'):
        _ = dt1 - 1
    with pytest.raises(TypeError, match=r'Quantity could not be converted to SCETimeDelta'):
        _ = dt1 - (1*u.m)

    # test sub deltatimes and quantities
    dt1_dt2 = dt1 - dt2
    dt1_float = dt1 - (200 + 2 / MAX_FINE) * u.s
    assert dt1_dt2 == dt1_float
    assert dt1_dt2.coarse == -100
    assert dt1_dt2.fine == -1

    dt2_dt1 = dt2 - dt1
    float_dt1 = (200 + 2/MAX_FINE) * u.s - dt1
    assert dt2_dt1 == float_dt1
    assert dt2_dt1.coarse == 100
    assert dt2_dt1.fine == 1

    # test sub times
    with pytest.raises(TypeError, match=f'Unsupported operation for types.*'):
        dt1 - t1

    t2 = t1 - dt1
    assert t2.coarse == 0
    assert t2.fine == 1
    with pytest.raises(ValueError, match=r'Coarse time must be in range.*'):
        t1 - dt2
Esempio n. 2
0
def test_timedelta_eq():
    dt1 = SCETimeDelta(123, 456)
    dt2 = SCETimeDelta((123 + 456/MAX_FINE)*u.s)
    dt3 = SCETimeDelta(-1, -1)
    assert dt1 == dt2
    assert dt1 != dt3
    assert dt1 == (123 + 456/MAX_FINE)*u.s
Esempio n. 3
0
    def _get_time(self):
        # Replicate the start time of each for the number of samples in that packet
        base_coarse, base_fine = zip(
            *[([ct] * ns, [ft] * ns) for ns, ct, ft in self[
                ['num_samples', 'scet_coarse', 'scet_fine']]])
        base_coarse = np.hstack(base_coarse)
        base_fine = np.hstack(base_fine)
        bases = SCETime(base_coarse, base_fine)

        # Create start time for each time bin by multiplying the duration by the sample number
        deltas = SCETimeDelta(
            np.hstack([(np.arange(ns) * it)
                       for ns, it in self[['num_samples', 'integration_time']]
                       ]))

        # Create integration time for each sample in each packet by replicating the duration for
        # number of sample in each packet
        durations = SCETimeDelta(
            np.hstack([
                np.ones(num_sample) * int_time for num_sample, int_time in
                self[['num_samples', 'integration_time']]
            ]))

        # Add the delta time to base times and convert to bin centers
        times = bases + deltas + (durations / 2)

        # Create a time range object covering the total observation time
        tr = SCETimeRange(start=bases[0],
                          end=bases[-1] + deltas[-1] + durations[-1])

        return times, durations, tr
Esempio n. 4
0
def test_timedelta_add():
    t1 = SCETime(1, 1)
    dt1 = SCETimeDelta(100, 1)
    dt2 = SCETimeDelta(200, 2)

    # test time plus timedelta
    t1_dt1 = dt1 + t1
    dt1_t1 = t1 + dt1
    assert t1_dt1 == dt1_t1
    assert t1_dt1.coarse == 101
    assert t1_dt1.fine == 2

    with pytest.raises(ValueError, match=f'.*are not convertible'):
        _ = dt1 + (1*u.m)

    # test timedelta plus timedelta/quantity
    dt1_dt2 = dt1 + dt2
    dt1_float = dt1 + (200+2/MAX_FINE)*u.s
    dt2_dt1 = dt2 + dt1
    float_dt2 = (100 + 1/MAX_FINE) * u.s + dt2
    assert dt1_dt2 == dt2_dt1
    assert dt1_float == dt1_dt2
    assert float_dt2 == dt1_dt2
    assert dt1_dt2.coarse == 300
    assert dt1_dt2.fine == 3
Esempio n. 5
0
def test_timedelta_init():
    dt1 = SCETimeDelta(0, 0)
    dt2 = SCETimeDelta.from_float(0*u.s)
    dt3 = SCETimeDelta(dt1)
    assert dt1 == dt2
    assert dt2 == dt3
    assert dt1 == dt3

    with pytest.raises(ValueError):
        _ = SCETimeDelta(2 ** 32 + 1, 0)

    with pytest.raises(ValueError):
        SCETime(0, 2**16+1)

    with pytest.raises(ValueError):
        SCETime(0.0, 0)
Esempio n. 6
0
    def _get_time(cls, control, num_energies, packets, pad_after):
        times = []
        durations = []
        start = 0
        for i, (ns, it) in enumerate(control['num_samples',
                                             'integration_time']):
            off_sets = packets.get_value('NIX00485')[start:start + ns] * it
            base_time = SCETime(control["scet_coarse"][i],
                                control["scet_fine"][i])
            start_times = base_time + off_sets
            end_times = base_time + off_sets + it
            cur_time = start_times + (end_times - start_times) / 2
            times.extend(cur_time)
            durations.extend([it] * ns)
            start += ns

        time = np.array([(t.coarse, t.fine) for t in times])
        time = np.pad(time, ((0, pad_after), (0, 0)), mode='edge')
        time = SCETime(time[:, 0], time[:, 1]).reshape(-1, num_energies)
        duration = SCETimeDelta(
            np.pad(np.hstack(durations),
                   (0, pad_after)).reshape(-1, num_energies))

        scet_timerange = SCETimeRange(start=time[0, 0] - duration[0, 0] / 2,
                                      end=time[-1, -1] + duration[-1, 0] / 2)

        return duration, time, scet_timerange
Esempio n. 7
0
    def from_levelb(cls, levelb, parent=''):
        packets, idb_versions, control = HKProduct.from_levelb(levelb,
                                                               parent=parent)

        # Create array of times as dt from date_obs
        times = SCETime(control['scet_coarse'], control['scet_fine'])

        # Data
        data = Data()
        data['time'] = times
        data['timedel'] = SCETimeDelta(0, 0)

        for nix, param in packets.data[0].__dict__.items():

            if nix.startswith("NIXG") or nix == 'NIX00020':
                continue

            name = param.idb_info.get_product_attribute_name()
            data.add_basic(name=name, nix=nix, attr='value', packets=packets)

        data['control_index'] = range(len(control))

        return cls(service_type=packets.service_type,
                   service_subtype=packets.service_subtype,
                   ssid=packets.ssid,
                   control=control,
                   data=data,
                   idb_versions=idb_versions)
Esempio n. 8
0
def test_time_minmax():
    assert SCETime.min_time() == SCETime(coarse=0, fine=0)
    assert SCETime.max_time() == SCETime(coarse=MAX_COARSE, fine=MAX_FINE)
    # TODO enable after https://github.com/i4Ds/STIXCore/issues/102
    # assert SCETime.min_time() - SCETime(coarse=0, fine=1) == SCETime.min_time()
    with pytest.raises(ValueError, match=r'Coarse time must be in range.*'):
        m = SCETime.max_time()
        dt = SCETimeDelta(0, 1)
        nm = m + dt
        print(nm)
Esempio n. 9
0
    def from_levelb(cls, levelb, parent):
        packets, idb_versions = GenericProduct.getLeveL0Packets(levelb)

        control = Control()
        control['scet_coarse'] = packets.get('scet_coarse')
        control['scet_fine'] = packets.get('scet_fine')
        control['integration_time'] = 0
        control['index'] = np.arange(len(control)).astype(
            get_min_uint(len(control)))

        control['raw_file'] = levelb.control['raw_file']
        control['packet'] = levelb.control['packet']
        control['parent'] = parent

        # Create array of times as dt from date_obs
        times = SCETime(control['scet_coarse'], control['scet_fine'])

        # Data
        data = Data()
        data['time'] = times
        data['timedel'] = SCETimeDelta(0, 0)

        reshape_nixs = {'NIX00103', 'NIX00104'}
        reshape = False
        if reshape_nixs.intersection(packets.data[0].__dict__.keys()):
            reshape = True
        for nix, param in packets.data[0].__dict__.items():

            name = param.idb_info.get_product_attribute_name()
            data.add_basic(name=name,
                           nix=nix,
                           attr='value',
                           packets=packets,
                           reshape=reshape)

        data['control_index'] = np.arange(len(control)).astype(
            get_min_uint(len(control)))

        return cls(service_type=packets.service_type,
                   service_subtype=packets.service_subtype,
                   ssid=packets.ssid,
                   control=control,
                   data=data,
                   idb_versions=idb_versions,
                   packets=packets)
Esempio n. 10
0
    def from_levelb(cls, levelb, parent=''):
        packets, idb_versions = GenericProduct.getLeveL0Packets(levelb)

        control = Control()
        control['scet_coarse'] = packets.get('scet_coarse')
        control['scet_fine'] = packets.get('scet_fine')
        control['index'] = np.arange(len(control)).astype(get_min_uint(len(control)))

        # When the packets are parsed empty packets are dropped but in LB we don't parse so this
        # is not known need to compare control and levelb.control and only use matching rows
        if len(levelb.control) > len(control):
            matching_index = np.argwhere(
                np.in1d(levelb.control['scet_coarse'], np.array(packets.get('scet_coarse'))))
            control['raw_file'] = levelb.control['raw_file'][matching_index].reshape(-1)
            control['packet'] = levelb.control['packet'][matching_index].reshape(-1)
        else:
            control['raw_file'] = levelb.control['raw_file'].reshape(-1)
            control['packet'] = levelb.control['packet'].reshape(-1)

        control['parent'] = parent

        tmp = Data()
        tmp.add_basic(name='ubsd_counter', nix='NIX00285', packets=packets, dtype=np.uint32)
        tmp.add_basic(name='pald_counter', nix='NIX00286', packets=packets, dtype=np.uint32)
        tmp.add_basic(name='num_flares', nix='NIX00294', packets=packets, dtype=np.uint16)

        colnames = ['start_scet_coarse', 'end_scet_coarse', 'highest_flareflag', 'tm_byte_volume',
                    'average_z_loc', 'average_y_loc', 'processing_mask']

        flares = Data()
        if tmp['num_flares'].sum() > 0:
            flares.add_basic(name='start_scet_coarse', nix='NIX00287', packets=packets)
            flares.add_basic(name='end_scet_coarse', nix='NIX00288', packets=packets)
            flares.add_basic(name='highest_flareflag', nix='NIX00289', packets=packets,
                             dtype=np.byte)
            flares.add_basic(name='tm_byte_volume', nix='NIX00290', packets=packets, dtype=np.byte)
            flares.add_basic(name='average_z_loc', nix='NIX00291', packets=packets, dtype=np.byte)
            flares.add_basic(name='average_y_loc', nix='NIX00292', packets=packets, dtype=np.byte)
            flares.add_basic(name='processing_mask', nix='NIX00293', packets=packets, dtype=np.byte)

        tmp_data = defaultdict(list)
        start = 0
        for i, (ubsd, pald, n_flares) in enumerate(tmp):
            end = start + n_flares
            if n_flares == 0:
                tmp_data['control_index'].append(i)
                tmp_data['coarse'].append(control['scet_coarse'][i])
                tmp_data['fine'].append(control['scet_fine'][i])
                tmp_data['ubsd'].append(ubsd)
                tmp_data['pald'].append(pald)
                for name in colnames:
                    tmp_data[name].append(0)
            else:
                tmp_data['control_index'].append([i] * n_flares)
                tmp_data['coarse'].append([control['scet_coarse'][i]] * n_flares)
                tmp_data['fine'].append([control['scet_fine'][i]] * n_flares)
                ubsd['ubsd']([ubsd] * n_flares)
                pald['pald'].append([pald] * n_flares)
                for name in colnames:
                    tmp_data[name].extend(flares[name][start:end])

            start = end

        data = Data(tmp_data)
        data['time'] = SCETime(tmp_data['coarse'], tmp_data['fine'])
        data['timedel'] = SCETimeDelta(np.full(len(data), 0), np.full(len(data), 0))
        data.remove_columns(['coarse', 'fine'])

        return cls(service_type=packets.service_type,
                   service_subtype=packets.service_subtype,
                   ssid=packets.ssid,
                   control=control,
                   data=data,
                   idb_versions=idb_versions,
                   packets=packets)
Esempio n. 11
0
    def from_levelb(cls, levelb, parent=''):
        packets, idb_versions, control = QLProduct.from_levelb(levelb, parent=parent)

        # Control
        control.add_basic(name='integration_time', nix='NIX00122', packets=packets,
                          dtype=np.uint32, attr='value')
        control.add_basic(name='quiet_time', nix='NIX00123', packets=packets,
                          dtype=np.uint16, attr='value')
        control.add_basic(name='live_time', nix='NIX00124', packets=packets,
                          dtype=np.uint32, attr='value')
        control.add_basic(name='average_temperature', nix='NIX00125', packets=packets,
                          dtype=np.uint16, attr='value')
        control.add_data('detector_mask', _get_detector_mask(packets))
        control.add_data('pixel_mask', _get_pixel_mask(packets))

        control.add_data('subspectrum_mask', _get_sub_spectrum_mask(packets))
        control.add_data('compression_scheme_counts_skm',
                         _get_compression_scheme(packets, 'NIX00158'))

        subspec_data = {}
        j = 129
        for subspec, i in enumerate(range(300, 308)):
            subspec_data[subspec+1] = {'num_points': packets.get_value(f'NIXD0{j}'),
                                       'num_summed_channel': packets.get_value(f'NIXD0{j + 1}'),
                                       'lowest_channel': packets.get_value(f'NIXD0{j + 2}')}
            j += 3

        control.add_basic(name='num_samples', nix='NIX00159', packets=packets, dtype=np.uint16)

        control['subspec_num_points'] = (
                np.vstack([v['num_points'] for v in subspec_data.values()]).T + 1).astype(np.uint16)
        control['subspec_num_summed_channel'] = (np.vstack(
            [v['num_summed_channel'] for v in subspec_data.values()]).T + 1).astype(np.uint16)
        control['subspec_lowest_channel'] = (
            np.vstack([v['lowest_channel'] for v in subspec_data.values()]).T).astype(np.uint16)

        channels = []
        for i, subspectrum_mask in enumerate(control['subspectrum_mask']):
            subspec_index = np.argwhere(subspectrum_mask == 1)
            sub_channels = [np.arange(control['subspec_num_points'][i, index])
                            * (control['subspec_num_summed_channel'][i, index])
                            + control['subspec_lowest_channel'][i, index] for index in
                            subspec_index]
            channels.append(list(chain(*[ch.tolist() for ch in sub_channels])))
        control['num_channels'] = [len(c) for c in channels]

        duration = SCETimeDelta(packets.get_value('NIX00122').astype(np.uint32))
        time = SCETime(control['scet_coarse'], control['scet_fine']) + duration / 2

        dids = packets.get_value('NIXD0155')
        pids = packets.get_value('NIXD0156')
        ssids = packets.get_value('NIXD0157')
        num_spec_points = packets.get_value('NIX00146')

        unique_times, unique_time_indices = np.unique(time.as_float(), return_index=True)
        unique_times_lookup = {k: v for k, v in zip(unique_times, np.arange(unique_times.size))}

        # should really do the other way make a smaller lookup rather than repeating many many times
        tids = np.hstack([[unique_times_lookup[t.as_float()]] * n
                          for t, n in zip(time, control['num_samples'])])
        c_in = list(chain.from_iterable([repeat(c, n)
                                         for c, n in zip(channels, control['num_samples'])]))

        counts = packets.get_value('NIX00158')
        counts_var = packets.get_value('NIX00158', attr='error')

        c_out = np.arange(1025)
        start = 0
        count_map = defaultdict(list)
        counts_var_map = defaultdict(list)
        for tid, did, pid, ssid, nps, cin in zip(tids, dids, pids, ssids, num_spec_points, c_in):
            end = start + nps

            logger.debug('%d, %d, %d, %d, %d, %d', tid, did, pid, ssid, nps, end)
            count_map[tid, did, pid].append(counts[start:end])
            counts_var_map[tid, did, pid].append(counts_var[start:end])
            start = end

        full_counts = np.zeros((unique_times.size, 32, 12, 1024))
        full_counts_var = np.zeros((unique_times.size, 32, 12, 1024))

        for tid, did, pid in count_map.keys():
            cur_counts = count_map[tid, did, pid]
            cur_counts_var = counts_var_map[tid, did, pid]

            counts_rebinned = rebin_proportional(np.hstack(cur_counts), cin, c_out)
            counts_var_rebinned = rebin_proportional(np.hstack(cur_counts_var), cin, c_out)

            full_counts[tid, did, pid] = counts_rebinned
            full_counts_var[tid, did, pid] = counts_var_rebinned

        control = control[unique_time_indices]
        control['index'] = np.arange(len(control))

        # Data
        data = Data()
        data['time'] = time[unique_time_indices]
        data['timedel'] = duration[unique_time_indices]
        data.add_meta(name='timedel', nix='NIX00122', packets=packets)

        data['counts'] = (full_counts*u.ct).astype(get_min_uint(full_counts))
        data.add_meta(name='counts', nix='NIX00158', packets=packets)
        data['counts_err'] = (np.sqrt(full_counts_var)*u.ct).astype(np.float32)
        data['control_index'] = np.arange(len(control)).astype(np.uint16)

        return cls(service_type=packets.service_type,
                   service_subtype=packets.service_subtype,
                   ssid=packets.ssid,
                   control=control,
                   data=data,
                   idb_versions=idb_versions,
                   packets=packets)
Esempio n. 12
0
def test_timedelta_from_float():
    dt = SCETimeDelta.from_float(-1 * u.s)
    assert dt == SCETimeDelta(coarse=-1, fine=0)
Esempio n. 13
0
def test_timedelta_as_float():
    dt = SCETimeDelta(coarse=-1, fine=0)
    assert dt.as_float() == -1.0 * u.s
Esempio n. 14
0
    def __call__(self, *args, **kwargs):
        if len(args) == 1 and len(kwargs) == 0:
            if isinstance(args[0], (str, Path)):
                file_path = Path(args[0])
                header = fits.getheader(file_path)

                service_type = int(
                    header.get('stype')) if 'stype' in header else 0
                service_subtype = int(
                    header.get('sstype')) if 'sstype' in header else 0
                parent = header.get('parent').split(
                    ';') if 'parent' in header else ''
                raw = header.get('raw_file').split(
                    ';') if 'raw_file' in header else ''
                try:
                    ssid = int(header.get('ssid'))
                except (ValueError, TypeError):
                    ssid = None
                level = header.get('Level')
                header.get('TIMESYS')

                hdul = fits.open(file_path)
                control = read_qtable(file_path, hdu='CONTROL', hdul=hdul)

                # Weird issue where time_stamp wasn't a proper table column?
                if 'time_stamp' in control.colnames:
                    ts = control['time_stamp'].value
                    control.remove_column('time_stamp')
                    control['time_stamp'] = ts * u.s

                data = read_qtable(file_path, hdu='DATA', hdul=hdul)

                if level == 'LL01':
                    # TODO remova that hack in favor for a proper header information after
                    # https://github.com/i4Ds/STIXCore/issues/224 is solved
                    if "lightcurve" in args[0]:
                        service_type = 21
                        service_subtype = 6
                        ssid = 30
                    if "flareflag" in args[0]:
                        service_type = 21
                        service_subtype = 6
                        ssid = 34

                if level not in ['LB', 'LL01']:
                    data['timedel'] = SCETimeDelta(data['timedel'])
                    offset = SCETime.from_float(header['OBT_BEG'] * u.s)

                    try:
                        control['time_stamp'] = SCETime.from_float(
                            control['time_stamp'])
                    except KeyError:
                        pass

                    data['time'] = offset + data['time']

                energies = None
                if level == 'L1':
                    try:
                        energies = read_qtable(file_path, hdu='ENERGIES')
                    except KeyError:
                        logger.info(
                            f"no ENERGIES data found in FITS: {file_path}")
                idb_versions = defaultdict(SCETimeRange)
                if level in ('L0', 'L1'):
                    try:
                        idbt = read_qtable(file_path, hdu='IDB_VERSIONS')
                        for row in idbt.iterrows():
                            idb_versions[row[0]] = SCETimeRange(
                                start=SCETime.from_float(row[1]),
                                end=SCETime.from_float(row[2]))
                    except KeyError:
                        logger.warn(f"no IDB data found in FITS: {file_path}")

                Product = self._check_registered_widget(
                    level=level,
                    service_type=service_type,
                    service_subtype=service_subtype,
                    ssid=ssid,
                    control=control,
                    data=data,
                    energies=energies)

                return Product(level=level,
                               service_type=service_type,
                               service_subtype=service_subtype,
                               ssid=ssid,
                               control=control,
                               data=data,
                               energies=energies,
                               idb_versions=idb_versions,
                               raw=raw,
                               parent=parent)
Esempio n. 15
0
    def __call__(self, *args, **kwargs):
        if len(args) == 1 and len(kwargs) == 0:
            if isinstance(args[0], (str, Path)):
                file_path = Path(args[0])
                header = fits.getheader(file_path)
                service_type = int(header.get('stype'))
                service_subtype = int(header.get('sstype'))
                parent = header.get('parent').split(';')
                raw = header.get('raw_file').split(';')
                try:
                    ssid = int(header.get('ssid'))
                except ValueError:
                    ssid = None
                level = header.get('Level')
                header.get('TIMESYS')

                hdul = fits.open(file_path)
                control = read_qtable(file_path, hdu='CONTROL', hdul=hdul)

                # Weird issue where time_stamp wasn't a proper table column?
                if 'time_stamp' in control.colnames:
                    ts = control['time_stamp'].value
                    control.remove_column('time_stamp')
                    control['time_stamp'] = ts * u.s

                data = read_qtable(file_path, hdu='DATA', hdul=hdul)

                if level != 'LB':
                    data['timedel'] = SCETimeDelta(data['timedel'])
                    offset = SCETime.from_float(header['OBT_BEG'] * u.s)

                    try:
                        control['time_stamp'] = SCETime.from_float(
                            control['time_stamp'])
                    except KeyError:
                        pass

                    data['time'] = offset + data['time']

                energies = None
                if level == 'L1':
                    try:
                        energies = read_qtable(file_path, hdu='ENERGIES')
                    except KeyError:
                        logger.info(
                            f"no ENERGIES data found in FITS: {file_path}")
                idb_versions = defaultdict(SCETimeRange)
                if level in ('L0', 'L1'):
                    try:
                        idbt = read_qtable(file_path, hdu='IDB_VERSIONS')
                        for row in idbt.iterrows():
                            idb_versions[row[0]] = SCETimeRange(
                                start=SCETime.from_float(row[1]),
                                end=SCETime.from_float(row[2]))
                    except KeyError:
                        logger.warn(f"no IDB data found in FITS: {file_path}")

                Product = self._check_registered_widget(
                    level=level,
                    service_type=service_type,
                    service_subtype=service_subtype,
                    ssid=ssid,
                    control=control,
                    data=data,
                    energies=energies)

                return Product(level=level,
                               service_type=service_type,
                               service_subtype=service_subtype,
                               ssid=ssid,
                               control=control,
                               data=data,
                               energies=energies,
                               idb_versions=idb_versions,
                               raw=raw,
                               parent=parent)