Beispiel #1
0
def fnComputeCCF_OLD(fluxOrder, waveOrder, maskOrder, RV, BERV=0.0):
    '''
    fluxOrder    -   flux of spectrum
    waveOrder    -   wavelength solution
    maskOrder    -   binary mask for the CCF
    '''
    fnPrintLine(None,
                'Computing CCF for BERV corrected RV = {:.2f}km/s'.format(RV),
                sameLine=True)
    waveResolution = waveOrder[1] - waveOrder[0]

    fluxOrderPlusOne = np.roll(fluxOrder, -1)

    waveorderPlusOne = np.roll(waveOrder, -1)

    nLines = 0
    lines = []
    CCF = 0.0
    for lineIni, lineEnd, lineDepth in maskOrder:

        lineIniShifted = fnRVLambdaShift(RV, lineIni)

        lineEndShifted = fnRVLambdaShift(RV, lineEnd)

        if waveOrder[0] < lineIniShifted and lineEndShifted < waveOrder[-1]:
            linePixelIni, linePixelEnd = [
                np.where(waveOrder > lineIniShifted)[0][0],
                np.where(waveOrder < lineEndShifted)[0][-1]
            ]

            lineFractionIni = (waveOrder[linePixelIni] -
                               lineIniShifted) / waveResolution
            lineFractionEnd = (lineEndShifted -
                               waveOrder[linePixelEnd]) / waveResolution

            CCF += lineDepth * (
                np.nansum(fluxOrder[linePixelIni:linePixelEnd]) +
                (lineFractionIni) * fluxOrder[linePixelIni - 1] +
                (lineFractionEnd) * fluxOrder[linePixelEnd + 1])
            nLines += 1
            lines.append(lineIniShifted)

    # print ii, lines[0], lines[-1], waveOrder[0], waveOrder[-1]
    # raw_input()

    return CCF, nLines
Beispiel #2
0
def main_function():
    # region --- Define planet parameters




    planetParams = clsPlanetParametersOLD(params={param: value for param, value in cfgFile.items('orbital_params')})
    planetParams.sysRV = 0.0
    # endregion




    # region --- Get files list
    # data files
    fnPrintLine('CCF', 'get ccf list')
    fullCCFList = sorted(
        [os.path.join(scienceInputFolder, fileName) for fileName in os.listdir(scienceInputFolder) \
         if fileName.lower().endswith('fits')])

    # region --- load fits files
    fnPrintLine('CCF', 'Extracting CCFs, please wait')
    fullCCFs = {ccfName: fnOpenHARPSFits(ccfName, headerOnly=True) for ccfName in sorted(fullCCFList)}

    # region --- Finding star CCF parameters
    fnPrintLine('CCF', 'Computing star and planet RVs')
    # define xxx axis

    mplt.ion()
    for ccfName in sorted(fullCCFList):
        fullCCFs[ccfName].PlanetPhaseFolded = ((fullCCFs[
                                                    ccfName].BJD - planetParams.t0) / planetParams.period + np.radians(
            planetParams.w) / (2 * np.pi)) % 1
        fullCCFs[ccfName].RV = fullCCFs[ccfName].RVC = fnRVStarOrbitElipse(planetParams, fullCCFs[
            ccfName].PlanetPhaseFolded - np.radians(planetParams.w) / (2 * np.pi))
        # fullCCFs[ccfName].RV = fullCCFs[ccfName].RVC = fnRVStarOrbitElipse(planetParams, fullCCFs[ccfName].PlanetPhaseFolded - np.radians(planetParams.w)/(2*np.pi))

        fullCCFs[ccfName].planetRV = -fullCCFs[ccfName].RV / planetParams.massRatio

    figTemplate, axTemplate = mplt.subplots(figsize=(12, 8))
    maxFWHM = np.nanmax([fullCCFs[ccfName].FWHM for ccfName in fullCCFList])

    allPoints = axTemplate.plot([fullCCFs[ccfName].PlanetPhaseFolded for ccfName in sorted(fullCCFList)], \
                                [fullCCFs[ccfName].planetRV for ccfName in sorted(fullCCFList)], 'bd', markersize=8)

    axTemplate.grid(b=True, which='major', color='k', linestyle='--', alpha=.5)
    axTemplate.set_ylim(-1.1 * planetParams.k2, 1.1 * planetParams.k2)
    axTemplate.set_yticks(
        np.arange(-(np.floor((1.1 * planetParams.k2) / 10) * 10), ((np.ceil(1.1 * planetParams.k2) / 10) * 10), 10))
    axTemplate.axhline(0.0, label=r'$RV_{CM}$')
    axTemplate.axvline(0.25, label='transit', color='red')
    axTemplate.axvline(0.75, label='opposition', color='green')

    axTemplate.axhline(-2 * maxFWHM, color='blue', alpha=.5, label=r'$2 \times FWHM$')
    axTemplate.axhline(2 * maxFWHM, color='blue', alpha=.5, )

    axTemplate.legend(loc='best', title=r'$\phi = 0$ - Ascending node')
    axTemplate.set_xlim(0, 1)
    axTemplate.set_xticks(np.arange(0, 1, .05))
    axTemplate.set_title('template selection - {}'.format(str(cfgFile.get('global', 'dataFolder'))))
    figTemplate.show()
    # endregion

    # region --- get template file list
    # fnPrintLine('template', 'Use all spectra for template?')
    # customTemplate = raw_input('\t\tyes/no: ').lower()
    selectPoints = 'no'
    while selectPoints == 'no':
        templatePhaseRanges = []
        phaseRange = [0, 1]
        print
        fnPrintLine('template', 'Input planet phase ranges for template')
        fnPrintLine(None, '(leave empty when complete)')
        while phaseRange:
            phaseRange = raw_input('\t\tmin_Phase, max_Phase: ').strip('"')
            if phaseRange:
                templatePhaseRanges.append(
                    [float(phaseRange.strip(' ').split(',')[0]), float(phaseRange.strip(' ').split(',')[-1])])
                templateCCFList = [ccfName for ccfName in sorted(fullCCFList) \
                                   for minPhase, maxPhase in templatePhaseRanges \
                                   if minPhase <= float(fullCCFs[ccfName].PlanetPhaseFolded) <= maxPhase \
                                   ]
                selectedPoints, = axTemplate.plot(
                    [fullCCFs[ccfName].PlanetPhaseFolded for ccfName in sorted(templateCCFList)], \
                    [fullCCFs[ccfName].planetRV for ccfName in sorted(templateCCFList)], 'r*', markersize=16)
                figTemplate.show()

                # mplt.plot([fullCCFs[ccfName].PlanetPhaseFolded for ccfName in sorted(fullCCFList)],\
                #   [fullCCFs[ccfName].planetRV for ccfName in sorted(fullCCFList)], 'bd', markersize = 8)

        fnPrintLine(None, 'Is the selection correct?')
        selectPoints = raw_input('\t\tyes/no: ').lower()

        axTemplate.lines.remove(selectedPoints)

    print

    # endregion

    # endregion

    figData, axData = figTemplate, axTemplate
    axData.set_title('data selection - {}'.format(str(cfgFile.get('global', 'dataFolder'))))
    figData.show()

    selectPoints = 'no'
    while selectPoints == 'no':
        dataRVRanges = []
        phaseRange = [0, 1]
        print
        fnPrintLine('data', 'Input planet phase waveRange for planet recovery')
        fnPrintLine(None, '(leave empty when complete)')
        while phaseRange:
            phaseRange = raw_input('\t\tmin_Phase, max_Phase: ').strip('"')
            if phaseRange:
                dataRVRanges.append(
                    [float(phaseRange.strip(' ').split(',')[0]), float(phaseRange.strip(' ').split(',')[-1])])

            dataCCFList = [ccfName for ccfName in sorted(fullCCFList) \
                           for minPhase, maxPhase in dataRVRanges \
                           if minPhase <= float(fullCCFs[ccfName].PlanetPhaseFolded) <= maxPhase \
                           ]
            selectedPoints, = mplt.plot([fullCCFs[ccfName].PlanetPhaseFolded for ccfName in sorted(dataCCFList)], \
                                        [fullCCFs[ccfName].planetRV for ccfName in sorted(dataCCFList)], 'r*',
                                        markersize=16)
            figTemplate.show()

        fnPrintLine(None, 'Is the selection correct?')
        selectPoints = raw_input('\t\tyes/no: ').lower()
        axData.lines.remove(selectedPoints)
        mplt.show()

    # region --- updating file lists and  config
    fnPrintLine('config', 'updating file lists and  config file')
    with open(
            os.path.join(scienceInputFolder, '{}_templateFileList.txt'.format(cfgFile.get('global', 'resultsFolder'))),
            'w') as templateFileList:
        templateFileList.write('\n'.join([fileName.split('/')[-1] for fileName in templateCCFList]))
        cfgFile.set('detection_settings', 'templateFilelist',
                    '{}_templateFileList.txt'.format(cfgFile.get('global', 'resultsFolder')))

    with open(os.path.join(scienceInputFolder, '{}_dataFilelist.txt'.format(cfgFile.get('global', 'resultsFolder'))),
              'w') as dataFileList:
        dataFileList.write('\n'.join([fileName.split('/')[-1] for fileName in dataCCFList]))
        cfgFile.set('detection_settings', 'dataFilelist',
                    '{}_dataFilelist.txt'.format(cfgFile.get('global', 'resultsFolder')))

    with open(os.path.abspath(sys.argv[1]), 'wb') as cfgFileName:
        cfgFile.write(cfgFileName)

    fnPrintLine('config', 'config file {} has been updated with file lists'.format(os.path.abspath(sys.argv[1])))
