Example #1
0
    def retrieve_comparison_image(self, downloader):
        """
        Search the DB for a comparison image for this cutout.
        """
        # selecting comparator when on a comparator should load a new one.

        ref_wcs = wcs.WCS(self.fits_header)
        try:
            ref_x = self.fits_header['NAXIS1'] / 2.0
            ref_y = self.fits_header['NAXIS2'] / 2.0
            (ref_ra, ref_dec) = ref_wcs.xy2sky(ref_x, ref_y)
        except Exception as e:
            logger.info(str(e))
            logger.info(str(self.fits_header))
            return None

        dra = self.fits_header['CD1_1'] * self.fits_header['NAXIS1'] / 2.0
        ddec = self.fits_header['CD2_2'] * self.fits_header['NAXIS2'] / 2.0
        radius = max(dra, ddec)

        logger.info("BOX({} {} {} {})".format(ref_ra, ref_dec, dra, ddec))

        query_result = storage.cone_search(ref_ra, ref_dec, dra, ddec)  # returns an astropy.table.table.Table

        comparison = None
        if len(query_result['collectionID']) > 0:  # are there any comparison images even available on that sky?
            for collectionID in query_result['collectionID']:
                if collectionID not in self._bad_comparison_images:
                    comparison = collectionID
                    self._bad_comparison_images.append(comparison)
                    break
            if comparison is None:
                logger.critical(str(self.fits_header))
                self._comparison_image = None
                return
        else:
            query_result.pprint()
            logger.info("No comparison images available for this piece of sky.")
            print "No comparison images available for this piece of sky."
            self._comparison_image = None
            return

        base_url = "https://www.cadc-ccda.hia-iha.nrc-cnrc.gc.ca/vospace/nodes/OSSOS/dbimages/{}/{}p.fits".format(
            comparison, comparison)
        cutout = 'CIRCLE ICRS {} {} {}'.format(ref_ra, ref_dec, radius)
        url = base_url + "?" + urllib.urlencode({'view': 'cutout', 'cutout': cutout})

        hdu_list = downloader.download_hdulist(uri=None, URL=url)

        comp_wcs = wcs.WCS(hdu_list[-1].header)
        (x, y) = comp_wcs.sky2xy(ref_ra, ref_dec)
        obs = Observation(str(comparison), 'p', ccdnum=str(hdu_list[-1].header.get('EXTVER', 0)))
        reading = SourceReading(x, y, ref_x, ref_y, ref_ra, ref_dec, ref_x, ref_y, obs, is_inverted=False)
        self._comparison_image = SourceCutout(reading, hdu_list, CoordinateConverter(0, 0))
Example #2
0
def compute_trans(expnums, ccd, version, prefix=None, default="WCS"):
    """
    Pull the astrometric header for each image, compute an x/y transform and compare to trans.jmp

    this one overides trans.jmp if they are very different.
    @param expnums:
    @param ccd:
    @param version:
    @param prefix:
    @return: None
    """
    wcs_dict = {}
    for expnum in expnums:
        try:
            # TODO This assumes that the image is already N/E flipped.
            # If compute_trans is called after the image is retrieved from archive then we get the disk version.
            filename = storage.get_image(expnum, ccd, version, prefix=prefix)
            this_wcs = wcs.WCS(fits.open(filename)[0].header)
        except Exception as err:
            logging.warning("WCS Trans compute failed. {}".format(str(err)))
            return
        wcs_dict[expnum] = this_wcs
    x0 = wcs_dict[expnums[0]].header['NAXIS1'] / 2.0
    y0 = wcs_dict[expnums[0]].header['NAXIS2'] / 2.0
    (ra0, dec0) = wcs_dict[expnums[0]].xy2sky(x0, y0)
    result = ""
    for expnum in expnums:
        filename = storage.get_file(expnum,
                                    ccd,
                                    version,
                                    ext='.trans.jmp',
                                    prefix=prefix)
        jmp_trans = file(filename, 'r').readline().split()
        (x, y) = wcs_dict[expnum].sky2xy(ra0, dec0)
        x1 = float(
            jmp_trans[0]) + float(jmp_trans[1]) * x + float(jmp_trans[2]) * y
        y1 = float(
            jmp_trans[3]) + float(jmp_trans[4]) * x + float(jmp_trans[5]) * y
        dr = math.sqrt((x1 - x0)**2 + (y1 - y0)**2)
        if dr > 0.5:
            result += "WARNING: WCS-JMP transforms mis-matched {} reverting to using {}.\n".format(
                expnum, default)
            if default == "WCS":
                uri = storage.dbimages_uri(expnum,
                                           ccd,
                                           version,
                                           ext='.trans.jmp',
                                           prefix=prefix)
                filename = os.path.basename(uri)
                trans = file(filename, 'w')
                trans.write("{:5.2f} 1. 0. {:5.2f} 0. 1.\n".format(
                    x0 - x, y0 - y))
                trans.close()
        else:
            result += "WCS-JMP transforms match {}\n".format(expnum)
    return result
