示例#1
0
def makeTelluricCorrection(
    telluricDirectory, path, continuuminter, hlineinter, tempInter, hline_method="vega", spectemp="",
    mag="", log="test.log", over=False):
    """FLUX CALIBRATION
    Consists of this start function and six required functions at the end of
    this file.
    """
    """iraf.gemini(_doprint=0, motd="no")
    iraf.gnirs(_doprint=0)
    iraf.imutil(_doprint=0)
    iraf.onedspec(_doprint=0)
    iraf.nsheaders('nifs',Stdout='/dev/null')"""
    # Overview of Telluric Correction procedure:
    # We make a telluric correction by:
    # Remove H-lines from combined 1D standard star spectrum.
    # Divide by H-line corrected standard spectrum by continuum fit.
    # We apply a telluric correction by:
    # Dividing the cube by the correction spectrum (with iraf.telluric) to figure out the shift and scaling.
    # Dividing again by the continuum to add a continuum shape back in.
    # Telluric correction done.


    # Overview of flux calibration procedure:
    # Make a blackbody spectrum.
    # Scale to the observed magnitude of the standard.
    # Multiply telluric corrected target spectrum by this scaled blackbody.
    # Done!
    iraffunctions.chdir(telluricDirectory)

    logging.info('I am starting to create telluric correction spectrum and blackbody spectrum')
    logging.info('I am starting to create telluric correction spectrum and blackbody spectrum ')

    # Open the combine extracted 1d spectrum.
    try:
        combined_extracted_1d_spectra = str(open('telluricfile', 'r').readlines()[0]).strip()
    except:
        logging.info("No telluricfile found in " + str(telluricDirectory) + "Skipping telluric correction and flux calibration.")
        return
    if not os.path.exists('scienceMatchedTellsList'):
        logging.info("No scienceMatchedTellsList found in " + str(telluricDirectory))
        return
    telheader = astropy.io.fits.open(combined_extracted_1d_spectra+'.fits')
    grating = telheader[0].header['GRATING'][0]

    # Get standard star spectral type, teff, and magnitude from the interwebs. Go forth, brave parser!
    getStandardInfo(path, mag, grating, spectemp)

    hLineCorrection(combined_extracted_1d_spectra, grating, path, hlineinter, tempInter, hline_method, log, over)

    # Fit a continuum from the standard star spectrum, saving both continuum and continuum divided standard spectrum.
    fitContinuum(continuuminter, tempInter, grating)
    # Divide the standard star spectrum by the continuum to normalize it.
    if os.path.exists("telluricCorrection.fits"):
        os.remove("telluricCorrection.fits")
    iraf.imarith('final_tel_no_hlines_no_norm', "/", 'fit', result='telluricCorrection',title='',divzero=0.0,hparams='',pixtype='',calctype='',verbose='no',noact='no',mode='al')
示例#2
0
def finalMergeCubes(mergeType, over):
    """
    Merge final merged cubes from all observations.
    """
    # Load data from the previous step.
    path = os.getcwd()
    with open('mergedInfo.txt') as data_file:
        mergedData = json.load(data_file)
    mergedCubes = mergedData['mergedCubes']
    Merged = mergedData['Merged']

    if len(mergedCubes)>1:
        os.chdir(Merged)
        iraffunctions.chdir(Merged)
        gratlist = []
        for i in range(len(mergedCubes)):
            cubeheader = astropy.io.fits.open(mergedCubes[i])
            grat = cubeheader[0].header['GRATING']
            gratlist.append(grat)
        print "gratlist is: ", gratlist
        # TODO(nat): right now we do more final merges here than we have to. Eg, if there are three H
        # grating directories in gratlist, we will do a final merge three times. We should only be doing this once!
        # Right now it is only a problem when overwrite is turned on but it should still be fixed.
        for n in range(len(gratlist)): # For each unique grating
            # Grab the indices of the cubes associated with that grating.
            indices = [k for k, x in enumerate(gratlist) if x==gratlist[n]]
            newcubelist = []
            for ind in indices:
                newcubelist.append(mergedCubes[ind])
            print newcubelist
            # Do some housekeeping before the final cube merging.
            resizeAndCenterCubes(newcubelist, over)
            makeWavelengthOffsets(newcubelist, grat)
            for i in range(len(newcubelist)):
                # Build an input string containing all the cubes to combine.
                if i==0:
                    inputstring = newcubelist[i]+'[1]'
                else:
                    inputstring += ','+newcubelist[i]+'[1]'
            if os.path.exists('temp_merged'+gratlist[n][0]+'.fits'):
                if over:
                    iraf.delete('temp_merged'+gratlist[n][0]+'.fits')
                    iraf.imcombine(inputstring, output = 'temp_merged'+gratlist[n][0]+'.fits', combine = mergeType, offsets = 'waveoffsets'+grat[0]+'.txt')
                    iraf.fxcopy(input=newcubelist[0]+'[0], temp_merged'+gratlist[n][0]+'.fits', output = 'TOTAL_merged'+gratlist[0][0]+'.fits')
                else:
                    logging.info('Output exists and -over- not set - skipping final cube merge')
            else:
                iraf.imcombine(inputstring, output = 'temp_merged'+gratlist[n][0]+'.fits', combine = mergeType, offsets = 'waveoffsets'+grat[0]+'.txt')
                iraf.fxcopy(input=newcubelist[0]+'[0], temp_merged'+gratlist[n][0]+'.fits', output = 'TOTAL_merged'+gratlist[n][0]+'.fits')
    os.chdir(path)
