Пример #1
0
    def divide_flat(self):
        """Divides all LMI science frames by the appropriate flat field image
        This method is LMI-specific, rather than being wrapper for a more
        general function.  Basic emulation of IRAF's ccdproc/flatcor function.
        :return: None
        """

        # Load the list of master flats and bias-subtracted data frames
        flat_cl = ccdp.ImageFileCollection(
            self.path, glob_include=f'flat_bin{self.bin_factor}_*.fits')
        sci_cl = ccdp.ImageFileCollection(
            self.path, glob_include=f'{self.prefix}.*b.fits')

        # Check to be sure there are, indeed, flats...
        if flat_cl.files:
            # Loop through the filters present
            for filt in sorted(list(flat_cl.summary['filters'])):

                # Load in the master flat for this filter
                if self.debug:
                    print(f'Dividing by master flat for filter: {filt}')
                master_flat, mflat_fn = next(
                    flat_cl.ccds(ccdsum=self.binning,
                                 filters=filt,
                                 return_fname=True))

                # Set up a progress bar, so we can see how the process is going
                sci_filt_files = sci_cl.files_filtered(filters=filt)
                prog_bar = tqdm(total=len(sci_filt_files),
                                unit='frame',
                                unit_scale=False,
                                colour='#D8BFD8')

                # Loop through the science frames to correct
                for ccd, sci_fn in sci_cl.ccds(ccdsum=self.binning,
                                               filters=filt,
                                               return_fname=True):

                    # Divide by master flat
                    ccdp.flat_correct(ccd, master_flat)

                    # Update the header
                    ccd.header['flatcor'] = True
                    ccd.header['HISTORY'] = PKG_NAME
                    ccd.header['HISTORY'] = 'Flat-corrected image saved: ' + \
                                            _savetime()
                    ccd.header['HISTORY'] = f'Divided by flat: {mflat_fn}'
                    ccd.header['HISTORY'] = f'Previous filename: {sci_fn}'

                    # Save the result (suffix = 'f'); delete the input file
                    ccd.write(f'{self.path}/{sci_fn[:-6]}f{sci_fn[-5:]}',
                              overwrite=True)
                    os.remove(f'{self.path}/{sci_fn}')

                    # Update the progress bar
                    prog_bar.update(1)
                # Close the progress bar, end of loop
                prog_bar.close()
Пример #2
0
def process_science(sci_list,fil,red_path,mbias=None,mflat=None,proc=None,log=None):
    masks = []
    processed = []
    for sci in sci_list:
        log.info('Loading file: '+sci)
        log.info('Applying gain correction and flat correction.')
        with fits.open(sci) as hdr:
            header = hdr[0].header
            data = hdr[0].data
        data[np.isnan(data)] = np.nanmedian(data)
        raw = CCDData(data,meta=header,unit=u.adu)
        red = ccdproc.ccd_process(raw, gain=raw.header['SYSGAIN']*u.electron/u.adu, readnoise=rdnoise(raw.header)*u.electron)
        log.info('Exposure time of science image is '+str(red.header['TRUITIME']*red.header['COADDONE']))
        flat = np.array(ccdproc.flat_correct(red, mflat))
        flat[np.isnan(flat)] = np.nanmedian(flat)
        processed_data = CCDData(flat,unit=u.electron,header=red.header,wcs=red.wcs)
        log.info('File proccessed.')
        log.info('Cleaning cosmic rays and creating mask.')
        mask = make_source_mask(processed_data, nsigma=3, npixels=5)
        masks.append(mask)
        clean, com_mask = create_mask.create_mask(sci.replace('.gz',''),processed_data,'_mask.fits',static_mask(proc)[0],mask,saturation(red.header),binning(),rdnoise(raw.header),cr_clean_sigclip(),cr_clean_sigcfrac(),cr_clean_objlim(),log)
        processed_data.data = clean
        log.info('Calculating 2D background.')
        bkg = Background2D(processed_data, (128, 128), filter_size=(3, 3),sigma_clip=SigmaClip(sigma=3), bkg_estimator=MeanBackground(), mask=mask, exclude_percentile=80)
        log.info('Median background: '+str(np.median(bkg.background)))
        fits.writeto(sci.replace('/raw/','/red/').replace('.fits','_bkg.fits').replace('.gz',''),bkg.background,overwrite=True)
        final = processed_data.subtract(CCDData(bkg.background,unit=u.electron),propagate_uncertainties=True,handle_meta='first_found').divide(red.header['TRUITIME']*red.header['COADDONE']*u.second,propagate_uncertainties=True,handle_meta='first_found')
        log.info('Background subtracted and image divided by exposure time.')
        final.write(sci.replace('/raw/','/red/').replace('.gz',''),overwrite=True)
        processed.append(final)
    return processed, masks
Пример #3
0
def flat_file_by_file(fname, flatname, datahdus=0):
    hdulist = fits.open(fname)
    hduflat = fits.open(flatname)
    nhdus = len(hdulist)
    if nhdus > 1:
        istart = 1
    else:
        istart = 0
    hduindexes = list(range(nhdus))[istart:]
    if datahdus != 0:
        hduindexes = datahdus
    for i in hduindexes:
        data1 = ccdproc.CCDData(hdulist[i].data, unit="adu")
        data1.header = hdulist[i].header
        flat1 = ccdproc.CCDData(hduflat[i].data, unit="adu")
        flat1.header = hduflat[i].header
        if i == 1:
            flatscale = np.mean(flat1)
        # flat1 = flat1/flatscale
        commentstr = "Flat image is " + flatname + " with scale" + str(
            flatscale)
        proc1 = ccdproc.flat_correct(data1,
                                     flat1,
                                     add_keyword={
                                         'flat': True,
                                         'calstat': 'OTZF',
                                         'history': commentstr
                                     })
        fits.update(fname, proc1.data, header=proc1.header, ext=i)
        # fits.update(fname, proc1.data, ext=i)
    hdulist.close()
    hduflat.close()
    mylog("Flat corrected {0} with {1}".format(fname, flatname))
    return
Пример #4
0
def process_science(sci_list,fil,red_path,mbias=None,mflat=None,proc=None,log=None):
    masks = []
    processed = []
    for sci in sci_list:
        log.info('Loading file: '+sci)
        log.info('Applying gain correction, dark subtraction, overscan correction, flat correction, and trimming image.')
        raw = CCDData.read(sci,hdu=1,unit=u.adu)
        red = ccdproc.ccd_process(raw, gain=raw.header['GAIN']*u.electron/u.adu, readnoise=raw.header['RDNOISE']*u.electron)
        log.info('Exposure time of science image is '+str(red.header['EXPTIME']))
        log.info('Loading correct master dark')
        mdark = CCDData.read(red_path+'DARK_'+str(red.header['EXPTIME'])+'.fits', unit=u.electron)
        red = ccdproc.subtract_dark(red, mdark, exposure_time='EXPTIME', exposure_unit=u.second)#dark_exposure=1*u.second, data_exposure=red.header['EXPTIME']*u.second, scale=True)
        red = ccdproc.subtract_overscan(red, overscan=red[:,0:4], overscan_axis=1, model=models.Chebyshev1D(3))
        red = ccdproc.flat_correct(red, mflat)
        processed_data = ccdproc.ccd_process(red, trim=raw.header['DATASEC'])
        log.info('File proccessed and trimmed.')
        log.info('Cleaning cosmic rays and creating mask.')
        mask = make_source_mask(processed_data, nsigma=3, npixels=5)
        masks.append(mask)
        clean, com_mask = create_mask.create_mask(sci,processed_data,'_mask.fits',static_mask(proc)[0],mask,saturation(red.header),binning(),rdnoise(red.header),cr_clean_sigclip(),cr_clean_sigcfrac(),cr_clean_objlim(),log)
        processed_data.data = clean
        log.info('Calculating 2D background.')
        bkg = Background2D(processed_data, (510, 510), filter_size=(9, 9),sigma_clip=SigmaClip(sigma=3), bkg_estimator=MeanBackground(), mask=mask, exclude_percentile=80)
        log.info('Median background: '+str(np.median(bkg.background)))
        fits.writeto(sci.replace('/raw/','/red/').replace('.fits','_bkg.fits'),bkg.background,overwrite=True)
        final = processed_data.subtract(CCDData(bkg.background,unit=u.electron),propagate_uncertainties=True,handle_meta='first_found').divide(red.header['EXPTIME']*u.second,propagate_uncertainties=True,handle_meta='first_found')
        log.info('Background subtracted and image divided by exposure time.')
        final.write(sci.replace('/raw/','/red/'),overwrite=True)
        processed.append(final)
    return processed, masks
Пример #5
0
 def action(self, ccd):
     select_dict = {'imagetyp': 'flat'}
     for keyword in self.match_on:
         if keyword in select_dict:
             raise ValueError("Keyword {} already has a value set".format(keyword))
         select_dict[keyword] = ccd.header[keyword]
     master = self._master_image(select_dict)
     return ccdproc.flat_correct(ccd, master)
Пример #6
0
 def action(self, ccd):
     select_dict = {'imagetyp': 'flat'}
     for keyword in self.match_on:
         if keyword in select_dict:
             raise ValueError(
                 "Keyword {} already has a value set".format(keyword))
         select_dict[keyword] = ccd.header[keyword]
     master = self._master_image(select_dict)
     return ccdproc.flat_correct(ccd, master)
def preprocess(fits_path):
    """Apply basic CCD reduction tasks.

    Ask for the path to all the calibration and science files, and perform Bias, Dark and Flat combinations and proper substractions.

    Pipeline que aplica una reduccion basica a imagenes de tipo CCD.
    Realiza combinacion de Bias, de Darks, y Flats. Luego realiza las restas inherentes.
    """
    import os
    import sys
    from image_collection import ImageFileCollection

    #Collect all FITS files in path in fitslist
    fitslist = []
    for root, dirs, files in os.walk(fits_path, topdown=True):
        fitslist.extend([os.path.join(root, name) for name in files if '.fit' in name])
    
    #Dictionary with the image type (value) for each image file name (key)
    imagetypes = {img:fits.getval(img, 'IMAGETYP') for img in fitslist}
    
    #Make different lists for different image types
    biaslist = []
    sciencelist = []
    flatlist = []
    darklist = []
    unknown = []
    for k, v in imagetypes.iteritems():
        if 'LIGHT' in v.upper() or v.upper()=='OBJECT':
            sciencelist.append(k)
        elif 'BIAS' in v.upper() or v.upper()=='ZERO':
            biaslist.append(k)
        elif 'FLAT' in v.upper():
            flatlist.append(k)
        elif 'DARK' in v.upper():
            darklist.append(k)
        else:
            unknown.append(k)

    #Create the flat master
    if darklist:
        darkmaster = combineDarks(darklist_flat)
        flatmaster = combineFlats(flatlist, dark=darkmaster)
    elif biaslist:
        biasmaster = combineBias(biaslist)
        flatmaster = combineFlats(flatlist, bias=biasmaster)
    else:
        flatmaster = combineFlats(flatlist)

    for ascience in sciencelist:
        sci_image = ccdproc.CCDData.read(ascience, unit='adu')
        sci_darksub = ccdproc.subtract_dark(sci_image, darkmaster, exposure_time='exptime', exposure_unit=u.second)
        sci_flatcorrected = ccdproc.flat_correct(sci_darksub, flatmaster)
        outpath = os.path.join('/Users/utb/Desktop/reduced/', 'reduced_' + os.path.basename(ascience))
        hdulist = sci_flatcorrected.to_hdu()
        hdulist.writeto(outpath, clobber=True)

    return
Пример #8
0
 def _correctForFlat(self, ccd):
     masterFlat = self.getFlatImage()
     print('Correcting for flat...')
     ccd = ccdproc.flat_correct(
         ccd,
         masterFlat,
         min_value=0.1,
         add_keyword={'HIERARCH GIULIA FLATFIELD CORRECTION': True})
     return ccd
Пример #9
0
def reduce_image(imagefile, dark=None, flat=None):
    im = CCDData.read(imagefile, unit='adu')
    if dark is not None:
        dark = CCDData.read(dark, unit='adu')
        im = im.subtract(dark)
    if flat is not None:
#         masterflat = CCDData.read(flat, unit='adu')
        hdul = fits.open(flat)
        masterflat = CCDData(data=hdul[0].data, uncertainty=None, meta=hdul[0].header, unit='adu')
        im = flat_correct(im, masterflat)
    return im
Пример #10
0
 def reduceFrames(self):
     self.getMedianForObjects()
     log.info('Reducing frames started')
     print 'Reducing frames started'
     
     for obj in self.objects.filesList:
         data = ccdproc.CCDData.read(obj, unit=u.adu)
         dataWithDeviation = ccdproc.create_deviation(data, 
                                                     gain=1.5*u.electron/u.adu,
                                                     readnoise=5*u.electron)
         reducedObject = ccdproc.gain_correct(dataWithDeviation, 
                                             1.5*u.electron/u.adu)
         
         if self.biases.isExists:
             reducedObject = ccdproc.subtract_bias(reducedObject, 
                                                   self.biases.masterCCD)
         if self.darks.isExists:
             reducedObject = ccdproc.subtract_dark(reducedObject, 
                                                   self.darks.masterCCD, 
                                                   exposure_time=cfg.exptime, 
                                                   exposure_unit=u.second, 
                                                   scale=True)
         if self.flats.isExists:
             reducedObject = ccdproc.flat_correct(reducedObject, 
                                                  self.flats.masterCCD)
         
         self.directory = '../../Reduction/' + directoryName
         if not os.path.exists(self.directory):
             os.makedirs(self.directory)
         
         reducedObject.write(self.directory + '/' + obj, clobber=True)
         os.system('solve-field ' + self.directory + '/' + obj) # + ' --overwrite')
         
         objName, objExtension = os.path.splitext(self.directory + '/' + obj)
         
         if not os.path.exists(objName + '.new'):
             log.warning(objName + ' cannot be solved')
         else:
             newObjectsList.append(objName + '.new')
             log.info('Frame ' + objName + ' reduced')
         
     log.info('Reduced ' + str(len(newObjectsList)) + ' frames')
     print 'Reduced ' + str(len(newObjectsList)) + ' frames'
     self.clean()
def correctscience():
    for sciencec, sciencen in enumerate(sciencelist):
        hdu = fits.open(sciencelist[sciencec])
        print('open', sciencen)
        if hdu[1].header['CHIPNAME'] == 'A5382-1-7':
            ccdscience = CCDData(hdu[1].data, unit=u.adu)
            if not os.path.exists('Corrected_Science'):
                os.makedirs('Corrected_Science')
            cccdscience = ccdproc.flat_correct(
                ccdproc.subtract_bias(ccdscience, ccdmbias_use),
                ccdmflat_use,
                norm_value=np.nanmedian(ccdmflat_use))
            path = 'Corrected_Science/' + sciencen[-12:]
            cccdscience.write(path, overwrite=True)
            hdu.close()
        else:
            hdu.close()
            print(sciencen, 'returned wrong chipname for selected extension')
            exit
Пример #12
0
def flat_correction(textlist_files, master_flat, prefix_str='f'):
    """
    To flat field the science images using master flat
    Args:
        textlist_files : A python list object with paths/names to the individual files.
        master_flat    : Master flat used to flat field the science image
        prefix_str     : String to be added to newly created sceince image
    Returns:
        None
    """
    master = CCDData.read(master_flat, unit=u.adu)

    for filename in textlist_files:
        ccd = CCDData.read(filename, unit=u.adu)
        flat_corrected = ccdp.flat_correct(ccd=ccd, flat=master, min_value=0.9)
        flat_corrected.meta['flatcorr'] = True
        flat_corrected.data = flat_corrected.data.astype('float32')

        flat_corrected.write(prefix_str + filename,
                             hdu_mask=None,
                             hdu_uncertainty=None)