Beispiel #3
0
def __main__():
    '''
        Routine to generate esorex commands to reduce UVES data via ESO's reduction recipes:
        1) create master bias - uves_cal_bias
        2) create guess order and line tables - uves_cal_predict
        3) create order table from order guess table  uves_cal_orderpos
        4) create master flat - uves_cal_mflat
        5) create line calibration table from guess table - uves_cal_wavecal
        6) reduce science frame - uves_obs_scired

    :return:
    '''

    # initialise esorex

    try:
        cpl.esorex.init(source=cfgFile.get('global', 'esorexrc'))
    except:
        cpl.esorex.init()
    #
    # cpl.Recipe.path = '/usr/src/debug/uves-5.8.2/recipes'

    # region - Define File Lists ---------------------------------------------------------------------------------------

    # endregion --------------------------------------------------------------------------------------------------------


    # region --- 1) create master bias -     uves_cal_mbias
    fnPrintLine('INIT', 'Recipes to run'.format(','.join([recipe for recipe in recipes2run])))
    recipe = 'uves_cal_mbias'
    if recipe in recipes2run:
        fnPrintLine('CALIB', 'starting {}, please wait...'.format(recipe))
        # get input file list
        recipeFileLists[recipe] = fngetRecipeFileList(recipeName=recipe, \
                                                      dataList=rawData_fileList, \
                                                      keyword=recipeKeywords[recipe]['DPR_TYPE'])

        # setup recipe "uves_cal_mbias"
        clpRecipes[recipe] = fnSetRecipe(recipe, customConfig=cfgFile)

        # run recipe "uves_cal_predict"
        clpResults[recipe] = clpRecipes[recipe](raw={recipeKeywords[recipe]['TAG']: recipeFileLists[recipe]}, \
                                                output_dir=outputFolders[recipe], tmp_dir=tmpFolder)

        clpResults[recipe] = None

        fnPrintLine('CALIB', '{} complete'.format(recipe))

    # endregion --------------------------------------------------------------------------------------------------------

    # region --- 2) create guess order and line tables - uves_cal_predict

    recipe = 'uves_cal_predict'
    if recipe in recipes2run:
        fnPrintLine('CALIB', 'starting {}, please wait...'.format(recipe))
        # get input file list
        recipeFileLists[recipe] = fngetRecipeFileList(recipeName=recipe, \
                                                      dataList=rawData_fileList, \
                                                      keyword=recipeKeywords[recipe]['DPR_TYPE'])

        calibrations_fileList.update(fnUpdateProductList(baseDataFolder_reduced, productList=calibrations_fileList))

        # setup recipe "uves_cal_predict"
        clpRecipes[recipe] = fnSetRecipe(recipe, cfgFile)

        # run recipe "uves_cal_predict"

        clpResults[recipe] = clpRecipes[recipe](raw={recipeKeywords[recipe]['TAG']: recipeFileLists[recipe]}, \
                                                calib=calibrations_fileList, output_dir=outputFolders[recipe],
                                                tmp_dir=tmpFolder)
        clpResults[recipe] = None

        fnPrintLine('CALIB', '{} complete'.format(recipe))

    # endregion --------------------------------------------------------------------------------------------------------

    # region  --- 3) create order table from order guess table      uves_cal_orderpos

    recipe = 'uves_cal_orderpos'
    if recipe in recipes2run:
        fnPrintLine('CALIB', 'starting {}, please wait...'.format(recipe))
        # get input file list
        recipeFileLists[recipe] = fngetRecipeFileList(recipeName=recipe, \
                                                      dataList=rawData_fileList, \
                                                      keyword=recipeKeywords[recipe]['DPR_TYPE'])

        # update calibration lists
        calibrations_fileList.update(fnUpdateProductList(baseDataFolder_reduced, productList=calibrations_fileList))

        # setup recipe "uves_cal_orderpos"
        clpRecipes[recipe] = fnSetRecipe(recipe, cfgFile)

        # run recipe "uves_cal_predict"
        clpResults[recipe] = clpRecipes[recipe](raw={recipeKeywords[recipe]['TAG']: recipeFileLists[recipe]},
                                                calib=calibrations_fileList, \
                                                output_dir=outputFolders[recipe], tmp_dir=tmpFolder)

        clpResults[recipe] = None

        fnPrintLine('CALIB', '{} complete'.format(recipe))

    # endregion --------------------------------------------------------------------------------------------------------

    # region --- 4) create master flat - uves_cal_mflat
    recipe = 'uves_cal_mflat'
    if recipe in recipes2run:
        fnPrintLine('CALIB', 'starting {}, please wait...'.format(recipe))
        # get input file list
        recipeFileLists[recipe] = fngetRecipeFileList(recipeName=recipe, \
                                                      dataList=rawData_fileList, \
                                                      keyword=recipeKeywords[recipe]['DPR_TYPE'])

        # update calibration lists
        calibrations_fileList.update(fnUpdateProductList(baseDataFolder_reduced, productList=calibrations_fileList))

        # setup recipe
        clpRecipes[recipe] = fnSetRecipe(recipe, cfgFile)

        # run recipe "uves_cal_predict"
        clpResults[recipe] = clpRecipes[recipe](raw={recipeKeywords[recipe]['TAG']: recipeFileLists[recipe]},
                                                calib=calibrations_fileList, \
                                                output_dir=outputFolders[recipe], tmp_dir=tmpFolder)

        clpResults[recipe] = None

        fnPrintLine('CALIB', '{} complete'.format(recipe))

    # endregion --------------------------------------------------------------------------------------------------------

    # region --- 5) create line calibration table from guess table - uves_cal_wavecal
    recipe = 'uves_cal_wavecal'
    if recipe in recipes2run:
        fnPrintLine('CALIB', 'startings {}, please wait...'.format(recipe))
        # get input file list
        recipeFileLists[recipe] = fngetRecipeFileList(recipeName=recipe, \
                                                      dataList=rawData_fileList, \
                                                      keyword=recipeKeywords[recipe]['DPR_TYPE'])

        # update calibration lists
        calibrations_fileList.update(fnUpdateProductList(baseDataFolder_reduced, productList=calibrations_fileList))

        # setup recipe "uves_cal_mflat"
        clpRecipes[recipe] = fnSetRecipe(recipe, cfgFile)

        print outputFolders[recipe]

        # run recipe "uves_cal_predict"
        clpResults[recipe] = clpRecipes[recipe](raw={recipeKeywords[recipe]['TAG']: recipeFileLists[recipe]},
                                                calib=calibrations_fileList, \
                                                output_dir=outputFolders[recipe], tmp_dir=tmpFolder)

        clpResults[recipe] = None


        fnPrintLine('CALIB', '{} complete'.format(recipe))

    # endregion --------------------------------------------------------------------------------------------------------

    # region --- 6) reduce science frame - uves_obs_scired

    recipe = 'uves_obs_scired'
    if recipe in recipes2run:
        fnPrintLine('SCIENCE', 'starting {}, please wait...'.format(recipe))

        # get input file list
        recipeFileLists[recipe] = fngetRecipeFileList(recipeName=recipe, \
                                                      dataList=rawData_fileList, \
                                                      keyword=recipeKeywords[recipe]['DPR_TYPE'])

        # update calibration lists
        calibrations_fileList.update(fnUpdateProductList(baseDataFolder_reduced, productList=calibrations_fileList))

        # setup recipe "uves_obs_scired"
        clpRecipes[recipe] = fnSetRecipe(recipe, cfgFile)

        # run recipe "uves_obs_scired"
        for scienceFile in recipeFileLists[recipe]:
            fnPrintLine('SCIENCE', '{}: reducing {}'.format(recipe, scienceFile.split('/')[-1]))
            clpResults[recipe] = clpRecipes[recipe](raw={recipeKeywords[recipe]['TAG']: [scienceFile]},
                                                    calib=calibrations_fileList, \
                                                    output_dir=os.path.join(outputFolders[recipe],
                                                                            fits.getheader(scienceFile)['DATE-OBS']),
                                                    tmp_dir=tmpFolder)

            clpResults[recipe] = None

        fnPrintLine('SCIENCE', '{} complete'.format(recipe))

    # endregion

    # region --- 7) create blaze file
    recipe = 'uves_cal_blaze'
    if recipe in recipes2run:
        fnPrintLine('BLAZE', 'starting {}, please wait...'.format(recipe))

        # get input file list
        reducedFileList = [filenameFull \
                           for root, dirs, files in os.walk(outputFolders['uves_obs_scired'], topdown=False) \
                           for filenameFull in [os.path.join(root, filename) for filename in files] \
                           if filenameFull.endswith('.fits')\
                           and 'WCALIB_FLAT'.lower() in fits.getheader(filenameFull)['HIERARCH ESO PRO CATG'].lower()\
                           ]

        for flatFile in reducedFileList:
            fnPrintLine('BLAZE', '{}: creating blaze from {}'.format(recipe, flatFile.split('/')[-1]))
            flatFits = fits.open(flatFile)

            blazeData = fnInferInstrumentResponse(flatFits[0].data,float(cfgFile.get(recipe, 'window')))
            blazeheader = flatFits[0].header
            # ii=0
            # for orderData, instData in zip(flatFits[0].data,blazeData):
            #     mplt.plot(orderData, 'bo')
            #     mplt.plot(instData, 'r')
            #     mplt.title('order %s' %ii)
            #     mplt.show()
            #     ii+=1

            blazeheader['HIERARCH ESO PRO CATG'] = flatFits[0].header['HIERARCH ESO PRO CATG'].replace('FLAT', 'BLAZE')
            blazeheader['HIERARCH BLAZE WINDOW'] = (float(cfgFile.get(recipe, 'window')), 'blaze moving average window in pixels')


            writeNameBlaze = os.path.join(*[outputFolders['uves_obs_scired'],flatFile.split('/')[-2],\
                                          'blaze_{}.fits'.format(flatFits[0].header['HIERARCH ESO PRO CATG'].split('_')[-1].lower())])


            fits.writeto(writeNameBlaze,blazeData,blazeheader, clobber=True)

        fnPrintLine('BLAZE', '{} complete'.format(recipe))




    # endregion
    return
