def gemini_read_amp(inp, ext): """ Read one amplifier of an Gemini GMOS multi-extension FITS image Parameters ---------- inp: tuple (str,int) filename, extension (hdu,int) FITS hdu, extension Returns ------- data predata postdata x1 y1 ;------------------------------------------------------------------------ function lris_read_amp, filename, ext, $ linebias=linebias, nobias=nobias, $ predata=predata, postdata=postdata, header=header, $ x1=x1, x2=x2, y1=y1, y2=y2, GAINDATA=gaindata ;------------------------------------------------------------------------ ; Read one amp from LRIS mHDU image ;------------------------------------------------------------------------ """ # Parse input if isinstance(inp, str): hdu = fits.open(inp) else: hdu = inp # get entire extension... temp = hdu[ext].data.transpose() tsize = temp.shape nxt = tsize[0] # parse the DETSEC keyword to determine the size of the array. header = hdu[ext].header detsec = header['DETSEC'] x1, x2, y1, y2 = np.array(parse.load_sections(detsec, fmt_iraf=False)).flatten() # parse the DATASEC keyword to determine the size of the science region (unbinned) datasec = header['DATASEC'] xdata1, xdata2, ydata1, ydata2 = np.array( parse.load_sections(datasec, fmt_iraf=False)).flatten() # grab the components... data = temp[xdata1 - 1:xdata2, :] # Overscan biassec = header['BIASSEC'] xdata1, xdata2, ydata1, ydata2 = np.array( parse.load_sections(biassec, fmt_iraf=False)).flatten() overscan = temp[xdata1 - 1:xdata2, :] # Return return data, overscan, datasec, biassec, x1, x2
def gemini_read_amp(inp, ext): """ Read one amplifier of an Gemini GMOS multi-extension FITS image Parameters ---------- inp: :obj:`tuple` A two-tuple with either the filename and extension ``(str,int)`` with the data to read or the already opened `astropy.io.fits.HDUList`_ object and extension ``(hdu,int)``. Returns ------- data : `numpy.ndarray`_ 2D array with the science region of the raw image. overscan : `numpy.ndarray`_ 2D array with the overscan region of the raw image. datasec : :obj:`str` String representation of the section in the raw image with the science data. baissec : :obj:`str` String representation of the section in the raw image with the overscan. x1 : :obj:`int` Starting pixel along the first axis with the science data in the raw image. y1 : :obj:`int` Starting pixel along the second axis with the science data in the raw image. """ # Parse input hdu = io.fits_open(inp) if isinstance(inp, str) else inp # get entire extension... temp = hdu[ext].data.transpose() tsize = temp.shape nxt = tsize[0] # parse the DETSEC keyword to determine the size of the array. header = hdu[ext].header detsec = header['DETSEC'] x1, x2, y1, y2 = np.array(parse.load_sections(detsec, fmt_iraf=False)).flatten() # parse the DATASEC keyword to determine the size of the science region (unbinned) datasec = header['DATASEC'] xdata1, xdata2, ydata1, ydata2 \ = np.array(parse.load_sections(datasec, fmt_iraf=False)).flatten() # grab the components... data = temp[xdata1-1:xdata2,:] # Overscan biassec = header['BIASSEC'] xdata1, xdata2, ydata1, ydata2 \ = np.array(parse.load_sections(biassec, fmt_iraf=False)).flatten() overscan = temp[xdata1-1:xdata2,:] # Return return data, overscan, datasec, biassec, x1, x2
def get_image_section(self, inp=None, det=1, section='datasec'): # hdu = fits.open(inp) head0 = hdu[0].header binning = head0['BINNING'] xbin, ybin = [int(ibin) for ibin in binning.split(',')] # Get post, pre-pix values precol = head0['PRECOL'] postpix = head0['POSTPIX'] preline = head0['PRELINE'] postline = head0['POSTLINE'] if section == 'datasec': datsec = hdu[det].header['DATASEC'] # THIS IS BINNED x1, x2, y1, y2 = np.array( parse.load_sections(datsec, fmt_iraf=False)).flatten() dy = (y2 - y1) + 1 section = '[{:d}:{:d},{:d}:{:d}]'.format( preline * ybin, preline * ybin + (dy) * ybin, x1 * xbin, x2 * xbin) # Eliminate lines elif section == 'oscansec': nx = hdu[det].data.shape[1] section = '[:,{:d}:{:d}]'.format(nx * 2 - postpix, nx * 2) # return [section], False, False, False
def deimos_read_1chip(hdu, chipno): """ Read one of the DEIMOS detectors Parameters ---------- hdu : HDUList chipno : int Returns ------- data : ndarray oscan : ndarray """ # Extract datasec from header datsec = hdu[chipno].header['DATASEC'] detsec = hdu[chipno].header['DETSEC'] postpix = hdu[0].header['POSTPIX'] precol = hdu[0].header['PRECOL'] x1_dat, x2_dat, y1_dat, y2_dat = np.array( parse.load_sections(datsec)).flatten() x1_det, x2_det, y1_det, y2_det = np.array( parse.load_sections(detsec)).flatten() # This rotates the image to be increasing wavelength to the top # data = np.rot90((hdu[chipno].data).T, k=2) # nx=data.shape[0] # ny=data.shape[1] # Science data fullimage = hdu[chipno].data data = fullimage[x1_dat:x2_dat, y1_dat:y2_dat] # Overscan oscan = fullimage[:, y2_dat:] # Flip as needed if x1_det > x2_det: data = np.flipud(data) oscan = np.flipud(oscan) if y1_det > y2_det: data = np.fliplr(data) oscan = np.fliplr(oscan) # Return return data, oscan
def get_rawimage(self, raw_file, det): """ Load up the raw image and generate a few other bits and pieces that are key for image processing Args: raw_file (str): det (int): Returns: tuple: raw_img (np.ndarray) -- Raw image for this detector hdu (astropy.io.fits.HDUList) exptime (float) rawdatasec_img (np.ndarray) oscansec_img (np.ndarray) """ # Check for file; allow for extra .gz, etc. suffix fil = glob.glob(raw_file + '*') if len(fil) != 1: msgs.error("Found {:d} files matching {:s}".format(len(fil))) # Read msgs.info("Reading MMIRS file: {:s}".format(fil[0])) hdu = fits.open(fil[0]) head1 = fits.getheader(fil[0],1) detector_par = self.get_detector_par(hdu, det if det is None else 1) # get the x and y binning factors... binning = head1['CCDSUM'] xbin, ybin = [int(ibin) for ibin in binning.split(' ')] # First read over the header info to determine the size of the output array... datasec = head1['DATASEC'] x1, x2, y1, y2 = np.array(parse.load_sections(datasec, fmt_iraf=False)).flatten() # ToDo: I am currently using the standard double correlated frame, that is a difference between # the first and final read-outs. In the future need to explore up-the-ramp fitting. if len(hdu)>2: data = mmirs_read_amp(hdu[1].data.astype('float64')) - mmirs_read_amp(hdu[2].data.astype('float64')) else: data = mmirs_read_amp(hdu[1].data.astype('float64')) array = data[x1-1:x2,y1-1:y2] ## ToDo: This is a hack. Need to solve this issue. I cut at 998 due to the HK zero order contaminating ## the blue part of the zJ+HK spectrum. For other setup, you do not need to cut the detector. if (head1['FILTER']=='zJ') and (head1['DISPERSE']=='HK'): array = array[:int(998/ybin),:] rawdatasec_img = np.ones_like(array,dtype='int') oscansec_img = np.ones_like(array,dtype='int') # Need the exposure time exptime = hdu[self.meta['exptime']['ext']].header[self.meta['exptime']['card']] # Return, transposing array back to orient the overscan properly return detector_par, np.flipud(array), hdu, exptime, np.flipud(rawdatasec_img),\ np.flipud(np.flipud(oscansec_img))
def read_gmos(raw_file, det=1): """ Read the GMOS data file Parameters ---------- raw_file : str Filename detector_par : ParSet Needed for numamplifiers if not other things det : int, optional Detector number; Default = 1 Returns ------- array : ndarray Combined image header : FITS header sections : list List of datasec, oscansec, ampsec sections """ # Check for file; allow for extra .gz, etc. suffix fil = glob.glob(raw_file + '*') if len(fil) != 1: msgs.error("Found {:d} files matching {:s}".format(len(fil))) # Read msgs.info("Reading GMOS file: {:s}".format(fil[0])) hdu = fits.open(fil[0]) head0 = hdu[0].header head1 = hdu[1].header # Number of amplifiers (could pull from DetectorPar but this avoids needing the spectrograph, e.g. view_fits) numamp = (len(hdu) - 1) // 3 # Setup for datasec, oscansec dsec = [] osec = [] # get the x and y binning factors... binning = head1['CCDSUM'] xbin, ybin = [int(ibin) for ibin in binning.split(' ')] # First read over the header info to determine the size of the output array... datasec = head1['DATASEC'] x1, x2, y1, y2 = np.array(parse.load_sections(datasec, fmt_iraf=False)).flatten() biassec = head1['BIASSEC'] b1, b2, b3, b4 = np.array(parse.load_sections(biassec, fmt_iraf=False)).flatten() nxb = b2 - b1 + 1 # determine the output array size... nx = (x2 - x1 + 1) * numamp + nxb * numamp ny = y2 - y1 + 1 # allocate output array... array = np.zeros((nx, ny)) if numamp == 2: if det == 1: # BLUEST DETECTOR order = range(6, 4, -1) elif det == 2: # BLUEST DETECTOR order = range(3, 5) elif det == 3: # BLUEST DETECTOR order = range(1, 3) elif numamp == 4: if det == 1: # BLUEST DETECTOR order = range(12, 8, -1) elif det == 2: # BLUEST DETECTOR order = range(8, 4, -1) elif det == 3: # BLUEST DETECTOR order = range(4, 0, -1) else: debugger.set_trace() # insert extensions into master image... for kk, jj in enumerate(order): # grab complete extension... data, overscan, datasec, biassec, x1, x2 = gemini_read_amp(hdu, jj) #, linebias=linebias, nobias=nobias, $ #x1=x1, x2=x2, y1=y1, y2=y2, gaindata=gaindata) # insert components into output array... inx = data.shape[0] xs = inx * kk xe = xs + inx # insert data... # Data section #section = '[:,{:d}:{:d}]'.format(xs, xe) # Eliminate lines section = '[{:d}:{:d},:]'.format(xs, xe) # Eliminate lines dsec.append(section) array[xs:xe, :] = np.flipud(data) #; insert postdata... xs = nx - numamp * nxb + kk * nxb xe = xs + nxb #debugger.set_trace() #section = '[:,{:d}:{:d}]'.format(xs, xe) osection = '[{:d}:{:d},:]'.format(xs, xe) # TRANSPOSED FOR WHAT COMES osec.append(osection) array[xs:xe, :] = overscan # make sure BZERO is a valid integer for IRAF obzero = head1['BZERO'] #head0['O_BZERO'] = obzero head0['BZERO'] = 32768 - obzero # Return, transposing array back to goofy Python indexing return array, head0, (dsec, osec)
def get_rawimage(self, raw_file, det): """ Load up the raw image and generate a few other bits and pieces that are key for image processing Args: raw_file (str): det (int): Returns: tuple: raw_img (np.ndarray) -- Raw image for this detector hdu (astropy.io.fits.HDUList) exptime (float) rawdatasec_img (np.ndarray) oscansec_img (np.ndarray) """ # Check for file; allow for extra .gz, etc. suffix fil = glob.glob(raw_file + '*') if len(fil) != 1: msgs.error("Found {:d} files matching {:s}".format(len(fil))) # Read msgs.info("Reading LBT/MODS file: {:s}".format(fil[0])) hdu = fits.open(fil[0]) head = hdu[0].header # TODO These parameters should probably be stored in the detector par # Number of amplifiers (could pull from DetectorPar but this avoids needing the spectrograph, e.g. view_fits) numamp = 4 # get the x and y binning factors... xbin, ybin = head['CCDXBIN'], head['CCDYBIN'] datasize = head['DETSIZE'] # Unbinned size of detector full array _, nx_full, _, ny_full = np.array( parse.load_sections(datasize, fmt_iraf=False)).flatten() # Determine the size of the output array... nx, ny = int(nx_full / xbin), int(ny_full / ybin) nbias1 = 48 nbias2 = 8240 # allocate output array... array = hdu[ 0].data.T * 1.0 ## Convert to float in order to get it processed with procimg.py rawdatasec_img = np.zeros_like(array, dtype=int) oscansec_img = np.zeros_like(array, dtype=int) ## allocate datasec and oscansec to the image # apm 1 rawdatasec_img[int(nbias1 / xbin):int(nx / 2), :int(ny / 2)] = 1 oscansec_img[1:int(nbias1 / xbin), :int( ny / 2)] = 1 # exclude the first pixel since it always has problem # apm 2 rawdatasec_img[int(nx / 2):int(nbias2 / xbin), :int(ny / 2)] = 2 oscansec_img[int(nbias2 / xbin):nx - 1, :int( ny / 2)] = 2 # exclude the last pixel since it always has problem # apm 3 rawdatasec_img[int(nbias1 / xbin):int(nx / 2), int(ny / 2):] = 3 oscansec_img[ 1:int(nbias1 / xbin), int(ny / 2):] = 3 # exclude the first pixel since it always has problem # apm 4 rawdatasec_img[int(nx / 2):int(nbias2 / xbin), int(ny / 2):] = 4 oscansec_img[ int(nbias2 / xbin):nx - 1, int(ny / 2):] = 4 # exclude the last pixel since it always has problem # Need the exposure time exptime = hdu[self.meta['exptime']['ext']].header[self.meta['exptime'] ['card']] # Return, transposing array back to orient the overscan properly return np.flipud(array), hdu, exptime, np.flipud( rawdatasec_img), np.flipud(oscansec_img)
def read_deimos(raw_file, det=None): """ Read a raw DEIMOS data frame (one or more detectors) Packed in a multi-extension HDU Based on pypeit.arlris.read_lris... Based on readmhdufits.pro Parameters ---------- raw_file : str Filename Returns ------- array : ndarray Combined image hdu: HDUList sections : tuple List of datasec, oscansec sections """ # Check for file; allow for extra .gz, etc. suffix fil = glob.glob(raw_file + '*') if len(fil) != 1: msgs.error('Found {0} files matching {1}'.format( len(fil), raw_file + '*')) # Read try: msgs.info("Reading DEIMOS file: {:s}".format(fil[0])) except AttributeError: print("Reading DEIMOS file: {:s}".format(fil[0])) hdu = fits.open(fil[0]) head0 = hdu[0].header # Get post, pre-pix values precol = head0['PRECOL'] postpix = head0['POSTPIX'] preline = head0['PRELINE'] postline = head0['POSTLINE'] detlsize = head0['DETLSIZE'] x0, x_npix, y0, y_npix = np.array(parse.load_sections(detlsize)).flatten() # Create final image if det is None: image = np.zeros((x_npix, y_npix + 4 * postpix)) # Setup for datasec, oscansec dsec = [] osec = [] # get the x and y binning factors... binning = head0['BINNING'] if binning != '1,1': msgs.error("This binning for DEIMOS might not work. But it might..") xbin, ybin = [int(ibin) for ibin in binning.split(',')] # DEIMOS detectors nchip = 8 if det is None: chips = range(nchip) else: chips = [det - 1] # Indexing starts at 0 here # Loop for tt in chips: data, oscan = deimos_read_1chip(hdu, tt + 1) #if n_elements(nobias) eq 0 then nobias = 0 # One detector?? if det is not None: image = np.zeros((data.shape[0], data.shape[1] + oscan.shape[1])) # Indexing x1, x2, y1, y2, o_x1, o_x2, o_y1, o_y2 = indexing(tt, postpix, det=det) # Fill image[y1:y2, x1:x2] = data image[o_y1:o_y2, o_x1:o_x2] = oscan # Sections idsec = '[{:d}:{:d},{:d}:{:d}]'.format(y1, y2, x1, x2) iosec = '[{:d}:{:d},{:d}:{:d}]'.format(o_y1, o_y2, o_x1, o_x2) dsec.append(idsec) osec.append(iosec) # Return return image, hdu, (dsec, osec)
def lris_read_amp(inp, ext): """ Read one amplifier of an LRIS multi-extension FITS image Args: inp (str, astropy.io.fits.HDUList): filename or HDUList ext (int): Extension index Returns: tuple: data predata postdata x1 y1 """ # Parse input if isinstance(inp, str): hdu = fits.open(inp) else: hdu = inp # Get the pre and post pix values # for LRIS red POSTLINE = 20, POSTPIX = 80, PRELINE = 0, PRECOL = 12 head0 = hdu[0].header precol = head0['precol'] postpix = head0['postpix'] # Deal with binning binning = head0['BINNING'] xbin, ybin = [int(ibin) for ibin in binning.split(',')] precol = precol//xbin postpix = postpix//xbin # get entire extension... temp = hdu[ext].data.transpose() # Silly Python nrow,ncol formatting tsize = temp.shape nxt = tsize[0] # parse the DETSEC keyword to determine the size of the array. header = hdu[ext].header detsec = header['DETSEC'] x1, x2, y1, y2 = np.array(parse.load_sections(detsec, fmt_iraf=False)).flatten() # parse the DATASEC keyword to determine the size of the science region (unbinned) datasec = header['DATASEC'] xdata1, xdata2, ydata1, ydata2 = np.array(parse.load_sections(datasec, fmt_iraf=False)).flatten() # grab the components... predata = temp[0:precol, :] # datasec appears to have the x value for the keywords that are zero # based. This is only true in the image header extensions # not true in the main header. They also appear inconsistent between # LRISr and LRISb! #data = temp[xdata1-1:xdata2-1,*] #data = temp[xdata1:xdata2+1, :] if (xdata1-1) != precol: msgs.error("Something wrong in LRIS datasec or precol") xshape = 1024 // xbin if (xshape+precol+postpix) != temp.shape[0]: msgs.warn("Unexpected size for LRIS detector. We expect you did some windowing...") xshape = temp.shape[0] - precol - postpix data = temp[precol:precol+xshape,:] postdata = temp[nxt-postpix:nxt, :] # flip in X as needed... if x1 > x2: xt = x2 x2 = x1 x1 = xt data = np.flipud(data) # flip in Y as needed... if y1 > y2: yt = y2 y2 = y1 y1 = yt data = np.fliplr(data) predata = np.fliplr(predata) postdata = np.fliplr(postdata) return data, predata, postdata, x1, y1
def read_hires(raw_file, det=None): """ Read a raw HIRES data frame (one or more detectors). Data are unpacked from the multi-extension HDU. Function is based :func:`pypeit.spectrographs.keck_lris.read_lris`, which was based on the IDL procedure ``readmhdufits.pro``. Parameters ---------- raw_file : str Filename Returns ------- array : ndarray Combined image header : FITS header sections : tuple List of datasec, oscansec sections """ # Check for file; allow for extra .gz, etc. suffix fil = glob.glob(raw_file + '*') if len(fil) != 1: msgs.error('Found {0} files matching {1}'.format(len(fil), raw_file + '*')) # Read try: msgs.info("Reading HIRES file: {:s}".format(fil[0])) except AttributeError: print("Reading HIRES file: {:s}".format(fil[0])) hdu = fits.open(fil[0]) head0 = hdu[0].header # Get post, pre-pix values precol = head0['PRECOL'] postpix = head0['POSTPIX'] preline = head0['PRELINE'] postline = head0['POSTLINE'] detlsize = head0['DETLSIZE'] x0, x_npix, y0, y_npix = np.array(parse.load_sections(detlsize)).flatten() # Create final image if det is None: image = np.zeros((x_npix,y_npix+4*postpix)) # Setup for datasec, oscansec dsec = [] osec = [] # get the x and y binning factors... binning = head0['BINNING'] if binning != '3,1': msgs.warn("This binning for HIRES might not work. But it might..") xbin, ybin = [int(ibin) for ibin in binning.split(',')] # HIRES detectors nchip = 3 if det is None: chips = range(nchip) else: chips = [det-1] # Indexing starts at 0 here # Loop for tt in chips: data, oscan = hires_read_1chip(hdu, tt+1) # One detector?? if det is not None: image = np.zeros((data.shape[0],data.shape[1]+oscan.shape[1])) # Indexing x1, x2, y1, y2, o_x1, o_x2, o_y1, o_y2 = indexing(tt, postpix, det=det,xbin=xbin,ybin=ybin) # Fill image[y1:y2, x1:x2] = data image[o_y1:o_y2, o_x1:o_x2] = oscan # Sections idsec = '[{:d}:{:d},{:d}:{:d}]'.format(y1, y2, x1, x2) iosec = '[{:d}:{:d},{:d}:{:d}]'.format(o_y1, o_y2, o_x1, o_x2) dsec.append(idsec) osec.append(iosec) # Return return image, head0, (dsec,osec)
def get_rawimage(self, raw_file, det): """ Load up the raw image and generate a few other bits and pieces that are key for image processing Args: raw_file (str): det (int): Returns: tuple: raw_img (np.ndarray) -- Raw image for this detector hdu (astropy.io.fits.HDUList) exptime (float) rawdatasec_img (np.ndarray) oscansec_img (np.ndarray) """ # Check for file; allow for extra .gz, etc. suffix fil = glob.glob(raw_file + '*') if len(fil) != 1: msgs.error("Found {:d} files matching {:s}".format(len(fil))) # Read msgs.info("Reading BINOSPEC file: {:s}".format(fil[0])) hdu = fits.open(fil[0]) head1 = hdu[1].header # TOdO Store these parameters in the DetectorPar. # Number of amplifiers detector_par = self.get_detector_par(hdu, det if det is None else 1) numamp = detector_par['numamplifiers'] # get the x and y binning factors... binning = head1['CCDSUM'] xbin, ybin = [int(ibin) for ibin in binning.split(' ')] # First read over the header info to determine the size of the output array... datasec = head1['DATASEC'] x1, x2, y1, y2 = np.array(parse.load_sections(datasec, fmt_iraf=False)).flatten() nxb = x1 - 1 # determine the output array size... nx = (x2 - x1 + 1) * int(numamp/2) + nxb * int(numamp/2) ny = (y2 - y1 + 1) * int(numamp/2) #datasize = head1['DETSIZE'] #_, nx, _, ny = np.array(parse.load_sections(datasize, fmt_iraf=False)).flatten() # allocate output array... array = np.zeros((nx, ny)) rawdatasec_img = np.zeros_like(array, dtype=int) oscansec_img = np.zeros_like(array, dtype=int) if det == 1: # A DETECTOR order = range(1, 5, 1) elif det == 2: # B DETECTOR order = range(5, 9, 1) # insert extensions into master image... for kk, jj in enumerate(order): # grab complete extension... data, overscan, datasec, biassec = binospec_read_amp(hdu, jj) # insert components into output array... inx = data.shape[0] xs = inx * kk xe = xs + inx iny = data.shape[1] ys = iny * kk yn = ys + iny b1, b2, b3, b4 = np.array(parse.load_sections(biassec, fmt_iraf=False)).flatten() if kk == 0: array[b2:inx+b2,:iny] = data #*1.028 rawdatasec_img[b2:inx+b2,:iny] = kk + 1 array[:b2,:iny] = overscan oscansec_img[2:b2,:iny] = kk + 1 elif kk == 1: array[b2+inx:2*inx+b2,:iny] = np.flipud(data) #* 1.115 rawdatasec_img[b2+inx:2*inx+b2:,:iny] = kk + 1 array[2*inx+b2:,:iny] = overscan oscansec_img[2*inx+b2:,:iny] = kk + 1 elif kk == 2: array[b2+inx:2*inx+b2,iny:] = np.fliplr(np.flipud(data)) #* 1.047 rawdatasec_img[b2+inx:2*inx+b2,iny:] = kk + 1 array[2*inx+b2:, iny:] = overscan oscansec_img[2*inx+b2:, iny:] = kk + 1 elif kk == 3: array[b2:inx+b2,iny:] = np.fliplr(data) #* 1.045 rawdatasec_img[b2:inx+b2,iny:] = kk + 1 array[:b2,iny:] = overscan oscansec_img[2:b2,iny:] = kk + 1 # Need the exposure time exptime = hdu[self.meta['exptime']['ext']].header[self.meta['exptime']['card']] # Return, transposing array back to orient the overscan properly return detector_par, np.fliplr(np.flipud(array)), hdu, exptime, np.fliplr(np.flipud(rawdatasec_img)), \ np.fliplr(np.flipud(oscansec_img))
def lris_read_amp(inp, ext): """ Read one amplifier of an LRIS multi-extension FITS image Parameters ---------- inp: tuple (str,int) filename, extension (hdu,int) FITS hdu, extension Returns ------- data predata postdata x1 y1 ;------------------------------------------------------------------------ function lris_read_amp, filename, ext, $ linebias=linebias, nobias=nobias, $ predata=predata, postdata=postdata, header=header, $ x1=x1, x2=x2, y1=y1, y2=y2, GAINDATA=gaindata ;------------------------------------------------------------------------ ; Read one amp from LRIS mHDU image ;------------------------------------------------------------------------ """ # Parse input if isinstance(inp, str): hdu = fits.open(inp) else: hdu = inp # Get the pre and post pix values # for LRIS red POSTLINE = 20, POSTPIX = 80, PRELINE = 0, PRECOL = 12 head0 = hdu[0].header precol = head0['precol'] postpix = head0['postpix'] # Deal with binning binning = head0['BINNING'] xbin, ybin = [int(ibin) for ibin in binning.split(',')] precol = precol//xbin postpix = postpix//xbin # get entire extension... temp = hdu[ext].data.transpose() # Silly Python nrow,ncol formatting tsize = temp.shape nxt = tsize[0] # parse the DETSEC keyword to determine the size of the array. header = hdu[ext].header detsec = header['DETSEC'] x1, x2, y1, y2 = np.array(parse.load_sections(detsec, fmt_iraf=False)).flatten() # parse the DATASEC keyword to determine the size of the science region (unbinned) datasec = header['DATASEC'] xdata1, xdata2, ydata1, ydata2 = np.array(parse.load_sections(datasec, fmt_iraf=False)).flatten() # grab the components... predata = temp[0:precol, :] # datasec appears to have the x value for the keywords that are zero # based. This is only true in the image header extensions # not true in the main header. They also appear inconsistent between # LRISr and LRISb! #data = temp[xdata1-1:xdata2-1,*] #data = temp[xdata1:xdata2+1, :] if (xdata1-1) != precol: msgs.error("Something wrong in LRIS datasec or precol") xshape = 1024 // xbin if (xshape+precol+postpix) != temp.shape[0]: msgs.warn("Unexpected size for LRIS detector. We expect you did some windowing...") xshape = temp.shape[0] - precol - postpix data = temp[precol:precol+xshape,:] postdata = temp[nxt-postpix:nxt, :] # flip in X as needed... if x1 > x2: xt = x2 x2 = x1 x1 = xt data = np.flipud(data) #reverse(temporary(data),1) # flip in Y as needed... if y1 > y2: yt = y2 y2 = y1 y1 = yt data = np.fliplr(data) predata = np.fliplr(predata) postdata = np.fliplr(postdata) ''' #; correct gain if requested... if keyword_set(GAINDATA) then begin gain = gainvalue( gaindata, header) data = FLOAT(temporary(data)) * gain predata = FLOAT(temporary(predata)) * gain postdata = FLOAT(temporary(postdata)) * gain endif ''' ''' ;; optional bias subtraction... if ~ keyword_set(NOBIAS) then begin if keyword_set( LINEBIAS) then begin ;; compute a bias for each line... bias = median( postdata, dim=1) ;; subtract for data... buf = size(data) nx = buf[1] ny = buf[2] data2 = fltarr(nx,ny) for i=0,nx-1 do begin data2[i,*] = float(data[i,*]) - bias endfor data = data2 endif else begin ;; compute a scalar bias.... bias = median( postdata) data -= bias endelse endif ''' return data, predata, postdata, x1, y1
def read_lris(raw_file, det=None, TRIM=False): """ Read a raw LRIS data frame (one or more detectors) Packed in a multi-extension HDU Based on readmhdufits.pro Parameters ---------- raw_file : str Filename det : int, optional Detector number; Default = both TRIM : bool, optional Trim the image? This doesn't work.... Returns ------- array : ndarray Combined image header : FITS header sections : list List of datasec, oscansec, ampsec sections datasec, oscansec needs to be for an *unbinned* image as per standard convention """ # Check for file; allow for extra .gz, etc. suffix fil = glob.glob(raw_file+'*') if len(fil) != 1: msgs.error("Found {:d} files matching {:s}".format(len(fil))) # Read msgs.info("Reading LRIS file: {:s}".format(fil[0])) hdu = fits.open(fil[0]) head0 = hdu[0].header # Get post, pre-pix values precol = head0['PRECOL'] postpix = head0['POSTPIX'] preline = head0['PRELINE'] postline = head0['POSTLINE'] # Setup for datasec, oscansec dsec = [] osec = [] # get the x and y binning factors... binning = head0['BINNING'] xbin, ybin = [int(ibin) for ibin in binning.split(',')] # First read over the header info to determine the size of the output array... n_ext = len(hdu)-1 # Number of extensions (usually 4) xcol = [] xmax = 0 ymax = 0 xmin = 10000 ymin = 10000 for i in np.arange(1, n_ext+1): theader = hdu[i].header detsec = theader['DETSEC'] if detsec != '0': # parse the DETSEC keyword to determine the size of the array. x1, x2, y1, y2 = np.array(parse.load_sections(detsec, fmt_iraf=False)).flatten() # find the range of detector space occupied by the data # [xmin:xmax,ymin:ymax] xt = max(x2, x1) xmax = max(xt, xmax) yt = max(y2, y1) ymax = max(yt, ymax) # find the min size of the array xt = min(x1, x2) xmin = min(xmin, xt) yt = min(y1, y2) ymin = min(ymin, yt) # Save xcol.append(xt) # determine the output array size... nx = xmax - xmin + 1 ny = ymax - ymin + 1 # change size for binning... nx = nx // xbin ny = ny // ybin # Update PRECOL and POSTPIX precol = precol // xbin postpix = postpix // xbin # Deal with detectors if det in [1,2]: nx = nx // 2 n_ext = n_ext // 2 det_idx = np.arange(n_ext, dtype=np.int) + (det-1)*n_ext ndet = 1 elif det is None: ndet = 2 det_idx = np.arange(n_ext).astype(int) else: raise ValueError('Bad value for det') # change size for pre/postscan... if not TRIM: nx += n_ext*(precol+postpix) ny += preline + postline # allocate output array... array = np.zeros( (nx, ny) ) order = np.argsort(np.array(xcol)) # insert extensions into master image... for kk, i in enumerate(order[det_idx]): # grab complete extension... data, predata, postdata, x1, y1 = lris_read_amp(hdu, i+1) #, linebias=linebias, nobias=nobias, $ #x1=x1, x2=x2, y1=y1, y2=y2, gaindata=gaindata) # insert components into output array... if not TRIM: # insert predata... buf = predata.shape nxpre = buf[0] xs = kk*precol xe = xs + nxpre ''' if keyword_set(VERBOSITY) then begin section = '['+stringify(xs)+':'+stringify(xe)+',*]' message, 'inserting extension '+stringify(i)+ $ ' predata in '+section, /info endif ''' array[xs:xe, :] = predata # insert data... buf = data.shape nxdata = buf[0] nydata = buf[1] xs = n_ext*precol + kk*nxdata #(x1-xmin)/xbin xe = xs + nxdata #section = '[{:d}:{:d},{:d}:{:d}]'.format(preline,nydata-postline, xs, xe) # Eliminate lines section = '[{:d}:{:d},{:d}:{:d}]'.format(preline*ybin, (nydata-postline)*ybin, xs*xbin, xe*xbin) # Eliminate lines dsec.append(section) #print('data',xs,xe) array[xs:xe, :] = data # Include postlines #; insert postdata... buf = postdata.shape nxpost = buf[0] xs = nx - n_ext*postpix + kk*postpix xe = xs + nxpost #section = '[:,{:d}:{:d}]'.format(xs*xbin, xe*xbin) section = '[{:d}:{:d},{:d}:{:d}]'.format(preline*ybin, (nydata-postline)*ybin, xs*xbin, xe*xbin) osec.append(section) ''' if keyword_set(VERBOSITY) then begin section = '['+stringify(xs)+':'+stringify(xe)+',*]' message, 'inserting extension '+stringify(i)+ $ ' postdata in '+section, /info endif ''' array[xs:xe, :] = postdata else: buf = data.shape nxdata = buf[0] nydata = buf[1] xs = (x1-xmin)//xbin xe = xs + nxdata ys = (y1-ymin)//ybin ye = ys + nydata - postline yin1 = preline yin2 = nydata - postline ''' if keyword_set(VERBOSITY) then begin section = '['+stringify(xs)+':'+stringify(xe)+ $ ','+stringify(ys)+':'+stringify(ye)+']' message, 'inserting extension '+stringify(i)+ $ ' data in '+section, /info endif ''' array[xs:xe, ys:ye] = data[:, yin1:yin2] # make sure BZERO is a valid integer for IRAF obzero = head0['BZERO'] head0['O_BZERO'] = obzero head0['BZERO'] = 32768-obzero # Return, transposing array back to goofy Python indexing #from IPython import embed; embed() return array.T, head0, (dsec, osec)
def get_rawimage(self, raw_file, det): """ Load up the raw image and generate a few other bits and pieces that are key for image processing Args: raw_file (str): det (int): Returns: tuple: See :func:`pypeit.spectrograph.spectrograph.get_rawimage` """ # Check for file; allow for extra .gz, etc. suffix fil = glob.glob(raw_file + '*') if len(fil) != 1: msgs.error("Found {:d} files matching {:s}".format(len(fil))) # Read msgs.info("Reading GMOS file: {:s}".format(fil[0])) hdu = fits.open(fil[0]) head0 = hdu[0].header head1 = hdu[1].header # Number of amplifiers (could pull from DetectorPar but this avoids needing the spectrograph, e.g. view_fits) numamp = (len(hdu) - 1) // 3 # get the x and y binning factors... binning = head1['CCDSUM'] xbin, ybin = [int(ibin) for ibin in binning.split(' ')] # First read over the header info to determine the size of the output array... datasec = head1['DATASEC'] x1, x2, y1, y2 = np.array(parse.load_sections( datasec, fmt_iraf=False)).flatten() biassec = head1['BIASSEC'] b1, b2, b3, b4 = np.array(parse.load_sections( biassec, fmt_iraf=False)).flatten() nxb = b2 - b1 + 1 # determine the output array size... nx = (x2 - x1 + 1) * numamp + nxb * numamp ny = y2 - y1 + 1 # allocate output array... array = np.zeros((nx, ny)) rawdatasec_img = np.zeros_like(array, dtype=int) oscansec_img = np.zeros_like(array, dtype=int) if numamp == 2: # E2V if det == 1: # BLUEST DETECTOR order = range(6, 4, -1) elif det == 2: # NEXT order = range(3, 5) elif det == 3: # REDDEST DETECTOR order = range(1, 3) elif numamp == 4: # Hamamatsu if det == 1: # BLUEST DETECTOR order = range(12, 8, -1) elif det == 2: # BLUEST DETECTOR order = range(8, 4, -1) elif det == 3: # BLUEST DETECTOR order = range(4, 0, -1) else: embed() # insert extensions into master image... for kk, jj in enumerate(order): # grab complete extension... data, overscan, datasec, biassec, x1, x2 = gemini_read_amp(hdu, jj) # insert components into output array... inx = data.shape[0] xs = inx * kk xe = xs + inx # insert data... # Data section #section = '[{:d}:{:d},:]'.format(xs * xbin, xe * xbin) # Eliminate lines #dsec.append(section) array[xs:xe, :] = np.flipud(data) rawdatasec_img[xs:xe, :] = kk + 1 # ; insert postdata... xs = nx - numamp * nxb + kk * nxb xe = xs + nxb #osection = '[{:d}:{:d},:]'.format(xs * xbin, xe * xbin) # TRANSPOSED FOR WHAT COMES #osec.append(osection) array[xs:xe, :] = overscan oscansec_img[xs:xe, :] = kk + 1 # Need the exposure time exptime = hdu[self.meta['exptime']['ext']].header[self.meta['exptime'] ['card']] # Return, transposing array back to orient the overscan properly return self.get_detector_par(hdu, det if det is None else 1), \ array.T, hdu, exptime, rawdatasec_img.T, oscansec_img.T
def get_rawimage(self, raw_file, det): """ Read raw images and generate a few other bits and pieces that are key for image processing. Parameters ---------- raw_file : :obj:`str` File to read det : :obj:`int` 1-indexed detector to read Returns ------- detector_par : :class:`pypeit.images.detector_container.DetectorContainer` Detector metadata parameters. raw_img : `numpy.ndarray`_ Raw image for this detector. hdu : `astropy.io.fits.HDUList`_ Opened fits file exptime : :obj:`float` Exposure time read from the file header rawdatasec_img : `numpy.ndarray`_ Data (Science) section of the detector as provided by setting the (1-indexed) number of the amplifier used to read each detector pixel. Pixels unassociated with any amplifier are set to 0. oscansec_img : `numpy.ndarray`_ Overscan section of the detector as provided by setting the (1-indexed) number of the amplifier used to read each detector pixel. Pixels unassociated with any amplifier are set to 0. """ # Check for file; allow for extra .gz, etc. suffix fil = glob.glob(raw_file + '*') if len(fil) != 1: msgs.error("Found {:d} files matching {:s}".format(len(fil))) # Read msgs.info("Reading MMIRS file: {:s}".format(fil[0])) hdu = io.fits_open(fil[0]) head1 = fits.getheader(fil[0], 1) detector_par = self.get_detector_par(hdu, det if det is None else 1) # get the x and y binning factors... binning = head1['CCDSUM'] xbin, ybin = [int(ibin) for ibin in binning.split(' ')] # First read over the header info to determine the size of the output array... datasec = head1['DATASEC'] x1, x2, y1, y2 = np.array(parse.load_sections( datasec, fmt_iraf=False)).flatten() # ToDo: I am currently using the standard double correlated frame, that is a difference between # the first and final read-outs. In the future need to explore up-the-ramp fitting. if len(hdu) > 2: data = mmirs_read_amp( hdu[1].data.astype('float64')) - mmirs_read_amp( hdu[2].data.astype('float64')) else: data = mmirs_read_amp(hdu[1].data.astype('float64')) array = data[x1 - 1:x2, y1 - 1:y2] ## ToDo: This is a hack. Need to solve this issue. I cut at 998 due to the HK zero order contaminating ## the blue part of the zJ+HK spectrum. For other setup, you do not need to cut the detector. if (head1['FILTER'] == 'zJ') and (head1['DISPERSE'] == 'HK'): array = array[:int(998 / ybin), :] rawdatasec_img = np.ones_like(array, dtype='int') oscansec_img = np.ones_like(array, dtype='int') # Need the exposure time exptime = hdu[self.meta['exptime']['ext']].header[self.meta['exptime'] ['card']] # Return, transposing array back to orient the overscan properly return detector_par, np.flipud(array), hdu, exptime, np.flipud(rawdatasec_img),\ np.flipud(np.flipud(oscansec_img))
def get_rawimage(self, raw_file, det): """ Read raw images and generate a few other bits and pieces that are key for image processing. Parameters ---------- raw_file : :obj:`str` File to read det : :obj:`int` 1-indexed detector to read Returns ------- detector_par : :class:`pypeit.images.detector_container.DetectorContainer` Detector metadata parameters. raw_img : `numpy.ndarray`_ Raw image for this detector. hdu : `astropy.io.fits.HDUList`_ Opened fits file exptime : :obj:`float` Exposure time read from the file header rawdatasec_img : `numpy.ndarray`_ Data (Science) section of the detector as provided by setting the (1-indexed) number of the amplifier used to read each detector pixel. Pixels unassociated with any amplifier are set to 0. oscansec_img : `numpy.ndarray`_ Overscan section of the detector as provided by setting the (1-indexed) number of the amplifier used to read each detector pixel. Pixels unassociated with any amplifier are set to 0. """ # Check for file; allow for extra .gz, etc. suffix fil = glob.glob(raw_file + '*') if len(fil) != 1: msgs.error("Found {:d} files matching {:s}".format(len(fil))) # Read FITS image msgs.info("Reading MMT Blue Channel file: {:s}".format(fil[0])) hdu = fits.open(fil[0]) hdr = hdu[0].header # we're flipping FITS x/y to pypeit y/x here. pypeit wants blue on the # bottom, slit bottom on the right... rawdata = np.fliplr(hdu[0].data.astype(float).transpose()) exptime = hdr['EXPTIME'] # TODO Store these parameters in the DetectorPar. # Number of amplifiers detector_par = self.get_detector_par(hdu, det if det is None else 1) numamp = detector_par['numamplifiers'] # First read over the header info to determine the size of the output array... datasec = hdr['DATASEC'] xdata1, xdata2, ydata1, ydata2 = np.array( parse.load_sections(datasec, fmt_iraf=False)).flatten() # Get the overscan section biassec = hdr['BIASSEC'] xbias1, xbias2, ybias1, ybias2 = np.array( parse.load_sections(biassec, fmt_iraf=False)).flatten() # allocate output arrays and fill in with mask values rawdatasec_img = np.zeros_like(rawdata, dtype=int) oscansec_img = np.zeros_like(rawdata, dtype=int) # trim bad sections at beginning of data and bias sections rawdatasec_img[xdata1 + 2:xdata2, ydata1:ydata2 - 1] = 1 oscansec_img[xbias1 + 2:xbias2, ybias1:ybias2 - 1] = 1 return detector_par, rawdata, hdu, exptime, rawdatasec_img, oscansec_img
def get_rawimage(self, raw_file, det): """ Read a raw DEIMOS data frame (one or more detectors). Data are unpacked from the multi-extension HDU. Function is based :func:`pypeit.spectrographs.keck_lris.read_lris`, which was based on the IDL procedure ``readmhdufits.pro``. Parameters ---------- raw_file : str Filename Returns ------- array : ndarray Combined image hdu: HDUList sections : tuple List of datasec, oscansec sections """ # Check for file; allow for extra .gz, etc. suffix fil = glob.glob(raw_file + '*') if len(fil) != 1: msgs.error('Found {0} files matching {1}'.format( len(fil), raw_file + '*')) # Read try: msgs.info("Reading DEIMOS file: {:s}".format(fil[0])) except AttributeError: print("Reading DEIMOS file: {:s}".format(fil[0])) hdu = fits.open(fil[0]) head0 = hdu[0].header # Get post, pre-pix values postpix = head0['POSTPIX'] detlsize = head0['DETLSIZE'] x0, x_npix, y0, y_npix = np.array( parse.load_sections(detlsize)).flatten() # Create final image if det is None: image = np.zeros((x_npix, y_npix + 4 * postpix)) rawdatasec_img = np.zeros_like(image, dtype=int) oscansec_img = np.zeros_like(image, dtype=int) # get the x and y binning factors... binning = head0['BINNING'] if binning != '1,1': msgs.error( "This binning for DEIMOS might not work. But it might..") # DEIMOS detectors nchip = 8 if det is None: chips = range(nchip) else: chips = [det - 1] # Indexing starts at 0 here # Loop for tt in chips: data, oscan = deimos_read_1chip(hdu, tt + 1) # One detector?? if det is not None: image = np.zeros( (data.shape[0], data.shape[1] + oscan.shape[1])) rawdatasec_img = np.zeros_like(image, dtype=int) oscansec_img = np.zeros_like(image, dtype=int) # Indexing x1, x2, y1, y2, o_x1, o_x2, o_y1, o_y2 = indexing(tt, postpix, det=det) # Fill image[y1:y2, x1:x2] = data rawdatasec_img[y1:y2, x1:x2] = 1 # Amp image[o_y1:o_y2, o_x1:o_x2] = oscan oscansec_img[o_y1:o_y2, o_x1:o_x2] = 1 # Amp # Return exptime = hdu[self.meta['exptime']['ext']].header[self.meta['exptime'] ['card']] return image, hdu, exptime, rawdatasec_img, oscansec_img
def binospec_read_amp(inp, ext): """ Read one amplifier of an MMT BINOSPEC multi-extension FITS image Parameters ---------- inp: tuple (str,int) filename, extension (hdu,int) FITS hdu, extension Returns ------- data predata postdata x1 y1 ;------------------------------------------------------------------------ function lris_read_amp, filename, ext, $ linebias=linebias, nobias=nobias, $ predata=predata, postdata=postdata, header=header, $ x1=x1, x2=x2, y1=y1, y2=y2, GAINDATA=gaindata ;------------------------------------------------------------------------ ; Read one amp from LRIS mHDU image ;------------------------------------------------------------------------ """ # Parse input if isinstance(inp, str): hdu = fits.open(inp) else: hdu = inp # get entire extension... temp = hdu[ext].data.transpose() nxt = temp.shape[0] nyt = temp.shape[1] # parse the DETSEC keyword to determine the size of the array. header = hdu[ext].header # parse the DATASEC keyword to determine the size of the science region (unbinned) datasec = header['DATASEC'] xdata1, xdata2, ydata1, ydata2 = np.array(parse.load_sections(datasec, fmt_iraf=False)).flatten() datasec = '[{:}:{:},{:}:{:}]'.format(xdata1 - 1, xdata2, ydata1-1, ydata2) #TODO: Since pypeit can only subtract overscan along one axis, I'm subtract the overscan here using median method. # Overscan X-axis if xdata1 > 1: overscanx = temp[2:xdata1-1, :] overscanx_vec = np.median(overscanx, axis=0) temp = temp - overscanx_vec[None,:] data = temp[xdata1 - 1:xdata2, ydata1 -1 : ydata2] ## Overscan Y-axis if ydata2<nyt: os1, os2 = ydata2+1, nyt-1 overscany = temp[xdata1 - 1:xdata2, ydata2:os2] overscany_vec = np.median(overscany, axis=1) data = data - overscany_vec[:,None] # Overscan biassec = '[0:{:},{:}:{:}]'.format(xdata1-1, ydata1-1, ydata2) xos1, xos2, yos1, yos2 = np.array(parse.load_sections(biassec, fmt_iraf=False)).flatten() overscan = np.zeros_like(temp[xos1:xos2, yos1:yos2]) # Give a zero fake overscan at the edge of each amplifiers #overscan = temp[xos1:xos2,yos1:yos2] return data, overscan, datasec, biassec
def get_rawimage(self, raw_file, det): """ Read raw images and generate a few other bits and pieces that are key for image processing. Parameters ---------- raw_file : :obj:`str` File to read det : :obj:`int` 1-indexed detector to read Returns ------- detector_par : :class:`pypeit.images.detector_container.DetectorContainer` Detector metadata parameters. raw_img : `numpy.ndarray`_ Raw image for this detector. hdu : `astropy.io.fits.HDUList`_ Opened fits file exptime : :obj:`float` Exposure time read from the file header rawdatasec_img : `numpy.ndarray`_ Data (Science) section of the detector as provided by setting the (1-indexed) number of the amplifier used to read each detector pixel. Pixels unassociated with any amplifier are set to 0. oscansec_img : `numpy.ndarray`_ Overscan section of the detector as provided by setting the (1-indexed) number of the amplifier used to read each detector pixel. Pixels unassociated with any amplifier are set to 0. """ # Check for file; allow for extra .gz, etc. suffix fil = glob.glob(raw_file + '*') if len(fil) != 1: msgs.error("Found {:d} files matching {:s}".format(len(fil))) # Read msgs.info("Reading BINOSPEC file: {:s}".format(fil[0])) hdu = io.fits_open(fil[0]) head1 = hdu[1].header # TOdO Store these parameters in the DetectorPar. # Number of amplifiers detector_par = self.get_detector_par(det if det is not None else 1, hdu=hdu) numamp = detector_par['numamplifiers'] # get the x and y binning factors... binning = head1['CCDSUM'] xbin, ybin = [int(ibin) for ibin in binning.split(' ')] # First read over the header info to determine the size of the output array... datasec = head1['DATASEC'] x1, x2, y1, y2 = np.array(parse.load_sections(datasec, fmt_iraf=False)).flatten() nxb = x1 - 1 # determine the output array size... nx = (x2 - x1 + 1) * int(numamp/2) + nxb * int(numamp/2) ny = (y2 - y1 + 1) * int(numamp/2) #datasize = head1['DETSIZE'] #_, nx, _, ny = np.array(parse.load_sections(datasize, fmt_iraf=False)).flatten() # allocate output array... array = np.zeros((nx, ny)) rawdatasec_img = np.zeros_like(array, dtype=int) oscansec_img = np.zeros_like(array, dtype=int) if det == 1: # A DETECTOR order = range(1, 5, 1) elif det == 2: # B DETECTOR order = range(5, 9, 1) # insert extensions into master image... for kk, jj in enumerate(order): # grab complete extension... data, overscan, datasec, biassec = binospec_read_amp(hdu, jj) # insert components into output array... inx = data.shape[0] xs = inx * kk xe = xs + inx iny = data.shape[1] ys = iny * kk yn = ys + iny b1, b2, b3, b4 = np.array(parse.load_sections(biassec, fmt_iraf=False)).flatten() if kk == 0: array[b2:inx+b2,:iny] = data #*1.028 rawdatasec_img[b2:inx+b2,:iny] = kk + 1 array[:b2,:iny] = overscan oscansec_img[2:b2,:iny] = kk + 1 elif kk == 1: array[b2+inx:2*inx+b2,:iny] = np.flipud(data) #* 1.115 rawdatasec_img[b2+inx:2*inx+b2:,:iny] = kk + 1 array[2*inx+b2:,:iny] = overscan oscansec_img[2*inx+b2:,:iny] = kk + 1 elif kk == 2: array[b2+inx:2*inx+b2,iny:] = np.fliplr(np.flipud(data)) #* 1.047 rawdatasec_img[b2+inx:2*inx+b2,iny:] = kk + 1 array[2*inx+b2:, iny:] = overscan oscansec_img[2*inx+b2:, iny:] = kk + 1 elif kk == 3: array[b2:inx+b2,iny:] = np.fliplr(data) #* 1.045 rawdatasec_img[b2:inx+b2,iny:] = kk + 1 array[:b2,iny:] = overscan oscansec_img[2:b2,iny:] = kk + 1 # Need the exposure time exptime = hdu[self.meta['exptime']['ext']].header[self.meta['exptime']['card']] # Return, transposing array back to orient the overscan properly return detector_par, np.fliplr(np.flipud(array)), hdu, exptime, np.fliplr(np.flipud(rawdatasec_img)), \ np.fliplr(np.flipud(oscansec_img))
def get_rawimage(self, raw_file, det): """ Read a raw LRIS data frame (one or more detectors) Packed in a multi-extension HDU Based on readmhdufits.pro Parameters ---------- raw_file : str Filename det (int or None): Detector number; Default = both Returns ------- array : ndarray Combined image hdu : HDUList sections : list List of datasec, oscansec, ampsec sections datasec, oscansec needs to be for an *unbinned* image as per standard convention """ # Check for file; allow for extra .gz, etc. suffix fil = glob.glob(raw_file + '*') if len(fil) != 1: msgs.error("Found {:d} files matching {:s}".format(len(fil))) # Read msgs.info("Reading LRIS file: {:s}".format(fil[0])) hdu = fits.open(fil[0]) head0 = hdu[0].header # Get post, pre-pix values precol = head0['PRECOL'] postpix = head0['POSTPIX'] preline = head0['PRELINE'] postline = head0['POSTLINE'] # get the x and y binning factors... binning = head0['BINNING'] xbin, ybin = [int(ibin) for ibin in binning.split(',')] # First read over the header info to determine the size of the output array... n_ext = len(hdu) - 1 # Number of extensions (usually 4) xcol = [] xmax = 0 ymax = 0 xmin = 10000 ymin = 10000 for i in np.arange(1, n_ext + 1): theader = hdu[i].header detsec = theader['DETSEC'] if detsec != '0': # parse the DETSEC keyword to determine the size of the array. x1, x2, y1, y2 = np.array(parse.load_sections(detsec, fmt_iraf=False)).flatten() # find the range of detector space occupied by the data # [xmin:xmax,ymin:ymax] xt = max(x2, x1) xmax = max(xt, xmax) yt = max(y2, y1) ymax = max(yt, ymax) # find the min size of the array xt = min(x1, x2) xmin = min(xmin, xt) yt = min(y1, y2) ymin = min(ymin, yt) # Save xcol.append(xt) # determine the output array size... nx = xmax - xmin + 1 ny = ymax - ymin + 1 # change size for binning... nx = nx // xbin ny = ny // ybin # Update PRECOL and POSTPIX precol = precol // xbin postpix = postpix // xbin # Deal with detectors if det in [1, 2]: nx = nx // 2 n_ext = n_ext // 2 det_idx = np.arange(n_ext, dtype=np.int) + (det - 1) * n_ext elif det is None: det_idx = np.arange(n_ext).astype(int) else: raise ValueError('Bad value for det') # change size for pre/postscan... nx += n_ext * (precol + postpix) ny += preline + postline # allocate output arrays... array = np.zeros((nx, ny)) order = np.argsort(np.array(xcol)) rawdatasec_img = np.zeros_like(array, dtype=int) oscansec_img = np.zeros_like(array, dtype=int) # insert extensions into master image... for amp, i in enumerate(order[det_idx]): # grab complete extension... data, predata, postdata, x1, y1 = lris_read_amp(hdu, i + 1) # insert predata... buf = predata.shape nxpre = buf[0] xs = amp * precol xe = xs + nxpre # predata (ignored) array[xs:xe, :] = predata # insert data... buf = data.shape nxdata = buf[0] xs = n_ext * precol + amp * nxdata # (x1-xmin)/xbin xe = xs + nxdata array[xs:xe, :] = data rawdatasec_img[xs:xe, preline:ny-postline] = amp+1 # ; insert postdata... buf = postdata.shape nxpost = buf[0] xs = nx - n_ext * postpix + amp * postpix xe = xs + nxpost array[xs:xe, :] = postdata oscansec_img[xs:xe, preline:ny-postline] = amp+1 # Need the exposure time exptime = hdu[self.meta['exptime']['ext']].header[self.meta['exptime']['card']] # Return return array.T, hdu, exptime, rawdatasec_img.T, oscansec_img.T
def get_rawimage(self, raw_file, det): """ Read raw images and generate a few other bits and pieces that are key for image processing. Parameters ---------- raw_file : :obj:`str` File to read det : :obj:`int` 1-indexed detector to read Returns ------- detector_par : :class:`pypeit.images.detector_container.DetectorContainer` Detector metadata parameters. raw_img : `numpy.ndarray`_ Raw image for this detector. hdu : `astropy.io.fits.HDUList`_ Opened fits file exptime : :obj:`float` Exposure time read from the file header rawdatasec_img : `numpy.ndarray`_ Data (Science) section of the detector as provided by setting the (1-indexed) number of the amplifier used to read each detector pixel. Pixels unassociated with any amplifier are set to 0. oscansec_img : `numpy.ndarray`_ Overscan section of the detector as provided by setting the (1-indexed) number of the amplifier used to read each detector pixel. Pixels unassociated with any amplifier are set to 0. """ # Check for file; allow for extra .gz, etc. suffix fil = glob.glob(raw_file + '*') if len(fil) != 1: msgs.error("Found {:d} files matching {:s}".format(len(fil))) # Read msgs.info("Reading LBT/MODS file: {:s}".format(fil[0])) hdu = io.fits_open(fil[0]) head = hdu[0].header # TODO These parameters should probably be stored in the detector par # Number of amplifiers (could pull from DetectorPar but this avoids needing the spectrograph, e.g. view_fits) detector_par = self.get_detector_par(hdu, det if det is None else 1) numamp = detector_par['numamplifiers'] # get the x and y binning factors... xbin, ybin = head['CCDXBIN'], head['CCDYBIN'] datasize = head['DETSIZE'] # Unbinned size of detector full array _, nx_full, _, ny_full = np.array( parse.load_sections(datasize, fmt_iraf=False)).flatten() # Determine the size of the output array... nx, ny = int(nx_full / xbin), int(ny_full / ybin) nbias1 = 48 nbias2 = 8240 # allocate output array... array = hdu[ 0].data.T * 1.0 ## Convert to float in order to get it processed with procimg.py rawdatasec_img = np.zeros_like(array, dtype=int) oscansec_img = np.zeros_like(array, dtype=int) ## allocate datasec and oscansec to the image # apm 1 rawdatasec_img[int(nbias1 / xbin):int(nx / 2), :int(ny / 2)] = 1 oscansec_img[1:int(nbias1 / xbin), :int( ny / 2)] = 1 # exclude the first pixel since it always has problem # apm 2 rawdatasec_img[int(nx / 2):int(nbias2 / xbin), :int(ny / 2)] = 2 oscansec_img[int(nbias2 / xbin):nx - 1, :int( ny / 2)] = 2 # exclude the last pixel since it always has problem # apm 3 rawdatasec_img[int(nbias1 / xbin):int(nx / 2), int(ny / 2):] = 3 oscansec_img[ 1:int(nbias1 / xbin), int(ny / 2):] = 3 # exclude the first pixel since it always has problem # apm 4 rawdatasec_img[int(nx / 2):int(nbias2 / xbin), int(ny / 2):] = 4 oscansec_img[ int(nbias2 / xbin):nx - 1, int(ny / 2):] = 4 # exclude the last pixel since it always has problem # Need the exposure time exptime = hdu[self.meta['exptime']['ext']].header[self.meta['exptime'] ['card']] # Return, transposing array back to orient the overscan properly return detector_par, np.flipud(array), hdu, exptime, np.flipud( rawdatasec_img), np.flipud(oscansec_img)
def get_rawimage(self, raw_file, det): """ Read raw images and generate a few other bits and pieces that are key for image processing. Parameters ---------- raw_file : :obj:`str` File to read det : :obj:`int`, :obj:`tuple` 1-indexed detector(s) to read. An image mosaic is selected using a :obj:`tuple` with the detectors in the mosaic, which must be one of the allowed mosaics returned by :func:`allowed_mosaics`. Returns ------- detector_par : :class:`~pypeit.images.detector_container.DetectorContainer`, :class:`~pypeit.images.mosaic.Mosaic` Detector metadata parameters for one or more detectors. raw_img : `numpy.ndarray`_ Raw image for this detector. hdu : `astropy.io.fits.HDUList`_ Opened fits file exptime : :obj:`float` Exposure time read from the file header rawdatasec_img : `numpy.ndarray`_ Data (Science) section of the detector as provided by setting the (1-indexed) number of the amplifier used to read each detector pixel. Pixels unassociated with any amplifier are set to 0. oscansec_img : `numpy.ndarray`_ Overscan section of the detector as provided by setting the (1-indexed) number of the amplifier used to read each detector pixel. Pixels unassociated with any amplifier are set to 0. """ # Read msgs.info(f'Attempting to read GMOS file: {raw_file}') # NOTE: io.fits_open checks that the file exists hdu = io.fits_open(raw_file) head0 = hdu[0].header head1 = hdu[1].header # Validate the entered (list of) detector(s) nimg, _det = self.validate_det(det) # Grab the detector or mosaic parameters mosaic = None if nimg == 1 else self.get_mosaic_par(det, hdu=hdu) detectors = [self.get_detector_par(det, hdu=hdu) ] if nimg == 1 else mosaic.detectors # Number of amplifiers is hard-coded as follows numamp = (len(hdu) - 1) // self.ndet if numamp != detectors[0].numamplifiers: msgs.error( f'Unexpected number of amplifiers for {self.name} based on number of ' f'extensions in {raw_file}.') # First read over the header info to determine the size of the output array... datasec = head1['DATASEC'] x1, x2, y1, y2 = np.array(parse.load_sections( datasec, fmt_iraf=False)).flatten() biassec = head1['BIASSEC'] b1, b2, b3, b4 = np.array(parse.load_sections( biassec, fmt_iraf=False)).flatten() nxb = b2 - b1 + 1 # determine the output array size... nx = (x2 - x1 + 1) * numamp + nxb * numamp ny = y2 - y1 + 1 # allocate output array... array = np.zeros((nimg, nx, ny)) rawdatasec_img = np.zeros_like(array, dtype=int) oscansec_img = np.zeros_like(array, dtype=int) # Get the HDU read order for this instrument order = self.hdu_read_order() for ii in range(nimg): # insert extensions into master image... for kk, jj in enumerate(order[_det[ii] - 1]): # grab complete extension... data, overscan, datasec, biassec, x1, x2 = gemini_read_amp( hdu, jj) # insert components into output array... inx = data.shape[0] xs = inx * kk xe = xs + inx # insert data... array[ii, xs:xe, :] = np.flipud(data) rawdatasec_img[ii, xs:xe, :] = kk + 1 # ; insert postdata... xs = nx - numamp * nxb + kk * nxb xe = xs + nxb array[ii, xs:xe, :] = overscan oscansec_img[ii, xs:xe, :] = kk + 1 # Need the exposure time exptime = self.get_meta_value(self.get_headarr(hdu), 'exptime') # Transpose now (helps with debuggin) array = np.transpose(array, axes=(0, 2, 1)) rawdatasec_img = np.transpose(rawdatasec_img, axes=(0, 2, 1)) oscansec_img = np.transpose(oscansec_img, axes=(0, 2, 1)) # Handle returning both single and multiple images if nimg == 1: return detectors[0], array[0], hdu, exptime, rawdatasec_img[ 0], oscansec_img[0] return mosaic, array, hdu, exptime, rawdatasec_img, oscansec_img
def get_rawimage(self, raw_file, det): """ Read raw images and generate a few other bits and pieces that are key for image processing. Parameters ---------- raw_file : :obj:`str` File to read det : :obj:`int` 1-indexed detector to read Returns ------- detector_par : :class:`pypeit.images.detector_container.DetectorContainer` Detector metadata parameters. raw_img : `numpy.ndarray`_ Raw image for this detector. hdu : `astropy.io.fits.HDUList`_ Opened fits file exptime : :obj:`float` Exposure time read from the file header rawdatasec_img : `numpy.ndarray`_ Data (Science) section of the detector as provided by setting the (1-indexed) number of the amplifier used to read each detector pixel. Pixels unassociated with any amplifier are set to 0. oscansec_img : `numpy.ndarray`_ Overscan section of the detector as provided by setting the (1-indexed) number of the amplifier used to read each detector pixel. Pixels unassociated with any amplifier are set to 0. """ # TODO: I don't remember what we decided about this use of glob... # Check for file; allow for extra .gz, etc. suffix fil = glob.glob(raw_file + '*') if len(fil) != 1: msgs.error("Found {:d} files matching {:s}".format(len(fil))) # Read msgs.info("Reading GMOS file: {:s}".format(fil[0])) hdu = io.fits_open(fil[0]) head0 = hdu[0].header head1 = hdu[1].header # TODO: I don't understand this comment, why not use self.ndet? # Number of amplifiers (could pull from DetectorPar but this avoids # needing the spectrograph, e.g. view_fits) numamp = (len(hdu) - 1) // 3 # get the x and y binning factors... binning = head1['CCDSUM'] xbin, ybin = [int(ibin) for ibin in binning.split(' ')] # First read over the header info to determine the size of the output array... datasec = head1['DATASEC'] x1, x2, y1, y2 = np.array(parse.load_sections(datasec, fmt_iraf=False)).flatten() biassec = head1['BIASSEC'] b1, b2, b3, b4 = np.array(parse.load_sections(biassec, fmt_iraf=False)).flatten() nxb = b2 - b1 + 1 # determine the output array size... nx = (x2 - x1 + 1) * numamp + nxb * numamp ny = y2 - y1 + 1 # allocate output array... array = np.zeros((nx, ny)) rawdatasec_img = np.zeros_like(array, dtype=int) oscansec_img = np.zeros_like(array, dtype=int) # TODO: Why is this stuff here and not in the relevant subclass? if numamp == 2: # E2V if det == 1: # BLUEST DETECTOR order = range(6, 4, -1) elif det == 2: # NEXT order = range(3, 5) elif det == 3: # REDDEST DETECTOR order = range(1, 3) elif numamp == 4: # Hamamatsu if det == 1: # BLUEST DETECTOR order = range(12, 8, -1) elif det == 2: # BLUEST DETECTOR order = range(8, 4, -1) elif det == 3: # BLUEST DETECTOR order = range(4, 0, -1) else: embed() # insert extensions into master image... for kk, jj in enumerate(order): # grab complete extension... data, overscan, datasec, biassec, x1, x2 = gemini_read_amp(hdu, jj) # insert components into output array... inx = data.shape[0] xs = inx * kk xe = xs + inx # insert data... # Data section #section = '[{:d}:{:d},:]'.format(xs * xbin, xe * xbin) # Eliminate lines #dsec.append(section) array[xs:xe, :] = np.flipud(data) rawdatasec_img[xs:xe, :] = kk+1 # ; insert postdata... xs = nx - numamp * nxb + kk * nxb xe = xs + nxb #osection = '[{:d}:{:d},:]'.format(xs * xbin, xe * xbin) # TRANSPOSED FOR WHAT COMES #osec.append(osection) array[xs:xe, :] = overscan oscansec_img[xs:xe, :] = kk+1 # Need the exposure time exptime = hdu[self.meta['exptime']['ext']].header[self.meta['exptime']['card']] # Transpose now (helps with debuggin) array = array.T rawdatasec_img = rawdatasec_img.T oscansec_img = oscansec_img.T # TODO: Move to the relevant subclass. # Hack me if self.name == 'gemini_gmos_north_ham_ns' \ and head0['object'] in ['GCALflat', 'CuAr', 'Bias'] \ and self.nod_shuffle_pix is not None: # TODO -- Should double check NOD&SHUFFLE was not on row1, row2 = 1456, 2812 # NEED TO FIGURE OUT HOW TO GENERALIZE THIS nodpix = self.nod_shuffle_pix # Shuffle me array[row1-nodpix:row2-nodpix,:] = array[row1:row2,:] # Return, transposing array back to orient the overscan properly return self.get_detector_par(hdu, det if det is None else 1), \ array, hdu, exptime, rawdatasec_img, oscansec_img