示例#3
0
def start(kind, telluricDirectoryList="", scienceDirectoryList=""):
    """

    start(kind): Do a full reduction of either Science or Telluric data.

    nifsReduce- for the telluric and science data reduction.

    Reduces NIFS telluric and science frames and attempts a flux calibration.

    Parameters are loaded from runtimeData/config.cfg. This script will
    automatically detect if it is being run on telluric data or science data.

    There are 6 steps.

    INPUT:
    + Raw files
        - Science frames
        - Sky frames
    + Calibration files
        - MDF shift file
        - Bad Pixel Mask (BPM)
        - Flat field frame
        - Reduced arc frame
        - Reduced ronchi mask frame
        - arc and ronchi database/ files

    OUTPUT:
        - If telluric reduction an efficiency spectrum used to telluric correct and absolute flux
          calibrate science frames
        - If science reduction a reduced science data cube.

    Args:
        kind (string): either 'Telluric' or 'Science'.
        telluricDirectoryList (string): Used by low memory pipeline.
        scienceDirectoryList (string): Used by low memory pipeline.

    """

    # TODO(nat): Right now the pipeline will crash if you decide to skip, say, doing a bad
    # pixel correction. This is because each step adds a prefix to the frame name, and most following
    # steps depend on that prefix being there.
    # One way to fix this is if a step is to be skipped, iraf.copy() is called instead to copy the frame and
    # add the needed prefix. Messy but it might work for now.

    ###########################################################################
    ##                                                                       ##
    ##                  BEGIN - GENERAL REDUCTION SETUP                      ##
    ##                                                                       ##
    ###########################################################################

    # Store current working directory for later use.
    path = os.getcwd()

    # Set up the logging file.
    log = os.getcwd() + '/Nifty.log'

    logging.info('\n#################################################')
    logging.info('#                                               #')
    logging.info('# Start the NIFS Science and Telluric Reduction #')
    logging.info('#                                               #')
    logging.info('#################################################\n')

    # Set up/prepare IRAF.
    iraf.gemini()
    iraf.gemtools()
    iraf.gnirs()
    iraf.nifs()

    # Reset to default parameters the used IRAF tasks.
    iraf.unlearn(iraf.gemini, iraf.gemtools, iraf.gnirs, iraf.nifs,
                 iraf.imcopy)

    # From http://bishop.astro.pomona.edu/Penprase/webdocuments/iraf/beg/beg-image.html:
    # Before doing anything involving image display the environment variable
    # stdimage must be set to the correct frame buffer size for the display
    # servers (as described in the dev$graphcap file under the section "STDIMAGE
    # devices") or to the correct image display device. The task GDEVICES is
    # helpful for determining this information for the display servers.
    iraf.set(stdimage='imt2048')

    # Prepare the IRAF package for NIFS.
    # NSHEADERS lists the header parameters used by the various tasks in the
    # NIFS package (excluding headers values which have values fixed by IRAF or
    # FITS conventions).
    iraf.nsheaders("nifs", logfile=log)

    # Set clobber to 'yes' for the script. This still does not make the gemini
    # tasks overwrite files, so:
    # YOU WILL LIKELY HAVE TO REMOVE FILES IF YOU RE_RUN THE SCRIPT.
    user_clobber = iraf.envget("clobber")
    iraf.reset(clobber='yes')

    # This helps make sure all variables are initialized to prevent bugs.
    scienceSkySubtraction = None
    scienceOneDExtraction = None
    extractionXC = None
    extractionYC = None
    extractionRadius = None
    telluricSkySubtraction = None

    # Load reduction parameters from runtimeData/config.cfg.
    with open('./config.cfg') as config_file:
        config = ConfigObj(config_file, unrepr=True)
        # Read general pipeline config.
        over = config['over']
        manualMode = config['manualMode']
        calDirList = config['calibrationDirectoryList']
        scienceOneDExtraction = config['scienceOneDExtraction']
        extractionXC = config['extractionXC']
        extractionYC = config['extractionYC']
        extractionRadius = config['extractionRadius']

        if kind == 'Telluric':
            # Telluric reduction specific config.
            telluricReductionConfig = config['telluricReductionConfig']
            if telluricDirectoryList:
                observationDirectoryList = telluricDirectoryList
            elif not telluricDirectoryList:
                observationDirectoryList = config['telluricDirectoryList']
            start = telluricReductionConfig['telStart']
            stop = telluricReductionConfig['telStop']
            telluricSkySubtraction = telluricReductionConfig[
                'telluricSkySubtraction']

        if kind == 'Science':
            # Science reduction specific config.
            scienceReductionConfig = config['scienceReductionConfig']
            if scienceDirectoryList:
                observationDirectoryList = scienceDirectoryList
            elif not scienceDirectoryList:
                observationDirectoryList = config['scienceDirectoryList']
            start = scienceReductionConfig['sciStart']
            stop = scienceReductionConfig['sciStop']
            scienceSkySubtraction = scienceReductionConfig[
                'scienceSkySubtraction']

    ###########################################################################
    ##                                                                       ##
    ##                 COMPLETE - GENERAL REDUCTION SETUP                    ##
    ##                                                                       ##
    ###########################################################################

    # nifsReduce has two nested loops that reduced data.
    # It loops through each science (or telluric) directory, and
    # runs through a series of calibrations steps on the data in that directory.

    # Loop through all the observation (telluric or science) directories to perform a reduction on each one.
    for observationDirectory in observationDirectoryList:

        ###########################################################################
        ##                                                                       ##
        ##                  BEGIN - OBSERVATION SPECIFIC SETUP                   ##
        ##                                                                       ##
        ###########################################################################

        # Print the current directory of data being reduced.
        logging.info(
            "\n#################################################################################"
        )
        logging.info("                                   ")
        logging.info("  Currently working on reductions in")
        logging.info("  in " + str(observationDirectory))
        logging.info("                                   ")
        logging.info(
            "#################################################################################\n"
        )

        os.chdir(observationDirectory)
        tempObs = observationDirectory.split(os.sep)
        obsid = tempObs[-1]

        # Change the iraf directory to the current directory.
        pwd = os.getcwd()
        iraffunctions.chdir(pwd)

        # Copy relevant calibrations over to the science directory.
        # Open and store the name of the MDF shift reference file from shiftfile into shift.
        shift = 'calibrations/shiftFile'
        # Open and store the name of the flat frame
        flat = 'calibrations/finalFlat'
        # Open and store the bad pixel mask
        finalBadPixelMask = 'calibrations/finalBadPixelMask'
        # Ronchi, arc and database must all be in local calibrations directory
        # Open and store the name of the reduced spatial correction ronchi flat frame name from ronchifile in ronchi.
        ronchi = 'finalRonchi'
        # Open and store the name of the reduced wavelength calibration arc frame from arclist in arc.
        arc = 'finalArc'

        if os.path.exists(os.getcwd() + '/' + ronchi + ".fits"):
            if over:
                iraf.delete(os.getcwd() + '/calibrations/finalRonchi.fits')
                # Copy the spatial calibration ronchi flat frame from Calibrations_grating to the observation directory.
                shutil.copy(os.getcwd() + '/calibrations/finalRonchi.fits',
                            ronchi + '.fits')
            else:
                print "\nOutput exists and -over not set - skipping copy of reduced ronchi"
        else:
            shutil.copy(os.getcwd() + '/calibrations/finalRonchi.fits',
                        ronchi + '.fits')

        if os.path.exists(os.getcwd() + '/' + arc + ".fits"):
            if over:
                iraf.delete(os.getcwd() + '/calibrations/finalArc.fits')
                # Copy the spatial calibration arc flat frame from Calibrations_grating to the observation directory.
                shutil.copy(os.getcwd() + '/calibrations/finalArc.fits',
                            arc + '.fits')
            else:
                print "\nOutput exists and -over not set - skipping copy of reduced arc"
        else:
            shutil.copy(os.getcwd() + '/calibrations/finalArc.fits',
                        arc + '.fits')
        # Make sure the database files are in place. Current understanding is that
        # these should be local to the reduction directory, so need to be copied from
        # the calDir.
        if os.path.isdir("./database"):
            if over:
                shutil.rmtree("./database")
                os.mkdir("./database")
                for item in glob.glob("calibrations/database/*"):
                    shutil.copy(item, "./database/")
            else:
                print "\nOutput exists and -over not set - skipping copy of database directory"
        else:
            os.mkdir('./database/')
            for item in glob.glob("calibrations/database/*"):
                shutil.copy(item, "./database/")

        if telluricSkySubtraction or scienceSkySubtraction:
            # Read the list of sky frames in the observation directory.
            try:
                skyFrameList = open("skyFrameList", "r").readlines()
                skyFrameList = [frame.strip() for frame in skyFrameList]
            except:
                logging.info(
                    "\n#####################################################################"
                )
                logging.info(
                    "#####################################################################"
                )
                logging.info("")
                logging.info(
                    "     WARNING in reduce: No sky frames were found in a directory."
                )
                logging.info("              Please make a skyFrameList in: " +
                             str(os.getcwd()))
                logging.info("")
                logging.info(
                    "#####################################################################"
                )
                logging.info(
                    "#####################################################################\n"
                )
                raise SystemExit
            sky = skyFrameList[0]

        # If we are doing a telluric reduction, open the list of telluric frames in the observation directory.
        # If we are doing a science reduction, open the list of science frames in the observation directory.
        if kind == 'Telluric':
            tellist = open('tellist', 'r').readlines()
            tellist = [frame.strip() for frame in tellist]
        elif kind == 'Science':
            scienceFrameList = open("scienceFrameList", "r").readlines()
            scienceFrameList = [frame.strip() for frame in scienceFrameList]
            # For science frames, check to see if the number of sky frames matches the number of science frames.
            # IF NOT duplicate the sky frames and rewrite the sky file and skyFrameList.
            if scienceSkySubtraction:
                if not len(skyFrameList) == len(scienceFrameList):
                    skyFrameList = makeSkyList(skyFrameList, scienceFrameList,
                                               observationDirectory)

        ###########################################################################
        ##                                                                       ##
        ##                 COMPLETE - OBSERVATION SPECIFIC SETUP                 ##
        ##                BEGIN DATA REDUCTION FOR AN OBSERVATION                ##
        ##                                                                       ##
        ###########################################################################

        # Check start and stop values for reduction steps. Ask user for a correction if
        # input is not valid.
        valindex = start
        while valindex > stop or valindex < 1 or stop > 6:
            logging.info(
                "\n#####################################################################"
            )
            logging.info(
                "#####################################################################"
            )
            logging.info("")
            logging.info(
                "     WARNING in reduce: invalid start/stop values of observation"
            )
            logging.info("                           reduction steps.")
            logging.info("")
            logging.info(
                "#####################################################################"
            )
            logging.info(
                "#####################################################################\n"
            )

            valindex = int(
                raw_input(
                    "\nPlease enter a valid start value (1 to 7, default 1): ")
            )
            stop = int(
                raw_input(
                    "\nPlease enter a valid stop value (1 to 7, default 7): "))

        while valindex <= stop:

            ###########################################################################
            ##  STEP 1: Prepare raw data; science, telluric and sky frames ->n       ##
            ###########################################################################

            if valindex == 1:
                if manualMode:
                    a = raw_input(
                        "About to enter step 1: locate the spectrum.")
                if kind == 'Telluric':
                    tellist = prepare(tellist, shift, finalBadPixelMask, log,
                                      over)
                elif kind == 'Science':
                    scienceFrameList = prepare(scienceFrameList, shift,
                                               finalBadPixelMask, log, over)
                if telluricSkySubtraction or scienceSkySubtraction:
                    skyFrameList = prepare(skyFrameList, shift,
                                           finalBadPixelMask, log, over)
                logging.info(
                    "\n##############################################################################"
                )
                logging.info("")
                logging.info(
                    "  STEP 1: Locate the Spectrum (and prepare raw data) ->n - COMPLETED "
                )
                logging.info("")
                logging.info(
                    "##############################################################################\n"
                )

            ###########################################################################
            ##  STEP 2: Sky Subtraction ->sn                                         ##
            ###########################################################################

            elif valindex == 2:
                if manualMode:
                    a = raw_input("About to enter step 2: sky subtraction.")
                # Combine telluric sky frames.
                if kind == 'Telluric':
                    if telluricSkySubtraction:
                        if len(skyFrameList) > 1:
                            combineImages(skyFrameList, "gn" + sky, log, over)
                        else:
                            copyImage(skyFrameList, 'gn' + sky + '.fits', over)
                        skySubtractTel(tellist, "gn" + sky, log, over)
                    else:
                        for image in tellist:
                            iraf.copy('n' + image + '.fits',
                                      'sn' + image + '.fits')

                if kind == 'Science':
                    if scienceSkySubtraction:
                        skySubtractObj(scienceFrameList, skyFrameList, log,
                                       over)
                    else:
                        for image in scienceFrameList:
                            iraf.copy('n' + image + '.fits',
                                      'sn' + image + '.fits')

                logging.info(
                    "\n##############################################################################"
                )
                logging.info("")
                logging.info("  STEP 2: Sky Subtraction ->sn - COMPLETED ")
                logging.info("")
                logging.info(
                    "##############################################################################\n"
                )

            ##############################################################################
            ##  STEP 3: Flat field, slice, subtract dark and correct bad pixels ->brsn  ##
            ##############################################################################

            elif valindex == 3:
                if manualMode:
                    a = raw_input(
                        "About to enter step 3: flat fielding and bad pixels correction."
                    )
                if kind == 'Telluric':
                    applyFlat(tellist, flat, log, over, kind)
                    fixBad(tellist, log, over)
                elif kind == 'Science':
                    applyFlat(scienceFrameList, flat, log, over, kind)
                    fixBad(scienceFrameList, log, over)
                logging.info(
                    "\n##############################################################################"
                )
                logging.info("")
                logging.info(
                    "  STEP 3: Flat fielding and Bad Pixels Correction ->brsn - COMPLETED "
                )
                logging.info("")
                logging.info(
                    "##############################################################################\n"
                )

            ###########################################################################
            ##  STEP 4: Derive and apply 2D to 3D transformation ->tfbrsn            ##
            ###########################################################################

            elif valindex == 4:
                if manualMode:
                    a = raw_input(
                        "About to enter step 4: 2D to 3D transformation and Wavelength Calibration."
                    )
                if kind == 'Telluric':
                    fitCoords(tellist, arc, ronchi, log, over, kind)
                    transform(tellist, log, over)
                elif kind == 'Science':
                    fitCoords(scienceFrameList, arc, ronchi, log, over, kind)
                    transform(scienceFrameList, log, over)
                logging.info(
                    "\n##############################################################################"
                )
                logging.info("")
                logging.info(
                    "  STEP 4: 2D to 3D transformation and Wavelength Calibration ->tfbrsn - COMPLETED "
                )
                logging.info("")
                logging.info(
                    "##############################################################################\n"
                )

            ############################################################################
            ##  STEP 5 (tellurics): For telluric data derive a telluric               ##
            ##                     correction ->gxtfbrsn                              ##
            ##  STEP 5 (science): For science apply an efficiency correction and make ##
            ##           a data cube (not necessarily in that order).                 ##
            ##           (i) Python method applies correction to nftransformed cube.  ##
            ##           Good for faint objects.                        ->cptfbrsn    ##
            ##           (ii) iraf.telluric method applies correction to              ##
            ##           nftransformed result (not quite a data cube) then            ##
            ##           nftransforms cube.                             ->catfbrsn    ##
            ##           (iii) If no telluric correction/flux calibration to be       ##
            ##           applied make a plain data cube.                ->ctfbrsn     ##
            ############################################################################

            elif valindex == 5:
                if manualMode:
                    a = raw_input("About to enter step 5.")
                # For telluric data:
                # Make a combined extracted 1D standard star spectrum.
                if kind == 'Telluric':
                    extractOneD(tellist, kind, log, over, extractionXC,
                                extractionYC, extractionRadius)

                    # TODO(nat): add this as a parameter; encapsulate this.
                    copyToScience = True
                    if copyToScience:
                        # Copy final extracted results to science directory.
                        try:
                            with open("scienceMatchedTellsList", "r") as f:
                                lines = f.readlines()
                            lines = [x.strip() for x in lines]

                            for i in range(len(lines)):
                                if "obs" in lines[i]:
                                    k = 1
                                    while i + k != len(
                                            lines) and "obs" not in lines[i +
                                                                          k]:
                                        copyResultsToScience(
                                            "gxtfbrsn" + tellist[0] + ".fits",
                                            "0_tel" + lines[i + k] + ".fits",
                                            over)
                                        k += 1
                        except IOError:
                            logging.info(
                                "\nNo scienceMatchedTellsList found in " +
                                os.getcwd() +
                                " . Skipping copy of extracted spectra to science directory."
                            )

                    logging.info(
                        "\n##############################################################################"
                    )
                    logging.info("")
                    logging.info(
                        "  STEP 5a: Extract 1D Spectra and Make Combined 1D Standard Star Spectrum"
                    )
                    logging.info("           ->gxtfbrsn - COMPLETED")
                    logging.info("")
                    logging.info(
                        "##############################################################################\n"
                    )
                    #TODO(nat): add this as a parameter.
                    makeTelluricCube = True
                    if makeTelluricCube:
                        makeCube('tfbrsn', tellist, log, over)
                        logging.info(
                            "\n##############################################################################"
                        )
                        logging.info("")
                        logging.info(
                            "  STEP 5b: Make uncorrected standard star data cubes, ->ctfbrsn  - COMPLETED"
                        )
                        logging.info("")
                        logging.info(
                            "##############################################################################\n"
                        )

                # For Science data:
                # Possibly extract 1D spectra, and make uncorrected cubes.
                elif kind == 'Science':
                    if scienceOneDExtraction:
                        extractOneD(scienceFrameList, kind, log, over,
                                    extractionXC, extractionYC,
                                    extractionRadius)
                        copyExtracted(scienceFrameList, over)
                        logging.info(
                            "\n##############################################################################"
                        )
                        logging.info("")
                        logging.info(
                            "  STEP 5a: Make extracted 1D Science spectra, ->ctgbrsn  - COMPLETED"
                        )
                        logging.info("")
                        logging.info(
                            "##############################################################################\n"
                        )
                    makeCube('tfbrsn', scienceFrameList, log, over)

                    # TODO(nat): encapsulate this inside a function.
                    if os.path.exists('products_uncorrected'):
                        if over:
                            shutil.rmtree('products_uncorrected')
                            os.mkdir('products_uncorrected')
                        else:
                            logging.info(
                                "\nOutput exists and -over not set - skipping creating of products_uncorrected directory"
                            )
                    else:
                        os.mkdir('products_uncorrected')
                    for item in scienceFrameList:
                        if os.path.exists('products_uncorrected/ctfbrsn' +
                                          item + '.fits'):
                            if over:
                                os.remove('products_uncorrected/ctfbrsn' +
                                          item + '.fits')
                                shutil.copy(
                                    'ctfbrsn' + item + '.fits',
                                    'products_uncorrected/ctfbrsn' + item +
                                    '.fits')
                            else:
                                logging.info(
                                    "\nOutput exists and -over not set - skipping copy of uncorrected cube"
                                )
                        else:
                            shutil.copy(
                                'ctfbrsn' + item + '.fits',
                                'products_uncorrected/ctfbrsn' + item +
                                '.fits')

                    if os.path.exists('products_telluric_corrected'):
                        if over:
                            shutil.rmtree('products_telluric_corrected')
                            os.mkdir('products_telluric_corrected')
                        else:
                            logging.info(
                                "\nOutput exists and -over not set - skipping creating of products_telluric_corrected directory"
                            )
                    else:
                        os.mkdir('products_telluric_corrected')
                    for item in scienceFrameList:
                        if os.path.exists(
                                'products_telluric_corrected/ctfbrsn' + item +
                                '.fits'):
                            if over:
                                os.remove(
                                    'products_telluric_corrected/ctfbrsn' +
                                    item + '.fits')
                                shutil.copy(
                                    'ctfbrsn' + item + '.fits',
                                    'products_telluric_corrected/ctfbrsn' +
                                    item + '.fits')
                            else:
                                logging.info(
                                    "\nOutput exists and -over not set - skipping copy of uncorrected cube"
                                )
                        else:
                            shutil.copy(
                                'ctfbrsn' + item + '.fits',
                                'products_telluric_corrected/ctfbrsn' + item +
                                '.fits')

                    logging.info(
                        "\n##############################################################################"
                    )
                    logging.info("")
                    logging.info(
                        "  STEP 5b: Make uncorrected science data cubes, ->ctfbrsn  - COMPLETED"
                    )
                    logging.info("")
                    logging.info(
                        "##############################################################################\n"
                    )

            valindex += 1

        logging.info(
            "\n##############################################################################"
        )
        logging.info("")
        logging.info("  COMPLETE - Reductions completed for " +
                     str(observationDirectory))
        logging.info("")
        logging.info(
            "##############################################################################\n"
        )

    # Return to directory script was begun from.
    os.chdir(path)