Пример #13
0
    def make_science(self, list_of_sciencefiles):


        science_list = [0]*len(list_of_sciencefiles)
        science_names = [0]*len(list_of_sciencefiles)
        for ii, kk in enumerate(list_of_sciencefiles):
            fitsfile = fits.open(kk)
            science = ccdproc.CCDData(data=fitsfile[1].data, meta=fitsfile[1].header, unit="adu")
            # science_cos = ccdproc.cosmicray_lacosmic(science, verbose = True)
            overscan_sub = ccdproc.subtract_overscan(science, fits_section='[5:35, :]')
            bias_sub = ccdproc.subtract_bias(overscan_sub, self.master_bias)
            flat_corr = ccdproc.flat_correct(bias_sub, self.master_flat)

            # science_list[ii] = flat_corr
            flat_corr.write(self.output_dir+"/"+self.filename+"_"+str(ii)+".fits", overwrite=True)
            science_names[ii] = self.output_dir+"/"+self.filename+"_"+str(ii)+".fits"



        # science_list = [0]*len(list_of_sciencefiles)
        coverages = [0]*len(list_of_sciencefiles)
        for ii, kk in enumerate(science_names):
            fitsfile = fits.open(kk)
            fitsfile_common, coverage = reproject_interp(fitsfile, fits.open(science_names[0])[0].header, hdu_in=0)
            science = ccdproc.CCDData(data=fitsfile_common, meta=fitsfile[0].header, unit="adu")
            science_list[ii] = science
            coverages[ii] = ccdproc.CCDData(data=coverage, meta=fitsfile[0].header, unit="adu")

        self.combined_science = ccdproc.combine(science_list, method="median")
        # self.combined_coverage = ccdproc.combine(coverages, method="sum")


        header0 = fits.open(list_of_sciencefiles[0])[0].header
        for key in header0:
            # print(str(key), header0[str(key)])
            if "COMMENT" in key:
                continue
            self.combined_science.header[str(key)] = header0[str(key)]

        self.combined_science.write(self.output_dir+"/"+self.filename+".fits", overwrite=True)
Пример #14
0
    def flat(self,im,superflat=None,display=None) :
         """ Flat fielding
         """
         # only flatfield if we are given a superflat!
         if superflat is None : return im

         if type(im) is not list : ims=[im]
         else : ims = im
         if type(superflat) is not list : superflats=[superflat]
         else : superflats = superflat
         out=[]
         for im,flat in zip(ims,superflats) :
             if self.verbose : print('  flat fielding...')
             if display is not None : 
                 display.tv(im)
             corr = ccdproc.flat_correct(im,flat)
             out.append(corr)
             if display is not None : 
                 display.tv(corr)
                 #plot central crossections
                 display.plotax1.cla()
                 dim=corr.data.shape
                 col = int(dim[1]/2)
                 row = corr.data[:,col]
                 display.plotax1.plot(row)
                 min,max=tv.minmax(row,low=5,high=5)
                 display.plotax1.set_ylim(min,max)
                 display.plotax1.set_xlabel('row')
                 display.plotax1.text(0.05,0.95,'Column {:d}'.format(col),transform=display.plotax1.transAxes)
                 display.plotax2.cla()
                 row = int(dim[0]/2)
                 col = corr.data[row,:]
                 min,max=tv.minmax(col,low=10,high=10)
                 display.plotax2.plot(col)
                 display.plotax2.set_xlabel('col')
                 display.plotax2.text(0.05,0.95,'Row {:d}'.format(row),transform=display.plotax2.transAxes)
                 display.plotax2.set_ylim(min,max)
                 input("  See flat-fielded image and original with - key. Hit any key to continue")
         if len(out) == 1 : return out[0]
         else : return out
    ccd = ccdproc.subtract_overscan(ccd, median=True,  overscan_axis=0, fits_section='[1:966,4105:4190]')
    ccd = ccdproc.trim_image(ccd, fits_section=ccd.header['TRIMSEC'] )
    ccd = ccdproc.subtract_bias(ccd, master_bias_blue)
    blue_flat_list.append(ccd)
master_flat_blue = ccdproc.combine(blue_flat_list, method='median')
master_flat_blue.write('master_flat_blue.fits', clobber=True)

#reduce the arc frames
for filename in ic1.files_filtered(obstype='Arc', isiarm='Blue arm'):
    hdu = fits.open(ic1.location + filename)
    ccd = CCDData(hdu[1].data, header=hdu[0].header+hdu[1].header, unit = u.adu)
    #this has to be fixed as the bias section does not include the whole section that will be trimmed
    ccd = ccdproc.subtract_overscan(ccd, median=True,  overscan_axis=0, fits_section='[1:966,4105:4190]')
    ccd = ccdproc.trim_image(ccd, fits_section=ccd.header['TRIMSEC'] )
    ccd = ccdproc.subtract_bias(ccd, master_bias_blue)
    ccd = ccdproc.flat_correct(ccd, master_flat_blue)
    ccd.data = ccd.data.T
    ccd.write('arc_'+filename, clobber=True)

red_flat_list = []
for filename in ic1.files_filtered(obstype='Arc', isiarm='Red arm'):
    hdu = fits.open(ic1.location + filename)
    ccd = CCDData(hdu[1].data, header=hdu[0].header+hdu[1].header, unit = u.adu)
    #this has to be fixed as the bias section does not include the whole section that will be trimmed
    ccd = ccdproc.subtract_overscan(ccd, median=True,  overscan_axis=0, fits_section='[1:966,4105:4190]')
    ccd = ccdproc.trim_image(ccd, fits_section=ccd.header['TRIMSEC'] )
    ccd = ccdproc.subtract_bias(ccd, master_bias_red)
    ccd = ccdproc.flat_correct(ccd, master_flat_red)
    ccd.data = ccd.data.T
    ccd.write('arc_'+filename, clobber=True)
Пример #16
0
    
ppdpath = Path(newfitspath/'PreprocessedImages')
if not ppdpath.exists():
    ppdpath.mkdir()

for i in ob_dic:
    print(i)
    for j in range(len(ob_dic[i])):
        c = CCDData(fits.getdata(ob_dic[i][j]['FILE']), unit = u.adu)
        hdr = fits.getheader(ob_dic[i][j]['FILE'])
        #Exposure Time에 맞는 Dark
        mdark = mdark_fdic[hdr['EXPTIME']]
        c = subtract_bias(c,mbias)
        c = subtract_dark(c,mdark
                            ,hdr['EXPTIME']*u.second,hdr['EXPTIME']*u.second)
        c = flat_correct(c,mflat,min_value=0.01)
        
        c.header = hdr
        c.header.add_history("B & D subtracted and F corrected")
        c = yfu.CCDData_astype(c,dtype = 'float32')
        c.write(ppdpath/ob_dic[i][j]['FILE'],overwrite=True) 
        
        
#%%
        
fig, axs = plt.subplots(2,len(ob_list),figsize=(12,12))
for i in range(len(ob_list)):
    data1 = CCDData.read(f"{ob_list[i]}-0001.fits")
    data2 = CCDData.read(ppdpath/f"{ob_list[i]}-0001.fits")
    im1 = yfu.zimshow(axs[0][i],data1)
    im2 = yfu.zimshow(axs[1][i],data2)
Пример #17
0
def make_flatdark_correction():
    """ for each light exposure do:
    subtract dark from light
    divide by dark-subtracted flat
    save fits to file
    add entry in database for each calibrated file generated"""
    # Eventually should be done as described in:
    # https://ccdproc.readthedocs.io/en/latest/reduction_toolbox.html
    # Or here:
    # https://mwcraig.github.io/ccd-as-book
    import ccdproc
    from astropy.nddata import CCDData
    import astroscrappy
    import numpy as np
    from astropy import units as u

    nb = models.NightBundle.get(telescope_night_bundle_id=1)
    nb_dir = nb.directory_path
    light_list_q = nb.exposures.select(
        lambda d: d.exposure_type == models.EXP_TYPE_CODES["LIGHT"])
    light_list = [os.path.join(nb_dir, f.filename) for f in light_list_q]

    master_dark_q = nb.combinations.select(
        lambda d: d.combination_type == models.COMB_TYPE_CODES["DARKM"]).get()
    master_dark_path = os.path.join(nb_dir, "products", master_dark_q.filename)
    master_flat_q = nb.combinations.select(
        lambda d: d.combination_type == models.COMB_TYPE_CODES["FLATM"]).get()
    master_flat_path = os.path.join(nb_dir, "products", master_flat_q.filename)

    for light_q, light_fname in zip(light_list_q, light_list):
        raw_data = CCDData.read(light_fname, unit="adu")
        master_dark = CCDData.read(master_dark_path, unit="adu")
        master_flat = CCDData.read(master_flat_path, unit="adu")
        # cr_cleaned = ccdproc.cosmicray_lacosmic(
        #     raw_data,
        #     satlevel=np.inf,
        #     sepmed=False,
        #     cleantype="medmask",
        #     fsmode="median",
        # )
        # crmask, cr_cleaned = astroscrappy.detect_cosmics(
        #     raw_data,
        #     inmask=None,
        #     satlevel=np.inf,
        #     sepmed=False,
        #     cleantype="medmask",
        #     fsmode="median",
        # )
        # cr_cleaned.unit = "adu"
        cr_cleaned = raw_data
        dark_subtracted = ccdproc.subtract_dark(
            cr_cleaned,
            master_dark,
            exposure_time="EXPTIME",
            exposure_unit=u.second,
            scale=True,
        )
        reduced_image = ccdproc.flat_correct(dark_subtracted,
                                             master_flat,
                                             min_value=0.9)
        reduced_filename = "calib_{}".format(os.path.basename(light_fname))
        reduced_path = os.path.join(nb_dir, "products", reduced_filename)
        makedirs = os.path.dirname(reduced_path)
        if makedirs:
            os.makedirs(makedirs, exist_ok=True)

        reduced_image.write(reduced_path, overwrite=True)
        reduced_comb = models.ExposureCombination(
            night_bundle=nb,
            filename=reduced_filename,
            combination_type=models.COMB_TYPE_CODES["CALIB_LIGHT"],
            exposures=light_q,
            uses_combinations=[master_flat_q, master_dark_q],
        )
    def process_spectroscopy_science(self, science_group, save_all=False):
        """Process Spectroscopy science images.

        This function handles the full image reduction process for science
        files. if save_all is set to True, all intermediate steps are saved.

        Args:
            science_group (object): :class:`~pandas.DataFrame` instance that contains a
                list of science images that where observed at the same pointing
                and time. It also contains a set of selected keywords from the
                image's header.
            save_all (bool): If True the pipeline will save all the intermadiate
                files such as after overscan correction or bias corrected and
                etc.

        """
        # TODO (simon): The code here is too crowded.
        # TODO cont. Create other functions as necessary

        target_name = ''
        slit_trim = None
        master_bias = None
        master_flat = None
        master_flat_name = None
        obstype = science_group.obstype.unique()
        # print(obstype)
        if 'OBJECT' in obstype or 'COMP' in obstype:
            object_comp_group = science_group[
                (science_group.obstype == 'OBJECT') |
                (science_group.obstype == 'COMP')]

            if 'OBJECT' in obstype:
                target_name = science_group.object[science_group.obstype ==
                                                   'OBJECT'].unique()[0]

                self.log.info('Processing Science Target: '
                              '{:s}'.format(target_name))
            else:
                # TODO (simon): This does not make any sense
                self.log.info('Processing Comparison Lamp: '
                              '{:s}'.format(target_name))

            if 'FLAT' in obstype and not self.args.ignore_flats:
                flat_sub_group = science_group[science_group.obstype == 'FLAT']

                master_flat, master_flat_name = \
                    self.create_master_flats(flat_group=flat_sub_group,
                                             target_name=target_name)
            elif self.args.ignore_flats:
                self.log.warning(
                    'Ignoring creation of Master Flat by request.')
                master_flat = None
                master_flat_name = None
            else:
                self.log.info('Attempting to find a suitable Master Flat')
                object_list = object_comp_group.file.tolist()

                # grab a random image from the list
                random_image = random.choice(object_list)

                # define random image full path
                random_image_full = os.path.join(self.args.raw_path,
                                                 random_image)

                # read the random chosen file
                ccd = CCDData.read(random_image_full, unit=u.adu)

                if not self.args.ignore_flats:
                    # define the master flat name
                    master_flat_name = self.name_master_flats(
                        header=ccd.header, group=object_comp_group, get=True)

                    # load the best flat based on the name previously defined
                    master_flat, master_flat_name = \
                        get_best_flat(flat_name=master_flat_name,
                                      path=self.args.red_path)
                    if (master_flat is None) and (master_flat_name is None):
                        self.log.critical('Failed to obtain master flat')

            if master_flat is not None and not self.args.ignore_flats:
                self.log.debug('Attempting to find slit trim section')
                slit_trim = get_slit_trim_section(master_flat=master_flat)
            elif self.args.ignore_flats:
                self.log.warning('Slit Trimming will be skipped, '
                                 '--ignore-flats is activated')
            else:
                self.log.info("Master flat inexistent, can't find slit trim "
                              "section")
            if slit_trim is not None:

                master_flat = image_trim(ccd=master_flat,
                                         trim_section=slit_trim,
                                         trim_type='slit')

                if self.master_bias is not None:
                    master_bias = image_trim(ccd=self.master_bias,
                                             trim_section=slit_trim,
                                             trim_type='slit')
            else:
                try:
                    master_bias = self.master_bias.copy()
                except AttributeError:
                    master_bias = None

            norm_master_flat = None
            norm_master_flat_name = None
            all_object_image = []
            all_comp_image = []
            for science_image in object_comp_group.file.tolist():
                self.out_prefix = ''

                # define image full path
                image_full_path = os.path.join(self.args.raw_path,
                                               science_image)

                # load image
                ccd = read_fits(image_full_path, technique=self.technique)

                # apply overscan
                ccd = image_overscan(ccd, overscan_region=self.overscan_region)
                self.out_prefix += 'o_'

                if save_all:
                    full_path = os.path.join(self.args.red_path,
                                             self.out_prefix + science_image)

                    # ccd.write(full_path, clobber=True)
                    write_fits(ccd=ccd, full_path=full_path)

                if slit_trim is not None:
                    # There is a double trimming of the image, this is to match
                    # the size of the other data
                    # TODO (simon): Potential problem here
                    ccd = image_trim(ccd=ccd,
                                     trim_section=self.trim_section,
                                     trim_type='trimsec')

                    ccd = image_trim(ccd=ccd,
                                     trim_section=slit_trim,
                                     trim_type='slit')

                    self.out_prefix = 'st' + self.out_prefix

                    if save_all:
                        full_path = os.path.join(
                            self.args.red_path,
                            self.out_prefix + science_image)

                        # ccd.write(full_path, clobber=True)
                        write_fits(ccd=ccd, full_path=full_path)

                else:
                    ccd = image_trim(ccd=ccd,
                                     trim_section=self.trim_section,
                                     trim_type='trimsec')

                    self.out_prefix = 't' + self.out_prefix

                    if save_all:
                        full_path = os.path.join(
                            self.args.red_path,
                            self.out_prefix + science_image)

                        # ccd.write(full_path, clobber=True)
                        write_fits(ccd=ccd, full_path=full_path)

                if not self.args.ignore_bias:
                    # TODO (simon): Add check that bias is compatible

                    ccd = ccdproc.subtract_bias(ccd=ccd,
                                                master=master_bias,
                                                add_keyword=False)

                    self.out_prefix = 'z' + self.out_prefix

                    ccd.header['GSP_BIAS'] = (os.path.basename(
                        self.master_bias_name), 'Master bias image')

                    if save_all:
                        full_path = os.path.join(
                            self.args.red_path,
                            self.out_prefix + science_image)

                        # ccd.write(full_path, clobber=True)
                        write_fits(ccd=ccd, full_path=full_path)
                else:
                    self.log.warning('Ignoring bias correction by request.')

                # Do flat correction
                if master_flat is None or master_flat_name is None:
                    self.log.warning('The file {:s} will not be '
                                     'flatfielded'.format(science_image))
                elif self.args.ignore_flats:
                    self.log.warning('Ignoring flatfielding by request.')
                else:
                    if norm_master_flat is None:

                        norm_master_flat, norm_master_flat_name = \
                            normalize_master_flat(
                                master=master_flat,
                                name=master_flat_name,
                                method=self.args.flat_normalize,
                                order=self.args.norm_order)

                    ccd = ccdproc.flat_correct(ccd=ccd,
                                               flat=norm_master_flat,
                                               add_keyword=False)

                    self.out_prefix = 'f' + self.out_prefix

                    ccd.header['GSP_FLAT'] = (
                        os.path.basename(norm_master_flat_name),
                        'Master flat image')

                    # propagate master flat normalization method
                    ccd.header['GSP_NORM'] = norm_master_flat.header[
                        'GSP_NORM']

                    if save_all:
                        full_path = os.path.join(
                            self.args.red_path,
                            self.out_prefix + science_image)

                        # ccd.write(full_path, clobber=True)
                        write_fits(ccd=ccd, full_path=full_path)

                ccd, prefix = call_cosmic_rejection(
                    ccd=ccd,
                    image_name=science_image,
                    out_prefix=self.out_prefix,
                    red_path=self.args.red_path,
                    dcr_par=self.args.dcr_par_dir,
                    keep_files=self.args.keep_cosmic_files,
                    method=self.args.clean_cosmic,
                    save=True)

                self.out_prefix = prefix

                if ccd is not None:
                    if ccd.header['OBSTYPE'] == 'OBJECT':
                        self.log.debug(
                            "Appending OBJECT image for combination")
                        all_object_image.append(ccd)
                    elif ccd.header['OBSTYPE'] == 'COMP':
                        self.log.debug("Appending COMP image for combination")
                        all_comp_image.append(ccd)
                    else:
                        self.log.error("Unknown OBSTYPE = {:s}"
                                       "".format(ccd.header['OBSTYPE']))
                else:
                    self.log.warning("Cosmic ray rejection returned a None.")

            if self.args.combine:
                self.log.warning("Combination of data is experimental.")
                if len(all_object_image) > 1:
                    print(len(all_object_image))
                    self.log.info("Combining {:d} OBJECT images"
                                  "".format(len(all_object_image)))

                    object_group = object_comp_group[object_comp_group.obstype
                                                     == "OBJECT"]

                    print(object_group, len(all_object_image))

                    combine_data(all_object_image,
                                 dest_path=self.args.red_path,
                                 prefix=self.out_prefix,
                                 save=True)
                elif len(all_object_image) == 1:
                    # write_fits(all_object_image[0])
                    pass

                else:
                    self.log.error("No OBJECT images to combine")

                if len(all_comp_image) > 1:
                    self.log.info("Combining {:d} COMP images"
                                  "".format(len(all_comp_image)))
                    # comp_group = object_comp_group[
                    #     object_comp_group.obstype == "COMP"]
                    combine_data(all_comp_image,
                                 dest_path=self.args.red_path,
                                 prefix=self.out_prefix,
                                 save=True)
                else:
                    self.log.error("No COMP images to combine")
            else:
                self.log.debug("Combine is disabled (default)")

        elif 'FLAT' in obstype:
            self.queue.append(science_group)
            self.log.warning('Only flats found in this group')
            flat_sub_group = science_group[science_group.obstype == 'FLAT']
            # TODO (simon): Find out if these variables are useful or not
            self.create_master_flats(flat_group=flat_sub_group)
        else:
            self.log.error('There is no valid datatype in this group')