Example #3
0
 def compute_inverted(self):
     """
     Returns:
       inverted: bool
         True if the stored image is inverted.
     """
     astheader = storage.get_astheader(self.obs.expnum,
                                       self.obs.ccdnum,
                                       version=self.obs.ftype)
     pvwcs = wcs.WCS(astheader)
     (x, y) = pvwcs.sky2xy(self.ra, self.dec)
     logger.debug("is_inverted: X,Y {},{}  -> wcs X,Y {},{}".format(
         self.x, self.y, x, y))
     dr2 = ((x - self.x)**2 + (y - self.y)**2)
     logger.debug("inverted is {}".format(dr2 > 2))
     return dr2 > 2
Example #4
0
    def ossos_pointings(self):
        """
        plot an OSSOS observation on the OSSOS plot.
        """
        match = re.match('(\d+)\D(\d+)', self.expnum.get())
        if match is not None:
            expnum = int(match.group(1))
            ccd = int(match.group(2))
            x = 2112 / 2.0
            y = 4644 / 2.0
        else:
            expnum = int(str(self.expnum.get()))
            ccd = 22
            x = 1000
            y = 4644 - 15 / 0.185
        header = None
        try:
            header = storage.get_astheader(expnum, ccd=ccd)
        except:
            if header is None:
                print "Didn't get a header... "
                return

        ossos_wcs = wcs.WCS(header)
        (ra, dec) = ossos_wcs.xy2sky(x, y)

        class MyEvent(object):
            def __init__(self, x, y):
                self.x = x
                self.y = y

        (x, y) = self.p2s((math.radians(ra), math.radians(dec)))
        event = MyEvent(x, y)
        self.create_pointing(event,
                             label_text=header['OBJECT'] +
                             ' ccd{}'.format(ccd))
