def thisMonthOverTime(month):
    for fname in ['MEAN_TEMP']:
        findex = daily.fields._fields.index(fname)
        data = []
        for year in range(min(cityData.keys()),2010):
            avg = filterAverage(YearMonthFilter(year, month), findex)
            if avg != None:
                data.append((year,avg.average))

        lineFit = linear.linearTrend(data)

        plot = gnuplot.Plot("ThisMonthOverTime_%s_%s" % (fname, monthName(month)), yaxis=2)
        plot.open()
        plot.addLine(gnuplot.Line(fname, data, lineColour='blue'))
        plot.addLine(gnuplot.Line('linear', lineFit, lineColour='green'))
        plot.plot()
        plot.close()


    for fname in ['TOTAL_SNOW_CM', 'TOTAL_PRECIP_MM']:
        findex = daily.fields._fields.index(fname)
        data = []
        for year in range(min(cityData.keys()),2010):
            data.append((year, filterSum(YearMonthFilter(year, month), findex).total))

        lineFit = linear.linearTrend(data)

        plot = gnuplot.Plot("ThisMonthOverTime_%s_%s" % (fname, monthName(month)), yaxis=2)
        plot.open()
        plot.addLine(gnuplot.Line(fname, data, lineColour='blue'))
        plot.addLine(gnuplot.Line('linear', lineFit, lineColour='green'))
        plot.plot()
        plot.close()
Esempio n. 2
0
def plotline(valueByYear, filename, chartTitle, yaxisLabel):
    data = sorted(tuple(valueByYear.items()))
    if len(data) > 1:
        lineFit = linear.linearTrend(tuple((a[0], float(a[1])) for a in data))
    plot = gnuplot.Plot(filename, yaxis=2)
    plot.open(title=chartTitle, ylabel=yaxisLabel)
    if len(data) > 1:
        plot.addLine(
            gnuplot.Line("Linear", lineFit, lineColour='green', plot='lines'))
    plot.addLine(gnuplot.Line("Temp", data, lineColour='purple'))
    plot.plot()
    plot.close()
    return plot.fname
Esempio n. 3
0
        print "Sun: %4d %2dC %3d" % (year, t, tempSunHours)

        if tempSunHours > recordVal:
            sunRecord[t] = (year, tempSunHours)

#
    thisyearsnowy = totalHours(weather.hourly.WEATHER, Snowy(year))
    snowData.append((year, thisyearsnowy))
    print "Snow: %d\t%d" % (year, thisyearsnowy)

print sunRecord

sunLineFit = {10: [], 15: [], 20: [], 25: [], 30: []}

for t in sunData:
    sunLineFit[t] = linear.linearTrend(sunData[t])

snowlineFit = linear.linearTrend(snowData)

plot = gnuplot.Plot("ottawa/SunnyHours", yaxis=2)
plot.open(ymin=0)
for t in sunData:
    plot.addLine(gnuplot.Line("Trend %d" % t, sunLineFit[t], plot='lines'))
    plot.addLine(gnuplot.Line("Sun %d" % t, sunData[t]))
plot.plot()
plot.close()

plot = gnuplot.Plot("ottawa/SnowHours", yaxis=2)
plot.open(ymin=0)
plot.addLine(
    gnuplot.Line("Trend", snowlineFit, lineColour='green', plot='lines'))
