示例#1
0
def schedule_predefined(locations,
                        date,
                        quat,
                        num_allowed,
                        mag_thres=13,
                        radius=25):
    """
    :locations: astropy Table with predefined yag, zag, row0, col0 coordinates,
                and number of times the location has been scheduled in the past
    :date: date
    :quat: pointing quaternion of this dwell
    :num_allowed: allowed number of monitor windows for this dwell
    :mag_thres: faintest magnitude of a spoiler star. Default = 13 mag
    :radius: radius of search for spoiler stars. Default = 25 arcsec
    """

    radius = (radius * u.arcsec).to('deg').value

    num_scheduled = 0

    idx_list = []

    for i, row in enumerate(locations):

        if num_scheduled < num_allowed and row['scheduled'] != 1:

            r = row['row']
            c = row['col']
            yag, zag = transform.pixels_to_yagzag(r, c)  # yag, zag in arcsec
            ra, dec = quatutil.yagzag2radec(yag / 3600., zag / 3600., quat)
            cat = agasc.agasc.get_agasc_cone(ra, dec, radius, date)

            if all(cat['MAG_ACA']) > mag_thres or len(cat) == 0:
                msg = ' '.join([
                    'Schedule {} monitor window at:\n'.format(num_scheduled +
                                                              1),
                    '    (yag, zag) = ({:.0f}, {:.0f}) arcsec\n'.format(
                        yag, zag), '    (row, col) = ({}, {})'.format(r, c)
                ])
                print(msg)
                num_scheduled = num_scheduled + 1
                idx_list.append(i)
            """
            else:
                msg = ' '.join(['Spoiler star(s) found at:\n',
                                '    (yag, zag) = ({:.0f}, {:.0f}) arcsec\n'.format(yag, zag),
                                '    (row, col) = ({}, {})'.format(r, c)])
                print(msg)
                ok = cat['MAG_ACA'] <= mag_thres
                print(cat['AGASC_ID'][ok])
            """

    return idx_list
示例#2
0
def test_edge_checking():
    """Test row/col edge checking"""

    # Within limits, doesn't fail
    yag, zag = pixels_to_yagzag(511.7, -511.7)
    yagzag_to_pixels(yag, zag)

    with pytest.raises(ValueError):
        pixels_to_yagzag(512.2, 0)

    with pytest.raises(ValueError):
        pixels_to_yagzag(0, -512.2)

    yag, zag = pixels_to_yagzag(512.2, -512.2, allow_bad=True)
    with pytest.raises(ValueError):
        yagzag_to_pixels(yag, zag)
示例#3
0
def get_centroids(slot_data, img_size, bgd_object, nframes=None):
    """
    For each frame:
    1. Compute background image using get_background() method of bgd_object.
       Algorithm depends on the class of bgd_object
            - FlightBgd: current on-board algorithm
            - DarkCurrent_Median_Bgd: median for sampled pixels, average bgd
              for not sampled pixels
            - DarkCurrent_SigmaClip_Bgd: sigma clipping for sampled pixels,
              avg bgd for not sampled pixels
    2. Subtract background
    3. Compute centroids in image coordinates 0:8 (variable name: row/col)
    4. Transform to get yagzag coordinates

    Returns:
    * rowcol_centroids: list of nframes centroid pairs,
                        [[row centroid1, col centroid1], [], ...]
    * yanzan_centroids: list of nframes centroid pairs,
                        [[yag centroid1, zag centroid1], [], ...]
    * bgd_imgs: list of nframes 8x8 arrays representing background images
    * deque_dicts: list of nframes dictionaries with keys being pixel
                   coordinates, e.g. (210, 130), and vals being deques of
                   ndeque pixel value samples

    :param slot_data: simulated or flight aca_l0 slot data
    :param img_size: image size, either 6 or 8 (pixels)
    :param bgd_object: background object defined in classes.py
    :param nframes: number of time frames
    """

    if img_size not in [6, 8]:
        raise ValueError('get_centroids:: expected img_size = 6 or 8')

    if nframes is None:
        nframes = len(slot_data)

    yagzag_centroids = []
    rowcol_centroids = []
    bgd_imgs = []
    deque_dicts = []

    for index in range(0, nframes):

        frame_data = slot_data[index:index + 1]

        bgd_object.bgdavg = frame_data['BGDAVG'][0]

        if isinstance(bgd_object, (DynamBgd_Median, DynamBgd_SigmaClip)):
            bgd_object.img = frame_data['IMGRAW'][0]
            bgd_object.row0 = frame_data['IMGROW0'][0]
            bgd_object.col0 = frame_data['IMGCOL0'][0]

        bgd_img = bgd_object.get_background()  # 8x8

        bgd_imgs.append(bgd_img)

        if isinstance(bgd_object, (DynamBgd_Median, DynamBgd_SigmaClip)):
            deque_dict = bgd_object.deque_dict
            deque_dicts.append(deepcopy(deque_dict))

        raw_img = frame_data['IMGRAW'][0].reshape(8, 8)

        img = raw_img - bgd_img

        # If dynamic background, don't oversubtract?
        # Value of pixel with bgd > raw image value will be set to zero:

        #if isinstance(bgd_object, (DynamBgd_Median, DynamBgd_SigmaClip)):
        #    bgd_mask = bgd_img > raw_img
        #    img = raw_img - ma.array(bgd_img, mask=bgd_mask)
        #    img = img.data * ~bgd_mask

        # Calculate centroids for current bgd-subtracted img, use first moments
        rowcol = get_current_centroids(img, img_size)
        rowcol_centroids.append(rowcol)

        # Translate (row, column) centroid to (yag, zag)
        y_pixel = rowcol[0] + frame_data['IMGROW0']
        z_pixel = rowcol[1] + frame_data['IMGCOL0']
        yagzag = transform.pixels_to_yagzag(y_pixel, z_pixel)

        yagzag_centroids.append(yagzag)

    return rowcol_centroids, yagzag_centroids, bgd_imgs, deque_dicts