Пример #19
0
 def run(self):
     """ Runs the calibrating algorithm. The calibrated data is
         returned in self.dataout
     """
     ### Preparation
     # Load bias files if necessary
     if not self.biasloaded or self.getarg('reload'):
         self.loadbias()
     # Else: check data for correct instrument configuration - currently not in use(need improvement)
     else:
         for keyind in range(len(self.biasfitkeys)):
             if self.biaskeyvalues[keyind] != self.datain.getheadval(
                     self.biasfitkeys[keyind]):
                 self.log.warn(
                     'New data has different FITS key value for keyword %s'
                     % self.biasfitkeys[keyind])
     # Load dark files if necessary
     if not self.darkloaded or self.getarg('reload'):
         self.loaddark()
     # Else: check data for correct instrument configuration
     else:
         for keyind in range(len(self.darkfitkeys)):
             if self.darkkeyvalues[keyind] != self.datain.getheadval(
                     self.darkfitkeys[keyind]):
                 self.log.warn(
                     'New data has different FITS key value for keyword %s'
                     % self.darkfitkeys[keyind])
     # Load flat files if necessary
     if not self.flatloaded or self.getarg('reload'):
         self.loadflat()
     # Else: check data for correct instrument configuration
     else:
         for keyind in range(len(self.flatfitkeys)):
             if self.flatkeyvalues[keyind] != self.datain.getheadval(
                     self.flatfitkeys[keyind]):
                 self.log.warn(
                     'New data has different FITS key value for keyword %s'
                     % self.flatfitkeys[keyind])
     #convert self.datain to CCD Data object
     image = ccdproc.CCDData(self.datain.image, unit='adu')
     image.header = self.datain.header
     #subtract bias from image
     image = ccdproc.subtract_bias(image, self.bias, add_keyword=False)
     #subtract dark from image
     image = ccdproc.subtract_dark(image,
                                   self.dark,
                                   scale=True,
                                   exposure_time='EXPTIME',
                                   exposure_unit=u.second,
                                   add_keyword=False)
     #apply flat correction to image
     image = ccdproc.flat_correct(image, self.flat, add_keyword=False)
     # copy calibrated image into self.dataout - make sure self.dataout is a pipedata object
     self.dataout = DataFits(config=self.datain.config)
     self.dataout.image = image.data
     self.dataout.header = image.header
     self.dataout.filename = self.datain.filename
     ### Finish - cleanup
     # Update DATATYPE
     self.dataout.setheadval('DATATYPE', 'IMAGE')
     # Add bias, dark files to History
     self.dataout.setheadval('HISTORY', 'BIAS: %s' % self.biasname)
     self.dataout.setheadval('HISTORY', 'DARK: %s' % self.darkname)
     self.dataout.setheadval('HISTORY', 'FLAT: %s' % self.flatname)
Пример #20
0
    def process_imaging_science(self, imaging_group):
        """Does image reduction for science imaging data.

        Args:
            imaging_group (object): pandas.DataFrame instance that contains a
                list of science data that are compatible with a given
                instrument configuration and can be reduced together.


        """
        # pick a random image in order to get a header
        random_image = random.choice(imaging_group.file.tolist())
        path_random_image = os.path.join(self.args.raw_path, random_image)
        sample_file = CCDData.read(path_random_image, unit=u.adu)

        master_flat_name = self.name_master_flats(header=sample_file.header,
                                                  group=imaging_group,
                                                  get=True)

        log.debug('Got {:s} for master flat name'.format(master_flat_name))

        master_flat, master_flat_name = get_best_flat(
            flat_name=master_flat_name)

        if master_flat is not None:
            for image_file in imaging_group.file.tolist():

                # start with an empty prefix
                self.out_prefix = ''

                image_full_path = os.path.join(self.args.raw_path, image_file)
                ccd = CCDData.read(image_full_path, unit=u.adu)

                # Trim image
                ccd = image_trim(ccd, trim_section=self.trim_section)
                self.out_prefix = 't_'
                if not self.args.ignore_bias:

                    ccd = ccdproc.subtract_bias(ccd,
                                                self.master_bias,
                                                add_keyword=False)

                    self.out_prefix = 'z' + self.out_prefix
                    ccd.header.add_history('Bias subtracted image')

                # apply flat correction
                ccd = ccdproc.flat_correct(ccd, master_flat, add_keyword=False)

                self.out_prefix = 'f' + self.out_prefix

                ccd.header.add_history('Flat corrected '
                                       '{:s}'.format(
                                           master_flat_name.split('/')[-1]))

                if self.args.clean_cosmic:
                    ccd = lacosmic_cosmicray_rejection(ccd=ccd)
                    self.out_prefix = 'c' + self.out_prefix
                else:
                    print('Clean Cosmic ' + str(self.args.clean_cosmic))

                final_name = os.path.join(self.args.red_path,
                                          self.out_prefix + image_file)
                ccd.write(final_name, clobber=True)
                log.info('Created science file: {:s}'.format(final_name))
        else:
            log.error('Can not process data without a master flat')
Пример #21
0
    def process_spectroscopy_science(self, science_group, save_all=False):
        """Process Spectroscopy science images.

        This function handles the full image reduction process for science
        files. if save_all is used, all intermediate steps are saved.

        Args:
            science_group (object): pandas.DataFrame instance that contains a
                list of science images that where observed at the same pointing
                and time. It also contains a set of selected keywords from the
                image's header.
            save_all (bool): If True the pipeline will save all the intermadiate
                files such as after overscan correction or bias corrected and
                etc.

        """
        # TODO (simon): The code here is too crowded.
        # TODO cont. Create other functions as necessary

        target_name = ''
        slit_trim = None
        master_flat = None
        master_flat_name = None
        obstype = science_group.obstype.unique()
        # print(obstype)
        if 'OBJECT' in obstype or 'COMP' in obstype:
            object_group = science_group[(science_group.obstype == 'OBJECT') |
                                         (science_group.obstype == 'COMP')]
            if 'OBJECT' in obstype:
                target_name = science_group.object[science_group.obstype ==
                                                   'OBJECT'].unique()[0]

                log.info('Processing Science Target: {:s}'.format(target_name))
            else:
                log.info(
                    'Processing Comparison Lamp: {:s}'.format(target_name))

            if 'FLAT' in obstype and not self.args.ignore_flats:
                flat_sub_group = science_group[science_group.obstype == 'FLAT']

                master_flat, master_flat_name =\
                    self.create_master_flats(flat_group=flat_sub_group,
                                             target_name=target_name)
            elif self.args.ignore_flats:
                log.warning('Ignoring creation of Master Flat by request.')
                master_flat = None
                master_flat_name = None
            else:
                log.info('Attempting to find a suitable Master Flat')
                object_list = object_group.file.tolist()

                # grab a random image from the list
                random_image = random.choice(object_list)

                # define random image full path
                random_image_full = os.path.join(self.args.raw_path,
                                                 random_image)

                # read the random chosen file
                ccd = CCDData.read(random_image_full, unit=u.adu)

                if not self.args.ignore_flats:
                    # define the master flat name
                    master_flat_name = self.name_master_flats(
                        header=ccd.header, group=object_group, get=True)

                    # load the best flat based on the name previously defined
                    master_flat, master_flat_name = \
                        get_best_flat(flat_name=master_flat_name)
                    if (master_flat is None) and (master_flat_name is None):
                        log.critical('Failed to obtain master flat')

            if master_flat is not None and not self.args.ignore_flats:
                log.debug('Attempting to find slit trim section')
                slit_trim = get_slit_trim_section(master_flat=master_flat)
            elif self.args.ignore_flats:
                log.warning('Slit Trimming will be skipped, --ignore-flats is '
                            'activated')
            else:
                log.info('Master flat inexistent, cant find slit trim section')
            if slit_trim is not None:

                master_flat = image_trim(ccd=master_flat,
                                         trim_section=slit_trim)

                if self.master_bias is not None:
                    master_bias = image_trim(ccd=self.master_bias,
                                             trim_section=slit_trim)
            else:
                try:
                    master_bias = self.master_bias.copy()
                except AttributeError:
                    master_bias = None

            norm_master_flat = None
            for science_image in object_group.file.tolist():
                self.out_prefix = ''

                # define image full path
                image_full_path = os.path.join(self.args.raw_path,
                                               science_image)

                # load image
                ccd = CCDData.read(image_full_path, unit=u.adu)

                # apply overscan
                ccd = image_overscan(ccd, overscan_region=self.overscan_region)
                self.out_prefix += 'o_'

                if save_all:
                    full_path = os.path.join(self.args.red_path,
                                             self.out_prefix + science_image)

                    ccd.write(full_path, clobber=True)

                if slit_trim is not None:
                    # There is a double trimming of the image, this is to match
                    # the size of the other data
                    # TODO (simon): Potential problem here
                    ccd = image_trim(ccd=ccd, trim_section=self.trim_section)
                    ccd = image_trim(ccd=ccd, trim_section=slit_trim)
                    self.out_prefix = 'st' + self.out_prefix

                    if save_all:
                        full_path = os.path.join(
                            self.args.red_path,
                            self.out_prefix + science_image)

                        ccd.write(full_path, clobber=True)

                else:
                    ccd = image_trim(ccd=ccd, trim_section=self.trim_section)
                    self.out_prefix = 't' + self.out_prefix

                    if save_all:
                        full_path = os.path.join(
                            self.args.red_path,
                            self.out_prefix + science_image)

                        ccd.write(full_path, clobber=True)

                if not self.args.ignore_bias:
                    # TODO (simon): Add check that bias is compatible

                    ccd = ccdproc.subtract_bias(ccd=ccd,
                                                master=master_bias,
                                                add_keyword=False)

                    self.out_prefix = 'z' + self.out_prefix
                    ccd.header.add_history('Bias subtracted image')

                    if save_all:
                        full_path = os.path.join(
                            self.args.red_path,
                            self.out_prefix + science_image)

                        ccd.write(full_path, clobber=True)
                else:
                    log.warning('Ignoring bias correction by request.')
                if master_flat is None or master_flat_name is None:
                    log.warning('The file {:s} will not be '
                                'flatfielded'.format(science_image))
                elif self.args.ignore_flats:
                    log.warning('Ignoring flatfielding by request.')
                else:
                    if norm_master_flat is None:

                        norm_master_flat = normalize_master_flat(
                            master=master_flat,
                            name=master_flat_name,
                            method=self.args.flat_normalize,
                            order=self.args.norm_order)

                    ccd = ccdproc.flat_correct(ccd=ccd,
                                               flat=norm_master_flat,
                                               add_keyword=False)

                    self.out_prefix = 'f' + self.out_prefix

                    ccd.header.add_history('master flat norm_'
                                           '{:s}'.format(master_flat_name))

                    if save_all:
                        full_path = os.path.join(
                            self.args.red_path,
                            self.out_prefix + science_image)

                        ccd.write(full_path, clobber=True)

                call_cosmic_rejection(ccd=ccd,
                                      image_name=science_image,
                                      out_prefix=self.out_prefix,
                                      red_path=self.args.red_path,
                                      dcr_par=self.args.dcr_par_dir,
                                      keep_files=self.args.keep_cosmic_files,
                                      method=self.args.clean_cosmic)

                # print(science_group)
        elif 'FLAT' in obstype:
            self.queue.append(science_group)
            log.warning('Only flats found in this group')
            flat_sub_group = science_group[science_group.obstype == 'FLAT']
            # TODO (simon): Find out if these variables are useful or not
            master_flat, master_flat_name = \
                self.create_master_flats(flat_group=flat_sub_group)
        else:
            log.error('There is no valid datatype in this group')