Esempio n. 4
0
def count(cityName,
          data,
          expr,
          name,
          verbose=True,
          skipIncomplete=False,
          lineChart=False):
    countByYear = {}
    thisYearCount = 0

    for baseyear in range(data.minYear, data.maxYear - YEAR_CROSS() + 1):
        countByYear[baseyear] = None
        countThisYear = 0

        starttime = datetime.datetime(baseyear, START_MONTH, START_DAY)
        endtime = datetime.datetime(baseyear + YEAR_CROSS(), END_MONTH,
                                    END_DAY)
        hourdiff = (endtime - starttime).days * 24
        hoursWithObservations = 0

        thisRunLen = 0
        #print baseyear
        for day in hourly.hourRange(starttime, endtime):
            dayValues = data.get(day, None)

            val = None
            flag = ''
            if dayValues != None:
                #print day, dayValues
                val, flag = expr(dayValues)

            if val != None:
                hoursWithObservations += 1
                if val and not (skipIncomplete and 'I' in flag):
                    countThisYear += 1
                    if baseyear + YEAR_CROSS() == now.year:
                        if verbose:
                            print "Count: %s" % day, float(val), flag
                        if (day.date() == min(
                                endtime.date() - datetime.timedelta(1),
                                datetime.date.today())):
                            # We only care about this year's count if the final day of
                            # this year actually met the criteria
                            thisYearCount = countThisYear
                else:
                    #if baseyear == 2014:
                    #    print "Skip: %s" % day
                    thisRunLen = 0

        if (hoursWithObservations >= hourdiff * 85 /
                100):  # or baseyear + YEAR_CROSS() == now.year:
            countByYear[baseyear] = countThisYear
            if verbose:
                print baseyear, countThisYear, hoursWithObservations
        else:
            # skip years with fewer than 90% of days recorded
            if verbose:
                print("Skipping %d because it has only %u/%u records" %
                      (baseyear, hoursWithObservations, hourdiff))

    #del countByYear[now.year]

    (fewest, most) = keyOfMinMaxValue(countByYear)

    if verbose:
        print "fewest %s was %s (%d)" % (name, fewest, countByYear[fewest[0]])
        print "most %s was %s (%d)" % (name, most, countByYear[most[0]])

    eThisYear = now.year
    if YEAR_CROSS():
        eThisYear -= 1

    avgKeys = filter(lambda t: t in countByYear,
                     range(eThisYear - 30, eThisYear))

    counts = [countByYear[a] for a in avgKeys]

    counts = filter(lambda t: t != None, counts)

    avg = float(sum(counts)) / len(counts)

    if verbose:
        print "average %s is %f" % (name, avg)

    #print thisYearCount
    mostSince = None
    prevRecordYears = []
    prevRecord = 0
    if eThisYear in countByYear:
        #thisYearCount = countByYear[eThisYear]
        if thisYearCount > 0:
            for year in reversed(sorted(countByYear.keys())):
                if mostSince == None and year != eThisYear and countByYear[
                        year] >= thisYearCount:
                    mostSince = year
                if year != eThisYear:
                    if countByYear[year] > prevRecord:
                        prevRecord = countByYear[year]
                        prevRecordYears = [year]
                    elif countByYear[year] == prevRecord:
                        prevRecordYears.append(year)

        if verbose:
            print now.year, name, "was", countByYear[eThisYear]
            if mostSince != None:
                print "Most since %d." % (mostSince)
            print(
                "%d of past %d years had more %s" %
                (len(filter(lambda t: countByYear[t] > thisYearCount,
                            avgKeys)), len(avgKeys), name),
                filter(lambda t: countByYear[t] > thisYearCount, avgKeys))
            print(
                "%d of past %d years had equal %s" %
                (len(filter(lambda t: countByYear[t] == thisYearCount,
                            avgKeys)), len(avgKeys), name),
                filter(lambda t: countByYear[t] == thisYearCount, avgKeys))
            print(
                "%d of past %d years had fewer %s" %
                (len(filter(lambda t: countByYear[t] < thisYearCount,
                            avgKeys)), len(avgKeys), name),
                filter(lambda t: countByYear[t] < thisYearCount, avgKeys))
            print

    if lineChart:
        plotdata = []
        for (year, plotCount) in countByYear.iteritems():
            if plotCount != None:
                plotdata.append((year, plotCount))

        lineFit = linear.linearTrend(plotdata)

        plot = gnuplot.Plot(
            "%s/svg/%s_count_%s-%u_before_%s" %
            (cityName, name.replace(' ', '_'), monthName(START_MONTH),
             START_DAY, lastDay().replace(' ', '-')),
            yaxis=2)
        plot.open(title='%s number of %s between %s %u and %s' %
                  (cityName.capitalize(), name, monthName(START_MONTH),
                   START_DAY, lastDay()))
        plot.addLine(
            gnuplot.Line("Linear", lineFit, lineColour='green', plot='lines'))
        plot.addLine(gnuplot.Line("Count", plotdata, lineColour='purple'))
        plot.plot()
        plot.close()
    else:
        barPlotData = makeFit(countByYear, 75)
        filename = ("%s/svg/%s_count_%s-%u_to_%s_bar" %
                    (cityName, name.replace(' ', '_'), monthName(START_MONTH),
                     START_DAY, lastDay().replace(' ', '-')))

        plotdict(barPlotData,
                 filename=filename,
                 chartTitle=('%s number of %s between %s %u and %s' %
                             (cityName.capitalize(), name,
                              monthName(START_MONTH), START_DAY, lastDay())),
                 yaxisLabel='',
                 thisYear=eThisYear,
                 ymin=0)
    return (filename, thisYearCount, mostSince, prevRecord, prevRecordYears)
    city = sys.argv[1]

    cityData = daily.load(city)

    for field in [
            FractionVal(daily.MAX_TEMP, "high temperature"),
            FractionVal(daily.MIN_TEMP, 'low temperature'),
            FractionVal(daily.AVG_WIND, 'wind'),
            Avg(daily.MIN_TEMP, daily.MAX_TEMP, 'average temperature')
    ]:
        fname = field.name
        print(fname)
        data = getAnnualValues(cityData, field, False)

        try:
            lineFit = linear.linearTrend(data)
        except ZeroDivisionError:
            print(data)
            raise

        for i in range(len(data)):
            year, val = data[i]
            lfitv = lineFit[i][1]
            print(year, float(val), lfitv)

        plot = gnuplot.Plot("%s/svg/Annual_%s" % (city, fname), yaxis=2)
        plot.open(title='%s %s per year' % (city.capitalize(), field.title),
                  ylabel='%s in %s' % (field.title, field.units))
        plot.addLine(
            gnuplot.Line("Linear", lineFit, lineColour='green', plot='lines'))
        plot.addLine(gnuplot.Line("Temp", data, lineColour='purple'))