Beispiel #4
0
def main_function():
    '''
        Routine to generate esorex commands to reduce UVES data via ESO's reduction recipes:
        1) create master bias - uves_cal_bias
        2) create guess order and line tables - uves_cal_predict
        3) create order table from order guess table  uves_cal_orderpos
        4) create master flat - uves_cal_mflat
        5) create line calibration table from guess table - uves_cal_wavecal
        6) reduce science frame - uves_obs_scired

    :return:
    '''

    # region - Define File Lists ---------------------------------------------------------------------------------------
    fnPrintLine('FILES', 'Defining file lists')
    # science/data files
    scienceFileList = [filename for filename in rawFileList \
                       if 'OBJECT,POINT'.lower() in fits.getheader(filename)['HIERARCH ESO DPR TYPE'].lower()]

    # bias files
    biasFileList = [filename for filename in rawFileList \
                    if 'BIAS'.lower() in fits.getheader(filename)['HIERARCH ESO DPR TYPE'].lower()]

    # flat files
    flatFileList = [filename for filename in rawFileList \
                    if 'FLAT'.lower in fits.getheader(filename)['HIERARCH ESO DPR TYPE'].lower()]

    esorexBaseString = 'esorex --config={esorexCfg} --recipe-config={recipeSettings} {recipeName} {fileList} \n'

    # endregion --------------------------------------------------------------------------------------------------------

    # Generate reduction scripts

    # region --- 1) create master bias -     uves_cal_mbiasls
    python

    fnCreateFolder('{}/masterBias/'.format(baseReducedDataFolder))
    # writing file list
    masterBiasFileList = '{}/fileList_uves_cal_mbias.sof'.format(scriptsFolder)

    with open(masterBiasFileList, 'w') as writeFile:
        writeFile.write('\n'.join(biasFileList))

    print '\n'.join(biasFileList)

    # writing esorex settings file
    with open(esorexSettings, 'r') as esorexDefaultsFile:
        esorexDefaults = str(esorexDefaultsFile.read())

    esorexSettings_uves_cal_mbias = esorexDefaults.replace(
        'DEFAULT_OUTPUT_DIR', '{}/masterBias/'.format(baseReducedDataFolder))
    esorexSettings_uves_cal_mbias = esorexSettings_uves_cal_mbias.replace(
        'DEFAULT_OUTPUT_PREFIX', 'masterBias')
    esorexSettingsFile_uves_cal_mbias = '{}/esorex_uves_cal_mbias.cfg'.format(
        scriptsFolder)

    with open(esorexSettingsFile_uves_cal_mbias, 'w') as writeFile:
        writeFile.write(esorexSettings_uves_cal_mbias)

    esorexCommands_uves_cal_mbias = esorexBaseString.format( \
        esorexCfg=esorexSettingsFile_uves_cal_mbias, \
        recipeSettings=os.path.abspath(settings.uves_cal_mbias), \
        recipeName='uves_cal_mbias', \
        fileList=masterBiasFileList)

    print esorexCommands_uves_cal_mbias

    # endregion --------------------------------------------------------------------------------------------------------

    # region --- 2) create guess order and line tables - uves_cal_predict

    # esorex_uves_cal_predict = esorexBaseString.format(esorexSettings, recipeSettingsFile, 'uves_cal_predict',
    #                                                  fileListUvesObsScired))

    # endregion --------------------------------------------------------------------------------------------------------

    # region  --- 3) create order table from order guess table      uves_cal_orderpos

    # esorex_uves_cal_orderpos = esorexBaseString.format(esorexSettings, recipeSettingsFile, 'uves_cal_orderpos',
    #                                                  fileListUvesObsScired))

    # endregion --------------------------------------------------------------------------------------------------------

    # region --- 4) create master flat - uves_cal_mflat

    # esorex_uves_cal_mflat = esorexBaseString.format(esorexSettings, recipeSettingsFile, 'uves_cal_mflat',
    #                                                  fileListUvesObsScired))

    # endregion --------------------------------------------------------------------------------------------------------

    # region --- 5) create line calibration table from guess table - uves_cal_wavecal

    # esorex_uves_cal_wavecal = esorexBaseString.format(esorexSettings, recipeSettingsFile, 'uves_cal_wavecal',
    #                                                  fileListUvesObsScired))

    # endregion --------------------------------------------------------------------------------------------------------

    # region --- 6) reduce science frame - uves_obs_scired

    # esorex_uves_obs_scired = esorexBaseString.format(esorexSettings, recipeSettingsFile, 'uves_obs_scired', fileListUvesObsScired))

    # endregion

    # print 'Create ESOREX scripts'
    #
    # # Create settings for esorex
    # with open('{}/scripts/defaults/esorex.cfg'.format(ReductPath)) as defaultEsorexFile:
    #     defaultEsorex = defaultEsorexFile.read()
    #
    # # create settings for recipe
    # with open('{}/scripts/defaults/{}.cfg'.format(ReductPath, settings.recipeName)) as defaultRecipeFile:
    #     customRecipe = defaultRecipeFile.read()
    #
    # with open(recipeSettings,'w') as customRecipeFile:
    #     customRecipeFile.write(customRecipe)
    #
    #
    #
    # # Create SOF files for esorex - standard calibration files
    # stdCalibsString = ''
    # for filename in stdCalibrationFilelist:
    #     headerSTDCalib  =   fits.getheader('{}/RawData/UVESCalibrationFiles/{}'.format(WorkPath,filename))
    #     stdCalibsString   +=  '{}/RawData/UVESCalibrationFiles/{}\t{}\n'.format(WorkPath, filename, headerSTDCalib['HIERARCH ESO PRO CATG'])
    #
    #
    # # Create SOF files for esorex - raw night calibration files
    # rawCalibrationFileList = [filename for filename in rawFileList if 'CALIB' in fits.getheader('{}/{}'.format(baseRawDataFolder, filename))['HIERARCH ESO DPR CATG']]
    # rawSOFCalibrationString = stdCalibsString
    #
    # for filename in rawCalibrationFileList:
    #     headerFile  =   fits.getheader('{}/{}'.format(baseRawDataFolder, filename))
    #     header = fnClassificationRules_UVES(headerFile)
    #     rawSOFCalibrationString   +=  '{}/{}\t{}\n'.format(baseRawDataFolder,filename, header['D0.CATG'])
    #
    #
    # # Create SOF files for esorex -  raw science files
    # rawScienceFileList = [filename for filename in rawFileList if 'SCIENCE' in fits.getheader('{}/{}'.format(baseRawDataFolder, filename))['HIERARCH ESO DPR CATG']]
    #
    # esorexCommand = ''
    # for filename in rawScienceFileList:
    #     print filename
    #
    #     rawScienceFileKey = 'UVES.{}.{}'.format(header['DATE-OBS'], header['HIERARCH ESO INS PATH '])
    #     rawScienceString = rawSOFCalibrationString
    #     headerFile  =   fits.getheader('{}/{}'.format(baseRawDataFolder, filename))
    #     header = fnClassificationRules_UVES(headerFile)
    #     rawScienceString   +=  '{}/{}\t{}\n'.format(baseRawDataFolder,filename, header['D0.CATG'])
    #
    #     esorexSettings = '{}/scripts/customESOREX_{}_{}.cfg'.format( ReductPath,settings.rawDataFolder, rawScienceFileKey)
    #     customESOREX = defaultEsorex.replace('DEFAULT_OUTPUT_DIR', '{}/reduced/{}/'.format(WorkPath, settings.rawDataFolder))
    #     customESOREX = customESOREX.replace('DEFAULT_OUTPUT_PREFIX', rawScienceFileKey)
    #
    #     with open(esorexSettings,'w') as customEsorexFile:
    #         customEsorexFile.write(customESOREX)
    #
    #     print '\n\ncustom esorex settings file has been created: {}\n\n'.format(esorexSettings)
    #
    #
    #     sofSettings = '{}/scripts/rawFiles2Reduce_{}_{}.sof'.format(ReductPath,settings.rawDataFolder,rawScienceFileKey)
    #
    #     with open(sofSettings,'w') as sofFile:
    #         sofFile.write(rawScienceString)
    #
    #     print '\n\nlist of raw data files to be reduced has been created: {}\n\n'.format(rawScienceFileKey)
    #
    #
    #
    #     # full esorex command
    #     esorexCommand += 'esorex --config={0} --recipe-config={1} {2} {3} \n'.format(esorexSettings, recipeSettings,settings.recipeName, sofSettings )
    #
    #
    # with open(esorexCommandfilename,'a') as esorexCommandFile:
    #     esorexCommandFile.write(esorexCommand)
    #
    #
    # print '\n\nto reduce your data please run: {}\n\n{}\n'.format(esorexCommandfilename , esorexCommand)

    return
Beispiel #5
0
# endregion


# region --- User Modules

from modules.InOut import fnPrintLine
from modules.recipeTools import fnSetRecipe
from modules.fileManip import fngetRecipeFileList, fnUpdateProductList
from modules.spectraTools import fnInferInstrumentResponse

# endregion

# region --- Init Terminal
os.system("cls")
os.system("clear")
fnPrintLine(None, '')
fnPrintLine(None, '', align='center', flush='=')
fnPrintLine(None, 'reduce UVES data CPL wrapper \t(version: {:<})'.format(__version__), align='center')
# fnPrintLine(None, '', align = 'center', flush = '=')
fnPrintLine(None, '')
fnPrintLine(None, 'Author:{:<} \temail: {:<}'.format(__author__, __email__), align='center')
fnPrintLine(None, '')
fnPrintLine(None, 'Last Update:{:<}'.format(__date__), align='center')
fnPrintLine(None, '')
fnPrintLine(None, '', align='center', flush='=')
fnPrintLine(None, '')

# endregion

# region --- Parse Settings
cfgFileName = sys.argv[1]
Beispiel #6
0
def main_function():
    print 'Recover planet CCFs'
    fnPrintLine('CCF', 'Extracting CCFs, please wait')

    fullCCFList = sorted([
        '{}/{}'.format(scienceInputFolder, fileName)
        for fileName in os.listdir(scienceInputFolder)
        if fileName.endswith('REDR_ccf.fits')
    ])

    fullCCFs = {
        ccfName: clsUVESCCF(ccfName)
        for ccfName in sorted(fullCCFList)
    }

    fnPrintLine('Config', 'Extracting planet parameters')
    planetParams = clsPlanetParametersOLD(
        fnGetYOrbit('{}/{}'.format(scienceInputFolder, settings.orbitParams)))

    print planetParams.__dict__
    # sys.exit()

    phaseZero = 0.5
    # planetRVs = {}

    FIX = True

    # =======================================================================
    fnPrintLine('CCF', 'getting planet RVS')
    rangeRVPixels = np.linspace(0,
                                len(fullCCFs[fullCCFList[0]].data) - 1,
                                len(fullCCFs[fullCCFList[0]].data))

    for ccfName in sorted(fullCCFList):
        if FIX == True:
            fullCCFs[ccfName].getPhase(planetParams.period, planetParams.t0)
            fullCCFs[ccfName].RV = fnRVStarOrbitCircular(
                planetParams, phaseZero, fullCCFs[ccfName].PlanetPhaseFolded)
            fullCCFs[ccfName].RVC = fullCCFs[ccfName].RV
        else:
            fullCCFs[ccfName].RV -= planetParams.Sysrv + .4
            fullCCFs[ccfName].RVC = fullCCFs[ccfName].RV

        # fullCCFs[ccfName].planetRV = -(fullCCFs[ccfName].RV )/planetParams.massratio
        # fullCCFs[ccfName].planetRVPixels

        fullCCFs[ccfName].ccfAmplitude, fullCCFs[
            ccfName].ccfMeanPixel, fullCCFs[ccfName].ccfFWHMPixels, fullCCFs[
                ccfName].ccfB = fnGaussianFitOLD(
                    rangeRVPixels,
                    fullCCFs[ccfName].data,
                    GaussParamsInitGuess=[
                        max(fullCCFs[ccfName].data) -
                        min(fullCCFs[ccfName].data),
                        len(fullCCFs[ccfName].data) / 2, 10.,
                        max(fullCCFs[ccfName].data)
                    ])
        fullCCFs[ccfName].planetRV = -(
            fullCCFs[ccfName].RV) / planetParams.massratio
        fullCCFs[ccfName].planetRVMeanPixel = (
            fullCCFs[ccfName].planetRV - fullCCFs[ccfName].RVC
        ) / fullCCFs[ccfName].CCFStep + fullCCFs[ccfName].ccfMeanPixel

        fullCCFs[ccfName].CCFWaveIni = fullCCFs[ccfName].RV - fullCCFs[
            ccfName].ccfMeanPixel * fullCCFs[ccfName].CCFStep

        fullCCFs[ccfName].wave = np.arange(len(fullCCFs[ccfName].data), dtype=np.float64) * fullCCFs[ccfName].CCFStep + \
                                 fullCCFs[ccfName].CCFWaveIni
        # print fullCCFs[ccfName].ccfMeanPixel, fullCCFs[ccfName].planetRVMeanPixel/

    # =======================================================================
    fnPrintLine('CCF', 'Building template')
    # starTemplateList = sorted(fullCCFList) #fnGetTemplateList('All', sorted(fullCCFList), fullCCFs, planetRVs.values(),planetParams)

    starTemplate, starTemplateWave, starTemplateMeanPixel = fnBuildStarTemplateNew(
        fullCCFs)

    templateA, templateMeanPixel, templateFWHM, templateB = fnGaussianFitOLD(
        rangeRVPixels,
        starTemplate,
        GaussParamsInitGuess=[
            max(starTemplate) - min(starTemplate),
            len(starTemplate) / 2, 10.,
            max(starTemplate)
        ])

    # =======================================================================
    planetCCF = []
    for ccfName in sorted(fullCCFList):

        diffPixels = (templateMeanPixel - fullCCFs[ccfName].ccfMeanPixel
                      )  # * fullCCFs[ccfName].CCFStep
        shiftedTemplate = fnShiftCCF(starTemplate, starTemplateWave,
                                     diffPixels)

        fullCCFs[ccfName].normCCF(shiftedTemplate)

        # fullCCFs[ccfName].data[int(starMeanPixel-25):int(starMeanPixel+25)] = None
        # fullCCFs[ccfName].data = fnShiftCCF(fullCCFs[ccfName].data, fullCCFs[ccfName].wave, planetRVs[ccfName] )

        planetXXXRange = np.where(
            (fullCCFs[ccfName].wave < fullCCFs[ccfName].planetRV + 40)
            & (fullCCFs[ccfName].wave > fullCCFs[ccfName].planetRV - 40))

        if fullCCFs[ccfName].planetRV - fullCCFs[ccfName].RV > 50:
            planetCCF.append(fullCCFs[ccfName].data[planetXXXRange][:80])
            mplt.plot(fullCCFs[ccfName].wave, fullCCFs[ccfName].data)
            # fullCCFs[ccfName].data[planetXXXRange] = max(fullCCFs[ccfName].data)

    mplt.savefig('{}/{}_normalisedCCFs.png'.format(scienceOuputFolder,
                                                   settings.ccfFolder))
    mplt.clf()

    mplt.imshow(np.array(
        [fullCCFs[ccfName].data for ccfName in sorted(fullCCFList)]),
                cmap='Greys')

    mplt.savefig('{}/{}_2D_normCCFs_noOrbit.png'.format(
        scienceOuputFolder, settings.ccfFolder))
    mplt.clf()
    iii = np.arange(len(fullCCFList))
    for ccfName, ii in zip(sorted(fullCCFList), iii):
        mplt.plot(fullCCFs[ccfName].planetRVMeanPixel, ii, 'ro')

    mplt.ylim([len(fullCCFList) - 1, 0])
    mplt.xlim([0, len(starTemplate) - 1])

    mplt.savefig('{}/{}_2D_normCCFs_withOrbit.png'.format(
        scienceOuputFolder, settings.ccfFolder))
    mplt.clf()

    finalCCF = np.nansum(planetCCF, axis=0)
    finalCCF = finalCCF / np.nanmedian(finalCCF) - 1
    mplt.plot(np.linspace(-50, 50, num=len(finalCCF)), finalCCF)
    mplt.axhline(1.e-5, color='r')
    mplt.axhline(-1.e-5, color='r')
    axFinalCCF = mplt.gca()
    axFinalCCF.ticklabel_format(useOffset=False)

    mplt.savefig('{}/{}_FinalPlanetCCFs.png'.format(scienceOuputFolder,
                                                    settings.ccfFolder))
    mplt.clf()