Пример #22
0
    def calibrate_image(self, options, img):
        if 'biasonly' in options:
            master_bias = self.find_master_bias(img)
            if master_bias:
                print(
                    f'{Fore.GREEN + Style.BRIGHT}Bias substraction...{Style.RESET_ALL}'
                )
                img = ccdp.subtract_bias(img, master_bias)

        elif 'flatonly' in options:
            master_flat = self.find_master_flat(img)
            if master_flat:
                print(
                    f'{Fore.GREEN + Style.BRIGHT}Flat correction...{Style.RESET_ALL}'
                )
                img = ccdp.flat_correct(img, master_flat)

        else:
            master_dark = self.find_master_dark(img)

            if master_dark:
                print(
                    f'{Fore.GREEN + Style.BRIGHT}Dark substraction...{Style.RESET_ALL}'
                )
                img = ccdp.subtract_dark(img,
                                         master_dark,
                                         exposure_time='exptime',
                                         exposure_unit=u.second)

            else:
                master_dark = self.find_master_dark_c(img)
                if master_dark:
                    master_bias = self.find_master_bias(img)
                    if master_bias:
                        print(
                            f'{Fore.GREEN + Style.BRIGHT}Bias substraction...{Style.RESET_ALL}'
                        )
                        img = ccdp.subtract_bias(img, master_bias)
                        print(
                            f'{Fore.GREEN + Style.BRIGHT}Calibrated dark substraction...{Style.RESET_ALL}'
                        )
                    else:
                        print(
                            f'{Fore.YELLOW + Style.BRIGHT}Substracted calibrated dark without bias...{Style.RESET_ALL}'
                        )
                    img = ccdp.subtract_dark(img,
                                             master_dark,
                                             exposure_time='exptime',
                                             exposure_unit=u.second,
                                             scale=True)
                else:
                    master_bias = self.find_master_bias(img)
                    if master_bias:
                        print(
                            f'{Fore.RED + Style.BRIGHT}No dark substraction.{Style.RESET_ALL}'
                        )
                        print(
                            f'{Fore.GREEN + Style.BRIGHT}Bias substraction...{Style.RESET_ALL}'
                        )
                        img = ccdp.subtract_bias(img, master_bias)
                    else:
                        print(
                            f'{Fore.RED + Style.BRIGHT}No dark or bias substraction.{Style.RESET_ALL}'
                        )

            if not 'noflat' in options:
                master_flat = self.find_master_flat(img)
                if master_flat:
                    print(
                        f'{Fore.GREEN + Style.BRIGHT}Flat correction...{Style.RESET_ALL}'
                    )
                    img = ccdp.flat_correct(img, master_flat)
                else:
                    print(
                        f'{Fore.RED + Style.BRIGHT}No flat correction.{Style.RESET_ALL}'
                    )

            else:
                print(
                    f'{Fore.YELLOW + Style.BRIGHT}Skipping flat correction.{Style.RESET_ALL}'
                )

        return img
Пример #23
0
def preprocess(fits_path):
    """Apply basic CCD reduction tasks.

    Ask for the path to all the calibration and science files, and perform Bias, Dark and Flat combinations and proper substractions.

    Pipeline que aplica una reduccion basica a imagenes de tipo CCD.
    Realiza combinacion de Bias, de Darks, y Flats. Luego realiza las restas inherentes.
    """
    import os
    import sys
    from image_collection import ImageFileCollection

    #Collect all FITS files in path in fitslist
    #fitslist = []
    #for root, dirs, files in os.walk(fits_path, topdown=True):
    #    fitslist.extend([os.path.join(root, name) for name in files if '.fit' in name])
    #
    ##Dictionary with the image type (value) for each image file name (key)
    #imagetypes = {img:fits.getval(img, 'IMAGETYP') for img in fitslist}

    # now we make different lists for different image types
    #biaslist = []
    #sciencelist = []
    #flatlist = []
    #darklist = []
    #unknown = []
    #for k, v in imagetypes.iteritems():
    #    if 'LIGHT' in v.upper() or v.upper()=='OBJECT':
    #        sciencelist.append(k)
    #    elif 'BIAS' in v.upper() or v.upper()=='ZERO':
    #        biaslist.append(k)
    #    elif 'FLAT' in v.upper():
    #        flatlist.append(k)
    #    elif 'DARK' in v.upper():
    #        darklist.append(k)
    #    else:
    #        unknown.append(k)


    #Create an image file collection storing the following keys
    keys = ['imagetyp', 'object', 'filter', 'exptime']
    allfits = ImageFileCollection('.', keywords=keys)

    #Collect all dark files and make a dark frame for each different exposure time
    dark_matches = np.ma.array(['dark' in typ.lower() for typ in allfits.summary['imagetyp']])
    darkexp_set = set(allfits.summary['exptime'][dark_matches])
    darklists = {}
    for anexp in darkexp_set:
        my_darks = allfits.summary['file'][(allfits.summary['exptime'] == anexp) & dark_matches]
        darklists[anexp] = combineDarks(my_darks)

    #Collect all science files
    sciencelist = allfits.files_filtered(imagetyp='light')

    #Collect all bias files
    #bias_matches = ([('zero' in typ.lower() or 'bias' in typ.lower()) for typ in allfits.summary['imagetyp']]
    #biaslist = allfits.summary['file'][bias_matches]

    #Create the flat master
    flatlist = allfits.files_filtered(imagetyp='flat')
    exptime = fits.getval(flatlist[0], 'exptime')
    darkmaster = chooseClosestDark(darklists, exptime)
    flatmaster = combineFlats(flatlist, dark=darkmaster)

    for ascience in sciencelist:
        sci_image = ccdproc.CCDData.read(ascience, unit='adu')
        exp_time = fits.getval(ascience, 'exptime')
        darkmaster = chooseClosestDark(darklists, exp_time)
        try:
            sci_darksub = ccdproc.subtract_dark(sci_image, darkmaster, exposure_time='exptime', exposure_unit=u.second)
            sci_flatcorrected = ccdproc.flat_correct(sci_darksub, flatmaster)
            outpath = os.path.join('/Users/utb/Desktop/reduced/', 'reduced_' + os.path.basename(ascience))
        except:
            sci_flatcorrected = sci_image
            outpath = os.path.join('/Users/utb/Desktop/reduced/', 'failed_' + os.path.basename(ascience))
        hdulist = sci_flatcorrected.to_hdu()
        hdulist.writeto(outpath, clobber=True)

    return
Пример #24
0
    def process_spectroscopy_science(self, science_group, save_all=False):
        """Process Spectroscopy science images.

        This function handles the full image reduction process for science
        files. if save_all is set to True, all intermediate steps are saved.

        Args:
            science_group (object): :class:`~pandas.DataFrame` instance that contains a
                list of science images that where observed at the same pointing
                and time. It also contains a set of selected keywords from the
                image's header.
            save_all (bool): If True the pipeline will save all the intermadiate
                files such as after overscan correction or bias corrected and
                etc.

        """
        # TODO (simon): The code here is too crowded.
        # TODO cont. Create other functions as necessary

        target_name = ''
        slit_trim = None
        master_bias = None
        master_flat = None
        master_flat_name = None
        obstype = science_group.obstype.unique()
        # print(obstype)
        if 'OBJECT' in obstype or 'COMP' in obstype:
            object_comp_group = science_group[
                (science_group.obstype == 'OBJECT') |
                (science_group.obstype == 'COMP')]

            if 'OBJECT' in obstype:
                target_name = science_group.object[science_group.obstype ==
                                                   'OBJECT'].unique()[0]

                self.log.info('Processing Science Target: '
                              '{:s}'.format(target_name))
            else:
                # TODO (simon): This does not make any sense
                self.log.info('Processing Comparison Lamp: '
                              '{:s}'.format(target_name))

            if 'FLAT' in obstype and not self.args.ignore_flats:
                flat_sub_group = science_group[science_group.obstype == 'FLAT']

                master_flat, master_flat_name = \
                    self.create_master_flats(flat_group=flat_sub_group,
                                             target_name=target_name)
            elif self.args.ignore_flats:
                self.log.warning('Ignoring creation of Master Flat by request.')
                master_flat = None
                master_flat_name = None
            else:
                self.log.info('Attempting to find a suitable Master Flat')
                object_list = object_comp_group.file.tolist()

                # grab a random image from the list
                random_image = random.choice(object_list)

                # define random image full path
                random_image_full = os.path.join(self.args.raw_path,
                                                 random_image)

                # read the random chosen file
                ccd = CCDData.read(random_image_full, unit=u.adu)

                if not self.args.ignore_flats:
                    # define the master flat name
                    master_flat_name = self.name_master_flats(
                        header=ccd.header,
                        group=object_comp_group,
                        get=True)

                    # load the best flat based on the name previously defined
                    master_flat, master_flat_name = \
                        get_best_flat(flat_name=master_flat_name,
                                      path=self.args.red_path)
                    if (master_flat is None) and (master_flat_name is None):
                        self.log.critical('Failed to obtain master flat')

            if master_flat is not None and not self.args.ignore_flats:
                self.log.debug('Attempting to find slit trim section')
                slit_trim = get_slit_trim_section(master_flat=master_flat)
            elif self.args.ignore_flats:
                self.log.warning('Slit Trimming will be skipped, '
                                 '--ignore-flats is activated')
            else:
                self.log.info("Master flat inexistent, can't find slit trim "
                              "section")
            if slit_trim is not None:

                master_flat = image_trim(ccd=master_flat,
                                         trim_section=slit_trim,
                                         trim_type='slit')

                if self.master_bias is not None:
                    master_bias = image_trim(ccd=self.master_bias,
                                             trim_section=slit_trim,
                                             trim_type='slit')
            else:
                try:
                    master_bias = self.master_bias.copy()
                except AttributeError:
                    master_bias = None

            norm_master_flat = None
            norm_master_flat_name = None
            all_object_image = []
            all_comp_image = []
            for science_image in object_comp_group.file.tolist():
                self.out_prefix = ''

                # define image full path
                image_full_path = os.path.join(self.args.raw_path,
                                               science_image)

                # load image
                ccd = read_fits(image_full_path, technique=self.technique)

                # apply overscan
                ccd = image_overscan(ccd, overscan_region=self.overscan_region)
                self.out_prefix += 'o_'

                if save_all:
                    full_path = os.path.join(self.args.red_path,
                                             self.out_prefix + science_image)

                    # ccd.write(full_path, clobber=True)
                    write_fits(ccd=ccd, full_path=full_path)

                if slit_trim is not None:
                    # There is a double trimming of the image, this is to match
                    # the size of the other data
                    # TODO (simon): Potential problem here
                    ccd = image_trim(ccd=ccd,
                                     trim_section=self.trim_section,
                                     trim_type='trimsec')

                    ccd = image_trim(ccd=ccd,
                                     trim_section=slit_trim,
                                     trim_type='slit')

                    self.out_prefix = 'st' + self.out_prefix

                    if save_all:
                        full_path = os.path.join(
                            self.args.red_path,
                            self.out_prefix + science_image)

                        # ccd.write(full_path, clobber=True)
                        write_fits(ccd=ccd, full_path=full_path)

                else:
                    ccd = image_trim(ccd=ccd,
                                     trim_section=self.trim_section,
                                     trim_type='trimsec')

                    self.out_prefix = 't' + self.out_prefix

                    if save_all:
                        full_path = os.path.join(
                            self.args.red_path,
                            self.out_prefix + science_image)

                        # ccd.write(full_path, clobber=True)
                        write_fits(ccd=ccd, full_path=full_path)

                if not self.args.ignore_bias:
                    # TODO (simon): Add check that bias is compatible

                    ccd = ccdproc.subtract_bias(ccd=ccd,
                                                master=master_bias,
                                                add_keyword=False)

                    self.out_prefix = 'z' + self.out_prefix

                    ccd.header['GSP_BIAS'] = (
                        os.path.basename(self.master_bias_name),
                        'Master bias image')

                    if save_all:
                        full_path = os.path.join(
                            self.args.red_path,
                            self.out_prefix + science_image)

                        # ccd.write(full_path, clobber=True)
                        write_fits(ccd=ccd, full_path=full_path)
                else:
                    self.log.warning('Ignoring bias correction by request.')

                # Do flat correction
                if master_flat is None or master_flat_name is None:
                    self.log.warning('The file {:s} will not be '
                                     'flatfielded'.format(science_image))
                elif self.args.ignore_flats:
                    self.log.warning('Ignoring flatfielding by request.')
                else:
                    if norm_master_flat is None:

                        norm_master_flat, norm_master_flat_name = \
                            normalize_master_flat(
                                master=master_flat,
                                name=master_flat_name,
                                method=self.args.flat_normalize,
                                order=self.args.norm_order)

                    ccd = ccdproc.flat_correct(ccd=ccd,
                                               flat=norm_master_flat,
                                               add_keyword=False)

                    self.out_prefix = 'f' + self.out_prefix

                    ccd.header['GSP_FLAT'] = (
                        os.path.basename(norm_master_flat_name),
                        'Master flat image')

                    # propagate master flat normalization method
                    ccd.header['GSP_NORM'] = norm_master_flat.header['GSP_NORM']

                    if save_all:
                        full_path = os.path.join(
                            self.args.red_path,
                            self.out_prefix + science_image)

                        # ccd.write(full_path, clobber=True)
                        write_fits(ccd=ccd, full_path=full_path)

                ccd, prefix = call_cosmic_rejection(
                    ccd=ccd,
                    image_name=science_image,
                    out_prefix=self.out_prefix,
                    red_path=self.args.red_path,
                    dcr_par=self.args.dcr_par_dir,
                    keep_files=self.args.keep_cosmic_files,
                    method=self.args.clean_cosmic,
                    save=True)

                self.out_prefix = prefix

                if ccd is not None:
                    if ccd.header['OBSTYPE'] == 'OBJECT':
                        self.log.debug("Appending OBJECT image for combination")
                        all_object_image.append(ccd)
                    elif ccd.header['OBSTYPE'] == 'COMP':
                        self.log.debug("Appending COMP image for combination")
                        all_comp_image.append(ccd)
                    else:
                        self.log.error("Unknown OBSTYPE = {:s}"
                                       "".format(ccd.header['OBSTYPE']))
                else:
                    self.log.warning("Cosmic ray rejection returned a None.")

            if self.args.combine:
                self.log.warning("Combination of data is experimental.")
                if len(all_object_image) > 1:
                    print(len(all_object_image))
                    self.log.info("Combining {:d} OBJECT images"
                                  "".format(len(all_object_image)))

                    object_group = object_comp_group[
                        object_comp_group.obstype == "OBJECT"]

                    print(object_group, len(all_object_image))

                    combine_data(all_object_image,
                                 dest_path=self.args.red_path,
                                 prefix=self.out_prefix,
                                 save=True)
                elif len(all_object_image) == 1:
                    # write_fits(all_object_image[0])
                    pass

                else:
                    self.log.error("No OBJECT images to combine")

                if len(all_comp_image) > 1:
                    self.log.info("Combining {:d} COMP images"
                                  "".format(len(all_comp_image)))
                    # comp_group = object_comp_group[
                    #     object_comp_group.obstype == "COMP"]
                    combine_data(all_comp_image,
                                 dest_path=self.args.red_path,
                                 prefix=self.out_prefix,
                                 save=True)
                else:
                    self.log.error("No COMP images to combine")
            else:
                self.log.debug("Combine is disabled (default)")

        elif 'FLAT' in obstype:
            self.queue.append(science_group)
            self.log.warning('Only flats found in this group')
            flat_sub_group = science_group[science_group.obstype == 'FLAT']
            # TODO (simon): Find out if these variables are useful or not
            self.create_master_flats(flat_group=flat_sub_group)
        else:
            self.log.error('There is no valid datatype in this group')
