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))
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
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
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))
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')
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
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