*Generate a list of dictionaries which describe if and when a SN is discovered in each and any filter.*

    **Key Arguments:**
        - ``log`` -- logger
        - ``limitingMags`` -- the limiting magnitudes of the survey
        - ``ripeDayList`` -- a list of dictionaries describing the time relative to peak that the SN reaches the limiting mag of the survey
        - ``cadenceDictionary``  -- a dictionary of { band : observedDayList }
        - ``observedFrameLightCurveInfo`` -- the observed franme lightcurve info (dictionary)
        - ``extraConstraints`` -- some extra constraints
        - ``plot`` -- generate plots?

    **Return:**
        - ``discoveredList`` -- a list of dictionaries which describe if and when a SN is discovered in each and any filter.

def determine_if_sne_are_discovered(
        log,
        limitingMags,
        ripeDayList,
        cadenceDictionary,
        observedFrameLightCurveInfo,
        extraSurveyConstraints,
        plot=True):
    """
    *Generate a list of dictionaries which describe if and when a SN is discovered in each and any filter.*

    **Key Arguments:**
        - ``log`` -- logger
        - ``limitingMags`` -- the limiting magnitudes of the survey
        - ``ripeDayList`` -- a list of dictionaries describing the time relative to peak that the SN reaches the limiting mag of the survey
        - ``cadenceDictionary``  -- a dictionary of { band : observedDayList }
        - ``observedFrameLightCurveInfo`` -- the observed franme lightcurve info (dictionary)
        - ``extraConstraints`` -- some extra constraints
        - ``plot`` -- generate plots?

    **Return:**
        - ``discoveredList`` -- a list of dictionaries which describe if and when a SN is discovered in each and any filter.
    """
    ################ > IMPORTS ################
    ## STANDARD LIB ##
    ## THIRD PARTY ##
    import numpy as np
    ## LOCAL APPLICATION ##

    ################ >ACTION(S) ################
    filters = ['g', 'r', 'i', 'z']
    models = ['he80', 'he100', 'he130']
    lunarMonth = 29.3
    surveyYear = 12. * lunarMonth

    surveyDiscoveryDayList = []
    lightCurveDiscoveryDayList = []
    snCampaignLengthList = []
    log.info('ripeDayList %s' % (len(ripeDayList),))
    for item in range(len(ripeDayList)):
        lightCurveEndDay = observedFrameLightCurveInfo[
            item]['endOfLightcurveDay']
        visibleDay = np.random.rand() * surveyYear
        surveyDiscoveryDayDict = {}
        lightCurveDiscoverDayDict = {}
        snCampaignLengthDict = {}
        if not ripeDayList[item]["any"]:
            surveyDiscoveryDayDict["any"] = False
            lightCurveDiscoverDayDict["any"] = False
            snCampaignLengthDict["any"] = False
            for ffilter in filters:
                lightCurveDiscoverDayDict[ffilter] = False
                surveyDiscoveryDayDict[ffilter] = False
                snCampaignLengthDict[ffilter] = False
            # log.info('NOTHING SEEN IN ANY FILTER FOR ITEM %s' % (item,))
            lightCurveDiscoveryDayList.append(lightCurveDiscoverDayDict)
            surveyDiscoveryDayList.append(surveyDiscoveryDayDict)
            snCampaignLengthList.append(snCampaignLengthDict)
        else:
            for ffilter in filters:
                if not ripeDayList[item][ffilter]:
                    surveyDiscoveryDayDict[ffilter] = False
                    lightCurveDiscoverDayDict[ffilter] = False
                    snCampaignLengthDict[ffilter] = False
                    # log.info('item %s, filter %s, NOT DISCOVERED' % (item, ffilter))
                else:
                    if visibleDay > max(cadenceDictionary[ffilter]):
                        waitingTime = surveyYear + \
                            min(cadenceDictionary[ffilter]) - visibleDay
                        surveyDiscoveryDayDict[ffilter] = min(
                            cadenceDictionary[ffilter])
                        cdIndex = 0
                    else:
                        cdIndex = -1
                        for day in cadenceDictionary[ffilter]:
                            cdIndex += 1
                            if day > visibleDay:
                                waitingTime = day - visibleDay
                                surveyDiscoveryDayDict[ffilter] = day
                                break

                    lightCurveDiscoverDayDict[ffilter] = ripeDayList[
                        item][ffilter] + waitingTime
                    if observedFrameLightCurveInfo[item]['lightCurves'][ffilter](lightCurveDiscoverDayDict[ffilter]) > limitingMags[ffilter]:
                        lightCurveDiscoverDayDict[ffilter] = False
                        surveyDiscoveryDayDict[ffilter] = False
                        snCampaignLengthDict[ffilter] = False
                    else:
                        snCampaignLengthDict[ffilter] = 0
                        lcDay = lightCurveDiscoverDayDict[ffilter]
                        cdIndex += 1
                        while 1 > 0:
                            if cdIndex >= len(cadenceDictionary[ffilter]):
                                log.info('item: %s. NEXT YEAR: cdIndex %s, len(cadenceDictionary[ffilter]) %s' % (
                                    item, cdIndex, len(cadenceDictionary[ffilter])))
                                nextLcDay = lcDay + surveyYear + \
                                    min(cadenceDictionary[
                                        ffilter]) - max(cadenceDictionary[ffilter])
                                cdIndex = 1
                            else:
                                log.info('item: %s. SAME YEAR: cdIndex %s, len(cadenceDictionary[ffilter]) %s' % (
                                    item, cdIndex, len(cadenceDictionary[ffilter])))
                                nextLcDay = lcDay + \
                                    cadenceDictionary[ffilter][
                                        cdIndex] - cadenceDictionary[ffilter][cdIndex - 1]
                                cdIndex += 1
                            if observedFrameLightCurveInfo[item]['lightCurves'][ffilter](nextLcDay) < limitingMags[ffilter] and (lightCurveEndDay > nextLcDay):
                                snCampaignLengthDict[
                                    ffilter] += nextLcDay - lcDay
                                log.info('campaign length %s, filter %s' % (
                                    snCampaignLengthDict[ffilter], ffilter))
                                lcDay = nextLcDay
                            else:
                                break

            surveyDiscoveryDayDict['any'] = False
            lightCurveDiscoverDayDict['any'] = False
            snCampaignLengthDict['max'] = 0
            for ffilter in filters:
                if surveyDiscoveryDayDict[ffilter]:
                    surveyDiscoveryDayDict['any'] = True
                    lightCurveDiscoverDayDict['any'] = True
                if snCampaignLengthDict[ffilter] > snCampaignLengthDict['max']:
                    snCampaignLengthDict['max'] = snCampaignLengthDict[ffilter]
            lightCurveDiscoveryDayList.append(lightCurveDiscoverDayDict)
            surveyDiscoveryDayList.append(surveyDiscoveryDayDict)
            snCampaignLengthList.append(snCampaignLengthDict)

    # log.info('surveyDiscoveryDayList %s' % (len(surveyDiscoveryDayList),))
    # log.info('lightCurveDiscoveryDayList %s' % (len(lightCurveDiscoveryDayList),))
    # log.info('snCampaignLengthList %s' % (len(snCampaignLengthList),))

    return lightCurveDiscoveryDayList, surveyDiscoveryDayList, snCampaignLengthList