示例#4
0
文件: monitor.py 项目: sot/proseco
    def process_monitors(self):
        """Process monitor window requests"""
        if self.monitors is None:
            return

        # Add columns for each of the three coordinate representations. The
        # original list input for monitors has been turned into a Table by the
        # Meta processing.
        monitors = self.monitors
        monitors['id'] = 0
        monitors['ra'] = 0.0
        monitors['dec'] = 0.0
        monitors['yang'] = 0.0
        monitors['zang'] = 0.0
        monitors['row'] = 0.0
        monitors['col'] = 0.0

        for monitor in monitors:
            if monitor['coord_type'] == MonCoord.RADEC:
                # RA, Dec
                monitor['ra'], monitor['dec'] = monitor['coord0'], monitor['coord1']
                monitor['yang'], monitor['zang'] = radec_to_yagzag(
                    monitor['ra'], monitor['dec'], self.att)
                monitor['row'], monitor['col'] = yagzag_to_pixels(
                    monitor['yang'], monitor['zang'], allow_bad=True)

            elif monitor['coord_type'] == MonCoord.ROWCOL:
                # Row, col
                monitor['row'], monitor['col'] = monitor['coord0'], monitor['coord1']
                monitor['yang'], monitor['zang'] = pixels_to_yagzag(
                    monitor['row'], monitor['col'], allow_bad=True, flight=True)
                monitor['ra'], monitor['dec'] = yagzag_to_radec(
                    monitor['yang'], monitor['zang'], self.att)

            elif monitor['coord_type'] == MonCoord.YAGZAG:
                # Yag, zag
                monitor['yang'], monitor['zang'] = monitor['coord0'], monitor['coord1']
                monitor['row'], monitor['col'] = yagzag_to_pixels(
                    monitor['yang'], monitor['zang'], allow_bad=True)
                monitor['ra'], monitor['dec'] = yagzag_to_radec(
                    monitor['yang'], monitor['zang'], self.att)

        # Process bona fide monitor windows according to function
        mon_id = 1000
        for monitor in self.monitors:
            if monitor['function'] in (MonFunc.GUIDE, MonFunc.MON_TRACK):
                # Try to get star at MON position
                dist = np.linalg.norm([self.stars['yang'] - monitor['yang'],
                                       self.stars['zang'] - monitor['zang']], axis=0)
                idx = np.argmin(dist)
                if dist[idx] < 2.0:
                    star = self.stars[idx]
                    monitor['id'] = star['id']
                    monitor['mag'] = star['mag']
                elif monitor['function'] == MonFunc.GUIDE:
                    raise BadMonitorError('no acceptable AGASC star within '
                                          '2 arcsec of monitor position')

            if monitor['function'] in (MonFunc.MON_FIXED, MonFunc.MON_TRACK):
                if monitor['id'] == 0:
                    monitor['id'] = mon_id
                    mon_id += 1

                # Make a stub row for a MON entry using zero everywhere. This
                # also works for str (giving '0').
                mon = {col.name: col.dtype.type(0) for col in self.itercols()}
                # These type codes get fixed later in merge_catalog
                mon['type'] = 'MFX' if monitor['function'] == MonFunc.MON_FIXED else 'MTR'
                mon['sz'] = '8x8'
                mon['dim'] = -999  # Set an obviously bad value for DTS, gets fixed later.
                mon['res'] = 0
                mon['halfw'] = 20
                mon['maxmag'] = ACA.monitor_maxmag
                for name in ('id', 'mag', 'yang', 'zang', 'row', 'col', 'ra', 'dec'):
                    mon[name] = monitor[name]

                # Finally add the MON as a row in table
                self.add_row(mon)

            elif monitor['function'] != MonFunc.GUIDE:
                raise ValueError(f'unexpected monitor function {monitor["function"]}')