Пример #25
0
            
            zccd = ccdproc.cosmicray_lacosmic(ccd, gain = float(args.gain), readnoise = float(args.rdnoise))
            outfile = 'z'+outfile

        # subtract dark
        if args.dark:
            if args.zap:
                infile=zccd
            else:
                infile = ccd
            dccd = ccdproc.subtract_dark(infile, dark)
            outfile = 'd'+outfile

        # flatten
        if args.flat:
            # flatten
            if args.dark:
                infile = dccd
            else:
                if args.zap:
                    infile = zccd
                else:
                    infile = ccd
            fccd = ccdproc.flat_correct(infile, gain = float(args.gain), readnoise = float(args.rdnoise),add_keywork='flat_corrected')
            outfile = 'f'+outfile
            fccd.write(outfile)
    i += 1
    print '\n'

                   
Пример #26
0
 reprojected = []
 for sci in sci_list:
     raw = CCDData.read(sci, hdu=1, unit=u.adu)
     red = ccdproc.subtract_overscan(raw,
                                     overscan=raw[0:4, :],
                                     overscan_axis=0,
                                     model=models.Chebyshev1D(3))
     red = ccdproc.ccd_process(
         red,
         gain=raw.header['GAIN'] * u.electron / u.adu,
         readnoise=raw.header['RDNOISE'] * u.electron)
     red = ccdproc.subtract_dark(red,
                                 mdark,
                                 exposure_time='EXPTIME',
                                 exposure_unit=u.second)
     red = ccdproc.flat_correct(red, mflat)
     processed_data = ccdproc.ccd_process(red,
                                          trim=raw.header['DATASEC'])
     sigma_clip = SigmaClip(sigma=3)
     bkg_estimator = MedianBackground()
     _, median, std = sigma_clipped_stats(processed_data, sigma=3.0)
     m = np.ma.masked_greater(processed_data, median + 3 * std)
     masks.append(m.mask)
     bkg = Background2D(processed_data, (30, 30),
                        filter_size=(3, 3),
                        sigma_clip=sigma_clip,
                        bkg_estimator=bkg_estimator,
                        mask=m.mask,
                        exclude_percentile=80)
     processed.append(
         processed_data.subtract(CCDData(bkg.background,
Пример #27
0
                    lights[lightcnt] = subtract_bias(lights[lightcnt], bias)
                if darkcal == True:
                    log("Calibrating dark...")
                    lights[lightcnt] = subtract_dark(
                        lights[lightcnt],
                        dark,
                        dark_exposure=darkexp * units.s,
                        data_exposure=exptimenow * units.s,
                        scale=True)
                if flatcal == True:
                    log("Calibrating flat...")
                    if lightfilter != flatfilter:
                        warning("Filter mismatch with flat: " + i + " (" +
                                headers[args.fits_header_filter].strip() +
                                " filter)")
                    lights[lightcnt] = flat_correct(lights[lightcnt], flat)

                #regularize exposure time
                lights[lightcnt] = lights[lightcnt].multiply(exptime /
                                                             exptimenow)
                lights[lightcnt] = lights[lightcnt].add(args.pedestal *
                                                        units.astrophys.adu)

                if args.offset != None:
                    try:
                        light_one = np.roll(light_one, -offset[i][0], axis=1)
                        light_one = np.roll(light_one, -offset[i][1], axis=0)
                        light_one = CCDData(light_one, unit='adu')
                        log("Shifted by " + str(-offset[i][0]) + ", " +
                            str(-offset[i][1]))
                    except KeyError:
Пример #28
0
master_flat_blue.write('master_flat_blue.fits', clobber=True)

#reduce the arc frames
for filename in ic1.files_filtered(obstype='Arc', isiarm='Blue arm'):
    hdu = fits.open(ic1.location + filename)
    ccd = CCDData(hdu[1].data,
                  header=hdu[0].header + hdu[1].header,
                  unit=u.adu)
    #this has to be fixed as the bias section does not include the whole section that will be trimmed
    ccd = ccdproc.subtract_overscan(ccd,
                                    median=True,
                                    overscan_axis=0,
                                    fits_section='[1:966,4105:4190]')
    ccd = ccdproc.trim_image(ccd, fits_section=ccd.header['TRIMSEC'])
    ccd = ccdproc.subtract_bias(ccd, master_bias_blue)
    ccd = ccdproc.flat_correct(ccd, master_flat_blue)
    ccd.data = ccd.data.T
    ccd.write('arc_' + filename, clobber=True)

red_flat_list = []
for filename in ic1.files_filtered(obstype='Arc', isiarm='Red arm'):
    hdu = fits.open(ic1.location + filename)
    ccd = CCDData(hdu[1].data,
                  header=hdu[0].header + hdu[1].header,
                  unit=u.adu)
    #this has to be fixed as the bias section does not include the whole section that will be trimmed
    ccd = ccdproc.subtract_overscan(ccd,
                                    median=True,
                                    overscan_axis=0,
                                    fits_section='[1:966,4105:4190]')
    ccd = ccdproc.trim_image(ccd, fits_section=ccd.header['TRIMSEC'])
Пример #29
0
def process_science(sci_list,
                    fil,
                    red_path,
                    mbias=None,
                    mflat=None,
                    proc=None,
                    log=None):
    masks = []
    processed = []
    flat_left = mflat[0]
    flat_right = mflat[1]
    left_list = []
    right_list = []
    if proc:
        for j, sci in enumerate(sci_list):
            log.info('Loading file: ' + sci)
            log.info('Applying flat correction and trimming left image.')
            left = CCDData.read(sci, hdu=1, unit=u.electron)
            left = ccdproc.flat_correct(left, flat_left)
            left = ccdproc.ccd_process(left, trim=left.header['DATASEC'])
            log.info('Left image proccessed and trimmed.')
            log.info('Cleaning cosmic rays and creating mask.')
            mask = make_source_mask(left, nsigma=3, npixels=5)
            clean, com_mask = create_mask.create_mask(sci, left,
                                                      '_mask_left.fits',
                                                      static_mask(proc)[0],
                                                      mask,
                                                      saturation(left.header),
                                                      binning(proc, 'left'),
                                                      rdnoise(left.header),
                                                      cr_clean_sigclip(),
                                                      cr_clean_sigcfrac(),
                                                      cr_clean_objlim(), log)
            left.data = clean
            log.info('Calculating 2D background.')
            bkg = Background2D(left, (120, 120),
                               filter_size=(3, 3),
                               sigma_clip=SigmaClip(sigma=3),
                               bkg_estimator=MeanBackground(),
                               mask=mask,
                               exclude_percentile=80)
            log.info('Median background for left iamge: ' +
                     str(np.median(bkg.background)))
            fits.writeto(sci.replace('/raw/',
                                     '/red/').replace('.fits',
                                                      '_bkg_left.fits'),
                         bkg.background,
                         overwrite=True)
            left = left.subtract(CCDData(bkg.background, unit=u.electron),
                                 propagate_uncertainties=True,
                                 handle_meta='first_found')
            log.info('Exposure time of left image is ' +
                     str(left.header['EXPTIME']))
            left = left.divide(left.header['EXPTIME'],
                               propagate_uncertainties=True,
                               handle_meta='first_found')
            log.info(
                'Background subtracted and image divided by exposure time.')
            left.header['DATASEC'] = '[1:' + str(
                np.shape(left)[1]) + ',1:' + str(np.shape(left)[0]) + ']'
            left_list.append(left)
            log.info('Applying flat correction and trimming right image.')
            right = CCDData.read(sci, hdu=2, unit=u.electron)
            right = ccdproc.flat_correct(right, flat_right)
            right = ccdproc.ccd_process(right, trim=right.header['DATASEC'])
            log.info('Right image proccessed and trimmed.')
            log.info('Cleaning cosmic rays and creating mask.')
            mask = make_source_mask(right, nsigma=3, npixels=5)
            clean, com_mask = create_mask.create_mask(sci, right,
                                                      '_mask_right.fits',
                                                      static_mask(proc)[1],
                                                      mask,
                                                      saturation(right.header),
                                                      binning(proc, 'right'),
                                                      rdnoise(right.header),
                                                      cr_clean_sigclip(),
                                                      cr_clean_sigcfrac(),
                                                      cr_clean_objlim(), log)
            right.data = clean
            log.info('Calculating 2D background.')
            bkg = Background2D(right, (120, 120),
                               filter_size=(3, 3),
                               sigma_clip=SigmaClip(sigma=3),
                               bkg_estimator=MeanBackground(),
                               mask=mask,
                               exclude_percentile=80)
            log.info('Median background for right image : ' +
                     str(np.median(bkg.background)))
            fits.writeto(sci.replace('/raw/',
                                     '/red/').replace('.fits',
                                                      '_bkg_right.fits'),
                         bkg.background,
                         overwrite=True)
            right = right.subtract(CCDData(bkg.background, unit=u.electron),
                                   propagate_uncertainties=True,
                                   handle_meta='first_found')
            log.info('Exposure time of right image is ' +
                     str(right.header['EXPTIME']))
            right = right.divide(right.header['EXPTIME'],
                                 propagate_uncertainties=True,
                                 handle_meta='first_found')
            log.info(
                'Background subtracted and image divided by exposure time.')
            right.header['DATASEC'] = '[1:' + str(
                np.shape(right)[1]) + ',1:' + str(np.shape(right)[0]) + ']'
            right_list.append(right)
    else:
        for j, sci in enumerate(sci_list):
            log.info('Loading file: ' + sci)
            log.info(
                'Applying gain correction, overscan correction, flat correction, and trimming image.'
            )
            with fits.open(sci) as hdr:
                header_left = hdr[1].header
                header_right = hdr[6].header
            data_list = []
            for i in range(8):
                data = ccdproc.CCDData.read(sci, hdu=i + 1, unit=u.adu)
                red = ccdproc.ccd_process(data,
                                          oscan=data[:, 0:50],
                                          oscan_model=models.Chebyshev1D(3),
                                          trim='[1200:2098,210:2056]',
                                          gain=gain()[i] * u.electron / u.adu,
                                          readnoise=4 * u.electron)
                data_list.append(np.asarray(red).astype(np.float32))
            top_left = np.concatenate(
                [data_list[0], np.fliplr(data_list[1])], axis=1)
            bot_left = np.flipud(
                np.concatenate(
                    [data_list[3], np.fliplr(data_list[2])], axis=1))
            left = CCDData(np.concatenate([top_left, bot_left]),
                           unit=u.electron,
                           header=header_left)
            left = ccdproc.flat_correct(left, flat_left[209:3903, 1149:2947])
            log.info('Left image proccessed and trimmed.')
            log.info('Cleaning cosmic rays and creating mask.')
            mask = make_source_mask(left, nsigma=3, npixels=5)
            # clean, com_mask = create_mask.create_mask(sci,left,static_mask(proc)[0],mask,saturation(left.header),binning(proc,'left'),rdnoise(left.header),cr_clean_sigclip(),cr_clean_sigcfrac(),cr_clean_objlim(),log)
            # processed_data.data = clean
            log.info('Calculating 2D background.')
            bkg = Background2D(left, (120, 120),
                               filter_size=(3, 3),
                               sigma_clip=SigmaClip(sigma=3),
                               bkg_estimator=MeanBackground(),
                               mask=mask,
                               exclude_percentile=80)
            log.info('Median background for left image : ' +
                     str(np.median(bkg.background)))
            fits.writeto(sci.replace('/raw/',
                                     '/red/').replace('.fits',
                                                      '_bkg_left.fits'),
                         bkg.background,
                         overwrite=True)
            left = left.subtract(CCDData(bkg.background, unit=u.electron),
                                 propagate_uncertainties=True,
                                 handle_meta='first_found')
            log.info('Exposure time of left image is ' +
                     str(left.header['EXPTIME']))
            left = left.divide(left.header['EXPTIME'] * u.second,
                               propagate_uncertainties=True,
                               handle_meta='first_found')
            log.info(
                'Background subtracted and image divided by exposure time.')
            left.header['DATASEC'] = '[1:1798,1:3694]'
            left.header['RADECSYS'] = 'ICRS'
            left.header['CUNIT1'] = 'deg'
            left.header['CUNIT2'] = 'deg'
            left.header['CTYPE1'] = 'RA---TAN'
            left.header['CTYPE2'] = 'DEC--TAN'
            left.header['CRPIX1'] = 2301
            left.header['CRPIX2'] = 1846
            coord = util.parse_coord(left.header['RA'], left.header['DEC'])
            left.header['CRVAL1'] = coord.ra.deg
            left.header['CRVAL2'] = coord.dec.deg
            left.header['PC1_1'] = -pixscale() / 3600 * np.sin(
                np.pi / 180. * (left.header['POSANG'] + 90))
            left.header['PC1_2'] = pixscale() / 3600 * np.cos(
                np.pi / 180. * (left.header['POSANG'] + 90))
            left.header['PC2_1'] = -pixscale() / 3600 * np.cos(
                np.pi / 180. * (left.header['POSANG'] + 90))
            left.header['PC2_2'] = pixscale() / 3600 * np.sin(
                np.pi / 180. * (left.header['POSANG'] + 90))
            left.write(sci.replace('/raw/',
                                   '/red/').replace('.fits', '_left.fits'),
                       overwrite=True)
            left_list.append(left)
            top_right = np.concatenate(
                [data_list[6], np.fliplr(data_list[7])], axis=1)
            bot_right = np.flipud(
                np.concatenate(
                    [data_list[5], np.fliplr(data_list[4])], axis=1))
            right = CCDData(np.concatenate([top_right, bot_right]),
                            unit=u.electron,
                            header=header_right)
            right = ccdproc.flat_correct(right, flat_right[209:3903,
                                                           1149:2947])
            log.info('Right image proccessed and trimmed.')
            log.info('Cleaning cosmic rays and creating mask.')
            mask = make_source_mask(right, nsigma=3, npixels=5)
            # clean, com_mask = create_mask.create_mask(sci,right,static_mask(proc)[1],mask,saturation(right.header),binning(proc,'right'),rdnoise(right.header),cr_clean_sigclip(),cr_clean_sigcfrac(),cr_clean_objlim(),log)
            # processed_data.data = clean
            log.info('Calculating 2D background.')
            bkg = Background2D(right, (120, 120),
                               filter_size=(3, 3),
                               sigma_clip=SigmaClip(sigma=3),
                               bkg_estimator=MeanBackground(),
                               mask=mask,
                               exclude_percentile=80)
            log.info('Median background for right image : ' +
                     str(np.median(bkg.background)))
            fits.writeto(sci.replace('/raw/',
                                     '/red/').replace('.fits',
                                                      '_bkg_right.fits'),
                         bkg.background,
                         overwrite=True)
            right = right.subtract(CCDData(bkg.background, unit=u.electron),
                                   propagate_uncertainties=True,
                                   handle_meta='first_found')
            log.info('Exposure time of right image is ' +
                     str(right.header['EXPTIME']))
            right = right.divide(right.header['EXPTIME'] * u.second,
                                 propagate_uncertainties=True,
                                 handle_meta='first_found')
            log.info(
                'Background subtracted and image divided by exposure time.')
            right.header['DATASEC'] = '[1:1798,1:3694]'
            right.header['RADECSYS'] = 'ICRS'
            right.header['CUNIT1'] = 'deg'
            right.header['CUNIT2'] = 'deg'
            right.header['CTYPE1'] = 'RA---TAN'
            right.header['CTYPE2'] = 'DEC--TAN'
            right.header['CRPIX1'] = -504
            right.header['CRPIX2'] = 1845
            coord = util.parse_coord(right.header['RA'], right.header['DEC'])
            right.header['CRVAL1'] = coord.ra.deg
            right.header['CRVAL2'] = coord.dec.deg
            right.header['PC1_1'] = -pixscale() / 3600 * np.sin(
                np.pi / 180. * (right.header['POSANG'] + 90))
            right.header['PC1_2'] = pixscale() / 3600 * np.cos(
                np.pi / 180. * (right.header['POSANG'] + 90))
            right.header['PC2_1'] = -pixscale() / 3600 * np.cos(
                np.pi / 180. * (right.header['POSANG'] + 90))
            right.header['PC2_2'] = pixscale() / 3600 * np.sin(
                np.pi / 180. * (right.header['POSANG'] + 90))
            right.write(sci.replace('/raw/',
                                    '/red/').replace('.fits', '_right.fits'),
                        overwrite=True)
            right_list.append(right)
    return [left_list, right_list], None
    def process_imaging_science(self, imaging_group):
        """Does image reduction for science imaging data.

        Args:
            imaging_group (object): :class:`~pandas.DataFrame` instance that contains a
              list of science data that are compatible with a given
              instrument configuration and can be reduced together.


        """
        # pick a random image in order to get a header
        random_image = random.choice(imaging_group.file.tolist())
        path_random_image = os.path.join(self.args.raw_path, random_image)
        sample_file = CCDData.read(path_random_image, unit=u.adu)

        master_flat_name = self.name_master_flats(header=sample_file.header,
                                                  group=imaging_group,
                                                  get=True)

        self.log.debug(
            'Got {:s} for master flat name'.format(master_flat_name))

        master_flat, master_flat_name = get_best_flat(
            flat_name=master_flat_name, path=self.args.red_path)

        if master_flat is not None:
            for image_file in imaging_group.file.tolist():

                # start with an empty prefix
                self.out_prefix = ''

                image_full_path = os.path.join(self.args.raw_path, image_file)
                ccd = read_fits(image_full_path, technique=self.technique)

                # Trim image
                ccd = image_trim(ccd=ccd,
                                 trim_section=self.trim_section,
                                 trim_type='trimsec')
                self.out_prefix = 't_'
                if not self.args.ignore_bias:

                    ccd = ccdproc.subtract_bias(ccd,
                                                self.master_bias,
                                                add_keyword=False)

                    self.out_prefix = 'z' + self.out_prefix

                    ccd.header['GSP_BIAS'] = (os.path.basename(
                        self.master_bias_name), 'Master bias image')

                # apply flat correction
                ccd = ccdproc.flat_correct(ccd, master_flat, add_keyword=False)

                self.out_prefix = 'f' + self.out_prefix

                ccd.header['GSP_FLAT'] = (os.path.basename(master_flat_name),
                                          'Master Flat image')

                if self.args.clean_cosmic:
                    ccd = astroscrappy_lacosmic(
                        ccd=ccd,
                        red_path=self.args.red_path,
                        save_mask=self.args.keep_cosmic_files)

                    self.out_prefix = 'c' + self.out_prefix
                else:
                    print('Clean Cosmic ' + str(self.args.clean_cosmic))

                final_name = os.path.join(self.args.red_path,
                                          self.out_prefix + image_file)
                # ccd.write(final_name, clobber=True)
                write_fits(ccd=ccd, full_path=final_name)
                self.log.info('Created science file: {:s}'.format(final_name))
        else:
            self.log.error('Can not process data without a master flat')
Пример #31
0
def reduce_night(science_collection, dark_collection, flat_collection, config, config_arguments):
    """
    This function reduce science data of one night and save the results to a folder named "reduced". The reduction
    is performed as follows:

        - Create a list of masterdarks (each masterdark has a different value of the exposure time) ^1
        - Create a list of masterflats (each masterflat has a different value of the filter) ^1

        - Reduce the science data as follows:

            *For each filter:
                *For each exposure time with that filter:

                    -- Look for the masterdark with the nearest exposure time
                    -- Look for the masterflat with the current filter.
                    -- Substract masterdark
                    -- Flat field correct the data
                    -- Clean cosmic rays (if requested)
                    -- Save image to ./Calibrated folder

    (1) The master(flat/dark)s are created using mean combine.

    :param science_collection: Numpy array - A numpy array with the science collection data produced by FitsLookup.
    :param dark_collection: Numpy array - A numpy array with the dark collection data produced by FitsLookup.
    :param flat_collection: Numpy array - A numpy array with the flat collection data produced by FitsLookup.
    :param config_values: Dictionary - Dictionary - A dictionary provided by the function get_config_dict that
                            contains the config of the fits files ( readed from conf.INI ).
    :param config_arguments: Dictionary - A dictionary provided by argparse initialization that contain the current flags.
    :return: Integer - 0 if no errors raised 1 if errors raised.
    """

    # Supress astropy warnings

    warnings.filterwarnings('ignore')

    # Renaming some config_arguments for easy acess

    work_dir = config_arguments.dir[0]

    # Get the filter and exposure collection of science and flat images

    science_filter_collection = set(science_collection['filter'])
    science_exposures_collection = set(science_collection['exptime'])
    dark_exposures_collection = set(dark_collection['exptime'])
    flat_filter_collection = set(flat_collection['filter'])

    # Inform the user of the filter / exptime found.
    science_exp_times_as_string = ", ".join(
        [str(x) for x in science_exposures_collection])
    dark_exp_times_as_string = ", ".join(
        [str(x) for x in dark_exposures_collection])
    module_logger.info("We have found {0} filters in the science images: {1}".format(
        len(science_filter_collection), ", ".join(science_filter_collection)))
    module_logger.info("We have found {0} exposure times science images: {1}".format(
        len(science_exposures_collection), science_exp_times_as_string))
    module_logger.info("We have found {0} exposure times dark calibrators: {1}".format(
        len(dark_exposures_collection), dark_exp_times_as_string))
    module_logger.info("We have found {0} filters in the flat calibrators {1}".format(
        len(flat_filter_collection), ", ".join(flat_filter_collection)))

    # Check if we have the same filters in flats and science, if not, get the
    # intersection

    if not science_filter_collection.issubset(flat_filter_collection):

        module_logger.warning(
            "There are more filters in the science images than in the flat calibrators")

        science_filter_collection = science_filter_collection.intersection(
            flat_filter_collection)

        module_logger.warning("Triying to work with common filters.")
        module_logger.info("We have found {0} common filters in the science images: {1}".format(
            len(science_filter_collection), ", ".join(science_filter_collection)))

        if not science_filter_collection:
            module_logger.warning(
                "There are no common filters between science images and flat calibrators")
            module_logger.warning("This night will be skiped.")
            return 1

    # Warn the user if we found science images of 0 seconds

    if 0 in science_exposures_collection:
        number_of_null_images = len(filter_collection(
            science_collection, [('exptime', 0)]))
        module_logger.warning(
            "We have found {0} science images with 0 seconds of exposure time.".format(number_of_null_images))
        science_exposures_collection.discard(0)
        module_logger.warning(
            "Discarding images with 0 seconds of exposure time for this night: {0} exposure(s) remain.".format(
                len(science_exposures_collection)))

    # ------- MASTER DARK CREATION --------

    module_logger.info("Starting the creation of the master dark")
    module_logger.info("{0} different exposures for masterdarks were found.".format(
        len(dark_exposures_collection)))

    master_dark_collection = dict()

    # Loop over each exposure time.
    for dark_exposure_item in dark_exposures_collection:
        module_logger.info("Creating masterdark with exposure of {0}s".format(dark_exposure_item))
        # Initializate dark list for current collection.
        exposure_dark_list = list()

        for dark_image_data in filter_collection(dark_collection, [('exptime', dark_exposure_item)]):
            # Open the images and append to the dark list
            dark_image = dark_image_data['filename']
            ccd = CCDData.read(dark_image, unit=config.image_units)
            # If we have overscan, subtract and trim.
            if config.subtract_overscan:
                if config_arguments.verbose_flag_2:
                    module_logger.info("Subtracting overscan of {0}".format(dark_image))
                ccd = subtract_and_trim_overscan(ccd, config)
            exposure_dark_list.append(ccd)

        # median combine the data
        cb = ccdproc.Combiner(exposure_dark_list)
        master_dark = cb.median_combine(median_func=np.median)

        # Add the masterdark to the master_flat collection
        master_dark_collection.update({dark_exposure_item: master_dark})

        # Save the masterdark if needed.
        if config.save_masterdark:
            # Filename to save
            aux = '{0}/masterdark_{1}.fits'.format(config_arguments.save_path, dark_exposure_item)
            module_logger.info('Saving master dark to {0}'.format(aux))
            master_dark.to_hdu().writeto(aux)

    # ------- MASTER FLAT CREATION --------

    module_logger.info("Starting the creation of the master flats")
    module_logger.info("{0} different filters for masterflats were found".format(
        len(flat_filter_collection)))

    master_flat_collection = dict()

    # Go thought the different filters in the collection

    for flat_filter in flat_filter_collection:

        module_logger.info(
            "Creating masterflat with filter {0}".format(flat_filter))

        # Initializate the list that will carry the flat images of the actual
        # filter

        filter_flat_list = list()

        for flat_image_data in filter_collection(flat_collection, [('filter', flat_filter)]):

            # Open the images and append to the filter's flat list
            flat_image = flat_image_data['filename']
            ccd = CCDData.read(flat_image, unit=config.image_units)
            # Subtract and trim overscan
            if config.subtract_overscan:
                if config_arguments.verbose_flag_2:
                    module_logger.info("Subtracting overscan of {0}".format(flat_image))
                ccd = subtract_and_trim_overscan(ccd, config)
            filter_flat_list.append(ccd)


        # median combine the flats after scaling each by its mean
        cb = ccdproc.Combiner(filter_flat_list)
        cb.scaling = lambda x: 1.0 / np.mean(x)
        master_flat = cb.median_combine(median_func=np.median)

        # Add the masterflat to the master_flat collection

        master_flat_collection.update({flat_filter: master_flat})

        # Save the masterflat if needed.
        if config.save_masterflat:
            aux = '{0}/masterflat_{1}.fits'.format(config_arguments.save_path, flat_filter)
            module_logger.info('Saving master flat to {0}'.format(aux))
            master_flat.to_hdu().writeto(aux)

    # ------- REDUCE SCIENCE DATA --------

    module_logger.info("Starting the calibration of the science images")

    # Go thought the different files in the collection

    for image_filter in science_filter_collection:

        module_logger.info("Now calibrating filter: {0}".format(image_filter))

        # Iterate thought each different exposure. This is because the dark files
        # can have different exposures and the calibration must be performed with
        # the masterdark with the nearest exposure time.
        for science_exposure in science_exposures_collection:

            # Important!! If you have more classifiers in the numpy dtype and you want
            # to use them, you must modify the code here. For example, if you want to
            # use a 'temp' value as classifier, after modify the dtype following the
            # instructions in FitsLookup, you must add a loop here and modify the sub_collection.
            # Once you have the 'temp' in the dtype, you must add a loop here as:
            #
            # >>>for temp_value in  set(science_collection['temp']):
            #        module_logger.info("Now calibrating temp: {0}".format(temp_value))
            #
            # After this, you MUST indent all the following code (of this function) four spaces to
            # the right, of course. Then, you only have to modify the science_subcollection as follows:
            #
            # >>> science_subcollection = filter_collection(
            #    science_collection, [('filter', image_filter),
            #                            ('exptime', science_exposure),
            #                             ('temp', temp_value) ])
            #
            # Follow this steps for every classifier you want to add. Yay!
            # --------------------------------------------------------------

            # Science subcollection is a really bad name, but is descriptive. Remember that this subcollection
            # are the images with the current filter that has the current
            # exposure time. E.g. ('r' and 20', 'r' and 30).
            science_subcollection = filter_collection(
                science_collection, [('filter', image_filter),
                                     ('exptime', science_exposure)])

            # Continue if we have files to process. This will check if for some filter
            # there are not enought images with the actual exposure time.
            if science_subcollection.size:

                module_logger.info(
                    "Now calibrating exposure: {0}".format(science_exposure))

                # Determine if we have a masterdark with the science exposure file.
                #
                #   - If we have a exposure matching masterdark, use it.
                #   - If we do not have a exposure matching masterdark, use the nearest.
                try:
                    selected_masterdark = master_dark_collection[science_exposure]
                    nearest_exposure = 0, science_exposure
                except KeyError:
                    # Get the nearest exoposure in the dark collection.
                    nearest_exposure = min(enumerate(master_dark_collection.keys()),
                                           key=lambda x: abs(x[1] - science_exposure))
                    # Notice that nearest_exposure is a tuple of the form
                    # (index,exposure).
                    selected_masterdark = master_dark_collection[
                        nearest_exposure[1]]

                # Initialize the progress bar variables

                total_len = len(science_subcollection)
                meantime = []

                # Loop for each image with current (filter,exptime).
                for contador, science_image_data_with_current_exposure in enumerate(science_subcollection):

                    # To supress astropy warnings.
                    devnull = open(os.devnull, "w")
                    sys.stdout = devnull

                    # Notice that until sys stdout is reasigned, no printing
                    # will be allowed in the following lines.

                    # Start timing
                    start = time.time()
                    # Extract the filename from the image data
                    science_image = science_image_data_with_current_exposure['filename']
                    # Read the image
                    ccd = CCDData.read(science_image, unit=config.image_units, wcs=None)
                    # Subtract overscan
                    if config.subtract_overscan:
                        if config_arguments.verbose_flag_2:
                            module_logger.info("Subtracting overscan of {0}".format(science_image))
                        ccd = subtract_and_trim_overscan(ccd, config)
                    # Master dark substraction
                    if config_arguments.verbose_flag_2:
                        sys.stdout = sys.__stdout__  # Restart stdout printing
                        module_logger.info("Subtracting dark of image {0} of {1}".format(contador + 1, total_len))
                        sys.stdout = devnull
                    else:
                        module_logger.debug("Subtracting dark of image {0} of {1}".format(contador + 1, total_len))

                    selected_masterdark._wcs = ccd._wcs  # FIXME: currently needed due to bug
                    ccd = ccdproc.subtract_dark(ccd, selected_masterdark, dark_exposure=nearest_exposure[1] * u.second,
                                                data_exposure=science_exposure * u.second)

                    # flat-field correct the data
                    if config_arguments.verbose_flag_2:
                        sys.stdout = sys.__stdout__  # Restart stdout printing
                        module_logger.info("Flat-field correcting image {0} of {1}".format(contador + 1, total_len))
                        sys.stdout = devnull
                    else:
                        module_logger.debug("Flat-field correcting image {0} of {1}".format(contador + 1, total_len))

                    current_master_flat = master_flat_collection[image_filter]
                    current_master_flat._wcs = ccd._wcs  # FIXME: currently needed due to bug
                    ccd = ccdproc.flat_correct(ccd, current_master_flat)

                    # If we need to clean cosmic rays, do it.

                    if config_arguments.cosmic_flag:

                        if config_arguments.verbose_flag_2:
                            sys.stdout = sys.__stdout__  # Restart stdout printing
                            module_logger.info(
                                "Cosmic ray cleaning of image {0} of {1}".format(contador + 1, total_len))
                            sys.stdout = devnull
                        else:
                            module_logger.debug(
                                "Cosmic ray cleaning of image {0} of {1}".format(contador + 1, total_len))

                        ccd = ccdproc.cosmicray_lacosmic(ccd, error_image=None, thresh=5, mbox=11, rbox=11, gbox=5)

                    # Save the calibrated image to a file
                    output_filename = os.path.join(config_arguments.save_path, os.path.basename(science_image))

                    if config_arguments.verbose_flag_2:
                        sys.stdout = sys.__stdout__  # Restart stdout printing
                        module_logger.info(
                            "Saving image {0} of {1} to {2}".format(contador + 1, total_len, output_filename))
                        sys.stdout = devnull
                    else:
                        module_logger.debug(
                            "Saving image {0} of {1} to {2}".format(contador + 1, total_len, output_filename))

                    ccd.write(output_filename, clobber=True)

                    end = time.time()
                    meantime.append(end - start)

                    sys.stdout = sys.__stdout__  # Restart stdout printing


                    # Progressbar in case that we have not activated the no_interaction flag nor the advance
                    # verbose flag.
                    if not config_arguments.no_interaction and not config_arguments.verbose_flag_2:

                        if config_arguments.verbose_flag:
                            update_progress(float(contador + 1) / total_len,
                                            np.mean(meantime) * (total_len - (contador + 1)))

    return 0
Пример #32
0
def correctData(filename, master_bias, master_flat, filetype):
    """
    Correct a science image using the available
    master calibrations. Skip a calibration step if the
    master frame does not exist.

    No reduced file is written in this new scheme.
    Instead, the corrected data is passed directly
    to the phot() routine, photometry is done as per
    the configuration and the photometry is written out
    only.

    TODO: Finish docstring
    """
    print('Reducing {0:s}...'.format(filename))
    with fits.open(filename) as fitsfile:
        # correct times for science spectra,
        # don't bother for arcs
        hdr = fitsfile[0].header
        if filetype == 'science':
            half_exptime = hdr[EXPTIME_KEYWORD]/2.
            utstart = hdr[UTSTART_KEYWORD]
            dateobs = hdr[DATEOBS_KEYWORD]
            ra = hdr[RA_KEYWORD]
            dec = hdr[DEC_KEYWORD]
            time_start = Time('{}T{}'.format(dateobs, utstart),
                              scale='utc',
                              format='isot',
                              location=OBSERVATORY)
            # correct to mid exposure time
            jd_mid = time_start + half_exptime*u.second
            ltt_bary, ltt_helio = getLightTravelTimes(ra, dec, jd_mid)
            time_bary = jd_mid.tdb + ltt_bary
            time_helio = jd_mid.utc + ltt_helio
            hdr['BJD-MID'] = time_bary.jd
            hdr['HJD-MID'] = time_helio.jd
            hdr['JD-MID'] = jd_mid.jd
            hdr['UT-MID'] = jd_mid.isot
    ccd = CCDData.read(filename, unit=u.adu)
    if master_bias:
        ccd = subtract_bias(ccd, master_bias)
    else:
        print('No master bias, skipping correction...')
    if master_flat:
        ccd = flat_correct(ccd, master_flat)
    else:
        print('No master flat, skipping correction...')
    # after calibrating we get np.float64 data
    # if there are no calibrations we maintain dtype = np.uint16
    # sep weeps
    # fix this by doing the following
    if isinstance(ccd.data[0][0], np.uint16):
        ccd.data = ccd.data.astype(np.float64)
    # trim the data
    ccd_trimmed = trim_image(ccd[1000:3001, :])
    # write out the trimmed file and the updated header
    #ccd_trimmed.write(filename, hdr, clobber=True)
    trimmed_filename = '{}_t.fits'.format(filename.split('.')[0])
    fits.writeto(trimmed_filename, ccd_trimmed.data, hdr)
    # remove the old untrimmed data
    os.system('rm {}'.format(filename))
Пример #33
0
from os import listdir

bias_hdu = ccdproc.CCDData.read('data_bias/master_bias.fits', unit='adu',)
flat_hdu_i = ccdproc.CCDData.read('data_flat/i/master_flat.fits', unit='adu')
flat_hdu_v = ccdproc.CCDData.read('data_flat/v/master_flat.fits', unit='adu')


print "Now cleaning I"
#Band I
subtracted_flat_i = flat_hdu_i
names_i = listdir('./data_obj/i/')
images_i = [ccdproc.CCDData.read('data_obj/i/'+i, unit='adu') for i in listdir('./data_obj/i')]

for i in range(len(names_i)):
	subt_obj = ccdproc.subtract_bias(images_i[i], bias_hdu)
	corr_obj = ccdproc.flat_correct(subt_obj, subtracted_flat_i, min_value=0.000000001)
	corr_obj.write('./data_corr/i/'+names_i[i])
	subt_obj.write('./data_biascorr/i/'+names_i[i])


print "Now cleaning V"
#Band V
subtracted_flat_v = flat_hdu_v
names_v = listdir('./data_obj/v/')
images_v = [ccdproc.CCDData.read('data_obj/v/'+i, unit='adu') for i in listdir('./data_obj/v')]


for i in range(len(names_v)):
	subt_obj = ccdproc.subtract_bias(images_v[i], bias_hdu)
	corr_obj = ccdproc.flat_correct(subt_obj, subtracted_flat_v, min_value=0.000000001)
	corr_obj.write('./data_corr/v/'+names_v[i])
Пример #34
0
        outpath = os.path.join(preprocessedpath, 'bias_master.fits')
        saveCCDDataAndLog(outpath, biasmaster)
    else:
        for adarkexp in darkexp_set:
            outpath = os.path.join(preprocessedpath, \
                                'dark_master_' + str(adarkexp) + 's.fits')
            saveCCDDataAndLog(outpath, darklists[adarkexp])
    outpath = os.path.join(preprocessedpath, 'flat_master.fits')
    saveCCDDataAndLog(outpath, flatmaster)

    for ascience in sciencelist:
        try:
            sci_image = ccdproc.CCDData.read(ascience, unit='adu')
            if args.usebias:
                sci_biassub = ccdproc.subtract_bias(sci_image, biasmaster)
                sci_flatcorrected = ccdproc.flat_correct(sci_biassub, flatmaster)
            else:
                exp_time = fits.getval(ascience, 'exptime')
                darkmaster = chooseClosestDark(darklists, exp_time)
                sci_darksub = ccdproc.subtract_dark(sci_image, darkmaster, \
                    exposure_time='exptime', exposure_unit=u.second)
                sci_flatcorrected = ccdproc.flat_correct(sci_darksub, flatmaster)
        except:
            logger.error("Couldn't reduce image %s." % (ascience))
            continue
        outpath = os.path.join(preprocessedpath, \
                 'preprocessed_' + os.path.basename(ascience))

        #deadpixmaskfilename = "../stackImages/deadpix.fits"
        deadpixmaskfilename = None
Пример #35
0
def preprocess(fits_path):
    """Apply basic CCD reduction tasks.

    Ask for the path to all the calibration and science files, and perform Bias, Dark and Flat combinations and proper substractions.

    Pipeline que aplica una reduccion basica a imagenes de tipo CCD.
    Realiza combinacion de Bias, de Darks, y Flats. Luego realiza las restas inherentes.
    """
    import os
    import sys
    from image_collection import ImageFileCollection

    #Collect all FITS files in path in fitslist
    fitslist = []
    for root, dirs, files in os.walk(fits_path, topdown=True):
        fitslist.extend(
            [os.path.join(root, name) for name in files if '.fit' in name])

    #Dictionary with the image type (value) for each image file name (key)
    imagetypes = {img: fits.getval(img, 'IMAGETYP') for img in fitslist}

    #Make different lists for different image types
    biaslist = []
    sciencelist = []
    flatlist = []
    darklist = []
    unknown = []
    for k, v in imagetypes.iteritems():
        if 'LIGHT' in v.upper() or v.upper() == 'OBJECT':
            sciencelist.append(k)
        elif 'BIAS' in v.upper() or v.upper() == 'ZERO':
            biaslist.append(k)
        elif 'FLAT' in v.upper():
            flatlist.append(k)
        elif 'DARK' in v.upper():
            darklist.append(k)
        else:
            unknown.append(k)

    #Create the flat master
    if darklist:
        darkmaster = combineDarks(darklist_flat)
        flatmaster = combineFlats(flatlist, dark=darkmaster)
    elif biaslist:
        biasmaster = combineBias(biaslist)
        flatmaster = combineFlats(flatlist, bias=biasmaster)
    else:
        flatmaster = combineFlats(flatlist)

    for ascience in sciencelist:
        sci_image = ccdproc.CCDData.read(ascience, unit='adu')
        sci_darksub = ccdproc.subtract_dark(sci_image,
                                            darkmaster,
                                            exposure_time='exptime',
                                            exposure_unit=u.second)
        sci_flatcorrected = ccdproc.flat_correct(sci_darksub, flatmaster)
        outpath = os.path.join('/Users/utb/Desktop/reduced/',
                               'reduced_' + os.path.basename(ascience))
        hdulist = sci_flatcorrected.to_hdu()
        hdulist.writeto(outpath, clobber=True)

    return
Пример #36
0
def clean_the_images(path, filename):
    #ast=AstrometryNet()
    #ast.api_key= 'iqmqwvazpvolmjmn'
    dir = path
    gain = 2 * u.electron / u.adu
    readnoise = 7.5 * u.electron
    ra = input('Enter the RA of the source:   ')
    dec = input('Enter the DEC of the source: ')
    '''
    wcs_header=ast.solve_from_image(path+filename)
    wcs=WCS(wcs_header)
    ran,decn=wcs.all_pix2world(1024,1024,0)
    print(ran,decn)
    '''
    file_name = os.path.join(dir, filename)
    image = ccdproc.CCDData.read(file_name, unit='adu')
    header = fits.getheader(file_name, 0)

    time = header['DATE']
    t = Time(time, format='isot', scale='utc')
    print(t.jd, t.mjd)
    header.insert(15, ('RA', ra))
    header.insert(16, ('DEC', dec))

    a = sorted(glob(os.path.join(dir, 'bias*.fits')))
    biaslist = []
    for i in range(0, len(a)):
        data = ccdproc.CCDData.read(a[i], unit='adu')
        #data = ccdproc.create_deviation(data, gain=gain, readnoise=readnoise)
        #data= data-(data.uncertainty.array)
        biaslist.append(data)
    combiner = ccdproc.Combiner(biaslist)
    masterbias = combiner.median_combine()
    masterbias.write('masterbias.fit', overwrite=True)
    mbias = ccdproc.CCDData.read('masterbias.fit', unit='adu')
    #masterbias.meta=image.meta
    print('master bias generated')
    print(np.mean(masterbias), np.median(masterbias))

    c = sorted(glob(os.path.join(dir, 'flat*.fits')))
    flatlist = []
    for j in range(0, len(c)):
        flat = ccdproc.CCDData.read(c[j], unit='adu')
        #flat= ccdproc.create_deviation(flat, gain=gain, readnoise=readnoise)
        flat = ccdproc.subtract_bias(flat, masterbias)
        flatlist.append(flat)
    combiner = ccdproc.Combiner(flatlist)
    masterflat = combiner.median_combine()
    masterflat.write('masterflat.fits', overwrite=True)
    mflat = ccdproc.CCDData.read('masterflat.fits', unit='adu')
    print('master flat generated')
    print(np.mean(masterflat), np.median(masterflat))

    #masterflat.meta=image.meta

    bias_subtracted = ccdproc.subtract_bias(image, masterbias)
    flat_corrected = ccdproc.flat_correct(bias_subtracted, masterflat)
    cr_cleaned = ccdproc.cosmicray_lacosmic(flat_corrected,
                                            readnoise=7.5,
                                            sigclip=5)
    print('cosmic ray removed')

    fits.writeto(dir + 'j_0947_i_1_clean.fits',
                 cr_cleaned,
                 header,
                 overwrite=True)

    print('image cleaned')
Пример #37
0
    for image, imname in mastercollection.ccds(imtype='subflat',return_fname=True):
        trimage=ccdp.trim_image(image,fits_section=str(sciwin))
        trimage.meta['trimwind']=(str(sciwin),'readout window')
        trimage.meta['imtype'] = ('mflat', 'windowed master flat')
        trimage.write(path+imname,overwrite=True)

tmastercollection=ImageFileCollection(cmpath)


'''check shape'''
#check shape
# print(sci.data.shape)
# for master in tmastercollection.ccds():
#     print(master.data.shape)


crop_masters()


for mbias, mbiasn in tmastercollection.ccds(imtype='mbias', combined='sigma_clip average',return_fname=True):
    print('using',mbiasn)
    for mflat, mflatn in tmastercollection.ccds(imtype='mflat', flatcom='sigma', return_fname=True):
        print('using', mflatn)
        start = time.time()
        for sci, scin in sciencecollection.ccds(return_fname=True, ccd_kwargs={'unit': 'adu'}):
            print('correcting',scin)
            subsci=ccdp.subtract_bias(sci,mbias,add_keyword={'subsci':'sigmbias'})
            corsci=ccdp.flat_correct(subsci,mflat,norm_value=float(mflat.header['normmed']))
            corsci.write(cspath+scin,overwrite=True)

print (time.time()-start)
Пример #38
0
    os.remove(f)
 
#get a list of all FITS files in the input directory
fits_files=glob.glob(input_path+'*.fits')+glob.glob(input_path+'*.fit')
#loop through all qualifying files and perform plate-solving
logme('Calibrating images in %s' %input_path)
for fits_file in fits_files:   
    #open image
    image = ccdproc.CCDData.read(fits_file, unit='adu', relax=True)
    #trim it, if necessary 
    if(len(trim_range) > 0):
        image = ccdproc.trim_image(image, trim_range);
    #subtract bias from light, dark, and flat frames    
    image = ccdproc.subtract_bias(image, bias, add_keyword=False)
    image = ccdproc.subtract_dark(image, dark, scale=True, exposure_time=exposure_label, exposure_unit=u.second, add_keyword=False)
    image = ccdproc.flat_correct(image, flat, add_keyword=False)    
    #save calibrated image
    output_file = "%s"%(fits_file.rsplit('.',1)[0])+output_suffix+".fits"
    output_file = output_file.rsplit('/',1)[1]
    output_file = output_path+output_file
    #scale calibrated image back to int16, some FITS programs don't like float    
    hdulist = image.to_hdu()
    #bzero has to be non-zero, use int32 to handle negative values effectively
    #hdulist[0].scale('int32', bzero=1)
    hdulist[0].scale('int16', bzero=32768)    
    hdulist[0].header['BIASCORR'] = bias_master
    hdulist[0].header['DARKCORR'] = dark_master        
    hdulist[0].header['FLATCORR'] = flat_master
    if(len(trim_range) > 0):
        hdulist[0].header['NAXIS1'] = '%d'%((naxis1_end-naxis1_start))
        hdulist[0].header['NAXIS2'] = '%d'%((naxis2_end-naxis2_start))        
Пример #39
0
def calibrate_images(
    x_d,
    x_f,
    x_s,
    it_s='object',
    x_b='',
):
    """
	Parameters
	----------
	----------
	x_b : str
		Path of the bias files.
		By default bias is not provided
	x_d : str
		Path of the dark files
	x_f : str
		Path of flat files
	x_s : str
		Path of Science files
	it_s : str
		Imagetyp of fits science file
		Default is set to object
	-----------
	"""
    path_b = Path(x_b)
    path_d = Path(x_d)
    path_f = Path(x_f)
    path_s = Path(x_s)

    #-----Bias
    if x_b == '' and path_b == Path(''):
        print(
            'Be aware: You did not provide the Bias files; the process will still continue though.'
        )
        files_b = None
    elif not path_b.is_dir():
        raise RuntimeError(
            'The path you provided for the Bias files does not exist.')
    else:
        files_b = ccdp.ImageFileCollection(path_b)
    #-----Dark
    if x_d == '' or not path_d.is_dir():
        raise RuntimeError(
            'You must provide Dark files for processing.\n Or the path you provided does not exist.'
        )
    else:
        files_d = ccdp.ImageFileCollection(path_d)
    #-----Flat
    if x_f == '' or not path_f.is_dir():
        raise RuntimeError(
            'You must provide Flatfield files for processing.\n Or the path you provided does not exist.'
        )
    else:
        files_f = ccdp.ImageFileCollection(path_f)
    #-----Science
    if x_s == '' or not path_s.is_dir():
        raise RuntimeError(
            'You must provide Science images for processing.\n Or the path you provided does not exist.'
        )
    else:
        files_s = ccdp.ImageFileCollection(path_s)

    #-----------------------------------
    #
    #--------Calibrating Images---------
    #
    #-----------------------------------

    if files_b is not None:
        #-------------------------------
        #------Creating Master-bias-----
        #-------------------------------
        cali_bias_path = Path(path_b / 'cali_bias')
        cali_bias_path.mkdir(exist_ok=True)
        files_b_cali = files_b.files_filtered(imagetyp='bias',
                                              include_path=True)
        combined_bias = ccdp.combine(files_b_cali,\
            method='average',\
            sigma_clip=True,\
            sigma_clip_low_thresh=5,\
            sigma_clip_high_thresh=5,\
            sigma_clip_func=np.ma.median,\
            sigma_clip_dev_func=mad_std,\
            mem_limit=350e6)
        combined_bias.meta['combined'] = True
        combined_bias.write(cali_bias_path / 'master_bias.fits')
        # Reading master bias
        master_bias = CCDData.read(cali_bias_path / 'master_bias.fits')
    else:
        master_bias = None

    #-------------------------------
    #-------Calibrating Darks-------
    #-------------------------------
    cali_dark_path = Path(path_d / 'cali_dark')
    cali_dark_path.mkdir(exist_ok=True)
    files_d_cali = files_d.files_filtered(imagetyp='DARK', include_path=True)
    for ccd, file_name in files_d.ccds(imagetyp='DARK',
                                       return_fname=True,
                                       ccd_kwargs={'unit': 'adu'}):
        if master_bias is not None:
            # Subtract bias
            ccd = ccdp.subtract_bias(ccd, master_bias)
        else:
            ccd = ccd
        # Save the result
        ccd.write(cali_dark_path / file_name)

    #--------------------------------
    #------Creating Master-Dark------
    #--------------------------------
    red_dark = ccdp.ImageFileCollection(cali_dark_path)
    # Calculating exposure times of DARK images
    dark_times = set(
        red_dark.summary['exptime'][red_dark.summary['imagetyp'] == 'DARK'])
    for exposure in sorted(dark_times):
        cali_darks = red_dark.files_filtered(imagetyp = 'dark',\
             exptime = exposure,\
             include_path = True)
        combined_dark = ccdp.combine(cali_darks,\
            method='average',\
            sigma_clip=True,\
            sigma_clip_low_thresh=5,\
            sigma_clip_high_thresh=5,\
            sigma_clip_func=np.ma.median,\
            sigma_clip_dev_func=mad_std,\
            mem_limit=350e6)
        combined_dark.meta['combined'] = True
        com_dark_name = 'combined_dark_{:6.3f}.fits'.format(exposure)
        combined_dark.write(cali_dark_path / com_dark_name)
    # Reading master dark of various exposure times
    red_dark = ccdp.ImageFileCollection(cali_dark_path)
    combined_darks = {
        ccd.header['exptime']: ccd
        for ccd in red_dark.ccds(imagetyp='DARK', combined=True)
    }

    #--------------------------------
    #-------Calibrating Flats--------
    #--------------------------------
    cali_flat_path = Path(path_f / 'cali_flat')
    cali_flat_path.mkdir(exist_ok=True)
    files_f_cali = files_f.files_filtered(imagetyp='FLAT', include_path=True)
    for ccd, file_name in files_f.ccds(imagetyp='FLAT',
                                       ccd_kwargs={'unit': 'adu'},
                                       return_fname=True):
        # Subtract bias
        if master_bias is not None:
            ccd = ccdp.subtract_bias(ccd, master_bias)
        else:
            ccd = ccd
        closest_dark = utl.find_nearest_dark_exposure(ccd, dark_times)
        if closest_dark is None:
            closest_dark1 = utl.find_nearest_dark_exposure(ccd,
                                                           dark_times,
                                                           tolerance=100)
            # Subtract scaled Dark
            ccd = ccdp.subtract_dark(ccd, combined_darks[closest_dark1],\
                exposure_time = 'exptime',\
                exposure_unit = u.second,\
                scale = True)
            ccd.write(cali_flat_path / ('flat-' + file_name))
        else:
            closest_dark2 = utl.find_nearest_dark_exposure(ccd, dark_times)
            # Subtracting Darks
            ccd = ccdp.subtract_dark(ccd,
                                     combined_darks[closest_dark2],
                                     exposure_time='exptime',
                                     exposure_unit=u.second)
            ccd.write(cali_flat_path / ('flat-' + file_name))

    #--------------------------------
    #-----Creating Master-Flat-------
    #--------------------------------
    red_flats = ccdp.ImageFileCollection(cali_flat_path)
    cali_flats = red_flats.files_filtered(imagetyp='FLAT', include_path=True)
    combined_flat = ccdp.combine(cali_flats,\
        method='average',\
        scale = utl.inverse_median,\
        sigma_clip=True,\
        sigma_clip_low_thresh=5,\
        sigma_clip_high_thresh=5,\
        sigma_clip_func=np.ma.median,\
        sigma_clip_dev_func=mad_std,\
        mem_limit=350e6)
    combined_flat.meta['combined'] = True
    combined_flat.write(cali_flat_path / 'master_flat.fits')
    # Reading master flat
    red_flats = ccdp.ImageFileCollection(cali_flat_path)
    combined_flat = CCDData.read(cali_flat_path / 'master_flat.fits')

    #--------------------------------
    #---Calibrating Science Images---
    #--------------------------------

    # Creating a list of spectrum images
    files_spec = files_s.summary['file', 'view_pos']
    files_spec_list = np.array([])
    for i in range(len(files_spec)):
        xxx = files_spec['view_pos'][i]
        if xxx[0:4] == 'open':
            files_spec_list = np.hstack(
                (files_spec_list, files_spec['file'][i]))

    # Sky subtracting images
    cali_science_path1 = Path(path_s / 'Sky_subtracted_science')
    cali_science_path1.mkdir(exist_ok=True)
    j = 0
    for i in range(int(len(files_spec_list) / 2)):
        ccd1 = CCDData.read(x_s + files_spec_list[j], unit='adu')
        ccd2 = CCDData.read(x_s + files_spec_list[j + 1], unit='adu')
        sky_sub1 = ccd1.data - ccd2.data
        ss1 = CCDData(sky_sub1, unit='adu')
        ss1.header = ccd1.header
        ss1.meta['sky_sub'] = True
        name1 = 'sky_sub_' + files_spec_list[j]
        ss1.write(cali_science_path1 / name1)
        sky_sub2 = ccd2.data - ccd1.data
        ss2 = CCDData(sky_sub2, unit='adu')
        ss2.header = ccd2.header
        ss2.meta['sky_sub'] = True
        name2 = 'sky_sub_' + files_spec_list[j + 1]
        ss2.write(cali_science_path1 / name2)
        j = j + 2

    files_s1 = ccdp.ImageFileCollection(cali_science_path1)
    final_calibrated = Path(path_s / 'Final_calibrated_science')
    final_calibrated.mkdir(exist_ok=True)

    # Correcting for flat
    for ccd, file_name in files_s1.ccds(imagetyp=it_s,
                                        ccd_kwargs={'unit': 'adu'},
                                        return_fname=True):
        # Subtract scaled Dark
        ccd = ccdp.flat_correct(ccd, combined_flat)  #['FLAT'])
        ccd.write(final_calibrated / file_name)
Пример #40
0
def bdf_process(ccd,
                output=None,
                mbiaspath=None,
                mdarkpath=None,
                mflatpath=None,
                fits_section=None,
                calc_err=False,
                unit='adu',
                gain=None,
                rdnoise=None,
                gain_key="GAIN",
                rdnoise_key="RDNOISE",
                gain_unit=u.electron / u.adu,
                rdnoise_unit=u.electron,
                dark_exposure=None,
                data_exposure=None,
                exposure_key="EXPTIME",
                exposure_unit=u.s,
                dark_scale=False,
                min_value=None,
                norm_value=None,
                verbose=True,
                output_verify='fix',
                overwrite=True,
                dtype="float32"):
    ''' Do bias, dark and flat process.
    Parameters
    ----------
    ccd: array-like
        The ccd to be processed.
    output: path-like
        Saving directory
    '''

    proc = CCDData(ccd)
    hdr_new = proc.header

    if mbiaspath is None:
        do_bias = False
        # mbias = CCDData(np.zeros_like(ccd), unit=unit)
    else:
        do_bias = True
        mbias = CCDData.read(mbiaspath, unit=unit)
        hdr_new.add_history(f"Bias subtracted using {mbiaspath}")

    if mdarkpath is None:
        do_dark = False
        mdark = None
    else:
        do_dark = True
        mdark = CCDData.read(mdarkpath, unit=unit)
        hdr_new.add_history(f"Dark subtracted using {mdarkpath}")
        if dark_scale:
            hdr_new.add_history(
                f"Dark scaling {dark_scale} using {exposure_key}")

    if mflatpath is None:
        do_flat = False
        # mflat = CCDData(np.ones_like(ccd), unit=unit)
    else:
        do_flat = True
        mflat = CCDData.read(mflatpath)
        hdr_new.add_history(f"Flat corrected using {mflatpath}")

    if fits_section is not None:
        proc = trim_image(proc, fits_section)
        mbias = trim_image(mbias, fits_section)
        mdark = trim_image(mdark, fits_section)
        mflat = trim_image(mflat, fits_section)
        hdr_new.add_history(f"Trim by FITS section {fits_section}")

    if do_bias:
        proc = subtract_bias(proc, mbias)

    if do_dark:
        proc = subtract_dark(proc,
                             mdark,
                             dark_exposure=dark_exposure,
                             data_exposure=data_exposure,
                             exposure_time=exposure_key,
                             exposure_unit=exposure_unit,
                             scale=dark_scale)
        # if calc_err and verbose:
        #     if mdark.uncertainty is not None:
        #         print("Dark has uncertainty frame: Propagate in arithmetics.")
        #     else:
        #         print("Dark does NOT have uncertainty frame")

    if calc_err:
        if gain is None:
            gain = fu.get_from_header(hdr_new,
                                      gain_key,
                                      unit=gain_unit,
                                      verbose=verbose,
                                      default=1.).value

        if rdnoise is None:
            rdnoise = fu.get_from_header(hdr_new,
                                         rdnoise_key,
                                         unit=rdnoise_unit,
                                         verbose=verbose,
                                         default=0.).value

        err = fu.make_errmap(proc, gain_epadu=gain, subtracted_dark=mdark)

        proc.uncertainty = StdDevUncertainty(err)
        errstr = (f"Error calculated using gain = {gain:.3f} [e/ADU] and " +
                  f"rdnoise = {rdnoise:.3f} [e].")
        hdr_new.add_history(errstr)

    if do_flat:
        if calc_err:
            if (mflat.uncertainty is not None) and verbose:
                print("Flat has uncertainty frame: Propagate in arithmetics.")
                hdr_new.add_history(
                    "Flat had uncertainty and is also propagated.")

        proc = flat_correct(proc,
                            mflat,
                            min_value=min_value,
                            norm_value=norm_value)

    proc = fu.CCDData_astype(proc, dtype=dtype)
    proc.header = hdr_new

    if output is not None:
        proc.write(output, output_verify=output_verify, overwrite=overwrite)

    return proc
Пример #41
0
    def process_imaging_science(self, imaging_group):
        """Does image reduction for science imaging data.

        Args:
            imaging_group (object): :class:`~pandas.DataFrame` instance that contains a
              list of science data that are compatible with a given
              instrument configuration and can be reduced together.


        """
        # pick a random image in order to get a header
        random_image = random.choice(imaging_group.file.tolist())
        path_random_image = os.path.join(self.args.raw_path, random_image)
        sample_file = CCDData.read(path_random_image, unit=u.adu)

        master_flat_name = self.name_master_flats(header=sample_file.header,
                                                  group=imaging_group,
                                                  get=True)

        self.log.debug('Got {:s} for master flat name'.format(master_flat_name))

        master_flat, master_flat_name = get_best_flat(
            flat_name=master_flat_name,
            path=self.args.red_path)

        if master_flat is not None:
            for image_file in imaging_group.file.tolist():

                # start with an empty prefix
                self.out_prefix = ''

                image_full_path = os.path.join(self.args.raw_path, image_file)
                ccd = read_fits(image_full_path, technique=self.technique)

                # Trim image
                ccd = image_trim(ccd=ccd,
                                 trim_section=self.trim_section,
                                 trim_type='trimsec')
                self.out_prefix = 't_'
                if not self.args.ignore_bias:

                    ccd = ccdproc.subtract_bias(ccd,
                                                self.master_bias,
                                                add_keyword=False)

                    self.out_prefix = 'z' + self.out_prefix

                    ccd.header['GSP_BIAS'] = (
                        os.path.basename(self.master_bias_name),
                        'Master bias image')

                # apply flat correction
                ccd = ccdproc.flat_correct(ccd,
                                           master_flat,
                                           add_keyword=False)

                self.out_prefix = 'f' + self.out_prefix

                ccd.header['GSP_FLAT'] = (
                    os.path.basename(master_flat_name),
                    'Master Flat image')

                if self.args.clean_cosmic:
                    ccd = astroscrappy_lacosmic(
                        ccd=ccd,
                        red_path=self.args.red_path,
                        save_mask=self.args.keep_cosmic_files)

                    self.out_prefix = 'c' + self.out_prefix
                else:
                    print('Clean Cosmic ' + str(self.args.clean_cosmic))

                final_name = os.path.join(self.args.red_path,
                                          self.out_prefix + image_file)
                # ccd.write(final_name, clobber=True)
                write_fits(ccd=ccd, full_path=final_name)
                self.log.info('Created science file: {:s}'.format(final_name))
        else:
            self.log.error('Can not process data without a master flat')