Beispiel #7
0
def __main__():
    # region -- getting file lists
    fnPrintLine('CONFIG', 'Getting file list, please wait')

    specType = 'WCALIB_SCI'

    try:
        fnPrintLine(
            'Config',
            'list of data files provided: {}'.format(settings.dataList))
        scienceFiles = np.genfromtxt('{}/{}'.format(scienceInputFolder,
                                                    settings.dataList),
                                     dtype=str)

        scienceFiles = [fileName for fileName in scienceFiles \
                        if specType in fits.getheader('{}/{}'.format(scienceInputFolder, fileName))[
                            'HIERARCH ESO PRO CATG']
                        ]

    except:
        fnPrintLine(
            'Config',
            'no data file list file provided, creating CCF for all files.')
        scienceFiles = ['{}/{}'.format(root, fileName) for root, dir, fileNames in
                    os.walk(scienceInputFolder, topdown=False) \
                    for fileName in fileNames \
                    if specType in fits.getheader('{}/{}'.format(root, fileName))['HIERARCH ESO PRO CATG'] \
                    ]

    ccfProcessedList = [
        '{}/{}'.format(scienceOuputFolder, fileName)
        for fileName in os.listdir(scienceOuputFolder)
    ]

    # endregion

    # region -- processing files
    for fitsFile in scienceFiles:

        fnPrintLine('CONFIG', 'Processing: {}  '.format(fitsFile))

        # region -- building response curves per order
        blazeFile = fits.open(fitsFile.replace('resampled_science_', 'blaze_'))
        instrumentResponse = blazeFile[0].data

        # for instData in instrumentResponse:
        #     mplt.plot(instData, 'bo')
        #     mplt.show()
        # sys.exit()

        # endregion

        # region -- getting science files
        scienceFile = fits.open(fitsFile)
        # endregion

        # region -- setting write names
        rawScienceFileKey = 'UVES.{}.{}{}'.format(
            scienceFile[0].header['DATE-OBS'],
            scienceFile[0].header['HIERARCH ESO INS PATH'],
            scienceFile[0].header['HIERARCH ESO DET OUT1 NAME'])
        ccfWriteFileName = '{}/{}_ccf.fits'.format(scienceOuputFolder,
                                                   rawScienceFileKey)
        # endregion

        # region -- Processing science files
        if ccfWriteFileName in ccfProcessedList:
            fnPrintLine(
                None, '{}_ccf.fits already been processed, skipping.'.format(
                    rawScienceFileKey))

        else:

            nOrders = scienceFile[0].header['NAXIS2']
            fnPrintLine(
                'CONFIG',
                '2D-Spectrum - Number of orders: {:>3} '.format(nOrders))

            # region - Defining science and wave arrays
            scienceData = np.empty((nOrders, scienceFile[0].header['NAXIS1']))
            waveData = np.empty((nOrders, scienceFile[0].header['NAXIS1']))
            for order in np.arange(nOrders):
                scienceData[order] = scienceFile[0].data[
                    order] * instrumentResponse[order]
                waveData[order] = fnCreateWave2(scienceFile[0].header, order)

            fnPrintLine('Mask', 'Building mask')
            maskData = np.genfromtxt('{}/masks/{}.mas'.format(
                ReductPath, cfgFile.get('ccf', 'maskCCF')))
            # endregion

            # region - Compute CCF
            fnPrintLine('CCF', 'Computing CCF for: {}  '.format(fitsFile))
            rangeRV = np.arange(
                float(cfgFile.get('ccf', 'guessRV')) -
                float(cfgFile.get('ccf', 'windowCCF')) -
                scienceFile[0].header['HIERARCH ESO QC VRAD BARYCOR'],
                float(cfgFile.get('ccf', 'guessRV')) +
                float(cfgFile.get('ccf', 'windowCCF')) -
                scienceFile[0].header['HIERARCH ESO QC VRAD BARYCOR'],
                float(cfgFile.get('ccf', 'stepCCF')))

            rangeCCF = np.empty((nOrders, len(rangeRV)))
            nLinesPerOrder = np.empty(nOrders)
            for order in np.arange(nOrders):
                fnPrintLine(
                    'CCF',
                    'Computing CCF for order {:>3}/{:<3}         '.format(
                        order + 1, nOrders))
                nonZeroRange = np.nonzero(scienceData[order])
                rangeCCF[order], nLines = zip(*[
                    fnComputeCCF(scienceData[order][nonZeroRange],
                                 waveData[order][nonZeroRange], maskData,
                                 testRV) for testRV in rangeRV
                ])
                nLinesPerOrder[order] = np.nanmin(nLines)
                fnPrintLine(None, 'Number of lines used for order {:>3}/{:<3}: {:>3.0f}'.format(\
                    order + 1, nOrders,nLinesPerOrder[order]))

            rangeRV += scienceFile[0].header['HIERARCH ESO QC VRAD BARYCOR']

            rangeCCF = np.vstack((rangeCCF, np.nansum(rangeCCF, axis=0)))

            # endregion

            # region - writing CCFs to fits files
            CCFFits = fits.PrimaryHDU()
            CCFFits.header = scienceFile[0].header
            CCFFits.data = rangeCCF

            # NLines per order
            for order in np.arange(nOrders):
                CCFFits.header.set(
                    'HIERARCH ESO DRS CCF LINES %2.f' % order,
                    nLinesPerOrder[order],
                    comment='Num. lines to compute CCF for order %2.f' % order)

            # CCF Params
            CCFFits.header.set('CDELT1',
                               float(cfgFile.get('ccf', 'stepCCF')),
                               comment='step of CCF')
            CCFFits.header.set(
                'CRVAL1',
                rangeRV[0],
                comment='first RV of CCF / beginning of CCF / BERV corrected')

            # fit gauss to summed CCF
            fnPrintLine(
                'CONFIG',
                'Fitting Gaussian to stacked ordersCCF'.format(fitsFile))
            (A, mean, FWHM, B), pcov = opt.curve_fit(
                fnGaussian,
                rangeRV,
                rangeCCF[-1],
                p0=(np.nanmax(rangeCCF[-1]) - np.nanmin(rangeCCF[-1]),
                    float(cfgFile.get('ccf', 'guessRV')), 10.,
                    np.nanmax(rangeCCF[-1])),
                #bounds=fitGaussBounds,
            )

            #print cov#
            (A_Err, mean_Err, FWHM_Err, B_Err) = np.sqrt(np.diag(pcov))

            # Gaussian fit params
            # CCFFits.header.set('HIERARCH ESO DRS CCF RVC', mean+ scienceFile[0].header['HIERARCH ESO QC VRAD BARYCOR'],comment='Computed Radial Velocity of target / mean of gaussian fit')
            CCFFits.header.set(
                'HIERARCH ESO DRS CCF RV',
                mean + scienceFile[0].header['HIERARCH ESO QC VRAD BARYCOR'],
                comment=
                'Computed Radial Velocity of target / mean of gaussian fit')
            CCFFits.header.set(
                'HIERARCH ESO DRS CCF RV ERR',
                mean_Err,
                comment='error on radial velocity of target - to be revised')
            CCFFits.header.set(
                'HIERARCH ESO DRS CCF FWHM',
                FWHM,
                comment='FWHM of fitted CCF / FWHM of gaussian fit')
            try:
                CCFFits.header.set(
                    'HIERARCH ESO DRS CCF FWHM ERR',
                    FWHM_Err,
                    comment=
                    'FWHM of fitted CCF / FWHM of gaussian fit - to be revised'
                )
            except:
                CCFFits.header.set(
                    'HIERARCH ESO DRS CCF FWHM ERR',
                    '-9999.9999',
                    comment=
                    'FWHM of fitted CCF / FWHM of gaussian fit - to be revised'
                )
            CCFFits.header.set('HIERARCH ESO DRS CCF CONTRAST',
                               A / B,
                               comment='Contrast of CCF')

            fits.writeto(ccfWriteFileName,
                         CCFFits.data,
                         CCFFits.header,
                         clobber=True)
            # endregion

            # region - plotting CCFs as pdf
            fnPrintLine(
                'PLOT', 'Saving image as pdf in {}'.format(
                    './tmp/{}_ccfs.pdf'.format(rawScienceFileKey)))
            # define multipage pdf file
            pdfFile = PdfPages('./tmp/{}_ccfs.pdf'.format(rawScienceFileKey))
            # define figures
            # figCCFs = mplt.figure(figsize=(50, 40), dpi=100)
            # figSpectra = mplt.figure(figsize=(50, 40), dpi=100)
            # # define titles
            # figCCFs.suptitle('CCF name key:{}\n'.format(rawScienceFileKey))
            # figSpectra.suptitle('spectrum name key:{}\n'.format(rawScienceFileKey))

            # setup axes and plot data
            for order in np.arange(nOrders):
                figOrder, [axSpectrum,
                           axCCFs] = mplt.subplots(2,
                                                   1,
                                                   figsize=(20, 15),
                                                   dpi=300)

                # axOrderCCFs = figCCFs.add_subplot(int(nOrders / 4) + 1, 4, order + 1)
                # axOrderSpectra = figSpectra.add_subplot(int(nOrders / 4) + 1, 4, order + 1)
                # CCFs ax
                axCCFs.plot(rangeRV,
                            rangeCCF[order] / np.nanmedian(rangeCCF[order]),
                            'b')
                axCCFs.set_xlabel('RV [km/s]', fontsize=20)
                axCCFs.set_xlim(np.nanmin(rangeRV), np.nanmax(rangeRV))

                # spectra ax
                axSpectrum.plot(
                    waveData[order][100:-100], scienceData[order][100:-100] /
                    np.nanmax(scienceData[order][100:-100]), 'b')
                axSpectrum.set_xlabel('wavelength [$\AA$]', fontsize=20)
                axSpectrum.set_xlim(np.nanmin(waveData[order][100:-100]),
                                    np.nanmax(waveData[order][100:-100]))

                # title
                figOrder.suptitle(r'file name: %s' %rawScienceFileKey + '\n' +  \
                             r'Order: %s     N_lines: %.0f     %.2f $\AA < \lambda < %.2f \AA$' \
                                     % (order, nLinesPerOrder[order],waveData[order][0], waveData[order][-1])\
                             , fontsize = 30)
                figOrder.tight_layout()
                figOrder.subplots_adjust(top=.9)
                pdfFile.savefig(figOrder)
                mplt.close(figOrder)

            # axAll = figCCFs.add_subplot(int(nOrders / 4) + 1, 4, 4 * (int(nOrders / 4) + 1))
            wholeCCF = rangeCCF[-1]  #np.nansum(rangeCCF, axis=0)
            figAll, axAll = mplt.subplots(1, 1, figsize=(20, 15), dpi=300)
            axAll.plot(rangeRV, wholeCCF / max(wholeCCF), 'g')
            axAll.set_xlabel('RV [km/s]', fontsize=20)
            axAll.set_xlim(np.nanmin(rangeRV), np.nanmax(rangeRV))
            axAll.text(
                0.05,
                0.05,
                ' Contrast: {:.2f}\n RV: {:.2f} +-{:.2f} km/s\n FWHM: {:.2f} +-{:.2f} km/s'
                .format(A / B, mean, mean_Err, FWHM, FWHM_Err),
                horizontalalignment='left',
                verticalalignment='bottom',
                transform=axAll.transAxes,
                fontsize=40)
            figAll.suptitle(r'file name: %s' %rawScienceFileKey + '\n' +  \
                         'All orders stacked: N_lines: %.0f  $%.2f \AA < \lambda < %.2f \AA$' \
                         % (np.nansum(nLinesPerOrder), waveData[0][0], waveData[-1][-1]),\
                         fontsize = 30)
            figAll.tight_layout()
            figAll.subplots_adjust(top=.9)

            pdfFile.savefig(figAll)
            # figCCFs.tight_layout()
            # figSpectra.tight_layout()
            # pdfFile.savefig(figSpectra)
            # pdfFile.savefig(figCCFs)
            pdfFile.close()
            mplt.close("all")
