#!/usr/bin/env python # Find the local max/min from a weather data day file # Version date: November 1, 2011 # import sys import os import string import time # # Define some station-specific constants. # station_name = "Table Mesa - Boulder, CO Weather" # 1 for English units, 0 for Metric English = 1 # Directories and filenames datadir = "/home/dv/data/" webdir = "/var/www/" maxminfile = "maxmin.html" BADVAL = -99.9 # # Unit Conversion Functions. # def c2f (tempc): return ((tempc * 1.8) + 32.0) def mb2inHg (presmb): return (presmb * 0.02953) def kph2mph (windmps): return (windmps * 0.6214) def mm2in (rainmm): return (rainmm * 0.03937) wind_dirs =["BAD", "N", "NNE", "NE", "ENE", "E", "ESE", "SE", "SSE", "S", "SSW", "SW", "WSW", "W", "WNW", "NW", "NNW"] # Calculate the wind direction name. def wdir_name (wdir): wdirofs = wdir + 11.25 if (wdirofs > 360.0): wdirofs = wdirofs - 360.0 return (wind_dirs[(int)((wdirofs / 22.5) + 1)]) # One line in the data file is: #sample time (unix time) (long) #outside temperature (deg C) (float) #outside humidity (%) (float) #wind chill (deg C) (float) #dewpoint (deg C) (float) #pressure (millibars) (float) #dp/dt (millibars/??) (float) #altitude corrected pressure (millibars) (float) #wind speed (M/sec) (float) #wind direction (degrees) (float) #peak gust (M/sec) (float) #rain accumulation (mm) (float) #inside temperature (deg C) (float) #inside humidity (%) (float) # There are 14 time/data fields per sample. # There should be 1440 samples per day, 1 per minute unless the file is short. # Data field indices Ftime = 0 Fotemp = 1 Fohum = 2 Fwchil = 3 Fdewp = 4 Fpres = 5 Fdpdt = 6 Fcpres = 7 Fwspd = 8 Fwdir = 9 Fgust = 10 Fraina = 11 Fitemp = 12 Fihum = 13 # Find the last 2 ascii data file names (.asc) in the data directory. file1 = "" file2 = "" # Get a list of the files in datadir, sort the list. dirlist = os.listdir(datadir) dirlist.sort () for filename in dirlist: pos = string.find (filename, ".asc") if (pos > 0): file1 = file2 file2 = filename print "Reading data from:", file1, "and", file2 # Check for non existent files. if ((len (file1) == 0) | (len (file2) == 0)): print "Error: data file(s) not found." sys.exit (1) # Verify that the two data files are readable. f1a = os.access (datadir + file1, os.R_OK) f2a = os.access (datadir + file2, os.R_OK) if ((f1a +f2a) != 2): print "Error: no read permissions for data file(s)." sys.exit (1) if (os.access (webdir + maxminfile, os.W_OK) != 1): print "Error: no write permissions for maxmin file." sys.exit (1) # # Read yesterday's full file and today's usually partial file # into flines. # flines = [] file1=open(datadir + file1,'r') for line in file1.readlines(): flines.append (string.split (line)) file1.close() f1lines = len(flines) #print "File 1 line count:", f1lines file2=open(datadir + file2,'r') for line in file2.readlines(): flines.append (string.split (line)) file2.close() #print "File 2 line count:", len(flines)-f1lines # # To Do: # Calculate missing vals based on date gaps, insert badvals into data list. # For now, just process a short list if the files are short. # if (len(flines) < 1440): dlines = len(flines) else: dlines = 1440 # # Time and Data vector lists # vtime = [] votemp = [] vohum = [] vwchil = [] vdewp = [] vpres = [] vdpdt = [] vcpres = [] vwspd = [] vwdir = [] vgust = [] vraina = [] vitemp = [] vihum = [] # # Convert and fill up the individual time/data lists. # Still breaks with missing data in the middle (at least in the 2nd file). # #print "len flines:", len(flines) #print "dlines:", dlines #print flines for ind in range (0-dlines,0): # print "ind:", ind vtime.append (time.localtime (int(flines[ind][Ftime]))) votemp.append (float(flines[ind][Fotemp])) vohum.append (float(flines[ind][Fohum])) vwchil.append (float(flines[ind][Fwchil])) vdewp.append (float(flines[ind][Fdewp])) vpres.append (float(flines[ind][Fpres])) vdpdt.append (float(flines[ind][Fdpdt])) vcpres.append (float(flines[ind][Fcpres])) vwspd.append (float(flines[ind][Fwspd])) vwdir.append (float(flines[ind][Fwdir])) vgust.append (float(flines[ind][Fgust])) vraina.append (float(flines[ind][Fraina])) vitemp.append (float(flines[ind][Fitemp])) vihum.append (float(flines[ind][Fihum])) # We're done with the file lines. del flines # # Build a list of lists with all of the data, build a list of field names. # alldata = [vtime, votemp, vohum, vwchil, vdewp, vpres, vdpdt, vcpres, vwspd, vwdir, vgust, vraina, vitemp, vihum] allnames = ["Sample Time", "Outside Temperature", "Outside Humidity", "Wind Chill", "Dewpoint", "Pressure", "Dp/Dt", "Pressure", "Wind Speed", "Wind Direction", "Peak Gust", "Rain Accumulation", "Inside Temperature", "Inside Humidity"] if English: Munits = ['°F', '%', '°F', '°F', 'in Hg', 'in Hg', 'in Hg', 'mph', '°', 'mph', 'in', '°F', '%', ''] else: Munits = ['°C', '%', '°C', '°C', 'mb', 'mb', 'mb', 'kph', '°', 'kph', 'mm', '°C', '%', ''] mindata = [] tmin = [] maxdata = [] tmax = [] # Keep numeric wind directions for max speed and max gust. maxspeeddir = -99.9 maxgustdir = -99.9 # # Loop through all of the data lists and look for max/min info. # range 1,14 produces 1 to 13. # for ind1 in range (1,14): workingmax = -5000.0 workingmin = 5000.0 for ind2 in range (0,dlines): if (alldata [ind1][ind2] < workingmin): workingmin = alldata [ind1][ind2] mintime = alldata [0][ind2] if (alldata [ind1][ind2] > workingmax): workingmax = alldata [ind1][ind2] maxtime = alldata [0][ind2] # Record wind direction of max speed and gust. if (ind1 == 8): maxspeeddir = alldata [9][ind2] elif (ind1 == 10): maxgustdir = alldata [9][ind2] # for ind3 in range (1,14): # print "data:", ind1,ind3,":",alldata[ind3][ind2] # Stuff the max/min and time lists. mindata.append (workingmin) tmin.append (mintime) maxdata.append (workingmax) tmax.append (maxtime) # # Write the max/min results to an html file. # wfile=open(webdir + maxminfile, 'w') # Write the DOCTYPE header. (This turns off the table colors for some reason.) #wfile.write ("\n") # Write the html header and table beginning. wfile.write ("\n\n%s\n\n\n\n" %(station_name)) wfile.write ("

