*Given all the randomly generated parameters of the survey, generate a dictionary of lightcurves for each object (one lightcurve per filter)*

    **Key Arguments:**
        - ``log`` -- logger
        - ``snLightCurves`` -- the sn lightcurve dictionary (with explosion / extinction dates)
        - ``rawLightCurveDict`` -- dictionary of the raw lightcurves (all peaking at mag = 0)
        - ``redshiftArray`` -- array of random redshifts,
        - ``snTypesArray`` --  array of random sn types,
        - ``peakMagnitudesArray`` --  array of random peak mags,
        - ``kCorrectionArray`` -- array of k-corrections,
        - ``hostExtinctionArray`` --  array of random host extinctions,
        - ``galacticExtinctionArray`` --  array of random galactic extinctions,
        - ``restFrameFilter`` -- the observed frame filter with which to calculate k-corrections with
        - ``pathToOutputDirectory`` -- path to the output directory (provided by the user)
        - ``pathToOutputPlotDirectory`` -- path to the output plot directory
        - ``polyOrder`` -- order of the polynomial used to fit the lightcurve
        - ``plot`` -- generate plots?

    **Return:**
        - None

def convert_lightcurves_to_observered_frame(
        log,
        snLightCurves,
        rawLightCurveDict,
        redshiftArray,
        snTypesArray,
        peakMagnitudesArray,
        hostExtinctionArray,
        kCorrectionArray,
        galacticExtinctionArray,
        restFrameFilter,
        pathToOutputDirectory,
        pathToOutputPlotDirectory,
        polyOrder,
        plot=True):
    """
    *Given all the randomly generated parameters of the survey, generate a dictionary of lightcurves for each object (one lightcurve per filter)*

    **Key Arguments:**
        - ``log`` -- logger
        - ``snLightCurves`` -- the sn lightcurve dictionary (with explosion / extinction dates)
        - ``rawLightCurveDict`` -- dictionary of the raw lightcurves (all peaking at mag = 0)
        - ``redshiftArray`` -- array of random redshifts,
        - ``snTypesArray`` --  array of random sn types,
        - ``peakMagnitudesArray`` --  array of random peak mags,
        - ``kCorrectionArray`` -- array of k-corrections,
        - ``hostExtinctionArray`` --  array of random host extinctions,
        - ``galacticExtinctionArray`` --  array of random galactic extinctions,
        - ``restFrameFilter`` -- the observed frame filter with which to calculate k-corrections with
        - ``pathToOutputDirectory`` -- path to the output directory (provided by the user)
        - ``pathToOutputPlotDirectory`` -- path to the output plot directory
        - ``polyOrder`` -- order of the polynomial used to fit the lightcurve
        - ``plot`` -- generate plots?

    **Return:**
        - None
    """
    ################ > IMPORTS ################
    ## STANDARD LIB ##
    ## THIRD PARTY ##
    import numpy as np
    import matplotlib.pyplot as plt
    import math
    import yaml
    ## LOCAL APPLICATION ##
    import dryxPython.astrotools as da
    import dryxPython.plotting as dp

    ################ >ACTION(S) ################
    filters = ['g', 'r', 'i', 'z']
    fileName = pathToOutputDirectory + "/transient_light_curves.yaml"
    stream = file(fileName, 'r')
    generatedLCs = yaml.load(stream)
    models = generatedLCs.keys()
    ebvConverters = {'g': 3.793, 'r': 2.751, 'i': 2.086, 'z': 1.479}
    stepNum = 0

    ###########################################################
    # STEP 1 - CONVERT RAW LIGHTCURVES TO ABSOLUTE MAG CURVES #
    ###########################################################
    stepNum += 1
    stepStr = "%02d" % stepNum
    # CONVERT PEAK MAGS TO POLYNOMIALS
    peakMagPolyList = []
    for item in peakMagnitudesArray:
        thisPoly = np.poly1d([item, ])
        peakMagPolyList.append(thisPoly)

    # CONVERT RAW LIGHTCURVES TO ABSOLUTE MAG CURVES
    absLightCurveList = []
    exampleDictionary = {}

    for item in range(len(snTypesArray)):
        thisModel = snTypesArray[item]
        # explosionDay = snLightCurves[thisModel]['Explosion Day Relative to Peak']
        log.debug('thisModel, restFrameFilter: %s, %s' %
                  (thisModel, restFrameFilter,))
        explosionDay = rawLightCurveDict[thisModel][
            restFrameFilter]['Explosion Day Relative to Peak']
        endOfLightcurveDay = snLightCurves[thisModel][
            'End of lightcurve relative to peak']
        log.info(
            'explosionDay, endOfLightcurveDay for absolute Light Curve: %s, %s' %
            (explosionDay, endOfLightcurveDay))
        absLightCurve = rawLightCurveDict[thisModel][
            restFrameFilter]['poly'] + peakMagPolyList[item]
        absLightCurve = np.poly1d(absLightCurve)
        absLightCurveList.append(absLightCurve)
        exampleDictionary['SN %02d @ z = %04.3f' %
                          (item, redshiftArray[item])] = absLightCurve
    if plot:
        plot_polynomial(
            log,
            title="Absoulte Magnitude Lightcurves - random sample",
            polynomialDict=exampleDictionary,
            orginalDataDictionary=False,
            pathToOutputPlotsFolder=pathToOutputPlotDirectory,
            xRange=[explosionDay, endOfLightcurveDay],
            xlabel="Days Relative to Peak (Rest Frame)",
            ylabel="Absolute Magnitude",
            xAxisLimits=False,
            yAxisLimits=False,
            yAxisInvert=True,
            prependNum=stepNum)

    ################################################################
    # STEP 2 - CONVERT ABSOLUTE LIGHTCURVES TO APPARENT MAG CURVES #
    ################################################################
    stepNum += 1
    stepStr = "%02d" % stepNum
    # CONVERT DISTANCE MOD TO POLYNOMIALS
    distanceModPolyList = []
    for item in redshiftArray:
        log.debug('redshift: %s' % (item,))
        if item == 0.0:
            item = 0.01
        distanceDictionary = da.convert_redshift_to_distance(item)
        distanceMpc = distanceDictionary["dl_mpc"]
        distanceModulus = distanceDictionary["dmod"]
        # log.debug('distanceMpc %s' % (distanceMpc,))
        # log.info('redshift %s = distanceModulus %s' % (item, distanceModulus,))
        thisPoly = np.poly1d([distanceModulus, ])
        distanceModPolyList.append(thisPoly)

    # CONVERT ABSOLUTE LIGHTCURVES TO APPARENT MAG CURVES
    apparentLightCurveList = []
    for item in range(len(snTypesArray)):
        thisModel = snTypesArray[item]
        # explosionDay = snLightCurves[thisModel]['Explosion Day Relative to Peak']
        explosionDay = rawLightCurveDict[thisModel][
            restFrameFilter]['Explosion Day Relative to Peak']
        endOfLightcurveDay = snLightCurves[thisModel][
            'End of lightcurve relative to peak']
        log.info(
            'explosionDay, endOfLightcurveDay for apparent Light Curve: %s, %s' %
            (explosionDay, endOfLightcurveDay))
        apparentLightCurve = absLightCurveList[
            item] + distanceModPolyList[item]
        # log.debug('apparentLightCurve %s' % (apparentLightCurve,))
        apparentLightCurve = np.poly1d(apparentLightCurve)
        apparentLightCurveList.append(apparentLightCurve)
        exampleDictionary['SN %02d @ z = %04.3f' %
                          (item, redshiftArray[item])] = apparentLightCurve
        #log.info('absLightCurveDictionary %s' % (absLightCurveDictionary,))
    if plot:
        plot_polynomial(
            log,
            title="Pre-KCorrection Apparent Magnitude Lightcurves - random sample",
            polynomialDict=exampleDictionary,
            orginalDataDictionary=False,
            pathToOutputPlotsFolder=pathToOutputPlotDirectory,
            xRange=[explosionDay, endOfLightcurveDay],
            xlabel="Days Relative to Peak (Rest Frame)",
            ylabel="Apparent Magnitude",
            xAxisLimits=False,
            yAxisLimits=False,
            yAxisInvert=True,
            prependNum=stepNum)

    ###########################################################
    # STEP 3 - (UN) K-CORRECT THE APPARENT LIGHTCURVES        #
    ###########################################################
    stepNum += 1
    stepStr = "%02d" % stepNum
    # (UN) K-CORRECT THE APPARENT LIGHTCURVES
    kCorApparentLightCurveList = []
    for i in range(len(apparentLightCurveList)):
        thisModel = snTypesArray[i]
        # explosionDay = snLightCurves[thisModel]['Explosion Day Relative to Peak']
        explosionDay = rawLightCurveDict[thisModel][
            restFrameFilter]['Explosion Day Relative to Peak']
        endOfLightcurveDay = snLightCurves[thisModel][
            'End of lightcurve relative to peak']
        log.info(
            'explosionDay, endOfLightcurveDay for unkcor apparent Light Curve: %s, %s' %
            (explosionDay, endOfLightcurveDay))
        kCorDict = kCorrectionArray[i]
        lcDict = {}
        plotLcDict = {}
        for ffilter, poly in kCorDict.iteritems():
            if poly is None:
                kcorLightCurve = None
            else:
                kcorLightCurve = apparentLightCurveList[i] - poly
                plotLcDict[ffilter] = kcorLightCurve
            lcDict[ffilter] = kcorLightCurve
            if plot:
                plot_polynomial(
                    log,
                    title="K(un)corrected Apparent Magnitude Lightcurves - SN Number %s" % (
                        i),
                    polynomialDict=plotLcDict,
                    orginalDataDictionary=False,
                    pathToOutputPlotsFolder=pathToOutputPlotDirectory,
                    xRange=[explosionDay, endOfLightcurveDay],
                    xlabel="Days Relative to Peak (Rest Frame)",
                    ylabel="Apparent Magnitude",
                    xAxisLimits=False,
                    yAxisLimits=False,
                    yAxisInvert=True,
                    prependNum=stepNum)

        kCorApparentLightCurveList.append(lcDict)

    ###########################################################
    # STEP 4 - INCLUDE GALACTIC EXTINCTION IN LIGHTCURVES     #
    ###########################################################
    stepNum += 1
    stepStr = "%02d" % stepNum
    # INCLUDE GALACTIC EXTINCTION
    # CONVERT EXT TO POLYNOMIALS
    galExtPolyList = []
    for ext in galacticExtinctionArray:
        extDict = {}
        for ffilter in filters:
            thisExt = ext * ebvConverters[ffilter]
            # log.info('ext %s, filter %s' % (thisExt, ffilter))
            thisPoly = np.poly1d([thisExt, ])
            extDict[ffilter] = thisPoly
        galExtPolyList.append(extDict)

    # INCLUDE GALAXTIC EXTINTION IN LIGHTCURVES
    galExtLightCurveList = []
    for item in range(len(kCorApparentLightCurveList)):
        thisModel = snTypesArray[item]
        # explosionDay = snLightCurves[thisModel]['Explosion Day Relative to Peak']
        explosionDay = rawLightCurveDict[thisModel][
            restFrameFilter]['Explosion Day Relative to Peak']
        endOfLightcurveDay = snLightCurves[thisModel][
            'End of lightcurve relative to peak']
        log.info(
            'explosionDay, endOfLightcurveDay for galatic extinction corr Frame Light Curve: %s, %s' %
            (explosionDay, endOfLightcurveDay))
        lcDict = {}
        plotLcDict = {}
        for ffilter in filters:
            if kCorApparentLightCurveList[item][ffilter] is not None:
                galExtLightCurve = kCorApparentLightCurveList[
                    item][ffilter] + galExtPolyList[item][ffilter]
                # log.debug('apparentLightCurve %s' % (apparentLightCurve,))
                galExtPoly = np.poly1d(galExtLightCurve)
                plotLcDict[ffilter] = galExtPoly
            else:
                galExtPoly = None
            lcDict[ffilter] = galExtPoly
        if plot:
            plot_polynomial(
                log,
                title="Galactic Extinction Corrected Lightcurves - SN Number %s" % (
                    item),
                polynomialDict=plotLcDict,
                orginalDataDictionary=False,
                pathToOutputPlotsFolder=pathToOutputPlotDirectory,
                xRange=[explosionDay, endOfLightcurveDay],
                xlabel="Days Relative to Peak (Rest Frame)",
                ylabel="Apparent Magnitude",
                xAxisLimits=False,
                yAxisLimits=False,
                yAxisInvert=True,
                prependNum=stepNum)

        galExtLightCurveList.append(lcDict)

    ###########################################################
    # STEP 5 - TIME-DILATE LIGHTCURVES                        #
    ###########################################################
    stepNum += 1
    stepStr = "%02d" % stepNum
    observedFrameLightCurveInfo = []
    peakAppMagList = []
    for item in range(len(redshiftArray)):
        timeDilation = 1. + redshiftArray[item]
        thisModel = snTypesArray[item]
        # explosionDay = snLightCurves[thisModel]['Explosion Day Relative to Peak']*timeDilation
        explosionDay = rawLightCurveDict[thisModel][restFrameFilter][
            'Explosion Day Relative to Peak'] * timeDilation
        endOfLightcurveDay = snLightCurves[thisModel][
            'End of lightcurve relative to peak'] * timeDilation
        log.info(
            'explosionDay, endOfLightcurveDay for observed time dil Frame Light Curve: %s, %s' %
            (explosionDay, endOfLightcurveDay))
        polyDict = {}
        lcPolyDict = {}
        peakMagDict = {}
        floatPeakMagDict = {}

        for ffilter in filters:
            if galExtLightCurveList[item][ffilter] is not None:
                xList = []
                yList = []
                for x in range(int(explosionDay), int(endOfLightcurveDay)):
                    xList.append(x * timeDilation)
                    y = galExtLightCurveList[item][ffilter](x)
                    yList.append(y)

                x = np.array(xList)
                y = np.array(yList)
                thisPoly = np.polyfit(x, y, polyOrder)
                flatPoly = np.poly1d(thisPoly)
                peakMag = flatPoly(0)
                floatPeakMag = float(peakMag)
                polyDict[ffilter] = flatPoly
                peakMagDict[ffilter] = peakMag
                floatPeakMagDict[ffilter] = floatPeakMag
                lcPolyDict[ffilter] = flatPoly
            else:
                polyDict[ffilter] = None
                peakMagDict[ffilter] = None
                floatPeakMagDict[ffilter] = None

        if plot:
            plot_polynomial(
                log,
                title="Observed Lightcurves - SN Number %s" % (item, ),
                polynomialDict=lcPolyDict,
                orginalDataDictionary=False,
                pathToOutputPlotsFolder=pathToOutputPlotDirectory,
                xRange=[explosionDay, endOfLightcurveDay],
                xlabel="Days Relative to Peak (Observed Frame)",
                ylabel="Apparent Magnitude",
                xAxisLimits=False,
                yAxisLimits=False,
                yAxisInvert=True,
                prependNum=stepNum,
                legend=True)

        thisData = {
            'lightCurves': polyDict,
            'peakMags': peakMagDict,
            'explosionDay': explosionDay,
            'endOfLightcurveDay': endOfLightcurveDay}
        # log.info('peakMagDict %s' % (peakMagDict,))
        observedFrameLightCurveInfo.append(thisData)
        peakAppMagList.append(floatPeakMagDict)

    return observedFrameLightCurveInfo, peakAppMagList