Beispiel #8
0
    :param FWHM: Full-Width Half-Maximum of gaussian curve
    :param B:fnProgress(
    return m * dataXXX + b
    '''
    return B - Amp * np.exp(-4 * np.log(2) * (((dataXXX - mean) / FWHM)**2))


# endregion

# endregion

# region --- Init Terminal
os.system('cls' if os.name == 'nt' else 'clear')
os.system("cls")
os.system("clear")
fnPrintLine(None, '')
fnPrintLine(None, '', align='center', flush='=')
fnPrintLine(None,
            'Create star+planet CCFs \t(version: {:<})'.format(__version__),
            align='center')
fnPrintLine(None, '')
fnPrintLine(None,
            'Author:{:<} \temail: {:<}'.format(__author__, __email__),
            align='center')
fnPrintLine(None, '')
fnPrintLine(None, 'Last Update:{:<}'.format(__date__), align='center')
fnPrintLine(None, '')
fnPrintLine(None, '', align='center', flush='=')
fnPrintLine(None, '')
# endregion
Beispiel #9
0
def main_function():
    fnPrintLine('CONFIG', 'Getting file list, please wait')

    if settings.specType.lower() == '1d':
        specType = 'RED_SCI_POINT'
        nOrders = 1
    if settings.specType.lower() == '2d':
        specType = 'WCALIB_SCI_POINT'

    try:
        fnPrintLine(
            'Config',
            'list of data files provided: {}'.format(settings.dataList))
        scienceFiles = np.genfromtxt('{}/{}'.format(scienceInputFolder,
                                                    settings.dataList),
                                     dtype=str)

        scienceFiles = [fileName for fileName in scienceFiles \
                        if specType in fits.getheader('{}/{}'.format(scienceInputFolder, fileName))[
                            'HIERARCH ESO PRO CATG']
                        ]

    except:
        fnPrintLine(
            'Config',
            'no data file list file provided, creating CCF for all files.')
        scienceFiles = [
            fileName for fileName in os.listdir(scienceInputFolder)
            if specType in fits.getheader('{}/{}'.format(
                scienceInputFolder, fileName))['HIERARCH ESO PRO CATG']
        ]

    ccfProcessedList = [
        '{}/{}'.format(scienceOuputFolder, fileName)
        for fileName in os.listdir(scienceOuputFolder)
    ]

    # getting flats

    if settings.specType.lower() == '1d':
        specTypeFlat = 'RED_FLAT_OBJ'
        nOrders = 1
    if settings.specType.lower() == '2d':
        specTypeFlat = 'WCALIB_FLAT_OBJ'

    fnPrintLine(
        'Config',
        'no data file list file provided, creating CCF for all files.')
    masterFlatFiles = [
        fileName for fileName in os.listdir(scienceInputFolder)
        if specType in fits.getheader('{}/{}'.format(
            scienceInputFolder, fileName))['HIERARCH ESO PRO CATG']
    ]

    ccfProcessedList = [
        '{}/{}'.format(scienceOuputFolder, fileName)
        for fileName in os.listdir(scienceOuputFolder)
    ]

    for fitsFile in scienceFiles:
        # Getting science data
        fnPrintLine('CONFIG', 'Processing: {}  '.format(fitsFile))
        scienceFile = fits.open('%s/%s' % (scienceInputFolder, fitsFile))

        rawScienceFileKey = 'UVES.{}.{}{}'.format(
            scienceFile[0].header['DATE-OBS'],
            scienceFile[0].header['HIERARCH ESO INS PATH'],
            scienceFile[0].header['HIERARCH ESO DET OUT1 NAME'])

        ccfWriteFileName = '{}/{}_ccf.fits'.format(scienceOuputFolder,
                                                   rawScienceFileKey)

        if ccfWriteFileName in ccfProcessedList:
            fnPrintLine(
                None, '{}_ccf.fits already been processed, skipping.'.format(
                    rawScienceFileKey))

        else:

            try:
                nOrders = scienceFile[0].header['NAXIS2']
                fnPrintLine(
                    'CONFIG',
                    '2D-Spectrum - Number of orders: {:>3} '.format(nOrders))
            except:
                nOrders = 1
                fnPrintLine('CONFIG', '1D-Spectrum')

            # Defining science and wave arrays
            if nOrders == 1:
                scienceData = scienceFile[0].data
                waveData = fnCreateWave2(scienceFile[0].header,
                                         1,
                                         numberOrders=1)
                # mplt.plot(waveData,scienceData)

            elif nOrders > 1:
                scienceData = np.empty(
                    (nOrders, scienceFile[0].header['NAXIS1']))
                waveData = np.empty((nOrders, scienceFile[0].header['NAXIS1']))
                for order in np.arange(nOrders):
                    scienceData[order] = scienceFile[0].data[order]
                    waveData[order] = fnCreateWave2(scienceFile[0].header,
                                                    order,
                                                    numberOrders=nOrders)

            # for order in np.arange(nOrders):
            #     mplt.plot(waveData[order], scienceData[order])
            #
            # mplt.show()
            # sys.exit()

            fnPrintLine('Mask', 'Building mask')
            maskData = np.genfromtxt('{}/masks/{}.mas'.format(
                ReductPath, settings.maskCCF))

            # Compute CCF
            fnPrintLine('CCF', 'Computing CCF for: {}  '.format(fitsFile))

            # rangeRV = np.arange(settings.guessRV-settings.windowCCF + scienceFile[0].header['HIERARCH ESO QC VRAD BARYCOR'], settings.guessRV+settings.windowCCF + scienceFile[0].header['HIERARCH ESO QC VRAD BARYCOR'], settings.stepCCF)

            rangeRV = np.arange(
                settings.guessRV - settings.windowCCF -
                scienceFile[0].header['HIERARCH ESO QC VRAD BARYCOR'],
                settings.guessRV + settings.windowCCF -
                scienceFile[0].header['HIERARCH ESO QC VRAD BARYCOR'],
                settings.stepCCF)

            if nOrders == 1:
                rangeCCF, nLines = zip(*[
                    fnComputeCCF(scienceData, waveData, maskData, testRV)
                    for testRV in rangeRV
                ])
                fnPrintLine(
                    None,
                    'Computing CCF for BERV corrected RV = {:.2f}km/s'.format(
                        rangeRV[-1]))
                mplt.plot(rangeRV, rangeCCF / max(rangeCCF))

            elif nOrders > 1:
                rangeCCF = np.empty((nOrders, len(rangeRV)))
                nLinesPerOrder = np.empty(nOrders)
                for order in np.arange(nOrders):
                    fnPrintLine(
                        'CCF',
                        'Computing CCF for order {:>3}/{:<3}         '.format(
                            order + 1, nOrders))

                    rangeCCF[order], nLines = zip(*[
                        fnComputeCCF(scienceData[order], waveData[order],
                                     maskData, testRV) for testRV in rangeRV
                    ])

                    nLinesPerOrder[order] = np.nanmin(nLines)

                    fnPrintLine(
                        None,
                        'Number of lines used for order {:>3}/{:<3}: {:>3.0f}'.
                        format(order + 1, nOrders, nLinesPerOrder[order]))

            # Fit gaussian CCF

            if nOrders == 1:
                A, mean, FWHM, B = fnGaussianFitOLD(
                    rangeRV,
                    rangeCCF,
                    GaussParamsInitGuess=[
                        max(rangeCCF) - min(rangeCCF), settings.guessRV -
                        scienceFile[0].header['HIERARCH ESO QC VRAD BARYCOR'],
                        10.,
                        max(rangeCCF)
                    ])
            elif nOrders > 1:
                A = np.empty(nOrders)
                mean = np.empty(nOrders)
                FWHM = np.empty(nOrders)
                B = np.empty(nOrders)
                AErr = np.empty(nOrders)
                meanErr = np.empty(nOrders)
                FWHMErr = np.empty(nOrders)
                BErr = np.empty(nOrders)

                from math_local.mathFunctions import fnGaussianFit
                for order in np.arange(nOrders):
                    # A[order], mean[order], FWHM[order], B[order] = fnGaussianFitOLD(rangeRV,rangeCCF[order],GaussParamsInitGuess =[max(rangeCCF[order])- min(rangeCCF[order]), settings.guessRV , 10., max(rangeCCF[order])])
                    A[order], mean[order], FWHM[order], B[order], AErr[
                        order], meanErr[order], FWHMErr[order], BErr[
                            order] = fnGaussianFit(
                                rangeRV,
                                rangeCCF[order],
                                GaussParamsInitGuess=[
                                    max(rangeCCF[order]) -
                                    min(rangeCCF[order]),
                                    settings.guessRV - scienceFile[0].
                                    header['HIERARCH ESO QC VRAD BARYCOR'],
                                    10.,
                                    max(rangeCCF[order])
                                ])

            # building fits file
            CCFFits = fits.PrimaryHDU()
            CCFFits.header = scienceFile[0].header
            CCFFits.data = rangeCCF

            # NLines per order
            for order in np.arange(nOrders):
                CCFFits.header.set(
                    'HIERARCH ESO DRS CCF LINES %2.f' % order,
                    nLinesPerOrder[order],
                    comment='Number of lines used to compute CCF of order %2.f'
                    % order)

            # CCF Params
            CCFFits.header.set('CDELT1',
                               settings.stepCCF,
                               comment='step of CCF')
            CCFFits.header.set('CRVAL1',
                               rangeRV[0],
                               comment='first RV of CCF / beginning of CCF')

            # Gaussian fit params
            # CCFFits.header.set('HIERARCH ESO DRS CCF RVC', mean+ scienceFile[0].header['HIERARCH ESO QC VRAD BARYCOR'],comment='Computed Radial Velocity of target / mean of gaussian fit')
            # CCFFits.header.set('HIERARCH ESO DRS CCF RV', mean+ scienceFile[0].header['HIERARCH ESO QC VRAD BARYCOR'],comment='Computed Radial Velocity of target / mean of gaussian fit')
            # CCFFits.header.set('HIERARCH ESO DRS CCF NOISE', meanErr ,comment='error on radial velocity of target - to be implemented')
            # CCFFits.header.set('HIERARCH ESO DRS CCF FWHM', FWHM ,comment='FWHM of fitted CCF / FWHM of gaussian fit')
            # CCFFits.header.set('HIERARCH ESO DRS CCF CONTRAST', A/B ,comment='Contrast of CCF')

            fits.writeto(ccfWriteFileName,
                         CCFFits.data,
                         CCFFits.header,
                         clobber=True)

            fnPrintLine(
                'PLOT', 'Saving image as pdf in {}'.format(
                    './tmp/{}_ccfs.png'.format(rawScienceFileKey)))
            # mplt.ion()
            fig = mplt.figure(figsize=(100, 80), dpi=50)
            mplt.title(ccfWriteFileName.split('/')[-1])
            for order in np.arange(nOrders):
                axOrder = fig.add_subplot(int(nOrders / 4) + 1, 4, order + 1)
                axOrder.plot(rangeRV, rangeCCF[order] / B[order], 'b')
                gaussFit = fnGauss(
                    rangeRV, [A[order], mean[order], FWHM[order], B[order]])
                axOrder.plot(
                    rangeRV,
                    gaussFit / B[order],
                    'r',
                )
                axOrder.annotate(
                    'Order: %s \n N_lines: %.0f \n %.2f < lambda < %.2f' %
                    (order, nLinesPerOrder[order], waveData[order][0],
                     waveData[order][-1]),
                    xy=(0.95, 0.05),
                    xycoords='axes fraction',
                    va='bottom',
                    ha='right')

            axAll = fig.add_subplot(
                int(nOrders / 4) + 1, 4, 4 * (int(nOrders / 4) + 1))
            wholeCCF = np.nansum(rangeCCF, axis=0)
            axAll.plot(rangeRV, wholeCCF / max(wholeCCF), 'g')
            axAll.annotate(
                'All orders stacked \n N_lines: %.0f \n %.2f < lambda < %.2f' %
                (np.nansum(nLinesPerOrder), waveData[0][0], waveData[-1][-1]),
                xy=(0.95, 0.05),
                xycoords='axes fraction',
                va='bottom',
                ha='right')

            # mplt.draw()

            fig.savefig('./tmp/{}_ccfs.png'.format(rawScienceFileKey),
                        format='png')
            mplt.close(fig)
Beispiel #10
0
def main_function():
    # region --- Define planet parameters
    planetParams = clsPlanetParametersOLD(params={
        param: value
        for param, value in cfgFile.items('orbital_params')
    })
    # endregion

    # region --- Get files list
    # data files
    try:
        # if a list with fits files from which to recover the planet CCF has been provided
        dataCCFList = sorted([os.path.join(scienceInputFolder, fileName) \
                              for fileName in list(
                np.genfromtxt(os.path.join(scienceInputFolder, cfgFile.get('detection_settings', 'dataFilelist')), \
                              dtype=str))])

        fnPrintLine('Config', 'data ccf list file provided: {}'.format( \
            os.path.join(scienceInputFolder, cfgFile.get('detection_settings', 'dataFilelist'))))
    except:
        dataCCFList = sorted([os.path.join(scienceInputFolder, fileName) for fileName in os.listdir(scienceInputFolder) \
                              if fileName.lower().endswith('fits')])

        fnPrintLine('Config',
                    'no data ccf list file provided, using all ccfs.')

    # template files
    try:
        # if a list with fits files from which to construct the template has been provided
        templateCCFList = sorted([os.path.join(scienceInputFolder, fileName) \
                                  for fileName in list(
                np.genfromtxt(os.path.join(scienceInputFolder, cfgFile.get('detection_settings', 'templateFilelist')), \
                              dtype=str))])

        fnPrintLine('Config', 'template ccf list file provided: {}'.format( \
            os.path.join(scienceInputFolder, cfgFile.get('detection_settings', 'templateFilelist'))))
    except:
        templateCCFList = sorted(
            [os.path.join(scienceInputFolder, fileName) for fileName in os.listdir(scienceInputFolder) \
             if fileName.lower().endswith('fits')])
        fnPrintLine('Config',
                    'no template ccf list file provided, using all ccfs.')

    # all files
    fullCCFList = sorted(set(dataCCFList + templateCCFList))

    # endregion

    # region --- load fits files
    fnPrintLine('CCF', 'Extracting CCFs, please wait')
    fullCCFs = {
        ccfName: fnOpenHARPSFits(ccfName)
        for ccfName in sorted(fullCCFList)
    }

    # constrain file lists
    try:
        dataCCFList = [ccfName for ccfName in dataCCFList \
                       if fullCCFs[ccfName].SN50 >= float(cfgFile.get('detection_settings', 'minSN50')) \
                       ]

        templateCCFList = [ccfName for ccfName in templateCCFList \
                           if fullCCFs[ccfName].SN50 >= float(cfgFile.get('detection_settings', 'minSN50')) \
                           ]
    except:
        pass

    # endregion

    # region --- Finding star CCF parameters
    fnPrintLine('CCF', 'finding star CCF parameters')
    # define xxx axis
    rangeRVPixels = np.linspace(0,
                                len(fullCCFs[fullCCFList[0]].data) - 1,
                                len(fullCCFs[fullCCFList[0]].data))

    ccfPixelTrimMargins = 10.  # in pixels

    for ccfName in sorted(fullCCFList):
        fullCCFs[ccfName].ccfAmplitude, fullCCFs[ccfName].ccfMeanPixel, fullCCFs[ccfName].ccfFWHMPixels, fullCCFs[
            ccfName].ccfB = \
            fnGaussianFitOLD(rangeRVPixels, fullCCFs[ccfName].data, \
                             GaussParamsInitGuess=[max(fullCCFs[ccfName].data) - min(fullCCFs[ccfName].data), \
                                                   len(fullCCFs[ccfName].data) / 2, \
                                                   10., \
                                                   max(fullCCFs[ccfName].data)])

        fullCCFs[ccfName].PlanetPhase = (
            fullCCFs[ccfName].BJD - planetParams.t0
        ) / planetParams.period + np.radians(planetParams.w) / (2 * np.pi)
        fullCCFs[ccfName].PlanetPhaseFolded = (
            fullCCFs[ccfName].PlanetPhase) % 1
        fullCCFs[ccfName].RV = fullCCFs[ccfName].RVC = fnRVStarOrbitElipse(
            planetParams, fullCCFs[ccfName].PlanetPhaseFolded -
            np.radians(planetParams.w) / (2 * np.pi))

        fullCCFs[
            ccfName].planetRV = -fullCCFs[ccfName].RV / planetParams.massRatio

        fullCCFs[ccfName].wave = np.arange(-fullCCFs[ccfName].ccfMeanPixel, \
                                           len(fullCCFs[ccfName].data) - fullCCFs[ccfName].ccfMeanPixel) * \
                                 fullCCFs[ccfName].CCFStep + \
                                 fullCCFs[ccfName].RV

    # endregion

    # region --- build template

    fnPrintLine('CCF', 'build star template')

    fullCCFs['template'] = fnBuildStarTemplateOLD(fullCCFs,
                                                  Templates=templateCCFList)
    fullCCFs['template'].CCFStep = fullCCFs[ccfName].CCFStep

    fullCCFs['template'].CCFWaveIni = -fullCCFs['template'].CCFStep * fullCCFs[
        'template'].ccfMeanPixel
    fullCCFs['template'].BJD = 0.0
    fullCCFs['template'].PlanetPhaseFolded = 0.0

    # endregion

    # region --- normalize CCFs by template
    fnPrintLine('CCF', 'normalise by star template')
    dataSelectedCCFList = [
        ccfName for ccfName in sorted(dataCCFList)
        if abs(fullCCFs[ccfName].planetRV - fullCCFs[ccfName].RV) > float(
            cfgFile.get('detection_settings', 'distancePlanetStar'))
    ]

    for ccfName in sorted(fullCCFList):
        templateMeanPixel = fullCCFs['template'].ccfMeanPixel
        starTemplate = fullCCFs['template'].data
        starTemplateWave = fullCCFs['template'].wave

        diffPixels = (templateMeanPixel - fullCCFs[ccfName].ccfMeanPixel)
        shiftedTemplate = fnShiftCCF(starTemplate, starTemplateWave,
                                     diffPixels)

        fullCCFs[ccfName].normCCF(shiftedTemplate)

    # endregion

    # region --- searching for planet
    fnPrintLine('CCF', 'searching for planet, please wait')
    rangeRVsPlanet = {}
    planetWindowHalfWidth = float(
        cfgFile.get('detection_settings', 'planetHalfWidth'))
    for ccfName in sorted(dataCCFList):
        rangeRVsPlanet[ccfName] = np.where( \
            (fullCCFs[ccfName].wave < fullCCFs[ccfName].planetRV + planetWindowHalfWidth) & \
            (fullCCFs[ccfName].wave > fullCCFs[ccfName].planetRV - planetWindowHalfWidth) \
            )

        #fullCCFs[ccfName].planetRVRange = fullCCFs[ccfName].data[rangeRVsPlanet[ccfName]]
        # print fullCCFs[ccfName].planetRVRange[0], len(fullCCFs[ccfName].planetRVRange)

    widthPlanet = np.nanmin([
        len(rangeRVsPlanet[ccfName][0])
        for ccfName in sorted(dataSelectedCCFList)
    ])

    planetCCF = np.nansum([
        fullCCFs[ccfName].data[rangeRVsPlanet[ccfName]][:widthPlanet]
        for ccfName in sorted(dataSelectedCCFList)
    ],
                          axis=0)

    planetWave = np.linspace(-planetWindowHalfWidth,
                             planetWindowHalfWidth,
                             num=len(planetCCF))

    # linear fit - y = m x + c
    m, c = np.polyfit(planetWave, planetCCF, 1)

    YYY = [m * x + c for x in planetWave]
    planetCCF = planetCCF / YYY
    planetCCF /= np.nanmedian(planetCCF)

    # planet CCF fit
    ccfAmplitude, ccfMean, ccfFWHM, ccfB = fnGaussianFitOLD(planetWave, planetCCF, \
                                                            GaussParamsInitGuess=[max(planetCCF) - min(planetCCF), \
                                                                                  0.0, \
                                                                                  10., \
                                                                                  np.nanmedian(planetCCF)]
                                                            )

    planetFit = fnGauss(planetWave, [ccfAmplitude, ccfMean, ccfFWHM, ccfB])

    # endregion

    # region --- correlating different nights
    fnPrintLine('CCF', 'correlation!!!')

    # delete central region of star CCF for better contrast
    # for ccfName in sorted(fullCCFList):

    nightList = sorted(
        set([int(fullCCFs[ccfName].BJD) for ccfName in dataCCFList]))

    ccfListNight = {night:[ccfName for ccfName in sorted(fullCCFList) \
                      if int(fullCCFs[ccfName].BJD) == night] for night in nightList}

    nightCorrelation = {}
    nightTemplates = {
        night: fnBuildStarTemplateOLD(fullCCFs, Templates=ccfListNight[night])
        for night in nightList
    }

    print len(nightList)

    # remove center of CCF
    for night in nightList:
        nightTemplates[night].data[fullCCFs[ccfName].ccfMeanPixel - starWidth * fullCCFs[ccfName].ccfFWHMPixels:\
            fullCCFs[ccfName].ccfMeanPixel + starWidth *fullCCFs[ccfName].ccfFWHMPixels] = None

        # mplt.plot(nightTemplates[night].data)

    # do correlation
    # for nightFirst, nightSecond in zip(nightList[:-1], nightList[1:] ):
    #     print nightFirst, nightSecond
    #     # # ratio = nightTemplates[nightFirst].data/nightTemplates[nightList[0]].data
    #     # # mplt.plot(ratio)
    #     # # mplt.plot()
    #     # # mplt.show()
    #     # correlation = []#np.correlate(nightTemplates[nightFirst].data, nightTemplates[nightSecond].data,mode='full')
    #     # pixRVmax = 2000
    #     # for pixRV in waveRange(0,pixRVmax):
    #     #     # print pixRV
    #     #     correlation.append(np.corrcoef(nightTemplates[nightFirst].data[pixRV:pixRV-pixRVmax], nightTemplates[nightSecond].data[pixRVmax:])[0,1])
    #     #     print np.corrcoef(nightTemplates[nightFirst].data[pixRV:pixRV-pixRVmax], nightTemplates[nightSecond].data[pixRVmax:])
    #     #     print
    #
    #     print np.corrcoef(nightTemplates[nightFirst].data, nightTemplates[nightSecond].data)
    #
    #     mplt.plot(nightTemplates[nightFirst].data)
    #     mplt.plot(nightTemplates[nightSecond].data)
    #
    #     # mplt.plot(correlation, 'ro')
    #     mplt.show()

    # mplt.show()
    # sys.exit()

    # endregion

    # region --- SN and phase function
    fnPrintLine('CCF', 'SN and phase function')
    expectedSN = np.sqrt(
        np.nansum([
            fullCCFs[ccfName].nLines * (fullCCFs[ccfName].SN50**2)
            for ccfName in sorted(dataSelectedCCFList)
        ]))
    measuredNoise = np.nanstd(planetCCF)

    phaseFunction = {
    ccfName: fnPhaseFunction(planetParams.I, fullCCFs[ccfName].PlanetPhaseFolded - .25, model='Lambert') \
    for ccfName in dataSelectedCCFList}

    medianPhaseFunction = np.nanmedian(phaseFunction.values())
    medianStarCCFContrast = np.nanmedian(
        [fullCCFs[ccfName].contrast for ccfName in dataSelectedCCFList])

    albedoLimitNoise = (planetParams.a / planetParams.radiusPlanet)**2 * 1 / (
        medianPhaseFunction) * (measuredNoise)
    albedoLimitCCF = (planetParams.a / planetParams.radiusPlanet)**2 * 1 / (
        medianPhaseFunction) * (ccfAmplitude / medianStarCCFContrast)

    # endregion

    # region --- PERIODOGRAMS
    # fnPrintLine('CCF', 'Periodograms of normalised CCFs')
    # # http://www.hs.uni-hamburg.de/DE/Ins/Per/Czesla/PyA/PyA/pyTimingDoc/pyPeriodDoc/examples.html
    #
    # # periodogram of template
    # fnPrintLine('CCF', 'Periodograms of star template')
    # starMask = np.ones(len(fullCCFs['template'].data), np.bool)
    # starMask[fullCCFs['template'].ccfMeanPixel - 3 * fullCCFs['template'].ccfFWHMPixels: \
    #     fullCCFs['template'].ccfMeanPixel + 3 * fullCCFs['template'].ccfFWHMPixels] = 0
    # fullCCFs['template'].wave = fullCCFs['template'].wave.copy()[starMask]
    # fullCCFs['template'].wave = fullCCFs['template'].wave * fullCCFs['template'].CCFStep + fullCCFs['template'].CCFWaveIni
    #
    #
    # fullCCFs['template'].data = fullCCFs['template'].data.copy()[starMask]
    #
    # periodogramTemplateTimeSeries = pyPeriod.TimeSeries(fullCCFs['template'].wave, fullCCFs['template'].data)
    # periodogramTemplate = pyPeriod.LombScargle(periodogramTemplateTimeSeries, ofac=1, hifac=1)
    #
    #
    #
    # # computes the Lomb Scargle Periodogram of the RV using each frequency as a guess for the planet CCF
    # fnPrintLine('CCF', 'Periodograms of planet CCF')
    #
    # periodogramPlanetCCFTimeSeries = pyPeriod.TimeSeries(planetWave, planetCCF)
    # periodogramPlanetCCF = pyPeriod.LombScargle(periodogramPlanetCCFTimeSeries, ofac=1, hifac=1)
    #
    #
    # powerPeaks = [float(peak) for peak in cfgFile.get('periodograms', 'powerPeaks').strip('[]').split(',')]
    # print powerPeaks
    #
    # for power in powerPeaks:
    #     print power, periodogramPlanetCCF.stats(power)
    #
    # # periodogram of RVs
    # fnPrintLine('CCF', 'Periodograms of RVs')
    #
    # periodogramRVTimeSeries = pyPeriod.TimeSeries(np.array([fullCCFs[ccfName].BJD for ccfName in fullCCFList]), \
    #                                               np.array([fullCCFs[ccfName].RV for ccfName in fullCCFList]))
    # periodogramRV = pyPeriod.LombScargle(periodogramRVTimeSeries, ofac=1, hifac=1)

    # endregion

    # region --- [PLOTS]
    pdfFile = PdfPages(
        os.path.join(
            resultsFolder,
            'figures_{}.pdf'.format(cfgFile.get('global', 'resultsFolder'))))

    # region [PLOT] orbit points
    fnPrintLine('PLOT', 'orbit points')
    figPhases, axPhases = mplt.subplots(2, 1, sharex=True, figsize=(12, 8))

    phasesFullOrbit = np.arange(0., 1., .01)
    rvFullOrbit = [
        -fnRVStarOrbitElipse(planetParams, phase - np.radians(planetParams.w) /
                             (2 * np.pi)) / planetParams.massRatio
        for phase in phasesFullOrbit
    ]

    for ax in axPhases:
        ax.plot([fullCCFs[ccfName].PlanetPhaseFolded for ccfName in sorted(fullCCFList)], \
                [fullCCFs[ccfName].planetRV for ccfName in sorted(fullCCFList)], 'bd', markersize=8)
        ax.grid(b=True, which='major', color='k', linestyle='--', alpha=.3)
        # ax.set_ylim(-1.1*planetParams.k2,1.1*planetParams.k2)
        # ax.axhline(0.0, label= r'$RV_{CM}$')
        ax.axvline(0.25, label='transit', color='red')
        ax.axvline(0.75, label='opposition', color='green')
        ax.legend(loc='best', title='r$\phi = 0$ - Ascending node')
        ax.set_xlim(0, 1)
        ax.set_xticks(np.arange(0, 1, .05))
        ax.plot(phasesFullOrbit, rvFullOrbit, 'b-', alpha=.3, markersize=8)

    # ax template
    axPhases[0].set_title('template points')
    templatePoints = axPhases[0].plot([fullCCFs[ccfName].PlanetPhaseFolded for ccfName in sorted(templateCCFList)], \
                                      [fullCCFs[ccfName].planetRV for ccfName in sorted(templateCCFList)], \
                                      'r*', markersize=16,
                                      label='{} ({} points)'.format('Template', len(templateCCFList)))
    # ax data
    axPhases[1].set_title('data points')
    dataPoints = axPhases[1].plot([fullCCFs[ccfName].PlanetPhaseFolded for ccfName in sorted(dataCCFList)], \
                                  [fullCCFs[ccfName].planetRV for ccfName in sorted(dataCCFList)], \
                                  'r*', markersize=16, label='{} ({} points)'.format('Data', len(dataCCFList)))
    figPhases.tight_layout()

    figPhases.savefig(pdfFile, format='pdf')

    # endregion

    # region [PLOT] template 2D normalised CCFS
    fnPrintLine('PLOT', '2D normalised CCFs')


    maxFlux = np.nanmax([np.nanmax((fullCCFs[ccfName].data / np.nanmedian(fullCCFs[ccfName].data) - 1) * 1000) \
                         for ccfName in fullCCFList])

    minFlux = np.nanmin([np.nanmin((fullCCFs[ccfName].data / np.nanmedian(fullCCFs[ccfName].data) - 1) * 1000) \
                         for ccfName in fullCCFList])

    # plot template nights 2D norm spectra
    fig2DNormCCFsTemplate = fnPlot2DCCFs(
        fullCCFs,
        templateCCFList,
        stellarCCFWidth=starWidth,
        title='normalised CCFs for template construction')
    fig2DNormCCFsTemplate.savefig(pdfFile, format='pdf')

    # endregion

    # region [PLOT] plot data nights 2D norm spectra

    fig2DNormCCFsPlanet = fnPlot2DCCFs(fullCCFs, dataCCFList, stellarCCFWidth = starWidth, title= 'normalised CCFs for planet recovery',\
                                       RVRanges={ccfName:fullCCFs[ccfName].wave[rangeRVsPlanet[ccfName]] for ccfName in dataCCFList})
    fig2DNormCCFsPlanet.savefig(pdfFile, format='pdf')

    # endregion

    # region [PLOT] phase function
    # fnPrintLine('PLOT', 'Phase function')
    # figPhaseFunction, axPhaseFunction = mplt.subplots()
    # phasefunctionFullOrbit = [fnPhaseFunction(planetParams.I, phase + .75, model='Lambert') for phase in
    #                           phasesFullOrbit]
    #
    # axPhaseFunction.plot(phasesFullOrbit, phasefunctionFullOrbit, 'k', alpha=0.5)
    # axPhaseFunction.plot([fullCCFs[ccfName].PlanetPhaseFolded for ccfName in dataSelectedCCFList], \
    #                      [phaseFunction[ccfName] for ccfName in dataSelectedCCFList], 'ro')
    #
    #
    # axPhaseFunction.set_xlim([0, 1])
    # axPhaseFunction.axvline(.75, color='green', label='Opposition')
    # axPhaseFunction.axvline(.25, color='red', label='Transit')
    # axPhaseFunction.axhline(medianPhaseFunction, color='blue',
    #                         label='average phase function:{:.2f}'.format(medianPhaseFunction))
    # axPhaseFunction.set_title('Phase function')
    #
    # figPhaseFunction.savefig(pdfFile, format='pdf')

    # endregion

    # # region [PLOT] Lomb Scargle Periodogram of template ccf
    fnPrintLine('PLOT', 'Lomb Scargle Periodogram of template ccf')
    figPeriodogramNormCCFs, axPeriodogramNormCCFs = mplt.subplots(2, 1)

    axPeriodogramNormCCFs[0].plot(fullCCFs['template'].wave,
                                  fullCCFs['template'].data,
                                  'ko',
                                  markersize=2)
    axPeriodogramNormCCFs[0].yaxis.set_major_formatter( \
        FuncFormatter(lambda y, pos: '{:.0f}'.format((y - np.nanmedian(fullCCFs['template'].data)) * 1e3)))
    axPeriodogramNormCCFs[0].set_xlim(min(fullCCFs['template'].wave),
                                      max(fullCCFs['template'].wave))

    # axPeriodogramNormCCFs[1].plot([1 / freq for freq in periodogramTemplate.freq], periodogramTemplate.power, 'r')
    # axLombscargleNormCCFs[1].text(0.05,0.95, 'max frequency: {:.2f} km/s'.format(periodogramStarTemplateMaxFrequency*fullCCFs[periodogramFileList[0]].CCFStep) ,\
    #                               fontsize = 12, horizontalalignment='left', verticalalignment='top',transform=axLombscargleNormCCFs[1].transAxes)

    axPeriodogramNormCCFs[0].set_title('Template')
    axPeriodogramNormCCFs[1].set_xlabel(r'RV period [km/s]')
    # axPeriodogramNormCCFs[1].set_xscale('log')

    # try:
    #     axPeriodogramNormCCFs[1].set_xlim(float(cfgFile.get('periodograms', 'frequencyTemplateLow')),
    #                                       float(cfgFile.get('periodograms', 'frequencyTemplateHigh')))
    # except:
    #     pass

    figPeriodogramNormCCFs.savefig(pdfFile, format='pdf')

    # endregion

    # region [PLOT] Lomb Scargle Periodogram of recovered planet CCF
    fnPrintLine('PLOT', 'Lomb Scargle Periodogram of recovered planet CCF')
    figPeriodogramPlanetCCF, axPeriodogramPlanetCCF = mplt.subplots(2, 1)

    axPeriodogramPlanetCCF[0].set_title('Planet CCF')
    axPeriodogramPlanetCCF[0].plot(planetWave, planetCCF, 'ko', markersize=1)
    # axPeriodogramPlanetCCF[0].plot(planetWave, fnGauss(planetWave,[ccfAmplitude, ccfMean, ccfFWHM, ccfB]), 'r')
    axPeriodogramPlanetCCF[0].axhline(1 - 1e-5, color='red')
    axPeriodogramPlanetCCF[0].axhline(1 + 1e-5, color='red')
    axPeriodogramPlanetCCF[0].axhline(1 - 1e-4, color='green')
    axPeriodogramPlanetCCF[0].axhline(1 + 1e-4, color='green')
    axPeriodogramPlanetCCF[0].axvline(-3.5, color='magenta')
    axPeriodogramPlanetCCF[0].axvline(3.5, color='magenta')
    axPeriodogramPlanetCCF[0].yaxis.set_major_formatter( \
        FuncFormatter(lambda y, pos: '{:.0f}'.format((y - np.nanmedian(planetCCF)) * 1e6)))
    axPeriodogramPlanetCCF[0].set_ylabel(r'$1-\frac{F_p}{F/*}$[ppm]')
    axPeriodogramPlanetCCF[0].set_xlabel(r'radial velocity [km/s]')

    # axPeriodogramPlanetCCF[1].plot([1 / freq for freq in periodogramPlanetCCF.freq],
    #                                [power for power in periodogramPlanetCCF.power], 'r', markersize=1)
    axPeriodogramPlanetCCF[1].set_xlabel(r'RV period [km/s]')
    # axPeriodogramPlanetCCF[1].set_xscale('log')
    # try:
    #     axPeriodogramPlanetCCF[1].set_xlim(float(cfgFile.get('periodograms', 'frequencyPlanetLow')),
    #                                        float(cfgFile.get('periodograms', 'frequencyPlanetHigh')))
    # except:
    #     pass

    figPeriodogramPlanetCCF.savefig(pdfFile, format='pdf')

    # endregion

    # region [PLOT] RVs and periodogram
    # figPeriodogramRV, axPeriodogramRV = mplt.subplots(2, 1)
    # axPeriodogramRV[0].set_title('Julian date vs Star RV')
    #
    # axPeriodogramRV[0].plot([fullCCFs[ccfName].BJD - 2.45e6 for ccfName in fullCCFList],
    #                         [fullCCFs[ccfName].RV for ccfName in fullCCFList], 'bo')
    # axPeriodogramRV[0].set_xlabel(r'Julian date - 2450 000 [day]')
    # axPeriodogramRV[1].tick_params(axis='x', which='minor', bottom='on')
    # axPeriodogramRV[1].plot([1 / freq for freq in periodogramRV.freq], [power for power in periodogramRV.power], 'r',
    #                         markersize=1)

    # minor_ticks = np.arange(0, max([1 / freq for freq in periodogramRV.freq]), 10)
    # axPeriodogramRV[1].set_xticks(minor_ticks, minor=True)
    # axPeriodogramRV[1].set_xlabel(r'period [day]')

    # axPeriodogramPlanetPhases[1].set_xscale('log')
    #
    # try:
    #     axPeriodogramRV[1].set_xlim(float(cfgFile.get('periodograms', 'frequencyRVLow')),
    #                                 float(cfgFile.get('periodograms', 'frequencyRVHigh')))
    # except:
    #     pass
    #
    # figPeriodogramRV.savefig(pdfFile, format='pdf')

    # endregion

    # region [PLOT] write config parameters
    fnPrintLine('PLOT', 'write config parameters')
    strFormat = '  {:<20s} = {}\n'
    strSettings = ''
    for section_name in cfgFile.sections():
        strSettings += '[{}]\n'.format(section_name)
        for name, value in cfgFile.items(section_name):
            lineLenght = 60
            value = '\n'.join([
                value[ini:ini + lineLenght]
                for ini in np.arange(0, len(value), lineLenght)
            ])
            strSettings += strFormat.format(name, value)
        strSettings += '\n'

    figSettings, axSettings = mplt.subplots(figsize=(8.27, 11.69),
                                            tight_layout=True)
    axSettings.text(0.05, 0.95, strSettings, fontsize=12, \
                    horizontalalignment='left', \
                    verticalalignment='top', \
                    )
    axSettings.axis('off')
    figSettings.savefig(pdfFile, format='pdf')

    # endregion

    # region [PLOT] recovered parameters
    fnPrintLine('PLOT', 'recovered parameters')
    strFormat = '  {:<20s} = {}\n'
    strPlanetRecoveredParams = '[Gauss Parameters]\n'
    strPlanetRecoveredParams += strFormat.format(
        'Amplitude ($A_{CCF}$)', '{:.0f} ppm'.format(ccfAmplitude * 1e6))
    strPlanetRecoveredParams += strFormat.format('Mean',
                                                 '{:.1f} km/s'.format(ccfMean))
    strPlanetRecoveredParams += strFormat.format('FWHM',
                                                 '{:.1f} km/s'.format(ccfFWHM))

    strPlanetRecoveredParams += '\n[Noise]\n'
    strPlanetRecoveredParams += strFormat.format('expected SN50',
                                                 '{:.1e}'.format(expectedSN))
    strPlanetRecoveredParams += strFormat.format(
        'expected noise', '{:.1e}'.format(1 / expectedSN))
    strPlanetRecoveredParams += strFormat.format(
        'measured noise', '{:.1e}'.format(measuredNoise))

    strPlanetRecoveredParams += '\n[Albedo]\n'
    strPlanetRecoveredParams += strFormat.format(
        r'Median Phase function $g(\alpha)$',
        '{:.2f} (maximum at opposition; minimum at transit)'.format(
            medianPhaseFunction))
    strPlanetRecoveredParams += strFormat.format(
        r'Planet radius', '{:.0f} km'.format(planetParams.radiusPlanet))
    strPlanetRecoveredParams += strFormat.format(
        r'semi-major axis', '{:.0f} km'.format(planetParams.a))
    strPlanetRecoveredParams += strFormat.format(
        r'Min albedo [from noise]', '{:.2f}'.format(albedoLimitNoise))
    strPlanetRecoveredParams += '\n\n' + r'$A_g = \left(\frac{a}{R_p}\right)^2 \times\, \frac{1}{avg(g(\alpha))} \times\, noise_{measured}$' + '\n\n'

    strPlanetRecoveredParams += strFormat.format(
        r'median star contrast', '{:.2f}'.format(medianStarCCFContrast))
    strPlanetRecoveredParams += strFormat.format(
        r'Min albedo [from detected "ccf"]', '{:.2f}'.format(albedoLimitCCF))

    strPlanetRecoveredParams += '\n\n' + r'$A_g = \left(\frac{a}{R_p}\right)^2 \times\, \frac{1}{avg(g(\alpha))} \times\, \frac{amplitude_{planet}}{median(contrast_{star})}$' + '\n\n'

    strPlanetRecoveredParams += strFormat.format(
        r'$\left(\frac{R_p}{a} \right)^2$', '{:.1e}'.format(
            (planetParams.radiusPlanet / planetParams.a)**2))

    figParams, axParams = mplt.subplots(figsize=(8.27, 11.69),
                                        tight_layout=True)
    axParams.text(0.05, 0.95, strPlanetRecoveredParams, fontsize=12, \
                  horizontalalignment='left', \
                  verticalalignment='top', \
                  )
    axParams.axis('off')
    figParams.savefig(pdfFile, format='pdf')

    # endregion

    pdfFile.close()
    # endregion

    # region --- [TEXT DATA]
    # region [TEXT DATA] initial configuration parameters
    with open(
            os.path.join(
                resultsFolder, 'initConfigParams_{}.txt'.format(
                    cfgFile.get('global', 'resultsFolder'))),
            'w') as textSettings:
        textSettings.write(strSettings)

    # endregion

    # region [TEXT DATA] Planet CCF
    #
    strFormat = '{:.10f}\t{:.10f}\t{:.10f}\n'
    strPlanetData = strFormat.replace('10f',
                                      '13s').format('# RV', 'planet_flux',
                                                    'ccf_Fit')
    for pixWave, pixPlanet, pixFit in zip(planetWave, planetCCF, planetFit):
        strPlanetData += strFormat.format(pixWave, pixPlanet, pixFit)

    with open(
            os.path.join(
                resultsFolder, 'planetCCFData_{}.txt'.format(
                    cfgFile.get('global', 'resultsFolder'))),
            'w') as textPlanetData:
        textPlanetData.write(strPlanetData)

    # endregion

    # region [TEXT DATA] List of CCFs for template
    strFormat = '{:.50s}\t{:.10f}\t{:.10f}\t{:.10f}\t{:.10f}\n'
    strData = strFormat.replace('10f',
                                '13s').format('# filename', 'BJD', 'Phase',
                                              'star RV', 'planet RV')
    for ccfName in templateCCFList:
        strData += strFormat.format(ccfName.split('/')[-1], fullCCFs[ccfName].BJD, \
                                    fullCCFs[ccfName].PlanetPhaseFolded, fullCCFs[ccfName].RV, \
                                    fullCCFs[ccfName].planetRV)

    with open(
            os.path.join(
                resultsFolder, 'templateListData_{}.txt'.format(
                    cfgFile.get('global', 'resultsFolder'))),
            'w') as textTemplateData:
        textTemplateData.write(strData)

    # endregion

    # region [TEXT DATA] List of CCFs available for planet recovery
    strFormat = '{:.50s}\t{:.10f}\t{:.10f}\t{:.10f}\t{:.10f}\n'
    strData = strFormat.replace('.10f',
                                '.13s').format('# filename', 'BJD', 'Phase',
                                               'star RV', 'planet RV')
    for ccfName in dataCCFList:
        strData += strFormat.format(ccfName.split('/')[-1], fullCCFs[ccfName].BJD, \
                                    fullCCFs[ccfName].PlanetPhaseFolded, fullCCFs[ccfName].RV, \
                                    fullCCFs[ccfName].planetRV)

    with open(
            os.path.join(
                resultsFolder, 'planetRecoveryData_{}.txt'.format(
                    cfgFile.get('global', 'resultsFolder'))),
            'w') as textTemplateData:
        textTemplateData.write(strData)

    # endregion

    # region [TEXT DATA] List of CCFs selected for planet recovery
    strFormat = '{:.50s}\t{:.10f}\t{:.10f}\t{:.10f}\t{:.10f}\n'
    strData = strFormat.replace('10f',
                                '13s').format('# filename', 'BJD', 'Phase',
                                              'star RV', 'planet RV')
    for ccfName in dataSelectedCCFList:
        strData += strFormat.format(ccfName.split('/')[-1], fullCCFs[ccfName].BJD, \
                                    fullCCFs[ccfName].PlanetPhaseFolded, fullCCFs[ccfName].RV, \
                                    fullCCFs[ccfName].planetRV)

    with open(os.path.join(resultsFolder, \
                           'selectedPlanetRecoveryData_{}.txt'.format(cfgFile.get('global', 'resultsFolder'))),
              'w') as textTemplateData:
        textTemplateData.write(strData)

    # endregion

    # region [TEXT DATA] recovered parameters

    with open(
            os.path.join(
                resultsFolder, 'planetRecoveredParams_{}.txt'.format(
                    cfgFile.get('global', 'resultsFolder'))),
            'w') as textSettings:
        textSettings.write(strPlanetRecoveredParams)