示例#4
0
def applyTelluric(objlist, obsid, skylist, telinter, log, over):
    # corrects the data for telluric absorption features
    # nftelluric is currently only run interactively

    obsDir = os.getcwd()
    os.chdir('../Tellurics')
    telDirList = glob.glob('*')

    if telinter == 'no':
        telCor(obsDir, telDirList, over)
    else:
        for telDir in telDirList:
            if 'obs' in telDir:
                os.chdir(telDir)
                if os.path.exists('objtellist'):
                    objtellist = open("objtellist", "r").readlines()
                    objlist = [image.strip() for image in objtellist]
                else:
                    os.chdir('..')
                    continue
                try:
                    telluric = str(open('corrtellfile',
                                        'r').readlines()[0]).strip()
                except:
                    print "No telluric spectrum found in ", telDir
                    os.chdir('..')
                    continue
                shutil.copy(telluric + '.fits', obsDir)
                '''
                continuum = str(open('continuumfile', 'r').readlines()[0]).strip()
                bblist = open('blackbodyfile', 'r').readlines()
                bblist = [image.strip() for image in bblist]
                '''

                os.chdir(obsDir)
                iraffunctions.chdir(obsDir)
                if obsid in objlist:
                    index = objlist.index(obsid)
                    i = index + 1

                    while i < len(objlist) and 'obs' not in objlist[i]:
                        if os.path.exists("atfbrgn" + objlist[i] + ".fits"):
                            if over:
                                iraf.delete("atfbrgn" + objlist[i] + ".fits")
                                iraf.nftelluric('tfbrgn' + objlist[i],
                                                outprefix='a',
                                                calspec=telluric,
                                                fl_inter='yes',
                                                logfile=log)
                            else:
                                print "Output file exists and -over not set - skipping nftelluric in applyTelluric"
                        elif not os.path.exists('atfbrgn' + objlist[i] +
                                                '.fits'):
                            iraf.nftelluric('tfbrgn' + objlist[i],
                                            outprefix='a',
                                            calspec=telluric,
                                            fl_inter='yes',
                                            logfile=log)
                        '''
                        # remove continuum fit from reduced science image
                        if over:
                            if os.path.exists("cont"+objlist[i]+".fits"):
                                iraf.delete("cont"+objlist[i]+".fits")
                            MEFarithpy('atfbrgn'+objlist[i], '../Tellurics/'+telDir+'/'+continuum, 'divide', 'cont'+objlist[i]+'.fits')
                        elif not os.path.exists('cont'+objlist[i]+'.fits'):
                            MEFarithpy('atfbrgn'+objlist[i], '../Tellurics/'+telDir+'/'+continuum, 'divide', 'cont'+objlist[i]+'.fits')
                        else:
                            print "Output file exists and -over not set - skipping continuum division in applyTelluric"

                        # multiply science by blackbody
                        for bb in bblist:
                            objheader = pyfits.open(obsDir+'/'+objlist[i]+'.fits')
                            exptime = objheader[0].header['EXPTIME']
                            if str(int(exptime)) in bb:
                                if over:
                                    if os.path.exists('bbatfbrgn'+objlist[i]+'.fits'):
                                        os.remove('bbatfbrgn'+objlist[i]+'.fits')
                                    MEFarithpy('cont'+objlist[i], '../Tellurics/'+telDir+'/'+bb, 'multiply', 'bbatfbrgn'+objlist[i]+'.fits') 
                                elif not os.path.exists('bbatfbrgn'+objlist[i]+'.fits'):
                                    MEFarithpy('cont'+objlist[i], '../Tellurics/'+telDir+'/'+bb, 'multiply', 'bbatfbrgn'+objlist[i]+'.fits') 
                                else:
                                    print "Output file exists and -over- not set - skipping blackbody calibration in applyTelluric"
                        '''
                        i += 1
            os.chdir('../Tellurics')