%s

\n" %(station_name)) wfile.write ("\n") # Get the time from the most recent data packet. ts = alldata[0][dlines-1] # Write out the current time and header info. wfile.write ("" %(ts[0],ts[1],ts[2],ts[3],ts[4])) wfile.write ("\n") # Write the Column headers. wfile.write ("\n") # # Loop through selected data elements in a particular order # and write data and max/min info. # The order of the max/min data fields is determined by the for list. # for i1 in [0,11,1,12,3,2,6,10,7,9]: data_ok = 1 if English: if (i1 == 0) | (i1 == 2) | (i1 == 3) | (i1 == 11): Cur_dat = c2f (alldata[i1+1][dlines-1]) # Don't convert bad data to Farenheit. if (Cur_dat > BADVAL + 1): Min_dat = c2f (mindata[i1]) Max_dat = c2f (maxdata[i1]) else: Cur_dat = BADVAL Min_dat = BADVAL Max_dat = BADVAL elif (i1 == 4) | (i1 == 6): Cur_dat = mb2inHg (alldata[i1+1][dlines-1]) Min_dat = mb2inHg (mindata[i1]) Max_dat = mb2inHg (maxdata[i1]) elif (i1 == 7) | (i1 == 9): Cur_dat = kph2mph (alldata[i1+1][dlines-1]) #Add small offset to prevent xx.99 readings. Max_dat = kph2mph (maxdata[i1]) + .005 elif (i1 == 10): #Cur_dat = mm2in (alldata[i1+1][dlines-1]) Min_dat = mm2in (mindata[i1]) Max_dat = mm2in (maxdata[i1]) # Rain accumulation is max - min Cur_dat = Max_dat - Min_dat else: Cur_dat = alldata[i1+1][dlines-1] Min_dat = mindata[i1] Max_dat = maxdata[i1] else: Cur_dat = alldata[i1+1][dlines-1] Min_dat = mindata[i1] Max_dat = maxdata[i1] # Special case for wind chill, skip bogus data and hot weather cases. if (i1 == 2): if (Min_dat < -140) | (Max_dat > 50): data_ok = 0 # Special cases for wind speed and peak gust, # print direction instead of min val. if (i1 == 7): wfile.write ("\n" %(allnames[i1+1], Cur_dat, Munits[i1], wdir_name (maxspeeddir), Max_dat, Munits[i1], tmax[i1][1], tmax[i1][2], tmax[i1][3], tmax[i1][4])) elif (i1 == 9): wfile.write ("\n" %(allnames[i1+1], Cur_dat, Munits[i1], wdir_name (maxgustdir), Max_dat, Munits[i1], tmax[i1][1], tmax[i1][2], tmax[i1][3], tmax[i1][4])) elif data_ok: wfile.write ("\n" %(allnames[i1+1], Cur_dat, Munits[i1], Min_dat, Munits[i1], tmin[i1][1], tmin[i1][2], tmin[i1][3], tmin[i1][4], Max_dat, Munits[i1], tmax[i1][1], tmax[i1][2], tmax[i1][3], tmax[i1][4])) # Write the wind direction as a special case. wfile.write ("\n" %(allnames[9], alldata[9][dlines-1], Munits[8], wdir_name (alldata[9][dlines-1]))) # Write the end of the metric table wfile.write ("
Sample Time: %d/%d/%d %02d:%02dMax/Min values for the previous 24 hours
Data TypeCurrentMinTime of MinMaxTime of Max
%s%3.2f %sMax Direction: %s%3.2f %s%d/%d %02d:%02d
%s%3.2f %sGust Direction: %s%3.2f %s%d/%d %02d:%02d
%s%3.2f %s%3.2f %s%d/%d %02d:%02d%3.2f %s%d/%d %02d:%02d
%s%3.2f %sWind From The %s
\n") #wfile.write ("Outside Temp Max: %3.2f at %d:%d on %d/%d/%d" %(otempmax,ts[3],ts[4],ts[1],ts[2],ts[0])), wfile.write ("\n\n\n") wfile.close()