Example #5
0
def ephem_search(mpc_filename, search_date="2014 07 24.0"):
    """
    builds a TSV file in the format of SSOIS by querying for possible observations in CADC/CAOM2.

    This is a fall back program, should only be useful when SSOIS is behind.
    """
    columns = ('Image', 'Ext', 'X', 'Y', 'MJD', 'Filter', 'Exptime',
               'Object_RA', 'Object_Dec', 'Image_target',
               'Telescope/Instrument', 'MetaData', 'Datalink')

    ephem_table = Table(names=columns,
                        dtypes=('S10', 'i4', 'f8', 'f8', 'f8', 'S10', 'f8',
                                'f8', 'f8', 'S20', 'S20', 'S20', 'S50'))

    ephem_table.pprint()

    o = orbfit.Orbfit(mpc.MPCReader(mpc_filename).mpc_observations)
    o.predict(search_date)
    fields = storage.cone_search(o.coordinate.ra.degrees,
                                 o.coordinate.dec.degrees,
                                 dra=0.3,
                                 ddec=0.3,
                                 calibration_level=1)
    mjdates = numpy.unique(fields['mjdate'])

    collectionIDs = []
    for mjdate in mjdates:
        jd = 2400000.5 + mjdate
        o.predict(jd)
        for field in storage.cone_search(o.coordinate.ra.degrees,
                                         o.coordinate.dec.degrees,
                                         dra=30. / 3600.0,
                                         ddec=30. / 3600.0,
                                         mjdate=mjdate,
                                         calibration_level=1):
            collectionIDs.append(field['collectionID'])

    expnums = numpy.unique(numpy.array(collectionIDs))

    for expnum in expnums:
        header = storage.get_astheader(expnum, 22)
        o.predict(header['MJDATE'] + 2400000.5)
        print(o.time.iso, o.coordinate.ra.degrees, o.coordinate.dec.degrees)
        for ccd in range(36):
            header = storage.get_astheader(expnum, ccd)
            w = wcs.WCS(header)
            (x, y) = w.sky2xy(o.coordinate.ra.degrees,
                              o.coordinate.dec.degrees)
            print(ccd, x, y)
            if 0 < x < header['NAXIS1'] and 0 < y < header['NAXIS2']:
                ephem_table.add_row([
                    expnum, ccd + 1, x, y, header['MJDATE'], header['FILTER'],
                    header['EXPTIME'], o.coordinate.ra.degrees,
                    o.coordinate.dec.degrees, header['OBJECT'], 'CFHT/MegaCam',
                    None,
                    "https://www.cadc-ccda.hia-iha.nrc-cnrc.gc.ca/data/pub/CFHT/{}p[{}]"
                    .format(expnum, ccd)
                ])
                break

    ephem_table.pprint()
    ephem_table.write('backdoor.tsv', format='ascii', delimiter='\t')