示例#5
0
def start(obsDirList, calDirList, start, stop, tel, telinter, over):

    path = os.getcwd()

    # set up log
    FORMAT = '%(asctime)s %(message)s'
    DATEFMT = datefmt()
    logging.basicConfig(filename='main.log',
                        format=FORMAT,
                        datefmt=DATEFMT,
                        level=logging.DEBUG)
    log = os.getcwd() + '/main.log'

    # loops through all the observation directories to perform the science reduction on each one
    for obsDir in obsDirList:
        os.chdir(obsDir)
        tempObs = obsDir.split(os.sep)

        # finds the Calibrations directory that corresponds to the science observation date
        for calDir in calDirList:
            tempCal = calDir.split(os.sep)
            if tempObs[-3] == tempCal[-2]:
                calDir = calDir + '/'
                break
            elif tempObs[-4] == tempCal[-2]:
                calDir = calDir + '/'
                break

        obsid = tempObs[-1]

        # reset iraf tasks
        iraf.unlearn(iraf.gemini, iraf.gemtools, iraf.gnirs, iraf.nifs,
                     iraf.imcopy)

        iraf.set(stdimage='imt2048')

        # change the iraf directory to the current directory
        pwd = os.getcwd()
        iraffunctions.chdir(pwd)
        iraf.nsheaders("nifs", logfile=log)

        # define all the necessary variables and lists for the calibration and science images
        shift = calDir + str(open(calDir + "shiftfile",
                                  "r").readlines()[0]).strip()
        flat = calDir + str(open(calDir + "flatfile",
                                 "r").readlines()[0]).strip()
        ronchi = open(calDir + "ronchifile", "r").readlines()[0].strip()
        iraf.copy(calDir + ronchi + ".fits", output="./")
        sflat_bpm = calDir + str(
            open(calDir + "sflat_bpmfile", "r").readlines()[0]).strip()
        arcdark = calDir + str(
            open(calDir + "arcdarkfile", "r").readlines()[0]).strip()

        # copy wavelength calibrated arc to obsDir
        arc = "wrgn" + str(open(calDir + "arclist",
                                "r").readlines()[0]).strip()
        iraf.copy(calDir + arc + ".fits", output="./")

        # determines whether the data is science or telluric
        if tempObs[-2] == 'Tellurics':
            kind = 'Telluric'
            objlist = open('tellist', 'r').readlines()
            objlist = [image.strip() for image in objlist]
            try:
                skylist = open("skylist", "r").readlines()
                skylist = [image.strip() for image in skylist]
            except:
                print "\nNo sky images were found for standard star. Please make a skylist in the telluric directory\n"
                raise SystemExit
            sky = skylist[0]
        else:
            kind = 'Object'
            objlist = open("objlist", "r").readlines()
            objlist = [image.strip() for image in objlist]
            skylist = open("skylist", "r").readlines()
            skylist = [image.strip() for image in skylist]
            sky = skylist[0]
            # check to see if the number of sky images matches the number of science images and if not duplicates sky images and rewrites the sky file and skylist
        if not len(skylist) == len(objlist):
            skylist = makeSkyList(skylist, objlist, obsDir)

        centers = writeCenters(objlist)

        # Make sure the database files are in place. Current understanding is that
        # these should be local to the reduction directory, so need to be copied from
        # the calDir.
        if os.path.isdir("./database"):
            if over:
                shutil.rmtree("./database")
                os.mkdir("./database")
        elif not os.path.isdir("./database"):
            os.mkdir('./database/')
        iraf.copy(input=calDir + 'database/*', output="./database/")

        #=========================================================
        # Start main processing steps. Do this within a while loop
        # to allow the use of start and stop positions
        #=========================================================

        logging.info('############################')
        logging.info('                            ')
        logging.info('   Reducing Observations    ')
        logging.info('                            ')
        logging.info('############################')

        print '############################'
        print '                            '
        print '   Reducing Observations    '
        print '                            '
        print '############################'

        valindex = start
        if valindex > stop or valindex < 1 or stop > 9:
            print "problem with start/stop values"
        while valindex <= stop:

            ####################
            ## Prepare raw data ->n
            logging.info('Prepare raw data ->n')
            if valindex == 1:
                objlist = prepare(objlist, shift, sflat_bpm, log, over)
                skylist = prepare(skylist, shift, sflat_bpm, log, over)

            #####################
            ## Combine multiple frames ->gn
            elif valindex == 2:
                if kind == 'Object':
                    logging.info('Combine multiple frames ->gn')
                    if len(skylist) > 1:
                        combineImages(skylist, "gn" + sky, log, over)
                    else:
                        copyImage(skylist, 'gn' + sky + '.fits', over)
                else:
                    pass

            ##################
            ## Sky Subtraction ->gn
            elif valindex == 3:
                skySubtractObj(objlist, skylist, log, over)
                logging.info('Sky Subtraction ->gn')

            #################
            ## Flat field ->rgn
            elif valindex == 4:
                applyFlat(objlist, flat, log, over, kind)
                logging.info('Flat field ->rgn')

            #################
            ## Correct bad pixels ->brgn
            elif valindex == 5:
                fixBad(objlist, log, over)
                logging.info('Correct bad pixels ->brgn')

            #################
            ## Derive 2D->3D transformation ->fbrgn
            elif valindex == 6:
                fitCoords(objlist, arc, ronchi, log, over, kind)
                logging.info('Derive 2D->3D transformation ->fbrgn')

            #################
            ## Apply transformation ->tfbrgn
            elif valindex == 7:
                transform(objlist, log, over)
                logging.info('Apply transformation ->tfbrgn')

            #################
            ## Derive or apply telluric correction ->atfbrgn
            elif valindex == 8:
                logging.info('Derive or apply telluric correction ->atfbrgn')
                if kind == 'Telluric':
                    makeTelluric(objlist, log, over)
                elif kind == 'Object' and tel and telinter == 'no':
                    makeCube('tfbrgn', objlist, False, obsDir, log, over)
                    applyTelluric(objlist, obsid, skylist, telinter, log, over)
                elif kind == 'Object' and tel and telinter == 'yes':
                    applyTelluric(objlist, obsid, skylist, telinter, log, over)

            #################
            ## Create a 3D cube -> catfbrgn
            elif valindex == 9:
                if kind == "Telluric":
                    print "No cube being made for tellurics"
                elif telinter == 'yes' and kind == 'Object' and tel:
                    logging.info('Create a 3D cube -> catfbrgn')
                    makeCube('atfbrgn', objlist, tel, obsDir, log, over)
                elif kind == 'Object' and not tel and telinter == 'yes':
                    logging.info('Create a 3D cube -> ctfbrgn')
                    makeCube('tfbrgn', objlist, tel, obsDir, log, over)

            valindex += 1

    os.chdir(path)
    return
示例#6
0
def chdir(path):
    """General chdir updating also pyraf's path """
    os.chdir(path)
    iraffunctions.chdir(path)
    return
示例#7
0
def start(obsDirList, calDirList, over, start, stop):

    # Set up the logging file
    FORMAT = '%(asctime)s %(message)s'
    DATEFMT = datefmt()
    logging.basicConfig(filename='main.log',
                        format=FORMAT,
                        datefmt=DATEFMT,
                        level=logging.DEBUG)
    log = os.getcwd() + '/main.log'

    logging.info('###############################')
    logging.info('#                             #')
    logging.info('# Start Calibration Reduction #')
    logging.info('#                             #')
    logging.info('###############################')

    print '###############################'
    print '#                             #'
    print '# Start Calibration Reduction #'
    print '#                             #'
    print '###############################'

    # Unlearn the used tasks
    iraf.unlearn(iraf.gemini, iraf.gemtools, iraf.gnirs, iraf.nifs)

    # Prepare the package for NIFS
    iraf.nsheaders("nifs", logfile=log)

    iraf.set(stdimage='imt2048')
    user_clobber = iraf.envget("clobber")
    iraf.reset(clobber='yes')

    path = os.getcwd()

    # loop over the Calibrations directories and reduce the day cals in each one
    for calpath in calDirList:
        os.chdir(calpath)
        pwdDir = os.getcwd() + "/"
        iraffunctions.chdir(pwdDir)

        # define the cals lists and images
        flatlist = open('flatlist', "r").readlines()
        flatdarklist = open("flatdarklist", "r").readlines()
        arcdarklist = open("arcdarklist", "r").readlines()
        arclist = open("arclist", "r").readlines()
        ronchilist = open("ronchilist", "r").readlines()

        calflat = (flatlist[0].strip()).rstrip('.fits')
        flatdark = (flatdarklist[0].strip()).rstrip('.fits')
        arcdark = (arcdarklist[0].strip()).rstrip('.fits')
        arc = (arclist[0].strip()).rstrip('.fits')
        ronchiflat = (ronchilist[0].strip()).rstrip('.fits')

        # check start and stop values for reduction steps
        valindex = start
        if valindex > stop or valindex < 1 or stop > 6:
            print "problem with start/stop values"
            print(valindex, start, stop)
        while valindex <= stop:

            ####################
            ## Prepare raw data

            if valindex == 1:
                getShift(calflat, over, log)

            ####################
            ## Make flat

            elif valindex == 2:
                makeFlat(flatlist, flatdarklist, calflat, flatdark, over, log)

            ####################
            ## Combine arc darks

            elif valindex == 3:
                makeArcDark(arcdarklist, arcdark, calflat, over, log)

            ####################
            ##  Combine and flat field arcs

            elif valindex == 4:
                reduceArc(arclist, arc, log, over)

            ####################
            ##  Determine the wavelength of the observation and set the arc coordinate file

            elif valindex == 5:
                wavecal("rgn" + arc, log, over)

            ####################
            ## Combine arc darks

            elif valindex == 6:
                ronchi(ronchilist, ronchiflat, calflat, over, flatdark, log)
            else:
                print "No step associated to this value"

            valindex += 1
    os.chdir(path)
    return