示例#5
0
def schedule_monitor_windows(t,
                             predefined_locs=False,
                             mag_thres=13,
                             radius=25):
    """
    :t: astropy Table
    :predefined_locs: if True, try the predefined CCD locations first,
                      default=False.
    """
    locations = Table.read(PREDEFINED, delimiter=' ', format='ascii')

    for row in t:

        obsid = row['obsid']
        dur = row['duration']
        num_allowed = row['num_mon_windows']

        msg = ' '.join([
            '\nObsID = {}, duration = {:.0f} sec:'.format(obsid, dur),
            '{} monitor windows allowed'.format(num_allowed)
        ])
        print(msg)

        date = row['date']
        quat = row['quat']

        num_scheduled = 0

        stars = {}

        # If flag set, try predefined locations first
        if predefined_locs:

            print("Predefined locations:")

            kwargs = {'mag_thres': mag_thres, 'radius': radius}

            if not all(locations['scheduled']) == 1:
                idx_list = schedule_predefined(locations, date, quat,
                                               num_allowed, **kwargs)
                num_scheduled = len(idx_list)
                # Update status of predefined locations
                for idx in idx_list:
                    locations['scheduled'][idx] = 1

        # All allowed predefined locations are scheduled, or predefined_locs=False,
        # Add random locations if needed
        if num_scheduled < num_allowed:

            print("Random locations:")

            ra, dec = quatutil.yagzag2radec(0, 0, quat)
            cat = agasc.agasc.get_agasc_cone(ra, dec, 1.5, date)

            # Filter to pick up bright spoiler stars
            ok = np.array(cat['MAG_ACA'] < mag_thres, dtype=bool)
            cat = cat[ok]

            yags, zags = quatutil.radec2yagzag(cat['RA_PMCORR'],
                                               cat['DEC_PMCORR'], quat)
            rows, cols = transform.yagzag_to_pixels(yags * 3600.,
                                                    zags * 3600,
                                                    allow_bad=True)

            # Identify spoiler stars that fit on ccd
            ok = (rows > -512.5) * (rows < 511.5) * (cols > -512.5) * (cols <
                                                                       511.5)

            rows = np.array(np.round(rows[ok]), dtype=int)
            cols = np.array(np.round(cols[ok]), dtype=int)

            # Collect spoiler stars
            vals = np.ones(len(rows))
            stars = get_spoiler_stars(rows, cols, vals)

            # Now dict stars contains keys that represent (row, col) of
            # spoiler star centers and a 10px rim around each spoiler star.

            while num_scheduled < num_allowed:
                # Draw a random location on ccd, avoid edges:
                r, c = np.random.randint(-504, 505, 2)

                # Check if the location was previously scheduled - TBD

                # Check if the location is free of stars
                if (r, c) not in stars:
                    yag, zag = transform.pixels_to_yagzag(
                        r, c)  # yag, zag in arcsec
                    msg = ' '.join([
                        'Schedule {} monitor window at:\n'.format(
                            num_scheduled + 1),
                        '    (yag, zag) = ({:.0f}, {:.0f}) arcsec\n'.format(
                            yag,
                            zag), '    (row, col) = ({}, {})'.format(r, c)
                    ])
                    print(msg)
                    num_scheduled = num_scheduled + 1
                    stars = get_spoiler_stars([r], [c], [5], stars, rim=4)

    # Update the PREDEFINED file - TBD

    return stars