mag = np.where((dqflag==0), mag, None) # Now ditch the values out of the arrays where mag is None # NB do mag last magerr = magerr[np.flatnonzero(mag)] refmag = refmag[np.flatnonzero(mag)] refmagerr = refmagerr[np.flatnonzero(mag)] mag = mag[np.flatnonzero(mag)] if(len(mag) == 0): print "No good sources to plot" sys.exit(1) # Now apply the exposure time and nom_at_ext corrections to mag et = float(ad.exposure_time()) if(ad.is_type('GMOS_NODANDSHUFFLE')): print "Imaging Nod-And-Shuffle. Photometry may be dubious" et /= 2.0 etmag = 2.5*math.log10(et) nom_at_ext = float(ad.nominal_atmospheric_extinction()) mag += etmag mag += nom_at_ext # Can now calculate the zp array zp = refmag - mag zperr = np.sqrt(refmagerr*refmagerr + magerr*magerr) # Trim values out of zp where the zeropoint error is > 0.1 zp_trim = np.where((zperr<0.1), zp, None)
def __init__(self,fname,linelist=None,extv=1,nsum=10,match=6,radius=10): self.extv = extv self.nsum = nsum self.match = match self.radius = radius ad = AstroData(fname) self.imdata = ad['SCI',extv].data if ad.dispersion_axis() == 2: # Transpose to work on the X-axis. self.imdata = self.imdata.transpose() self.filename = ad.filename self.ad = ad linelist_file = linelist scrpix = 'crpix1' scrval = 'crval1' scdelt = 'cd1_1' fpath=os.path.dirname(spu.__file__) if ad.is_type('F2_SPECT') or self.ad.is_type('GNIRS'): reffile = 'calibrated_arc.fits' wmin = 7035.14 # x*0.24321 + 7035.1381. wavelength at [0] wmax = 25344.54 # wavelength at [-1] scrpix = 'crpix2' scrval = 'crval2' scdelt = 'cd2_2' sz = np.shape(self.imdata) if len(sz) == 3: self.imdata = self.imdata.reshape(sz[1],sz[2]) if linelist_file==None: linelist_file = 'argon.dat' #linelist_file = 'lowresargon.dat' elif ad.is_type('GMOS_SPECT'): if linelist_file==None: linelist_file = 'cuar.dat' reffile = 'cuar.fits' wmin = 3053. # x*0.25 + 3053. cuar.fits wavelength at cuarf[0] wmax = 10423. # cuar.fits wavelength at cuarf[-1] elif ad.is_type('NIRI_SPECT'): reffile = 'calibrated_arc.fits' wmin = 7032.706 wmax = 25342.113 if linelist_file==None: linelist_file = 'lowresargon.dat' elif ad.is_type('NIFS_SPECT'): filtername = str(self.ad.filter_name()) if 'JH' in filtername: if linelist_file==None: linelist_file = 'argon.dat' wmin = 7032.706 wmax = 25342.113 reffile = 'calibrated_arc.fits' elif 'HK' in filtername: if linelist_file==None: linelist_file = 'ArXe_K.dat' wmin = 20140.259 wmax = 24491.320 reffile = 'NIFS_K_arc_1D.fits' elif 'ZJ' in filtername: if linelist_file==None: linelist_file = 'argon.dat' wmin = 7035.14 wmax = 25344.54 reffile = 'calibrated_arc.fits' else: raise ValueError('Input file is not supported: '+ad.filename) self.reffile = os.path.join(fpath,reffile) self.wmin = wmin self.wmax = wmax self.pixs=[] self.users=[] linelist_file = os.path.join(fpath,linelist_file) linelist = np.loadtxt(linelist_file,usecols=(0,)) hdr = ad['SCI',extv].header self.wcs={'crpix':hdr[scrpix], 'crval':hdr[scrval], 'cdelt':hdr[scdelt]} cdelt = self.wcs['cdelt'] if cdelt < 0: linelist = linelist[::-1] # Change to decreasing order self.cuar = linelist # cuar is the IRAF name self.ad = ad sz = np.shape(self.imdata) nsum = 6 if len(sz) == 2: ny = max(3,nsum/2) ym = sz[0]/2 lpix = np.mean(self.imdata[ym-ny:ym+ny],axis=0) elif len(sz) == 1: lpix = self.imdata else: raise ValueError("Image dimesions are greater than 2.") self.lpix = lpix # Now find the arc peaks pixel coordinates upeaks,uflux,fw = spu.find_upeaks(self.lpix, 2, nmax=50, cradius=12) self.xfluxs = uflux self.xpeaks = upeaks # A synonim
class AcquisitionImage(object): def __init__(self, filename, mosmask=None, mdfdir=None): self.ad = AstroData(filename) self.mosmask = mosmask self.mdfdir = mdfdir # Determine extension nsci = len(self.ad) debug("...nsci = ", nsci) if nsci > 1: l_sci_ext = 1 else: l_sci_ext = 0 debug("...using extension [" + str(l_sci_ext) + "]") overscan_dv = self.ad[l_sci_ext].overscan_section() if self.is_mos_mode(): self.box_coords = parse_box_coords(self, self.get_mdf_filename()) self.box_mosaic = BoxMosaic(self, self.box_coords) self.scidata = self.box_mosaic.get_science_data() elif self.is_new_gmosn_ccd(): # tile the 2 center parts of the new GMOS image self.scidata = gmultiamp(self.ad) elif not overscan_dv.is_none(): # remove the overscan so we don't have to take it into account when guessing the slit location self.scidata = subtract_overscan(self.ad[l_sci_ext]) # it still affects the center of rotation however ox1, ox2, oy1, oy2 = overscan_dv.as_list() correction = np.array([ox2 - ox1, 0]) center = self.get_binned_data_center() - correction self.fieldcenter = center * self.detector_y_bin() else: self.scidata = self.ad[l_sci_ext].data @cache def instrument(self): return str(self.ad.instrument()) def is_new_gmosn_ccd(self): header = self.ad.phu.header if "DETECTOR" not in header: return False if header["DETECTOR"] == "GMOS + e2v DD CCD42-90": return True return False def get_science_data(self): assert self.scidata is not None return self.scidata @cache def unbinned_pixel_scale(self): return float(self.ad.pixel_scale()) / self.detector_y_bin() @cache def binned_pixel_scale(self): return float(self.ad.pixel_scale()) def _check_binning(self): if int(self.ad.detector_x_bin()) != int(self.ad.detector_y_bin()): error("ERROR: incorrect binning!") error("Sorry about that, better luck next time.") sys.exit(1) @cache def detector_x_bin(self): self._check_binning() return int(self.ad.detector_x_bin()) @cache def detector_y_bin(self): self._check_binning() return int(self.ad.detector_y_bin()) @cache def program_id(self): return str(self.ad.program_id()) @cache def observation_id(self): return str(self.ad.observation_id()) @cache def saturation_level(self): dv = self.ad.saturation_level() return min(dv.as_list()) @cache def focal_plane_mask(self): return str(self.ad.focal_plane_mask()) @cache def grating(self): return str(self.ad.grating()) def get_detector_size(self): # mos mode acquisitions don't necessarily have the entire # field of view in their data sections, so we have to rely on # other tricks to figure out the center of rotation. detsize = self.ad.phu_get_key_value("DETSIZE") xmin, xdim, ymin, ydim = extract_dimensions(detsize) # adjust for chip gaps nccds = int(self.ad.phu_get_key_value("NCCDS")) xdim += ((nccds - 1) * _obtain_unbinned_arraygap(self.ad)) # adjust for un-illuminated pixels if self.is_gmos(): ydim -= 36 # magic number that should be replaced with a lookup table later return xdim, ydim def get_field_center(self): """ The center of rotation in pixels. """ if hasattr(self, "fieldcenter"): return self.fieldcenter if self.is_mos_mode(): xdim, ydim = self.get_detector_size() return np.array([float(xdim) / 2.0, float(ydim) / 2.0]) return self.get_data_center() def get_data_center(self): ydim, xdim = self.get_science_data().shape return np.array([float(xdim) / 2.0, float(ydim) / 2.0]) * self.detector_y_bin() def get_binned_data_center(self): return self.get_data_center() / self.detector_y_bin() def set_goal_center(self, center): self.goal_center = np.array(center) def get_goal_center(self): default = self.get_data_center() return getattr(self, "goal_center", default) def set_binned_custom_center(self, center): self.set_binned_goal_center(center) self.custom_center = True def has_custom_center(self): return getattr(self, "custom_center", False) def get_binned_goal_center(self): return self.get_goal_center() / self.detector_y_bin() def set_binned_goal_center(self, center): center = np.array(center) * self.detector_y_bin() self.set_goal_center(center) def get_mask_width(self): debug("...finding slit dimensions...") slitxbin = self.detector_x_bin() slitybin = self.detector_y_bin() debug("...slit image binning = ", slitxbin, " x ", slitybin) if slitxbin > 1 or slitybin > 1: warning("! WARNING: Slit image is binned " + slitxbin + " x " + slitybin) slitmask = self.focal_plane_mask() return float(slitmask.replace("arcsec", "")) def get_mask_width_in_pixels(self): return self.get_mask_width() / self.unbinned_pixel_scale() def get_slit_size_in_pixels(self): xsize = self.get_mask_width_in_pixels() ysize = self.get_science_data().shape[0] return xsize, ysize def get_expected_slit_tilt(self): if self.is_gmos(): return 0.0 error("Instrument is not supported, need to know an expected slit tilt") sys.exit(1) @property def phu(self): return self.ad.phu @property def filename(self): return self.ad.filename def get_program_id_parts(self): gemprgid = str(self.ad.program_id()) parts = gemprgid.split("-") if len(parts) != 4: msg = "Cannot parse program id '%s'" % gemprgid error(msg) raise ValueError(msg) observatory, semester, prgtype, queuenum = parts return observatory, semester, prgtype, int(queuenum) def get_semester(self): """ Return something in the form of '2006B' """ observatory, semester, prgtype, queuenum = self.get_program_id_parts() return semester def get_observatory_prefix(self): """ Return something in the form of 'GN' """ observatory, semester, prgtype, queuenum = self.get_program_id_parts() return observatory def is_mos_mode(self): return self.mosmask is not None or self.has_mos_mask() @cache def has_mos_mask(self): if not self.is_gmos() and not self.is_f2(): return False maskname = self.focal_plane_mask() if ("Q" in maskname or # Queue program "C" in maskname or # Classical program "D" in maskname or # DD program "V" in maskname): # SV program xbin = self.detector_x_bin() ybin = self.detector_y_bin() if xbin != 1 or ybin != 1: error ("MOS acquisition image binning must be 1x1, found %ix%i binning." % (xbin, ybin)) clean() return True return False def has_mask_in_beam(self): maskname = self.focal_plane_mask().lower() if "imag" in maskname: return False slitmask = self.focal_plane_mask() if self.is_gmos() and "arcsec" in slitmask: return True if self.is_gnirs() and "arcsec" in slitmask: acqmir = slitimage_ad.phu.header["ACQMIR"] debug("...acqmir = ", acqmir) if acqmir == "In": return True if self.is_niri() and "cam" not in slitmask: return True if self.is_f2() and "slit" in slitmask: return True if self.is_f2() and "mos" in slitmask: return True return self.has_mos_mask() def get_mdf_filename(self): if hasattr(self, "mdffile"): return self.mdffile self.mdffile = self._get_mdf_filename() return self.mdffile def _get_mdf_filename(self): if self.mosmask is not None: mdffile = self.mosmask # Expand the MOS mask number if is_number(self.mosmask): observatory, semester, prgtype, queuenum = self.get_program_id_parts() mdffile = "%s%s%s%03i-%02i" % (observatory, semester, prgtype, queuenum, int(self.mosmask)) debug("...mosmask =", mdffile) else: mdffile = self.focal_plane_mask() mdffile = fits_filename(mdffile) #----------------------------------------------------------------------- # Start searching around willy nilly for the MDF file if os.path.exists(mdffile): return mdffile # note, the order in which directories are added to this list gives priority dirs = [] if self.mdfdir is not None: dirs.append(self.mdfdir) dname = os.path.dirname(self.filename) if dname and dname != ".": dirs.append(dname) dirs.append(os.getcwd()) # search through semester directories as well semester_dir = self.get_observatory_prefix() + self.get_semester() directories_to_search = [] for dname in dirs: directories_to_search.append(dname) dname = os.path.join(dname, semester_dir) directories_to_search.append(dname) # now search through the directories for dname in directories_to_search: fname = os.path.join(dname, mdffile) debug("...trying", fname) if os.path.exists(fname): return fname raise ValueError("Unable to find MDF file named '%s'" % mdffile) def get_num_mos_boxes(self): return self.box_mosaic.get_num_mos_boxes() def get_mos_boxes(self): return self.box_mosaic.get_boxes() def get_mos_box_borders(self): for border in self.box_mosaic.get_box_borders(): yield border @cache def get_min_slitsize(self): mdffile_ad = AstroData(self.get_mdf_filename()) xsize = Ellipsis ysize = Ellipsis for row in mdffile_ad["MDF"].data: # select the alignment boxes, designated by priority 0 if row["priority"] not in ["1", "2", "3"]: continue xsize = min(xsize, row["slitsize_x"]) ysize = min(ysize, row["slitsize_y"]) return xsize, ysize def get_extensions(self): for ext in self.ad: yield ext def _get_lazy_detector_section_finder(self): if not hasattr(self, "detsec_finder"): self.detsec_finder = DetectorSectionFinder(self) return self.detsec_finder def get_box_size(self): return self._get_lazy_detector_section_finder().get_box_size() def find_detector_section(self, point): return self._get_lazy_detector_section_finder().find_detector_section(point) def get_full_field_of_view(self): return self._get_lazy_detector_section_finder().get_full_field_of_view() def is_altair(self): aofold = self.ad.phu.header["AOFOLD"] if aofold == "IN": return True return False def is_south_port(self): inportnum = int(self.ad.phu.header["INPORT"]) if inportnum == 1: return True return False def is_type(self, typename): return self.ad.is_type(typename) def is_gmos(self): return self.is_type("GMOS") def is_gmosn(self): return self.is_type("GMOS_N") def is_gmoss(self): return self.is_type("GMOS_S") def is_gnirs(self): return self.is_type("GNIRS") def is_f2(self): return self.is_type("F2") def is_nifs(self): return self.is_type("NIFS") def is_niri(self): return self.is_type("NIRI")
except: log.warning('getBPM: CCDSUM value not supported with BPM: '+indx) return None # Find where are these BPM files fp, pathname, description = imp.find_module('detectSources') fname = os.path.join(os.path.dirname(pathname),dq) return AstroData(fname) if __name__ == '__main__': import sys,glob #ad = AstroData('/home/nzarate/zp/zzz.fits') #ff = Fluxcal(ad) # Create object #ff.runFC() # run the scripts for ifile in glob.glob('[g,m]*.fits'): if 'rgS20110125S' in ifile: continue if 'zp_' in ifile: continue ad = AstroData(ifile) if ad.is_type('CAL'): print "\nWARNING: 'CAL' type for file:",ifile," not supported." continue print "\n >>>>>>>>>>>>>>>>>>FluxCAL for:",ifile ff = Fluxcal(ad,addBPM=False) # Create object ff.runFC()