Esempio n. 6
0
def first(cityName,
          expr,
          name,
          dateRange,
          excludeThisYear=False,
          order="first",
          yaxisLabel=None,
          run=1,
          limitToMostRecentYears=None,
          verboseIfInDateRange=None,
):
    data = daily.load(cityName)
    if limitToMostRecentYears != None:
        ndata = daily.Data()
        yearsAgo = datetime.date(now.year-limitToMostRecentYears, now.month, now.day)
        for key in data:
            if key >= yearsAgo:
                ndata[key] = data[key]
        data = ndata
    fieldDict = {
        'min': Value(daily.MIN_TEMP),
        'max': Value(daily.MAX_TEMP),
        'tempSpan': ValueDiff(daily.MAX_TEMP, daily.MIN_TEMP),
        'rain': Value(daily.TOTAL_RAIN_MM),
        'humidex': Value(daily.MAX_HUMIDEX),
        'snow': Value(daily.TOTAL_SNOW_CM),
        'snowpack': ValueEmptyZero(daily.SNOW_ON_GRND_CM),
        'windgust': Value(daily.SPD_OF_MAX_GUST_KPH),
        'wind': Value(daily.AVG_WIND),
        'windchill': Value(daily.MIN_WINDCHILL),
        'avgWindchill': Value(daily.MIN_WINDCHILL),
    }
    fieldValues = fieldDict.values()
    referencedValues=[]
    for fieldName in fieldDict.keys():
        if '{'+fieldName+'}' in expr:
            referencedValues.append(fieldName)

    firstByYear = {}
    eThisYear = now.year
    endTimeThisYear = datetime.date(now.year, dateRange.endMonth, dateRange.endDay)
    if dateRange.yearCross() and now < endTimeThisYear:
        eThisYear -= 1


    for baseyear in range(data.minYear, data.maxYear-dateRange.todayIsYearCross()+1):

        try:
            dayOffset = datacache.readCache(cityName, baseyear,
                                            '{}.{}.{}.{}'.format(name,order,str(dateRange),expr))
            if dayOffset != None:
                firstByYear[baseyear] = dayOffset
            continue
        except datacache.NotInCache:
            pass
        starttime = datetime.date(baseyear, dateRange.startMonth, dateRange.startDay)
        endtime = datetime.date(baseyear+dateRange.yearCross(), dateRange.endMonth, dateRange.endDay)

        #print baseyear, starttime, endtime
        dayRange = daily.dayRange(starttime,endtime)
        if order=="last":
            dayRange = daily.dayRange(endtime-datetime.timedelta(1), starttime-datetime.timedelta(1), -1)
            if excludeThisYear and baseyear == now.year-dateRange.yearCross():
                # don't consider this year when looking for records for last event, because this year is not over
                continue

        expectedDayCount = 0
        observedDayCount = 0
        for day in dayRange:
            expectedDayCount += 1
            if day in data:
                observedDayCount += 1
            else:
                continue

            if baseyear in firstByYear:
                # We already figured out which day was first
                continue

            vals = {}
            for fieldName, fieldCall in fieldDict.items():
                try:
                    vals[fieldName] = fieldCall(data[day], day)
                    vals[fieldName+'Flag'] = '"' + fieldCall.getFlag(data[day]) + '"'
                except KeyError:
                    #print day, 'KeyError'
                    vals[fieldName] = None
            skip=False
            usedVals={}
            for fieldName in fieldDict.keys():
                if fieldName in referencedValues:
                    if vals[fieldName] is None:
                        #print 'Skipping {} because {} is None'.format(day, fieldName)
                        skip=True
                        break
                    usedVals[fieldName] = vals[fieldName]
            if skip:
                continue

            #resolvedExpr = expr.format(**vals)
            #print(vals)
            #val = eval(expr)
            val = eval(expr, vals)

            #if True: #day == datetime.date(2015,10,17):
            #print day, resolvedExpr, val

            if val is True:
                dayOffset = (day - starttime).days
                firstByYear[baseyear] = dayOffset
                break

        observedPercent = observedDayCount * 100 / expectedDayCount
        if observedPercent < 85 and baseyear != eThisYear:
            print('Skipping {baseyear} because it only had {observedPercent:.1f}% of the days'.format(**locals()))
            if baseyear in firstByYear:
                firstByYear.pop(baseyear)
        elif baseyear not in firstByYear and baseyear != eThisYear:
            print('Event did not happen during {}.'.format(baseyear))
        datacache.cacheThis(cityName, baseyear,
                            '{}.{}.{}.{}'.format(name,order,str(dateRange),expr),
                            firstByYear.get(baseyear, None))


    yearByFirst = reverseDict(firstByYear)
    #for offset in sorted(yearByFirst.keys()):
    #    for year in yearByFirst[offset]:
    #        print datetime.date(year, dateRange.startMonth, dateRange.startDay) + datetime.timedelta(offset)
    #print yearByFirst

    verbose = False
    if verboseIfInDateRange == None:
        verbose = True
    elif eThisYear in firstByYear:
        thisYearFirstDayOffset = firstByYear[eThisYear]
        firstThisYearDate = (
            datetime.date(eThisYear, dateRange.startMonth, dateRange.startDay)
            + datetime.timedelta(thisYearFirstDayOffset) )
        if ( firstThisYearDate >= verboseIfInDateRange[0]
             and firstThisYearDate <= verboseIfInDateRange[1] ):
            verbose = True

    (earliest, secondEarliest, *ignore) = sorted(filter(lambda y: y!=now.year-dateRange.yearCross(), yearByFirst.keys()))[:2] + [None,None]
    (secondLatest, latest, *ignore) = sorted(filter(lambda y: y!=now.year-dateRange.yearCross(), yearByFirst.keys()))[-2:] + [None,None]

    earliestYears = lookupEmptyListIfNone(yearByFirst, earliest)
    secondEarliestYears = lookupEmptyListIfNone(yearByFirst, secondEarliest)

    latestYears = lookupEmptyListIfNone(yearByFirst, latest)
    secondLatestYears = lookupEmptyListIfNone(yearByFirst, secondLatest)

    earliestDates=[]
    latestDates=[]
    if verbose:
        earliestDates=showRecords(name, 'earliest', earliestYears, firstByYear, dateRange)
        showRecords(name, '2nd earliest', secondEarliestYears, firstByYear, dateRange)
        showRecords(name, '2nd latest', secondLatestYears, firstByYear, dateRange)
        latestDates=showRecords(name, 'latest', latestYears, firstByYear, dateRange)

    avgKeys = filter(lambda t: t in firstByYear, range(eThisYear-30, eThisYear))

    offsets = sorted([firstByYear[a] for a in avgKeys])
    avg = calcAvg(offsets)
    median = calcMedian(offsets)

    avgFirst = calcDate(eThisYear, dateRange.startMonth, dateRange.startDay, avg)
    medianFirst = calcDate(eThisYear, dateRange.startMonth, dateRange.startDay, median)
    if verbose:
        print("average {name} is {avgFirst}".format(**locals()))
        print("median {name} is {medianFirst}".format(**locals()))

    ret = None
    if eThisYear in firstByYear:
        thisYearFirst = firstByYear[eThisYear]
        countEarlier = 0
        countEqual = 0
        countLater = 0
        recentCountEarlier = []
        recentCountEqual = []
        recentCountLater = []

        for first in sorted(yearByFirst.keys()):
            if first < thisYearFirst:
                countEarlier += len(yearByFirst[first])
                recentCountEarlier += filter(lambda y: y<eThisYear and y > eThisYear-31, yearByFirst[first])
            elif first == thisYearFirst:
                countEqual += len(yearByFirst[first]) - 1 #Subtract the current year
                recentCountEqual += filter(lambda y: y<eThisYear and y > eThisYear-31, yearByFirst[first])
            else:
                countLater += len(yearByFirst[first])
                recentCountLater += filter(lambda y: y<eThisYear and y > eThisYear-31, yearByFirst[first])

        totalCount = countEarlier + countEqual + countLater
        totalRecentCount = len(recentCountEarlier) + len(recentCountEqual) + len(recentCountLater)

        firstThisYear = ( datetime.date(eThisYear, dateRange.startMonth, dateRange.startDay)
                          + datetime.timedelta(thisYearFirst) )
        if verbose:
            print('%s %s was %s' % (now.year, name, firstThisYear ))
            print('%d%% of last %d years were earlier.'
                  % (round(countEarlier * 100.0 / totalCount), totalCount))
            print('%d%% of last %d years were the same.'
                  % (round(countEqual * 100.0 / totalCount), totalCount))
            print('%d%% of last %d years were later.'
                  % (round(countLater * 100.0 / totalCount), totalCount))
            print('%d of last %d years were earlier.'
                  % (len(recentCountEarlier), totalRecentCount), sorted(recentCountEarlier))
            print('%d of last %d years were the same.'
                  % (len(recentCountEqual), totalRecentCount), sorted(recentCountEqual))
            print('%d of last %d years were later.'
                  % (len(recentCountLater), totalRecentCount), sorted(recentCountLater))
        ret = firstThisYear, medianFirst, earliestDates, latestDates
    else:
        print('Not showing this year because eThisYear="{}" and firstByYear="{}"'.format(eThisYear, firstByYear))

    if len(yearByFirst) == 0:
        # There's nothing to plot, so don't even bother trying
        return ret
    plotDataOtherYears = []
    plotDataThisYear = []
    dateLabels = []
    for key in sorted(yearByFirst.keys()):
        if eThisYear in yearByFirst[key]:
            plotDataThisYear.append((key, len(yearByFirst[key]), '#%s' % ','.join(map(str, yearByFirst[key])) ))
        else:
            plotDataOtherYears.append((key, len(yearByFirst[key]), '#%s' % ','.join(map(str, yearByFirst[key]))))
    histogramFname = '%s/svg/%s' % (cityName, name.replace(' ', '_'))
    if ret != None:
        ret = ret + (histogramFname,)
    plot = gnuplot.Plot(histogramFname)
    dateMin = min(yearByFirst.keys())
    dateMax = max(yearByFirst.keys())
    plotDateMin = dateMin-1 #int(dateMin - (dateMax - dateMin)*.25)
    plotDateMax = dateMax+1 #int(dateMax + (dateMax - dateMin)*.25)

    for dayOffset in range(plotDateMin, plotDateMax+1, 1):
        date = datetime.date(now.year, dateRange.startMonth, dateRange.startDay) + datetime.timedelta(dayOffset)
        if date.day % 5 == 1 and date.day != 31:
            dateLabels.append('"%s" %d' % (date.strftime('%b/%d'), dayOffset))

    ylabel = 'Number of years when %s happened on this day' % name
    if yaxisLabel != None:
        ylabel = yaxisLabel
    plot.open(title='%s in %s' % (name, cityName.capitalize()),
              ylabel=ylabel,
              xmin=plotDateMin,
              xmax=plotDateMax,
              ymin=0,
              ymax=max(len(a) for a in yearByFirst.values())+1,
              xtics=dateLabels, xticsRotate=45,
              margins=[7,8,2,5])
    plot.addLine(gnuplot.Line('Other years', plotDataOtherYears, plot='boxes'))
    plot.addLine(gnuplot.Line('This year', plotDataThisYear, plot='boxes'))
    plot.plot()
    plot.close()

    print('')

    plotdata = []
    for (year, plotCount) in firstByYear.items():
        if plotCount != None:
            plotdata.append(
                (year, plotCount,
                 ( '#'
                   +str(datetime.date(year, dateRange.startMonth, dateRange.startDay)
                        + datetime.timedelta(plotCount)))))

    ytics = []
    for m in range(1,13):
        for d in (1,10,20):
            thisDate = datetime.date(2015,m,d)
            dayOffset = (thisDate - datetime.date(2015, dateRange.startMonth, dateRange.startDay)).days
            ytics.append('"%s" %d' % (thisDate.strftime('%b %d'), dayOffset))

    #print(tuple(t[:2] for t in plotdata))
    lineFit = linear.linearTrend(tuple(t[:2] for t in plotdata))

    plot = gnuplot.Plot("%s/svg/%s_%s-%u_%s.line"
                        % (cityName, name.replace(' ', '_'),
                           monthName(dateRange.startMonth), dateRange.startDay,
                           dateRange.lastDay().replace(' ', '-') ),
                        yaxis=2)
    plot.open(title='%s %s between %s %u and %s'
              % (cityName.capitalize(), name,
                 monthName(dateRange.startMonth), dateRange.startDay,
                 dateRange.lastDay() ),
              ytics=ytics)
    plot.addLine(gnuplot.Line("Linear", lineFit, lineColour='green', plot='lines'))
    plot.addLine(gnuplot.Line("Date", plotdata, lineColour='purple'))
    plot.plot()
    plot.close()
    return ret