def start():
    """
         nifsBaselineCalibration

         This module contains all the functions needed to reduce
         NIFS GENERAL BASELINE CALIBRATIONS

         INPUT FILES FOR EACH BASELINE CALIBRATION:

         Raw files:
           - Flat frames (lamps on)
           - Flat frames (lamps off)
           - Arc frames
           - Arc dark frames
           - Ronchi mask flat frames

         OUTPUT FILES:
         - Shift file. Eg: sCALFLAT.fits
         - Bad Pixel Mask. Eg: rgnCALFLAT_sflat_bmp.pl
         - Flat field. Eg: rgnCALFLAT_flat.fits
         - Reduced arc frame. Eg: wrgnARC.fits
         - Reduced ronchi mask. Eg: rgnRONCHI.fits
         - Reduced dark frame. Eg: rgnARCDARK.fits

    Args:
        # Loaded from runtimeData/config.cfg
        calDirList:      list of paths to calibrations. ['path/obj/date/Calibrations_grating']
        over (boolean):  overwrite old files. Default: False.
        start (int):     starting step of daycal reduction. Specified at command line with -a. Default: 1.
        stop (int):      stopping step of daycal reduction. Specified at command line with -z. Default: 6.
        debug (boolean): enable optional debugging pauses. Default: False.

    """

    # TODO(nat): stop using first frame from list as name for combined frames. Find better names and implement
    # them in pipeline and docs.
    # TODO(nat): Finish converting the print statements to logging.info() statements.

    # Store current working directory for later use.
    path = os.getcwd()

    # Set up the logging file.
    log = os.getcwd()+'/Nifty.log'

    logging.info('#################################################')
    logging.info('#                                               #')
    logging.info('# Start the NIFS Baseline Calibration Reduction #')
    logging.info('#                                               #')
    logging.info('#################################################')

    # Set up/prepare IRAF.
    iraf.gemini()
    iraf.nifs()
    iraf.gnirs()
    iraf.gemtools()

    # Reset to default parameters the used IRAF tasks.
    iraf.unlearn(iraf.gemini,iraf.gemtools,iraf.gnirs,iraf.nifs)

    # From http://bishop.astro.pomona.edu/Penprase/webdocuments/iraf/beg/beg-image.html:
    # Before doing anything involving image display the environment variable
    # stdimage must be set to the correct frame buffer size for the display
    # servers (as described in the dev$graphcap file under the section "STDIMAGE
    # devices") or to the correct image display device. The task GDEVICES is
    # helpful for determining this information for the display servers.
    iraf.set(stdimage='imt2048')

    # Prepare the IRAF package for NIFS.
    # NSHEADERS lists the header parameters used by the various tasks in the
    # NIFS package (excluding headers values which have values fixed by IRAF or
    # FITS conventions).
    iraf.nsheaders("nifs",logfile=log)

    # Set clobber to 'yes' for the script. This still does not make the gemini
    # tasks overwrite files, so:
    # YOU WILL LIKELY HAVE TO REMOVE FILES IF YOU RE_RUN THE SCRIPT.
    user_clobber=iraf.envget("clobber")
    iraf.reset(clobber='yes')

    # Load reduction parameters from ./config.cfg.
    with open('./config.cfg') as config_file:
        options = ConfigObj(config_file, unrepr=True)
        calDirList = options['calibrationDirectoryList']
        over = options['over']
        start = options['rstart']
        stop = options['rstop']
        debug = options['debug']

    ################################################################################
    # Define Variables, Reduction Lists AND identify/run number of reduction steps #
    ################################################################################

    # Loop over the Calibrations directories and reduce the day calibrations in each one.
    for calpath in calDirList:
        os.chdir(calpath)
        pwdDir = os.getcwd()+"/"
        iraffunctions.chdir(pwdDir)

        # However, don't do the reduction for a Calibration_"grating" directory without associated telluric or science data.
        # Check that a "grating" directory exists at the same level as the Calibrations_"grating" directory.
        # If not, skip the reduction of calibrations in that Calibrations_grating directory.
        # "grating" should be the last letter of calpath.
        grating = calpath[-1]
        if not os.path.exists("../"+grating):

            print "\n##############################################################################"
            print ""
            print "  No grating directory (including science or telluric data) found for  "
            print "  ", calpath
            print "  Skipping reduction of calibrations in that directory."
            print ""
            print "##############################################################################\n"

            continue

        # Create lists of each type of calibration from textfiles in Calibrations directory.
        flatlist = open('flatlist', "r").readlines()
        flatdarklist = open("flatdarklist", "r").readlines()
        arcdarklist = open("arcdarklist", "r").readlines()
        arclist = open("arclist", "r").readlines()
        ronchilist = open("ronchilist", "r").readlines()

        # Store the name of the first image of each calibration-type-list in
        # a variable for later use (Eg: calflat). This is because gemcombine will
        # merge a list of files (Eg: "n"+flatlist) and the output file will have the same
        # name as the first file in the list (Eg: calflat). These first file names are used
        # later in the pipeline.
        calflat = (flatlist[0].strip()).rstrip('.fits')
        flatdark = (flatdarklist[0].strip()).rstrip('.fits')
        arcdark = (arcdarklist[0].strip()).rstrip('.fits')
        arc = (arclist[0].strip()).rstrip('.fits')
        ronchiflat = (ronchilist[0].strip()).rstrip('.fits')

        # Check start and stop values for reduction steps. Ask user for a correction if
        # input is not valid.
        valindex = start
        while valindex > stop  or valindex < 1 or stop > 4:
            print "\n#####################################################################"
            print "#####################################################################"
            print ""
            print "     WARNING in calibrate: invalid start/stop values of calibration "
            print "                           reduction steps."
            print ""
            print "#####################################################################"
            print "#####################################################################\n"

            valindex = int(raw_input("\nPlease enter a valid start value (1 to 4, default 1): "))
            stop = int(raw_input("\nPlease enter a valid stop value (1 to 4, default 4): "))

        # Print the current directory of calibrations being processed.
        print "\n#################################################################################"
        print "                                   "
        print "  Currently working on calibrations "
        print "  in ", calpath
        print "                                   "
        print "#################################################################################\n"


        while valindex <= stop:

            #############################################################################
            ##  STEP 1: Determine the shift to the MDF (mask definition file)          ##
            ##          using nfprepare (nsoffset). Ie: locate the spectra.            ##
            ##  Output: First image in flatlist with "s" prefix.                       ##
            #############################################################################

            if valindex == 1:
                if debug:
                    a = raw_input("About to enter step 1: locate the spectrum.")
                getShift(calflat, over, log)
                print "\n###################################################################"
                print ""
                print "    STEP 1: Locate the Spectrum (Determine the shift to the MDF) - COMPLETED"
                print ""
                print "###################################################################\n"

            #############################################################################
            ##  STEP 2: Create Flat Field frame and BPM (Bad Pixel Mask)               ##
            ##  Output: Flat Field image with spatial and spectral information.        ##
            ##          First image in flatlist with  "rgn" prefix and "_flat" suffix. ##
            #############################################################################

            elif valindex == 2:
                if debug:
                    a = raw_input("About to enter step 2: flat field.")
                makeFlat(flatlist, flatdarklist, calflat, flatdark, over, log)
                print "\n###################################################################"
                print ""
                print "    STEP 2: Flat Field (Create Flat Field image and BPM image) - COMPLETED       "
                print ""
                print "###################################################################\n"

            ############################################################################
            ##  STEP 3: NFPREPARE and Combine arc darks.                              ##
            ##          NFPREPARE, Combine and flat field arcs.                       ##
            ##          Determine the wavelength solution and create the wavelength   ##
            ##          referenced arc.                                               ##
            ############################################################################

            elif valindex == 3:
                if debug:
                    a = raw_input("About to enter step 3: wavelength solution.")
                reduceArc(arclist, arc, arcdarklist, arcdark, log, over)
                wavecal(arc, log, over, path)
                print "\n###################################################################"
                print ""
                print "         STEP 3: Wavelength Solution (NFPREPARE and Combine arc darks.  "
                print "                 NFPREPARE, Combine and flat field arcs."
                print "                 Determine the wavelength solution and create the"
                print "                 wavelength referenced arc) - COMPLETED"
                print ""
                print "###################################################################\n"

            ######################################################################################
            ##  Step 4: Trace the spatial curvature and spectral distortion in the Ronchi flat. ##
            ######################################################################################

            elif valindex == 4:
                if debug:
                    a = raw_input("About to enter step 4: spatial distortion.")
                ronchi(ronchilist, ronchiflat, calflat, over, flatdark, log)
                print "\n###################################################################"
                print ""
                print "     Step 4: Spatial Distortion (Trace the spatial curvature and spectral distortion "
                print "             in the Ronchi flat) - COMPLETED"
                print ""
                print "###################################################################\n"

            else:
                print "\nERROR in nifs_baseline_calibration: step ", valindex, " is not valid.\n"
                raise SystemExit

            valindex += 1

        print "\n##############################################################################"
        print ""
        print "  COMPLETE - Calibration reductions completed for "
        print "  ", calpath
        print ""
        print "##############################################################################\n"


    # Return to directory script was begun from.
    os.chdir(path)
    return