Example #6
0
def remeasure(mpc_in):
    """
    re-measure the astrometry and photometry of the given mpc line
    """
    # TODO  Actually implement this.
    if mpc_in.null_observation:
        return mpc_in
    mpc_obs = deepcopy(mpc_in)
    logging.debug("rm start: {}".format(mpc_obs.to_string()))

    if not isinstance(mpc_obs.comment, mpc.OSSOSComment):
        return mpc_in

    parts = re.search('(?P<expnum>\d{7})(?P<type>\S)(?P<ccd>\d\d)', mpc_obs.comment.frame)
    if not parts:
        return mpc_in

    start_coordinate = mpc_in.coordinate
    assert isinstance(start_coordinate, ICRSCoordinates)

    try:
        header = storage.get_astheader(parts.group('expnum'), int(parts.group('ccd')))
    except IOError as ioerr:
        logging.error(str(ioerr))
        logging.error("Failed to get astrometric header for: {}".format(mpc_obs))
        return mpc_in

    this_wcs = wcs.WCS(header)
    try:
        x = float(mpc_obs.comment.x)
        y = float(mpc_obs.comment.y)
        if mpc_in.discovery:
            logging.debug("Discovery astrometric lines are normally flipped relative to storage.")
            x = header['NAXIS1'] - x + 1
            y = header['NAXIS2'] - y + 1
    except:
        logging.warn("Failed to X/Y from comment line.")
        return mpc_in

    (ra, dec) = this_wcs.xy2sky(x, y)
    mpc_obs.coordinate = (ra, dec)
    logging.debug("rm updat: {}".format(mpc_obs.to_string()))
    sep = start_coordinate.separation(mpc_obs.coordinate).degrees * 3600.0
    if sep > TOLERANCE and mpc_in.discovery:
        logging.warn("{} --> Using the unflipped X/Y for a discovery observation line.".format(sep))
        logging.debug("{} {} {} {} {}".format(sep, x, y, mpc_obs.comment.x, mpc_obs.comment.y))
        # Try un-flipping.
        x = float(mpc_obs.comment.x)
        y = float(mpc_obs.comment.y)
        (ra, dec) = this_wcs.xy2sky(x, y)
        #print "--> x/y coordinates ({},{}) and recomputing ra/dec ({},{})".format(x, y, ra, dec)
        mpc_obs.coordinate = (ra, dec)
        sep = start_coordinate.separation(mpc_obs.coordinate).degrees * 3600.0
        logging.debug("remod: {}".format(mpc_obs.coordinate))
        logging.debug("SEP: {}".format(sep))
        logging.debug("rm  flip: {}".format(mpc_obs.to_string()))
    if sep > TOLERANCE:
        ## use the old header RA/DEC to predict the X/Y and then use that X/Y to get new RA/DEC
        logging.debug("Ignoring recorded X/Y and using previous to RA/DEC and WCS to compute X/Y")
        header2 = storage.get_image(parts.group('expnum'),
                                    int(parts.group('ccd')),
                                    return_file=False,
                                    flip_image=False)[0].header
        image_wcs = wcs.WCS(header2)
        (x, y) = image_wcs.sky2xy(mpc_in.coordinate.ra.degrees, mpc_in.coordinate.dec.degrees)
        (ra, dec) = this_wcs.xy2sky(x, y)
        logging.debug("({},{}) --> ({},{})".format(mpc_obs.comment.x, mpc_obs.comment.y, x, y))
        mpc_obs.coordinate = (ra, dec)
        mpc_obs.comment.x = x
        mpc_obs.comment.y = y
    try:
        merr = float(mpc_obs.comment.mag_uncertainty)
        fwhm = float(storage.get_fwhm(parts.group('expnum'), int(parts.group('ccd')))) * header['PIXSCAL1']
        centroid_err = merr * fwhm
        logging.debug("Centroid uncertainty:  {} {} => {}".format(merr, fwhm, centroid_err))
    except Exception as err:
        logging.error(str(err))
        logging.error("Failed to compute centroid for observation:\n"
                      "{}\nUsing default of 0.2".format(mpc_obs.to_string()))
        centroid_err = 0.2
    mpc_obs.comment.astrometric_level = header.get('ASTLEVEL', "0")
    try:
        asterr = float(header['ASTERR'])
        residuals = (asterr ** 2 + centroid_err ** 2) ** 0.5
        logging.debug("Residuals: {} {} => {}".format(asterr, centroid_err, residuals))
    except Exception as err:
        logging.error(str(err))
        logging.error("Failed while trying to compute plate uncertainty for\n{}".format(mpc_obs.to_stirng()))
        logging.error('Using default of 0.25')
        residuals = 0.25
    mpc_obs.comment.plate_uncertainty = residuals
    logging.debug("sending back: {}".format(mpc_obs.to_string()))
    return mpc_obs
