예제 #1
0
    def fnInferInstrumentResponse(data):
        instrumentResponse = np.empty_like(data)
        nOrders = len(data)
        for order in np.arange(nOrders):
            orderData = data[order]
            orderResponse = instrumentResponse[order]
            orderWave = np.linspace(0, len(orderData) - 1, num=len(orderData))
            fitParams = fnGaussFit(orderWave[np.nonzero(orderData)], orderData[np.nonzero(orderData)], \
                                   GaussParamsInitGuess=[-max(orderData[np.nonzero(orderData)]), len(orderData) / 2,
                                                         len(orderData) / 4, 0.], \
                                   fixed=['Amplitude', 'B'] \
                                   )
            instrumentResponse[order] = fnGauss(orderWave, fitParams)

        return instrumentResponse
예제 #2
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)
예제 #3
0
def main_function():
    fnPrintLine('CONFIG', 'defining "blaze" curve')

    filename = '/home/jmartins/WORK/DataReduction/51Peg_UVES_Martins_et_al_2015/reduced/responseFilesWithGasgano/resampled_science_redl_0000.fits'
    hdulist = fits.open(filename)
    fileData = hdulist[0].data

    def fnInferInstrumentResponse(data):
        instrumentResponse = np.empty_like(data)
        nOrders = len(data)
        for order in np.arange(nOrders):
            orderData = data[order]
            orderResponse = instrumentResponse[order]
            orderWave = np.linspace(0, len(orderData) - 1, num=len(orderData))
            fitParams = fnGaussFit(orderWave[np.nonzero(orderData)], orderData[np.nonzero(orderData)], \
                                   GaussParamsInitGuess=[-max(orderData[np.nonzero(orderData)]), len(orderData) / 2,
                                                         len(orderData) / 4, 0.], \
                                   fixed=['Amplitude', 'B'] \
                                   )
            instrumentResponse[order] = fnGauss(orderWave, fitParams)

        return instrumentResponse

    instrumentResponse = fnInferInstrumentResponse(fileData)

    # for orderData, orderResponse in zip(fileData, response):
    #     orderWave = np.linspace(0, len(orderData) - 1, num = len(orderData));
    #     mplt.plot(orderWave, orderData, 'kd');
    #     mplt.plot(orderWave, orderResponse, 'r');
    #     mplt.show()
    #
    # sys.exit()

    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_SCIENCE'

    # 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']]

    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'] \
                    ]

    for fileName in scienceFiles:
        print fileName

    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(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] / instrumentResponse[order][len(
                            scienceFile[0].data[order])]
                    waveData[order] = fnCreateWave2(scienceFile[0].header,
                                                    order,
                                                    numberOrders=nOrders)

            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 fnGaussFit
                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] = fnGaussFit(
                        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)