示例#9
0
def start(telDirList, continuuminter, hlineinter, hline_method, spectemp, mag,
          over):
    path = os.getcwd()
    # Set up the logging file
    FORMAT = '%(asctime)s %(message)s'
    DATEFMT = datefmt()
    logging.basicConfig(filename='main.log',
                        format=FORMAT,
                        datefmt=DATEFMT,
                        level=logging.DEBUG)
    log = os.getcwd() + '/main.log'

    logging.info('##########################')
    logging.info('#                        #')
    logging.info('# Start Flux Calibration #')
    logging.info('#                        #')
    logging.info('##########################')

    print "telDirList= ", telDirList
    print " continuuminter=", continuuminter
    print "hlineinter= ", hlineinter
    print " hline_method=", hline_method
    print "spectemp= ", spectemp
    print " mag=", mag
    print " over=", over

    for telDir in telDirList:
        os.chdir(telDir)
        iraffunctions.chdir(telDir)

        # open and define standard star spectrum and its relevant header keywords
        try:
            standard = str(open('telluricfile', 'r').readlines()[0]).strip()
        except:
            print "No telluricfile found in ", telDir
            continue
        if not os.path.exists('objtellist'):
            print "No objtellist found in ", telDir
            continue

        telheader = pyfits.open(standard + '.fits')
        band = telheader[0].header['GRATING'][0]
        RA = telheader[0].header['RA']
        Dec = telheader[0].header['DEC']
        airmass_std = telheader[0].header['AIRMASS']
        temp1 = os.path.split(telDir)
        temp2 = os.path.split(temp1[0])
        # make directory PRODUCTS above the Telluric observation directory
        # telluric_hlines.txt is stored there
        if not os.path.exists(temp1[0] + '/PRODUCTS'):
            os.mkdir(temp1[0] + '/PRODUCTS')

        # defines 'name' that is passed to mag2mass
        if '-' in str(Dec):
            name = str(RA) + 'd' + str(Dec) + 'd'
        else:
            name = str(RA) + 'd+' + str(Dec) + 'd'

        # find standard star spectral type, temperature, and magnitude
        mag2mass(name, path, spectemp, mag, band)
        print " list", name, path, spectemp, mag, band

        # File for recording shift/scale from calls to "telluric"
        t1 = open('telluric_hlines.txt', 'w')

        # Remove H lines from standard star
        no_hline = False
        if os.path.exists("ftell_nolines" + band + '.fits'):
            if over:
                iraf.delete("ftell_nolines" + band + '.fits')
            else:
                no_hline = True
                print "Output file exists and -over- not set - skipping H line removal"

        if hline_method == "none":
            #need to copy files so have right names for later use
            iraf.imcopy(input=standard + '[sci,' + str(1) + ']',
                        output="ftell_nolines" + band,
                        verbose='no')

        if hline_method == "none" and not no_hline:
            print ""
            print "***Removing intrinsic lines in standard star***"
            print ""

        if hline_method == "vega" and not no_hline:
            vega(standard, band, path, hlineinter, airmass_std, t1, log, over)

        if hline_method == "linefit_auto" and not no_hline:
            linefit_auto(standard, band)

        if hline_method == "linefit_manual" and not no_hline:
            linefit_manual(standard + '[sci,1]', band)

        if hline_method == "vega_tweak" and not no_hline:
            #run vega removal automatically first, then give user chance to interact with spectrum as well
            vega(standard, band, path, hlineinter, airmass_std, t1, log, over)
            linefit_manual("ftell_nolines" + band, band)

        if hline_method == "linefit_tweak" and not no_hline:
            #run Lorentz removal automatically first, then give user chance to interact with spectrum as well
            linefit_auto(standard, band)
            linefit_manual("ftell_nolines" + band, band)

        # make a list of exposure times from the science images that use this standard star spectrum for the telluric correction
        # used to make flux calibrated blackbody spectra
        objtellist = open('objtellist', 'r').readlines()
        objtellist = [image.strip() for image in objtellist]
        exptimelist = []
        for item in objtellist:
            if 'obs' in item:
                os.chdir(telDir)
                os.chdir('../../' + item)
            else:
                objheader = pyfits.open(item + '.fits')
                exptime = objheader[0].header['EXPTIME']
                if not exptimelist or exptime not in exptimelist:
                    exptimelist.append(int(exptime))

        os.chdir(telDir)
        for tgt_exp in exptimelist:

            # Make blackbody spectrum to be used in nifsScience.py
            file = open('std_star.txt', 'r')
            lines = file.readlines()
            #Extract stellar temperature from std_star.txt file , for use in making blackbody
            star_kelvin = float(lines[0].replace('\n', '').split()[3])
            #Extract mag from std_star.txt file and convert to erg/cm2/s/A, for a rough flux scaling

            try:
                #find out if a matching band mag exists in std_star.txt
                if band == 'K':
                    star_mag = lines[0].replace('\n', '').split()[2]
                    star_mag = float(star_mag)
                    flambda = 10**(-star_mag / 2.5) * 4.28E-11
                if band == 'H':
                    star_mag = lines[1].replace('\n', '').split()[2]
                    star_mag = float(star_mag)
                    flambda = 10**(-star_mag / 2.5) * 1.133E-10
                if band == 'J':
                    star_mag = lines[2].replace('\n', '').split()[2]
                    star_mag = float(star_mag)
                    flambda = 10**(-star_mag / 2.5) * 3.129E-10
                print "flambda=", flambda

            except:
                #if not then just set to 1; no absolute flux cal. attempted
                flambda = 1
                print "No ", band, " magnitude found for this star. A relative flux calibration will be performed"
                print "star_kelvin=", star_kelvin
                print "star_mag=", star_mag

            effspec(telDir, standard, 'ftell_nolines' + band + '.fits',
                    star_mag, star_kelvin, over)
            '''
            #account for standard star/science target exposure times
            std_exp = telheader[0].header['EXPTIME']
            flambda = flambda * (float(std_exp) / float(tgt_exp))
            
            #find the start and end wavelengths of the spectrum
            wstart = iraf.hselect(images=standard+'[SCI]', field='CRVAL1', expr='yes',  missing='INDEF', mode='al', Stdout=1)
            wstart = float(wstart[0].replace("'",""))
            wdelt = iraf.hselect(images=standard+'[SCI]', field='CD1_1', expr='yes',  missing='INDEF', mode='al', Stdout=1)
            wend = wstart + (2039 * float(wdelt[0].replace("'","")))

            #make a blackbody
            if over:
                if os.path.exists('blackbody'+str(tgt_exp)+'.fits'):
                    os.remove('blackbody'+str(tgt_exp)+'.fits')
                iraf.mk1dspec(input="blackbody"+str(tgt_exp),output="blackbody"+str(tgt_exp),ap=1,rv=0.0,z='no',title='',ncols=2040,naps=1,header='',wstart=wstart,wend=wend,continuum=1000,slope=0.0,temperature=star_kelvin,fnu='no',lines='',nlines=0,profile='gaussian',peak=-0.5,gfwhm=20.0,lfwhm=20.0,seed=1,comments='yes',mode='ql')
                    #scale it to the science target
                meana = iraf.imstat(images="blackbody"+str(tgt_exp), fields="mean", lower='INDEF', upper='INDEF', nclip=0, lsigma=3.0, usigma=3.0, binwidth=0.1, format='yes', cache='no', mode='al',Stdout=1)
                scalefac = flambda / float(meana[1].replace("'",""))
            elif not os.path.exists('blackbody'+str(tgt_exp)+'.fits'):
                iraf.mk1dspec(input="blackbody"+str(tgt_exp),output="blackbody"+str(tgt_exp),ap=1,rv=0.0,z='no',title='',ncols=2040,naps=1,header='',wstart=wstart,wend=wend,continuum=1000,slope=0.0,temperature=star_kelvin,fnu='no',lines='',nlines=0,profile='gaussian',peak=-0.5,gfwhm=20.0,lfwhm=20.0,seed=1,comments='yes',mode='ql')
                #scale it to the science target
                meana = iraf.imstat(images="blackbody"+str(tgt_exp), fields="mean", lower='INDEF', upper='INDEF', nclip=0, lsigma=3.0, usigma=3.0, binwidth=0.1, format='yes', cache='no', mode='al',Stdout=1)
                scalefac = flambda / float(meana[1].replace("'",""))
            else:
                print "Output file exists and -over- not set - skipping mk1dspec"

            if over:
                if os.path.exists("bbscale"+str(tgt_exp)+'.fits'):
                    os.remove("bbscale"+str(tgt_exp)+'.fits')
                iraf.imarith(operand1="blackbody"+str(tgt_exp), op="*", operand2=scalefac, result="bbscale"+str(tgt_exp),title='',divzero=0.0,hparams='',pixtype='',calctype='',verbose='no',noact='no',mode='al')
            elif not os.path.exists("bbscale"+str(tgt_exp)+'.fits'):
                iraf.imarith(operand1="blackbody"+str(tgt_exp), op="*", operand2=scalefac, result="bbscale"+str(tgt_exp),title='',divzero=0.0,hparams='',pixtype='',calctype='',verbose='no',noact='no',mode='al')
            else:
                print "Output file exists and -over- not set - skipping blackbody flux scaling"
                
            writeList("bbscale"+str(tgt_exp), "blackbodyfile", telDir)
            '''

    os.chdir(path)
示例#10
0
    index = exptimes > 100.
    return specs[index].tolist()

if __name__ == "__main__":
    wdir = os.path.join(home, "data/reduced")
    outroot = wdir.replace("reduced", "combined")
    outroot2 = wdir.replace("reduced", "single")
    if not os.path.exists(outroot):
        os.mkdir(outroot)
    os.chdir(wdir)
    for night in nights:
        print "Working in night ", night
        outdir = os.path.join(outroot, night)
        outdir2 = os.path.join(outroot2, night)
        os.chdir(os.path.join(wdir, night))
        iraffunctions.chdir(os.path.join(wdir, night))
        outfile = PdfPages("log_scombine.pdf")
        fig = plt.figure(1)
        if not os.path.exists(outdir):
            os.mkdir(outdir)
        if not os.path.exists(outdir2):
            os.mkdir(outdir2)
        fits = [x for x in os.listdir(".") if x.endswith("fits")]
        objs = set(["_".join(x.split("_")[1:]) for x in fits])
        for i, obj in enumerate(objs):
            print "File: {0} ({1}/{2})".format(obj, i+1, len(objs))
            lis = [x for x in fits if x.endswith(obj)]
            goodlis = select_specs(lis)
            filenames = ", ".join(goodlis)
            output = os.path.join(outdir, obj)
            if  len(goodlis) == 1:
示例#11
0
def mergeCubes(obsDirList, cubeType, mergeType, use_pq_offsets, im3dtran, over=""):
    """MERGE

    This module contains all the functions needed to merge
    the final data cubes.

    NOTE: If you wish to shift the cubes manually in QFits View
    you can combine them in this script by making sure that you
    attach the prefix "shif" to each shifted image and save them
    in the observation directory (ie. obs108). This is necessary
    for very faint objects.

    TODO(nat): I think what we want as a final product is one cube per grating,
    per object. I need to finish generalizing this so it really works with multiple
    gratings, observations and objects.

    We should loop like this: For each object, for each grating, for each observation.
    Merge all cubes in an observation. Then Merge all cubes of the same grating. Then
    do that for every object in the program.

    INPUT:
        - Reference data cubes
        - A list of paths where final data cubes are located
        - Transformed integral field spectra

    OUTPUT:
        - Merged cubes for each observation (ie. DATE_obs##(#).fits)
        - One final merged cube from entire observation program
    """

    # Store the current working directory so we can find our way back later on.
    path = os.getcwd()
    iraffunctions.chdir(path)

    # Set the default logfile for iraf tasks.
    # TODO: Set the logfile for all iraf tasks! Right now it is not logging their output because of im3dtran...
    # It seems im3dtran doesn't have a "log" parameter.
    log = "Nifty.log"

    # Set appropriate suffix for cube type.
    if cubeType == "uncorrected":
        suffix = "_uncorrected"
        unmergedDirectory = 'products_uncorrected'
    elif cubeType == "telluricCorrected":
        suffix = "_telluricCorrected"
        unmergedDirectory = 'products_telluric_corrected'
    elif cubeType == "telCorAndFluxCalibrated":
        suffix = "_telCorAndFluxCalibrated"
        unmergedDirectory = 'products_fluxcal_AND_telluric_corrected'
    else:
        logging.info("No suffix found!")
        return

    # Create some lists here.
    listsOfCubes = []        # List of lists of cubes (one list for each science observation directory).
    mergedCubes = []         # List of Merged cubes (one merged cube for each science observation directory).
    obsidlist = []           # List of science observation id s.

    # Store the merged directory
    targetDirectory = None

    # Pixel scale in arcseconds/pixel.
    pixScale = 0.05

    # TODO(nat): implement a way to read and save cubelists to textfiles. It would be nice for users to
    # be able to edit the list of cubes to merge by hand.
    # If no Merged directory exists that contains a textfile list of cubes:
    # Go to each science directory and copy cubes from there to a new directory called Merged.

    # TODO(nat): This code seems to work really well, but it could use some polishing. Feel free to refactor nicely!
    for obsDir in obsDirList:
        # Get date, obsid and obsPath by splitting each science directory name.
        # Eg: directory name is ""/Users/ncomeau/research/newer-nifty/hd165459/20160705/H/obs13", then:
        # temp1 == ('/Users/ncomeau/research/newer-nifty/hd165459/20160705/H', 'obs13')
        # temp2 == ('/Users/ncomeau/research/newer-nifty/hd165459/20160705', 'H')
        # temp3 == ('/Users/ncomeau/research/newer-nifty/hd165459', '20160705')
        # temp4 == ('/Users/ncomeau/research/newer-nifty', 'hd165459')

        if not obsDir:
            raise ValueError("nifsMerge: There was a problem with the science directory list.")

        # TODO: make this clearer.
        temp1 = os.path.split(obsDir)
        temp2 = os.path.split(temp1[0])
        temp3 = os.path.split(temp2[0])
        temp4 = os.path.split(temp3[0])
        objname = temp3[1]
        date = temp3[1]
        obsid = temp1[1]
        obsPath = temp3[0]
        targetDirectory = temp4[0]
        try:
            os.chdir(obsDir + '/'+unmergedDirectory)
        except OSError:
            raise OSError("nifsMerge: a science directory didn't exist.")

        obsidlist.append(obsPath+'/Merged'+suffix+'/'+date+'_'+obsid)

        # Create a directory called Merged and copy all the data cubes to this directory.
        if not os.path.exists(obsPath+'/Merged'+suffix+'/'):
            os.mkdir(obsPath+'/Merged'+suffix+'/')
            logging.info('\nI am creating a directory called Merged'+str(suffix))

        Merged = obsPath+'/Merged'+suffix

        if not os.path.exists(Merged+'/'+date+'_'+obsid):
            os.mkdir(Merged+'/'+date+'_'+obsid)
            logging.info('\nI am creating a directory with date and abs ID inside Merged.')

        # If a list called shiftedcubes already exists then just merge those shifted cubes and continue.
        if glob.glob("./shift*.fits"):
            if over:
                if os.path.exists('./'+obsid+'_merged.fits'):
                    os.remove('./'+obsid+'_merged.fits')
                    iraf.gemcube(input="shif*.fits[SCI]", output=obsid+'_merged', logfile = log)
            elif not os.path.exists('./'+obsid+'_merged.fits'):
                iraf.gemcube(input="shif*.fits[SCI]", output=obsid+'_merged', logfile = log)
            else:
                logging.info("Output exists and -over- not set - shifted cubes are not being merged")
            shutil.copy('./'+obsid+'_merged.fits', Merged)
            if obsDir==obsDirList[-1]:
                return
            else:
                continue

        # Create a list called cubes, which stores all the cubes from a particular night.
        # Store all the cubes lists in a list of lists called listsOfCubes.
        # TODO: syntax is fairly ugly; there may be a better way to do this.

        if cubeType == "uncorrected":
            cubes = glob.glob('ctfbrsnN*.fits')          # Cubes order at this point is arbitrary so we need to sort.
            if cubes:
                cubes.sort(key=lambda x: x[-8:-5])    # Sort cubes in increasing order by last three digits.
                listsOfCubes.append(cubes)
            else:
                logging.info("Warning: no uncorrected cubes found in " + str(os.getcwd()))
                logging.info("Skipping cube merging in this directory.")
                return
        elif cubeType == "telluricCorrected":
            cubes = glob.glob('actfbrsnN*.fits')
            if cubes:
                cubes.sort(key=lambda x: x[-8:-5])    # Sort cubes in increasing order by last three digits.
                listsOfCubes.append(cubes)
            else:
                logging.info("Warning: no telluric corrected cubes found in " + str(os.getcwd()))
                logging.info("Skipping cube merging in this directory.")
                return
        elif cubeType == "telCorAndFluxCalibrated":
            cubes = glob.glob('factfbrsnN*.fits')
            if cubes:
                cubes.sort(key=lambda x: x[-8:-5])    # Sort cubes in increasing order by last three digits.
                listsOfCubes.append(cubes)
            else:
                logging.info("Warning: no flux calibrated and telluric corrected cubes found in " + str(os.getcwd()))
                logging.info("Skipping cube merging in this directory.")
                return
        else:
            logging.info("Invalid cube type; skipping cube merge for " + str(os.getcwd()))
            return
        # Copy cubes to their respective data_obsid directory within Merged.
        for cube in cubes:
            shutil.copy(cube, Merged+'/'+date+'_'+obsid)

        os.chdir(Merged)

    n=0
    for cubes in listsOfCubes:

        shiftlist = []
        os.chdir(obsidlist[n])
        iraffunctions.chdir(obsidlist[n])

        if use_pq_offsets:
            # Set the zero point p and q offsets to the p and q offsets of the first cube in each list of cubes.
            header = astropy.io.fits.open(cubes[0])
            p0 = header[0].header['POFFSET']
            q0 = header[0].header['QOFFSET']
            foff = open('offsets.txt', 'w')
            foff.write('%d %d %d\n' % (0, 0, 0))
            foff.close()

        suffix = cubes[0][-8:-5]
        if im3dtran:
            if os.path.exists('transcube'+suffix+'.fits'):
                if not over:
                    logging.info('Output already exists and -over- not set - skipping im3dtran')
                if over:
                    os.remove('transcube'+suffix+'.fits')
                    iraf.im3dtran(input = cubes[0]+'[SCI][*,*,-*]', new_x=1, new_y=3, new_z=2, output = 'transcube'+suffix)
            else:
                iraf.im3dtran(input = cubes[0]+'[SCI][*,*,-*]', new_x=1, new_y=3, new_z=2, output = 'transcube'+suffix)
        else:
            iraf.imcopy(cubes[0]+'[SCI][*,*,*]', 'NONtranscube'+suffix+'.fits')
        shiftlist.append('cube'+suffix+'.fits')
        iraffunctions.chdir(os.getcwd())

        for i in range(len(cubes)):
            # Skip the first cube!
            if i == 0:
                continue
            header2 = astropy.io.fits.open(cubes[i])
            # Check to see if we are using ALTAIR. If we are, later we will invert the x offset
            # because of the different light path.
            ALTAIR = header2[0].header['AOFOLD'].strip() == 'IN'
            suffix = cubes[i][-8:-5]

            # If user wants to merge using p and q offsets, grab those from .fits headers.
            if use_pq_offsets:
                # find the p and q offsets of the other cubes in the sequence.
                xoff = header2[0].header['POFFSET']
                yoff = header2[0].header['QOFFSET']
                # calculate the difference between the zero point offsets and the offsets of the other cubes and convert that to pixels
                if ALTAIR:
                    xShift = round(-1*(xoff - p0)/pixScale)
                else:
                    xShift = round((xoff - p0)/pixScale)
                yShift = round((yoff - q0)/pixScale)
                # write all offsets to a text file (keep in mind that the x and y offsets use different pixel scales)
                foff = open('offsets.txt', 'a')
                if im3dtran:
                    # If we swap the y and lambda axis we must also write the offsets in x, lambda, y.
                    foff.write('%d %d %d\n' % (int(xShift), 0, int(yShift)))
                else:
                    # Write offsets in regular x, y, lambda.
                    foff.write('%d\t%d\t%d\n' % (xShift, yShift, 0.))
                foff.close()

            if im3dtran:
                prefix = 'transcube'
                if os.path.exists('transcube'+suffix+'.fits'):
                    if not over:
                        logging.info('Output already exists and -over- not set - skipping im3dtran')
                    if over:
                        os.remove('transcube'+suffix+'.fits')
                        iraf.im3dtran(input = cubes[i]+'[SCI][*,*,-*]', new_x=1, new_y=3, new_z=2, output = 'transcube'+suffix)
                else:
                    iraf.im3dtran(input = cubes[i]+'[SCI][*,*,-*]', new_x=1, new_y=3, new_z=2, output = 'transcube'+suffix)
            else:
                prefix = 'NONtranscube'
                iraf.imcopy(cubes[i]+'[SCI][*,*,*]', prefix+suffix+'.fits')
            shiftlist.append('cube'+suffix+'.fits')

        if not use_pq_offsets:
            # Before we combine make sure a suitable offsets.txt file exists.
            a = raw_input("\nPaused. Please provide a suitable offsets.txt file in ", obsidlist[n])
            while not os.path.exists('offsets.txt'):
                a = raw_input("No offsets.txt file found. Please try again.")
            logging.info('offsets.txt found successfully for', obsidlist[n])

        if os.path.exists('cube_merged.fits'):
            if over:
                os.remove('cube_merged.fits')
                iraf.imcombine(prefix+'*', output = 'cube_merged.fits',  combine = mergeType, offsets = 'offsets.txt')
            else:
                logging.info('Output already exists and -over- not set - skipping imcombine')
        else:
            iraf.imcombine(prefix+'*', output = 'cube_merged.fits',  combine = mergeType, offsets = 'offsets.txt')
        # TODO(nat): barf. This is pretty nasty... We should fix the overwrite statements here and
        # find a way to use less nesting
        if im3dtran:
            # Transpose the cube back to x, y, lambda.
            if os.path.exists('out.fits'):
                if over:
                    os.remove('out.fits')
                    iraf.im3dtran(input='cube_merged[*,-*,*]', new_x=1, new_y=3, new_z=2, output = 'out.fits')
                else:
                    logging.info('Output already exists and -over- not set - skipping final im3dtran')
            else:
                iraf.im3dtran(input='cube_merged[*,-*,*]', new_x=1, new_y=3, new_z=2, output = 'out.fits')
            iraf.fxcopy(input=cubes[0]+'[0], out.fits', output = obsidlist[n]+'_merged.fits')
        else:
            iraf.fxcopy(input=cubes[0]+'[0], cube_merged.fits', output = obsidlist[n]+'_merged.fits')
        mergedCubes.append(obsidlist[n]+'_merged.fits')

        n+=1
        os.chdir(Merged)

    os.chdir(path)
    # Save the data with JSON so we can grab it in the next step.
    mergedData = {}
    mergedData['mergedCubes'] = mergedCubes
    mergedData['Merged'] = Merged
    with open(targetDirectory+"/mergedInfo.txt", "w") as outfile:
        json.dump(mergedData, outfile)