Example #7
0
def remeasure(mpc_in, reset_pixel_coordinates=True):
    """
    Compute the RA/DEC of the line based on the X/Y in the comment and the WCS of the associated image.

    Comment of supplied astrometric line (mpc_in) must be in OSSOSComment format.

    @param mpc_in: An line of astrometric measurement to recompute the RA/DEC from the X/Y in the comment.
    @type mpc_in: mp_ephem.Observation
    @param reset_pixel_coordinates: try and determine correct X/Y is X/Y doesn't map to correct RA/DEC value
    @type reset_pixel_coordinates: bool
    @type reset_pixecl_coordinates: bool

    """
    if mpc_in.null_observation:
        return mpc_in
    mpc_obs = deepcopy(mpc_in)
    logging.debug("rm start: {}".format(mpc_obs.to_string()))

    if not isinstance(mpc_obs.comment, mp_ephem.ephem.OSSOSComment):
        logging.error("Failed to convert comment line")
        return mpc_in

    parts = re.search('(?P<expnum>\d{7})(?P<type>\S)(?P<ccd>\d\d)',
                      str(mpc_obs.comment.frame))
    if not parts:
        logging.error("Failed to parse expnum from frame info in comment line")
        return mpc_in
    ccd = int(parts.group('ccd'))
    expnum = int(parts.group('expnum'))
    exp_type = parts.group('type')

    try:
        header = _connection_error_wrapper(storage._get_sghead,
                                           expnum)[ccd + 1]
    except IOError as ioerr:
        logging.error(str(ioerr))
        logging.error(
            "Failed to get astrometric header for: {}".format(mpc_obs))
        return mpc_in

    this_wcs = wcs.WCS(header)

    coordinate = this_wcs.xy2sky(mpc_obs.comment.x,
                                 mpc_obs.comment.y,
                                 usepv=True)
    mpc_obs.coordinate = coordinate[0].to('degree').value, coordinate[1].to(
        'degree').value
    sep = mpc_in.coordinate.separation(mpc_obs.coordinate)

    if sep > TOLERANCE * 20 and mpc_in.discovery and _flipped_ccd(ccd):
        logging.warn(
            "Large ({}) offset using X/Y in comment line to compute RA/DEC".
            format(sep))
        if reset_pixel_coordinates:
            logging.info(
                "flipping/flopping the discvoery x/y position recorded.")
            x = header['NAXIS1'] - mpc_obs.comment.x + 1
            y = header['NAXIS2'] - mpc_obs.comment.y + 1
            new_coordinate = this_wcs.xy2sky(x, y, usepv=True)
            new_sep = mpc_in.coordinate.separation(new_coordinate)
            if new_sep < TOLERANCE * 2:
                mpc_obs.coordinate = new_coordinate
                mpc_obs.comment.x = x
                mpc_obs.comment.y = y
                sep = new_sep

    if sep > TOLERANCE:
        # use the old header RA/DEC to predict the X/Y and then use that X/Y to get new RA/DEC
        logging.warn(
            "sep: {} --> large offset when using comment line X/Y to compute RA/DEC"
        )
        if reset_pixel_coordinates:
            logging.warn(
                "Using RA/DEC and original WCS to compute X/Y and replacing X/Y in comment."
                .format(sep))
            header2 = _connection_error_wrapper(storage.get_astheader, expnum,
                                                ccd)
            image_wcs = wcs.WCS(header2)
            (x, y) = image_wcs.sky2xy(mpc_in.coordinate.ra.degree,
                                      mpc_in.coordinate.dec.degree,
                                      usepv=False)
            mpc_obs.coordinate = this_wcs.xy2sky(x, y, usepv=True)
            mpc_obs.comment.x = x
            mpc_obs.comment.y = y
            logging.info(
                "Coordinate changed: ({:5.2f},{:5.2f}) --> ({:5.2f},{:5.2f})".
                format(mpc_obs.comment.x, mpc_obs.comment.y, x, y))

    if mpc_obs.comment.mag_uncertainty is not None:
        try:
            merr = float(mpc_obs.comment.mag_uncertainty)
            fwhm = float(
                _connection_error_wrapper(storage.get_fwhm, expnum, ccd))
            centroid_err = merr * fwhm * header['PIXSCAL1']
            logging.debug("Centroid uncertainty:  {} {} => {}".format(
                merr, fwhm, centroid_err))
        except Exception as err:
            logging.error(str(err))
            logging.error("Failed to compute centroid_err for observation:\n"
                          "{}\nUsing default of 0.2".format(
                              mpc_obs.to_string()))
            centroid_err = 0.2
    else:
        centroid_err = 0.2

    mpc_obs.comment.astrometric_level = header.get('ASTLEVEL', "0")

    try:
        asterr = float(header['ASTERR'])
        residuals = (asterr**2 + centroid_err**2)**0.5
        logging.debug("Residuals: {} {} => {}".format(asterr, centroid_err,
                                                      residuals))
    except Exception as err:
        logging.error(str(err))
        logging.error(
            "Failed while trying to compute plate uncertainty for\n{}".format(
                mpc_obs.to_string()))
        logging.error('Using default of 0.25')
        residuals = 0.25

    mpc_obs.comment.plate_uncertainty = residuals

    logging.debug("sending back: {}".format(mpc_obs.to_string()))

    return mpc_obs