Esempio n. 1
0
def getTempData():
    history = Temp_MinMax({}, {})

    for daysOffset in range(-historyDays, 8 + 1):
        date = now + datetime.timedelta(daysOffset)

        history.min[date] = dailyRecords.getInfo(city, date, daily.MIN_TEMP)
        history.max[date] = dailyRecords.getInfo(city, date, daily.MAX_TEMP)

    return history
Esempio n. 2
0
    def __call__(self, city):
        dInfo = dailyRecords.getInfo(city, today(city), self.field)
        msg = ''
        datemarker = dateMarkerFromDate(today(city))
        alreadyReportedRecord, oldTweet = self.datemarker.get(
            datemarker, (None, None))

        if (dInfo.median != None and alreadyReportedRecord != dInfo.recent
                and daily.timeByCity[city].hour < 11
                and dInfo.recent > dInfo.median):
            maybePostWarmMorningTweet(daily.timeByCity[city], dInfo.recent,
                                      dInfo.median)
            self.datemarker[datemarker] = dInfo.recent
Esempio n. 3
0
    def call(self, city, sampleDay):
        allcast = forecast.getForecastDataEnvCan(city)
        try:
            cast = allcast[sampleDay]
        except KeyError:
            return

        if len(cast[self.field.index]) == 0:
            # No forecast is available for this field for this day, skip
            return

        nextDay = sampleDay + datetime.timedelta(1)
        try:
            cast2 = allcast[sampleDay + datetime.timedelta(1)]
        except KeyError:
            return
        #print(cast.MIN_TEMP, cast2.MIN_TEMP, str(min(int(cast.MIN_TEMP),int(cast2.MIN_TEMP))))
        cast = cast._replace(
            MIN_TEMP=str(min(int(cast.MIN_TEMP), int(cast2.MIN_TEMP))))

        try:
            #print(city, sampleDay, cast)
            dInfo = dailyRecords.getInfo(city,
                                         sampleDay,
                                         self.field,
                                         recentValOverride=cast)
        except KeyError:
            return

        msg = ''
        msgPrefix = ''
        datemarker = dateMarkerFromDate(sampleDay)
        alreadyReportedRecord = self.datemarker.get(datemarker, None)
        if alreadyReportedRecord != None:
            print(repr(alreadyReportedRecord))
            updatedAlert = 'This alert corrects the last alert which reported a value of %.1f%s.<br>\n' % (
                alreadyReportedRecord.value, self.field.htmlunits)
            msgPrefix = updatedAlert + '\n' + alreadyReportedRecord.tweet

        #print('cast={} recent={} max={} day={} since={}'.format(str(cast), float(dInfo.recent), float(dInfo.max.value), sampleDay.year, dInfo.maxSince.year))
        if (dInfo.recent != None
                and (alreadyReportedRecord == None
                     or alreadyReportedRecord.value != dInfo.recent)):
            if ((dInfo.recent > dInfo.max.value or
                 (sampleDay.year - dInfo.maxSince.year) > 55)
                    and self.skipMaxRecords == False
                    and not (self.skipMaxEstimated and dInfo.recentEstimated)):
                print(msgPrefix)
                tweet = maybePostTweet(city,
                                       sampleDay,
                                       self.field,
                                       dInfo.recent,
                                       dInfo.maxSince.value,
                                       dInfo.maxSince.year,
                                       recordIsMax=True)
                msg += tweet + '<br>'
                if dInfo.maxSince.value == None:
                    compareDay = datetime.date(dInfo.max.year, sampleDay.month,
                                               sampleDay.day)
                else:
                    compareDay = datetime.date(dInfo.maxSince.year,
                                               sampleDay.month, sampleDay.day)

                self.datemarker[datemarker] = PreviousReport(
                    dInfo.recent, tweet)
            if len(msg) > 0:
                return Email(field=self.field,
                             date=sampleDay,
                             message=msgPrefix + msg)
                low = None
            else:
                search = re.search('<td class="(.*)">([-0-9]*)</td>',
                                   strippedLine)
                if search != None:
                    (label, temperature) = search.groups()
                    if temperature != '-':
                        if label == 'high':
                            high = int(temperature)
                        elif label == 'low lbtext':
                            low = int(temperature)
        if strippedLine == '</tr>' and low != None and high != None:
            forecastOffset = (curDay - forecastIssued).days
            print "%s(%d): Low %d, High %d" % (curDay, forecastOffset, low,
                                               high)
            lowRec = dailyRecords.getInfo('ottawa', curDay, daily.MIN_TEMP)
            highRec = dailyRecords.getInfo('ottawa', curDay, daily.MAX_TEMP)

            if lowRec.recent != None and highRec.recent != None:
                actualLow = lowRec.recent
                actualHigh = highRec.recent
                deviation = LowHigh(low - actualLow, high - actualHigh,
                                    low - lowRec.avg, high - highRec.avg)

                deviationsByDay[forecastOffset - 1].forecastLow.append(
                    deviation.forecastLow)
                deviationsByDay[forecastOffset - 1].forecastHigh.append(
                    deviation.forecastHigh)
                deviationsByDay[forecastOffset - 1].normalLow.append(
                    deviation.normalLow)
                deviationsByDay[forecastOffset - 1].normalHigh.append(
Esempio n. 5
0
    def call(self, city, sampleDay):
        try:
            dInfo = dailyRecords.getInfo(city, sampleDay, self.field)
        except KeyError:
            return

        msg = ''
        updatedAlert = ''
        datemarker = dateMarkerFromDate(sampleDay)
        alreadyReportedRecord = self.datemarker.get(datemarker,None)
        alreadyReportedRecordTweet = None
        if alreadyReportedRecord != None:
            updatedAlert = 'This alert corrects the last alert which reported a value of %.1f%s.<br>\n' % (alreadyReportedRecord.value, self.field.htmlunits)
            alreadyReportedRecordTweet = alreadyReportedRecord.tweet

        if ( dInfo.recent != None
             and ( alreadyReportedRecord == None
                   or alreadyReportedRecord.value != dInfo.recent )
             and not (self.skipIncomplete and dInfo.incomplete)
             and not (self.skipBelowZero and dInfo.recent < 0)
        ):
            tweet = None
            #if self.field is daily.MIN_TEMP and sampleDay == dt.date(2017,3,5):
            #    import pudb; pu.db
            closeToMax = calcCloseToRecordMax(self.field, dInfo.max.value, dInfo.recent)
            closeToMin = calcCloseToRecordMax(self.field, dInfo.min.value, dInfo.recent)
            recordMax = ( dInfo.recent > dInfo.max.value
                          or ( sampleDay.year - dInfo.maxSince.year) > 55 )
            tryMax = ( self.skipMaxRecords == False
                       and not (self.skipMaxEstimated and dInfo.recentEstimated )
                       and not (self.skipMaxIncomplete and dInfo.incomplete) )

            recordMin = ( dInfo.recent < dInfo.min.value
                          or ( sampleDay.year - dInfo.minSince.year) > 55 )
            tryMin = ( self.skipMinRecords == False
                       and not (self.skipMinEstimated and dInfo.recentEstimated)
                       and not (self.skipMinIncomplete and dInfo.incomplete) )
            if tryMax and recordMax:
                print(updatedAlert, end=' ')
                tweet = maybePostTweet(city,
                                       sampleDay, self.field, dInfo.recent,
                                       dInfo.recentEstimatedHour,
                                       dInfo.maxSince.value, dInfo.maxSince.year,
                                       oldTweet=alreadyReportedRecordTweet,
                                       recordIsMax=True)
                msg += tweet + '<br>'
                if dInfo.maxSince.value == None:
                    compareDay = datetime.date(dInfo.max.year,
                                               sampleDay.month, sampleDay.day)
                else:
                    compareDay = datetime.date(dInfo.maxSince.year,
                                               sampleDay.month, sampleDay.day)
                    msg += htmlday.htmlTable( daily.load(city), (sampleDay, compareDay) )
            elif tryMax and closeToMax:
                tweet = maybePostCloseTweet(
                    city,
                    sampleDay, self.field, dInfo.recent,
                    dInfo.recentEstimatedHour,
                    dInfo.max.value,
                    oldTweet=alreadyReportedRecordTweet,
                    recordIsMax=True)
            elif tryMin and recordMin:
                print(updatedAlert, end=' ')
                #import pudb; pu.db
                tweet = maybePostTweet(city,
                                       sampleDay, self.field, dInfo.recent,
                                       dInfo.recentEstimatedHour,
                                       dInfo.minSince.value, dInfo.minSince.year,
                                       oldTweet=alreadyReportedRecordTweet,
                                       recordIsMax=False)
                msg += tweet + '<br>'
                if dInfo.minSince.value == None:
                    compareDay = datetime.date(dInfo.min.year,
                                               sampleDay.month, sampleDay.day)
                else:
                    compareDay = datetime.date(dInfo.minSince.year,
                                               sampleDay.month, sampleDay.day)
                    print((dInfo.minSince.value, compareDay, sampleDay))
                    msg += htmlday.htmlTable( daily.load(city), (sampleDay, compareDay) )
            elif tryMin and closeToMin:
                tweet = maybePostCloseTweet(
                    city,
                    sampleDay, self.field, dInfo.recent,
                    dInfo.recentEstimatedHour,
                    dInfo.min.value,
                    oldTweet=alreadyReportedRecordTweet,
                    recordIsMax=False)
            if tweet is not None:
                self.datemarker[datemarker] = (dInfo.recent, tweet)
            if len(msg) > 0:
                return Email(field=self.field, date=sampleDay, message=msg)
Esempio n. 6
0
def main(
    city,
    force=False,
    lastCheckedValue=None,
    today=None,
    maxValueToCheck=None,
    allYear=False,
    allWinter=False,
    justTop5=False,
    dataSinceDay=None,
):
    #import pdb; pdb.set_trace()
    data = daily.load(city)
    if dataSinceDay is not None:
        for day in tuple(data.keys()):
            if day < dataSinceDay:
                del data[day]
    monthlyAverages.cityData = data
    if today is None:
        today = daily.timeByCity[city].date()
        #if allYear:
        #    today = dt.date(daily.timeByCity[city].date().year, 12, 31)
    yearToCheck = (today - dt.timedelta(7)).year
    if yearToCheck != today.year:
        today = dt.date(yearToCheck, 12, 31)
    monthlyAverages.now = today
    tomorrow = today + dt.timedelta(days=1)

    todayMaxInfo = dailyRecords.getInfo(city, today, daily.MAX_TEMP)

    todayAverageMax = roundAwayFromZero(todayMaxInfo.normal)
    todayMax = None
    if todayMaxInfo.recent is not None:
        todayMax = int(todayMaxInfo.recent)

    if lastCheckedValue is None:
        minValueToCheck = int(todayAverageMax) + 2
    else:
        minValueToCheck = int(lastCheckedValue) + 1

    if maxValueToCheck is None:
        maxValueToCheck = todayMax
        if todayMax is None:
            maxValueToCheck = 35

    maxValuesToCheck = filter(lambda t: t % 10 == 0,
                              range(minValueToCheck, maxValueToCheck + 1))

    fieldList = [
        #*[ ( ExprVal('max>={} if max is not None else None'.format(t),
        #             title=str(t) + "℃",
        #             name="max>=" + str(t),
        #             units="days",
        #             unit="day",
        #             precision=0,
        #             field=daily.MAX_TEMP,
        #             description=str(t)+"℃ days"),
        #     True ) for t in maxValuesToCheck ],
        #[ ( ExprVal('maxHumidex>max and maxHumidex>=' + str(t),
        #              title=str(t) + " humidex",
        #              name="humidex>=" + str(t),
        #              units="days",
        #              unit="day",
        #              precision=0),
        #      True ) for t in range(30, 51) ]
        #( FractionVal(daily.TOTAL_RAIN_MM, "Rain"), True ),
        (FractionVal(daily.TOTAL_SNOW_CM, "snow"), True),
        #( FractionVal(daily.TOTAL_PRECIP_MM, "precipitation"), True ),
        #( FractionVal(daily.AVG_WIND, "Wind"), False ),
        #( Avg(daily.MIN_TEMP, daily.MAX_TEMP, "temperature"), False ),
        #( FractionVal(daily.MEAN_HUMIDITY, "Humidity"), False ),
    ]

    monFilter = monthlyAverages.BeforeDateFilter(month=tomorrow.month,
                                                 day=tomorrow.day)
    if allYear:
        monFilter = monthlyAverages.BeforeDateFilter(month=1, day=1)
    if allWinter:
        monFilter = WinterFilter()
    todayFilter = monthlyAverages.OneDayFilter(month=today.month,
                                               day=today.day)

    #import pudb; pu.db
    for field, cumulative in fieldList:
        thisyear = today.year
        if allWinter:
            thisyear = today.year if today.month >= 7 else today.year - 1
        valByYear = monthlyAverages.yearDatas(monFilter,
                                              field=field,
                                              lastYear=thisyear,
                                              cumulative=cumulative)
        normalVal = monthlyAverages.normalMonthlyDatas(today.year,
                                                       monFilter,
                                                       field,
                                                       cumulative=cumulative)
        if thisyear not in valByYear:
            continue
        ci80 = confidenceInterval80(valByYear, thisyear)
        ci50 = confidenceInterval50(valByYear, thisyear)

        thisYearVal = valByYear[thisyear]
        maxSince = None
        minSince = None
        for year in reversed(sorted(valByYear.keys())):
            if year != thisyear:
                val = valByYear[year]
                if maxSince is None and val >= thisYearVal:
                    maxSince = year
                if minSince is None and val <= thisYearVal:
                    minSince = year
        del val
        insideCi80 = (thisYearVal >= ci80.low and thisYearVal <= ci80.high)
        insideCi50 = (thisYearVal >= ci50.low and thisYearVal <= ci50.high)

        if field.units == 'days':  # and False:
            todayValByYear = monthlyAverages.yearDatas(todayFilter,
                                                       field=field,
                                                       lastYear=today.year,
                                                       cumulative=cumulative)
            if todayValByYear[today.year] == 0:
                #The countable event did not occur today, so skip.
                continue
            #import pdb; pdb.set_trace()

        yearByVal = reverseDict(valByYear)
        top5 = topNValuesLists(yearByVal, 5)
        if ((allYear or allWinter)
                and (inListOfLists(top5.values(), thisyear) or args.force)):
            tweetTopN(city, top5, field, thisyear)
        if justTop5:
            continue

        amountDescription = ''
        if thisYearVal < ci50[0] and (field.units != 'days'
                                      or thisYearVal != 0):
            amountDescription = 'just '
        amount = formatWithUnits(thisYearVal, field, field.precision)
        if field.units == 'days':
            amount = formatWithUnits(thisYearVal, field, 0, skipUnits=True)
            if thisYearVal == 0:
                amount = "no"

        aboveBelow = 'above'
        if thisYearVal < normalVal.average:
            aboveBelow = 'below'

        if cumulative:
            deviation = deviationDescription(thisYearVal, normalVal.average,
                                             field)
        else:
            diff = abs(thisYearVal - normalVal.average)
            deviation = formatWithUnits(diff, field,
                                        field.precision) + ' ' + aboveBelow
        start = 'average'
        if cumulative:
            start = 'total'
        title = field.title.lower()
        ci80Low = formatWithUnits(ci80[0],
                                  field,
                                  field.precision,
                                  skipUnits=True)
        ci80High = formatWithUnits(ci80[1], field, field.precision)
        insideOutside = 'outside'
        if insideCi80:
            insideOutside = 'inside'
        cityName = stations.city[city].name
        avgWithUnits = formatWithUnits(normalVal.average, field,
                                       field.precision)
        #tweetText = (
        #    '#{cityName}\'s {start} {title} so far this year was'
        #    ' {amountDescription}{amount},'
        #    ' {deviation} {aboveBelow} average; {insideOutside} the normal range of'
        #    ' {ci80Low} to {ci80High}'.format(**locals()))
        tweetText = ('#{cityName}\'s {start} {title} so far this year was'
                     ' {amountDescription}{amount},'
                     ' {deviation} the average of'
                     ' {avgWithUnits}'.format(**locals()))
        if allYear:
            tweetText = (
                '#{cityName}\'s {start} {title} during {today.year} was'
                ' {amountDescription}{amount},'
                ' {deviation} the average of'
                ' {avgWithUnits}'.format(**locals()))
        if field.units == 'days':
            units = field.unit
            if thisYearVal != 1:
                units = field.units
            nth = alert.nth(thisYearVal)
            #import pdb; pdb.set_trace()
            average = formatWithUnits(normalVal.average, field, precision=1)
            todayString = 'Today is'
            if today != daily.timeByCity[city].date():
                todayString = 'Yesterday was'
            tweetText = (
                '{todayString} #{cityName}\'s {nth} {title} day so far this year,'
                ' {deviation} the average of {average}.'.format(**locals()))
        #alertTweets.maybeTweetWithSuffix(city, tweetText)
        recordMin = normalVal.minimum
        recordMax = normalVal.maximum
        print(
            'Record minimum was {recordMin}{field.units} in {normalVal.minYear}'
            .format(**locals()))
        print(
            'Record maximum was {recordMax}{field.units} in {normalVal.maxYear}'
            .format(**locals()))
        plotIt = not insideCi80 or args.force
        if maxSince is None:
            print('***Max since records began in {}.'.format(
                min(valByYear.keys())))
            plotIt = True
        elif today.year - maxSince > 10:
            maxSinceVal = valByYear[maxSince]
            print('***Max since {maxSince}:{maxSinceVal}{field.units}'.format(
                **locals()))
            plotIt = True
        if minSince is None:
            print('***Min since records began in {}.'.format(
                min(valByYear.keys())))
            plotIt = True
        elif today.year - minSince > 10:
            minSinceVal = valByYear[minSince]
            print('***Min since {minSince}:{minSinceVal}{field.units}'.format(
                **locals()))
            plotIt = True
        if plotIt:
            fname = field.name
            pngname = "%s/Annual_%s.png" % (city, fname)
            alertTweets.maybeTweetWithSuffix(city, tweetText, fname=pngname)
    if todayMax is None:
        return todayAverageMax + 2
    return max(todayMax, todayAverageMax + 2)