示例#12
0
def start(obsDirList, use_pq_offsets, im3dtran, over=""):
    """MERGE

    This module contains all the functions needed to merge
    the final data cubes.

    NOTE: If you wish to shift the cubes manually in QFits View
    you can combine them in this script by making sure that you
    attach the prefix "shif" to each shifted image and save them
    in the observation directory (ie. obs108). This is necessary
    for very faint objects.

    INPUT:
        - Reference data cubes
        - A list of paths where final data cubes are located
        - Transformed integral field spectra

    OUTPUT:
        - Merged cubes for each observation (ie. DATE_obs##(#).fits)
        - One final merged cube from entire observation program
    """

    # Store the current working directory so we can find our way back later on.
    path = os.getcwd()

    iraf.gemini()
    iraf.nifs()
    iraf.gnirs()
    iraf.gemtools()

    # Unlearn the used tasks.
    iraf.unlearn(iraf.gemini, iraf.gemtools, iraf.gnirs, iraf.nifs)

    # Prepare the package for NIFS
    iraf.nsheaders("nifs", logfile="Nifty.log")
    iraf.set(stdimage='imt2048')
    user_clobber = iraf.envget("clobber")
    iraf.reset(clobber='yes')

    # Set the default logfile for iraf tasks.
    # TODO: Set the logfile for all iraf tasks! Right now it is not logging their output because of im3dtran...
    # It seems im3dtran doesn't have a "log" parameter.
    log = "Nifty.log"

    # Change to the directory in iraf.
    iraffunctions.chdir(path)

    # Create some lists here.
    listsOfCubes = [
    ]  # List of lists of cubes (one list for each science observation directory).
    mergedCubes = [
    ]  # List of Merged cubes (one merged cube for each science observation directory).
    obsidlist = []  # List of science observation id s.

    # Pixel scale in arcseconds/pixel.
    pixScale = 0.05

    # TODO(ncomeau[*AT*]uvic.ca): implement a way to read and save cubelists to textfiles. It would be nice for users to
    # be able to edit the list of cubes to merge by hand.
    # If no Merged directory exists that contains a textfile list of cubes:
    # Go to each science directory and copy cubes from there to a new directory called Merged.
    for obsDir in obsDirList:
        # Get date, obsid and obsPath by splitting each science directory name.
        # Eg: directory name is ""/Users/ncomeau/research/newer-nifty/hd165459/20160705/H/obs13", then:
        # temp1 == ('/Users/ncomeau/research/newer-nifty/hd165459/20160705/H', 'obs13')
        # temp2 == ('/Users/ncomeau/research/newer-nifty/hd165459/20160705', 'H')
        # temp3 == ('/Users/ncomeau/research/newer-nifty/hd165459', '20160705')
        # temp4 == ('/Users/ncomeau/research/newer-nifty', 'hd165459')

        # TODO: make this clearer.

        temp1 = os.path.split(obsDir)
        temp2 = os.path.split(temp1[0])
        temp3 = os.path.split(temp2[0])
        temp4 = os.path.split(temp3[0])
        objname = temp4[1]
        date = temp3[1]
        obsid = temp1[1]
        obsPath = temp3[0]
        os.chdir(obsDir)
        obsidlist.append(date + '_' + obsid)

        # Create a directory called Merged and copy all the data cubes to this directory.
        if not os.path.exists(obsPath + '/Merged/'):
            os.mkdir(obsPath + '/Merged/')
            logging.info('I am creating a directory called Merged')

        Merged = obsPath + '/Merged'

        if not os.path.exists(Merged + '/' + date + '_' + obsid):
            os.mkdir(Merged + '/' + date + '_' + obsid)
            logging.info(
                'I am creating a directory with date and abs ID inside Merged '
            )

        # If a list called shiftedcubes already exists then just merge those shifted cubes and continue.
        if glob.glob("./shift*.fits"):
            if over:
                if os.path.exists('./' + obsid + '_merged.fits'):
                    os.remove('./' + obsid + '_merged.fits')
                    iraf.gemcube(input="shif*.fits[SCI]",
                                 output=obsid + '_merged',
                                 logfile=log)
            elif not os.path.exists('./' + obsid + '_merged.fits'):
                iraf.gemcube(input="shif*.fits[SCI]",
                             output=obsid + '_merged',
                             logfile=log)
            else:
                logging.info(
                    "Output exists and -over- not set - shifted cubes are not being merged"
                )
            shutil.copy('./' + obsid + '_merged.fits', Merged)
            if obsDir == obsDirList[-1]:
                return
            else:
                continue

        # Create a list called cubes, which stores all the cubes from a particular night.
        # Store all the cubes lists in a list of lists called listsOfCubes.
        # TODO: syntax is fairly ugly; there may be a better way to do this.
        cubes = glob.glob(
            'catfbrsnN*.fits'
        )  # Cubes order at this point is arbitrary so we need to sort.
        cubes.sort(key=lambda x: x[-8:-5]
                   )  # Sort cubes in increasing order by last three digits.

        if cubes:
            listsOfCubes.append(cubes)
        else:
            cubes = glob.glob('cptfbrsnN*.fits')
            if cubes:
                cubes.sort(
                    key=lambda x: x[-8:-5]
                )  # Sort cubes in increasing order by last three digits.
                listsOfCubes.append(cubes)
            else:
                cubes = glob.glob('ctfbrsnN*.fits')
                if cubes:
                    cubes.sort(
                        key=lambda x: x[-8:-5]
                    )  # Sort cubes in increasing order by last three digits.
                    listsOfCubes.append(cubes)
                else:
                    logging.info(
                        "\n+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"
                    )
                    logging.info(
                        "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"
                    )
                    logging.info("")
                    logging.info("     ERROR in merge: no cubes found!")
                    logging.info("")
                    logging.info(
                        "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"
                    )
                    logging.info(
                        "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n"
                    )
                    raise SystemExit
        # Copy cubes to their respective data_obsid directory within Merged.
        for cube in cubes:
            shutil.copy(cube, Merged + '/' + date + '_' + obsid)

        os.chdir(Merged)

    n = 0
    for cubes in listsOfCubes:

        shiftlist = []
        os.chdir(Merged + '/' + obsidlist[n])
        iraffunctions.chdir(Merged + '/' + obsidlist[n])

        if use_pq_offsets:
            # Set the zero point p and q offsets to the p and q offsets of the first cube in each list of cubes.
            header = astropy.io.fits.open(cubes[0])
            p0 = header[0].header['POFFSET']
            q0 = header[0].header['QOFFSET']
            foff = open('offsets.txt', 'w')
            foff.write('%d %d %d\n' % (0, 0, 0))
            foff.close()

        suffix = cubes[0][-8:-5]
        if im3dtran:
            if os.path.exists('transcube' + suffix + '.fits'):
                if not over:
                    logging.info(
                        'Output already exists and -over- not set - skipping im3dtran'
                    )
                if over:
                    os.remove('transcube' + suffix + '.fits')
                    iraf.im3dtran(input=cubes[0] + '[SCI][*,*,-*]',
                                  new_x=1,
                                  new_y=3,
                                  new_z=2,
                                  output='transcube' + suffix)
            else:
                iraf.im3dtran(input=cubes[0] + '[SCI][*,*,-*]',
                              new_x=1,
                              new_y=3,
                              new_z=2,
                              output='transcube' + suffix)
        else:
            iraf.imcopy(cubes[0] + '[SCI][*,*,*]',
                        'NONtranscube' + suffix + '.fits')
        shiftlist.append('cube' + suffix + '.fits')
        iraffunctions.chdir(os.getcwd())

        for i in range(len(cubes)):
            # Skip the first cube!
            if i == 0:
                continue
            header2 = astropy.io.fits.open(cubes[i])
            suffix = cubes[i][-8:-5]

            # If user wants to merge using p and q offsets, grab those from .fits headers.
            if use_pq_offsets:
                # find the p and q offsets of the other cubes in the sequence.
                xoff = header2[0].header['POFFSET']
                yoff = header2[0].header['QOFFSET']
                # calculate the difference between the zero point offsets and the offsets of the other cubes and convert that to pixels
                xShift = round((xoff - p0) / pixScale)
                yShift = round((yoff - q0) / pixScale)
                # write all offsets to a text file (keep in mind that the x and y offsets use different pixel scales)
                foff = open('offsets.txt', 'a')
                if im3dtran:
                    # If we swap the y and lambda axis we must also write the offsets in x, lambda, y.
                    foff.write('%d %d %d\n' % (int(xShift), 0, int(yShift)))
                else:
                    # Write offsets in regular x, y, lambda.
                    foff.write('%d\t%d\t%d\n' % (xShift, yShift, 0.))
                foff.close()

            if im3dtran:
                prefix = 'transcube'
                if os.path.exists('transcube' + suffix + '.fits'):
                    if not over:
                        logging.info(
                            'Output already exists and -over- not set - skipping im3dtran'
                        )
                    if over:
                        os.remove('transcube' + suffix + '.fits')
                        iraf.im3dtran(input=cubes[i] + '[SCI][*,*,-*]',
                                      new_x=1,
                                      new_y=3,
                                      new_z=2,
                                      output='transcube' + suffix)
                else:
                    iraf.im3dtran(input=cubes[i] + '[SCI][*,*,-*]',
                                  new_x=1,
                                  new_y=3,
                                  new_z=2,
                                  output='transcube' + suffix)
            else:
                prefix = 'NONtranscube'
                iraf.imcopy(cubes[i] + '[SCI][*,*,*]',
                            prefix + suffix + '.fits')
            shiftlist.append('cube' + suffix + '.fits')

        if not use_pq_offsets:
            # Before we combine make sure a suitable offsets.txt file exists.
            a = raw_input(
                "\nPaused. Please provide a suitable offsets.txt file in ",
                Merged + '/' + obsidlist[n])
            while not os.path.exists('offsets.txt'):
                a = raw_input("No offsets.txt file found. Please try again.")
            logging.info('offsets.txt found successfully for', obsidlist[n])

        if os.path.exists('cube_merged.fits'):
            if over:
                os.remove('cube_merged.fits')
                iraf.imcombine(prefix + '*',
                               output='cube_merged.fits',
                               combine='median',
                               offsets='offsets.txt')
            else:
                logging.info(
                    'Output already exists and -over- not set - skipping imcombine'
                )
        else:
            iraf.imcombine(prefix + '*',
                           output='cube_merged.fits',
                           combine='median',
                           offsets='offsets.txt')
        if im3dtran:
            # Transpose the cube back to x, y, lambda.
            if os.path.exists('out.fits'):
                if over:
                    os.remove('out.fits')
                    iraf.im3dtran(input='cube_merged[*,-*,*]',
                                  new_x=1,
                                  new_y=3,
                                  new_z=2,
                                  output='out.fits')
                else:
                    logging.info(
                        'Output already exists and -over- not set - skipping final im3dtran'
                    )
            else:
                iraf.im3dtran(input='cube_merged[*,-*,*]',
                              new_x=1,
                              new_y=3,
                              new_z=2,
                              output='out.fits')
            iraf.fxcopy(input=cubes[0] + '[0], out.fits',
                        output=obsidlist[n] + '_merged.fits')
        else:
            iraf.fxcopy(input=cubes[0] + '[0], cube_merged.fits',
                        output=obsidlist[n] + '_merged.fits')
        mergedCubes.append(obsidlist[n] + '_merged.fits')

        n += 1
        os.chdir(Merged)

    # Copy the merged observation sequence data cubes to the Merged directory.
    for i in range(len(mergedCubes)):
        shutil.copy(Merged + '/' + obsidlist[i] + '/' + mergedCubes[i], './')

    # Merge all the individual merged observation sequence data cubes.
    # TODO: test. Still untested.
    """
示例#13
0
import getopt