def main(): """Go Main Go""" ets = datetime.datetime.now() - datetime.timedelta(days=1) sts = datetime.datetime(ets.year, 1, 1) # Get the normal accumm with ncopen(iemre.get_dailyc_ncname()) as cnc: lons = cnc.variables["lon"][:] lats = cnc.variables["lat"][:] index0 = iemre.daily_offset(sts) index1 = iemre.daily_offset(ets) clprecip = np.sum(cnc.variables["p01d"][index0:index1, :, :], 0) with ncopen(iemre.get_daily_ncname(sts.year)) as nc: obprecip = np.sum(nc.variables["p01d"][index0:index1, :, :], 0) lons, lats = np.meshgrid(lons, lats) # Plot departure from normal mp = MapPlot( sector="midwest", title=("Precipitation Departure %s - %s") % (sts.strftime("%b %d %Y"), ets.strftime("%b %d %Y")), subtitle="based on IEM Estimates", ) mp.pcolormesh(lons, lats, (obprecip - clprecip) / 25.4, np.arange(-10, 10, 1)) mp.postprocess( pqstr="plot c 000000000000 summary/year/stage4_diff.png bogus png") mp.close() # Plot normals mp = MapPlot( sector="midwest", title=("Normal Precipitation:: %s - %s") % (sts.strftime("%b %d %Y"), ets.strftime("%b %d %Y")), subtitle="based on IEM Estimates", ) mp.pcolormesh(lons, lats, (clprecip) / 25.4, np.arange(0, 30, 2)) mp.postprocess( pqstr="plot c 000000000000 summary/year/stage4_normals.png bogus png") mp.close() # Plot Obs mp = MapPlot( sector="midwest", title=("Estimated Precipitation:: %s - %s") % (sts.strftime("%b %d %Y"), ets.strftime("%b %d %Y")), subtitle="based on IEM Estimates", ) mp.pcolormesh(lons, lats, (obprecip) / 25.4, np.arange(0, 30, 2)) mp.postprocess( pqstr="plot c 000000000000 summary/year/stage4obs.png bogus png") mp.close()
def workflow(ts): """Do Work""" # Load up our netcdf file! nc = ncopen(iemre.get_dailyc_ncname(), "a", timeout=300) grid_day(nc, ts) nc.close() nc = ncopen(iemre.get_dailyc_mrms_ncname(), "a", timeout=300) grid_day(nc, ts) nc.close()
def compute_hasdata(): """Compute the has_data grid""" nc = ncopen(iemre.get_dailyc_ncname(), 'a', timeout=300) czs = CachingZonalStats(iemre.AFFINE) pgconn = get_dbconn('postgis') states = gpd.GeoDataFrame.from_postgis(""" SELECT the_geom, state_abbr from states where state_abbr not in ('AK', 'HI') """, pgconn, index_col='state_abbr', geom_col='the_geom') data = np.flipud(nc.variables['hasdata'][:, :]) czs.gen_stats(data, states['the_geom']) for nav in czs.gridnav: grid = np.ones((nav.ysz, nav.xsz)) grid[nav.mask] = 0. yslice = slice(nav.y0, nav.y0 + nav.ysz) xslice = slice(nav.x0, nav.x0 + nav.xsz) data[yslice, xslice] = np.where(grid > 0, 1, data[yslice, xslice]) nc.variables['hasdata'][:, :] = np.flipud(data) nc.close()
def init_year(ts): """ Create a new NetCDF file for a year of our specification! """ fp = iemre.get_dailyc_ncname() nc = ncopen(fp, "w") nc.title = "IEM Daily Reanalysis Climatology %s" % (ts.year,) nc.platform = "Grided Climatology" nc.description = "IEM daily analysis on a 0.125 degree grid" nc.institution = "Iowa State University, Ames, IA, USA" nc.source = "Iowa Environmental Mesonet" nc.project_id = "IEM" nc.realization = 1 nc.Conventions = "CF-1.0" # *cough* nc.contact = "Daryl Herzmann, [email protected], 515-294-5978" nc.history = "%s Generated" % ( datetime.datetime.now().strftime("%d %B %Y"), ) nc.comment = "No Comment at this time" # Setup Dimensions nc.createDimension("lat", iemre.NY) nc.createDimension("lon", iemre.NX) ts2 = datetime.datetime(ts.year + 1, 1, 1) days = (ts2 - ts).days nc.createDimension("time", int(days)) # Setup Coordinate Variables lat = nc.createVariable("lat", np.float, ("lat",)) lat.units = "degrees_north" lat.long_name = "Latitude" lat.standard_name = "latitude" lat.axis = "Y" lat[:] = iemre.YAXIS lon = nc.createVariable("lon", np.float, ("lon",)) lon.units = "degrees_east" lon.long_name = "Longitude" lon.standard_name = "longitude" lon.axis = "X" lon[:] = iemre.XAXIS tm = nc.createVariable("time", np.float, ("time",)) tm.units = "Days since %s-01-01 00:00:0.0" % (ts.year,) tm.long_name = "Time" tm.standard_name = "time" tm.axis = "T" tm.calendar = "gregorian" tm[:] = np.arange(0, int(days)) # Tracked variables hasdata = nc.createVariable("hasdata", np.int8, ("lat", "lon")) hasdata.units = "1" hasdata.long_name = "Analysis Available for Grid Cell" hasdata.coordinates = "lon lat" hasdata[:] = 0 high = nc.createVariable( "high_tmpk", np.float, ("time", "lat", "lon"), fill_value=1.0e20 ) high.units = "K" high.long_name = "2m Air Temperature Daily High" high.standard_name = "2m Air Temperature" high.coordinates = "lon lat" low = nc.createVariable( "low_tmpk", np.float, ("time", "lat", "lon"), fill_value=1.0e20 ) low.units = "K" low.long_name = "2m Air Temperature Daily Low" low.standard_name = "2m Air Temperature" low.coordinates = "lon lat" p01d = nc.createVariable( "p01d", np.float, ("time", "lat", "lon"), fill_value=1.0e20 ) p01d.units = "mm" p01d.long_name = "Precipitation" p01d.standard_name = "Precipitation" p01d.coordinates = "lon lat" p01d.description = "Precipitation accumulation for the day" nc.close()
def plotter(fdict): """ Go """ ctx = util.get_autoplot_context(fdict, get_description()) ptype = ctx["ptype"] sdate = ctx["sdate"] edate = ctx["edate"] src = ctx["src"] opt = ctx["opt"] usdm = ctx["usdm"] if sdate.year != edate.year: raise NoDataFound("Sorry, do not support multi-year plots yet!") days = (edate - sdate).days sector = ctx["sector"] x0 = 0 x1 = -1 y0 = 0 y1 = -1 state = None if len(sector) == 2: state = sector sector = "state" title = compute_title(src, sdate, edate) if src == "mrms": ncfn = iemre.get_daily_mrms_ncname(sdate.year) clncfn = iemre.get_dailyc_mrms_ncname() ncvar = "p01d" source = "MRMS Q3" subtitle = "NOAA MRMS Project, GaugeCorr and RadarOnly" elif src == "iemre": ncfn = iemre.get_daily_ncname(sdate.year) clncfn = iemre.get_dailyc_ncname() ncvar = "p01d_12z" source = "IEM Reanalysis" subtitle = "IEM Reanalysis is derived from various NOAA datasets" else: ncfn = "/mesonet/data/prism/%s_daily.nc" % (sdate.year, ) clncfn = "/mesonet/data/prism/prism_dailyc.nc" ncvar = "ppt" source = "OSU PRISM" subtitle = ("PRISM Climate Group, Oregon State Univ., " "http://prism.oregonstate.edu, created 4 Feb 2004.") mp = MapPlot( sector=sector, state=state, axisbg="white", nocaption=True, title="%s:: %s Precip %s" % (source, title, PDICT3[opt]), subtitle="Data from %s" % (subtitle, ), titlefontsize=14, ) idx0 = iemre.daily_offset(sdate) idx1 = iemre.daily_offset(edate) + 1 if not os.path.isfile(ncfn): raise NoDataFound("No data for that year, sorry.") with util.ncopen(ncfn) as nc: if state is not None: x0, y0, x1, y1 = util.grid_bounds( nc.variables["lon"][:], nc.variables["lat"][:], state_bounds[state], ) elif sector in SECTORS: bnds = SECTORS[sector] x0, y0, x1, y1 = util.grid_bounds( nc.variables["lon"][:], nc.variables["lat"][:], [bnds[0], bnds[2], bnds[1], bnds[3]], ) lats = nc.variables["lat"][y0:y1] lons = nc.variables["lon"][x0:x1] if sdate == edate: p01d = mm2inch(nc.variables[ncvar][idx0, y0:y1, x0:x1]) elif (idx1 - idx0) < 32: p01d = mm2inch( np.sum(nc.variables[ncvar][idx0:idx1, y0:y1, x0:x1], 0)) else: # Too much data can overwhelm this app, need to chunk it for i in range(idx0, idx1, 10): i2 = min([i + 10, idx1]) if idx0 == i: p01d = mm2inch( np.sum(nc.variables[ncvar][i:i2, y0:y1, x0:x1], 0)) else: p01d += mm2inch( np.sum(nc.variables[ncvar][i:i2, y0:y1, x0:x1], 0)) if np.ma.is_masked(np.max(p01d)): raise NoDataFound("Data Unavailable") plot_units = "inches" cmap = get_cmap(ctx["cmap"]) cmap.set_bad("white") if opt == "dep": # Do departure work now with util.ncopen(clncfn) as nc: climo = mm2inch( np.sum(nc.variables[ncvar][idx0:idx1, y0:y1, x0:x1], 0)) p01d = p01d - climo [maxv] = np.percentile(np.abs(p01d), [99]) clevs = np.around(np.linspace(0 - maxv, maxv, 11), decimals=2) elif opt == "per": with util.ncopen(clncfn) as nc: climo = mm2inch( np.sum(nc.variables[ncvar][idx0:idx1, y0:y1, x0:x1], 0)) p01d = p01d / climo * 100.0 cmap.set_under("white") cmap.set_over("black") clevs = [1, 10, 25, 50, 75, 100, 125, 150, 200, 300, 500] plot_units = "percent" else: p01d = np.where(p01d < 0.001, np.nan, p01d) cmap.set_under("white") clevs = [0.01, 0.1, 0.3, 0.5, 1, 1.5, 2, 2.5, 3, 3.5, 4, 5, 6, 8, 10] if days > 6: clevs = [0.01, 0.3, 0.5, 1, 1.5, 2, 3, 4, 5, 6, 7, 8, 10, 15, 20] if days > 29: clevs = [0.01, 0.5, 1, 2, 3, 4, 5, 6, 8, 10, 15, 20, 25, 30, 35] if days > 90: clevs = [0.01, 1, 2, 3, 4, 5, 6, 8, 10, 15, 20, 25, 30, 35, 40] x2d, y2d = np.meshgrid(lons, lats) if ptype == "c": mp.contourf(x2d, y2d, p01d, clevs, cmap=cmap, units=plot_units, iline=False) else: res = mp.pcolormesh(x2d, y2d, p01d, clevs, cmap=cmap, units=plot_units) res.set_rasterized(True) if sector != "midwest": mp.drawcounties() mp.drawcities() if usdm == "yes": mp.draw_usdm(edate, filled=False, hatched=True) return mp.fig
def main(): """Go Main Go""" form = cgi.FieldStorage() ts1 = datetime.datetime.strptime(form.getfirst("date1"), "%Y-%m-%d") ts2 = datetime.datetime.strptime(form.getfirst("date2"), "%Y-%m-%d") if ts1 > ts2: send_error("date1 larger than date2") if ts1.year != ts2.year: send_error("multi-year query not supported yet...") # Make sure we aren't in the future tsend = datetime.date.today() if ts2.date() > tsend: ts2 = datetime.datetime.now() - datetime.timedelta(days=1) lat = float(form.getfirst("lat")) lon = float(form.getfirst("lon")) if lon < iemre.WEST or lon > iemre.EAST: send_error("lon value outside of bounds: %s to %s" % (iemre.WEST, iemre.EAST)) if lat < iemre.SOUTH or lat > iemre.NORTH: send_error("lat value outside of bounds: %s to %s" % (iemre.SOUTH, iemre.NORTH)) # fmt = form["format"][0] i, j = iemre.find_ij(lon, lat) offset1 = iemre.daily_offset(ts1) offset2 = iemre.daily_offset(ts2) + 1 # Get our netCDF vars with ncopen(iemre.get_daily_ncname(ts1.year)) as nc: hightemp = datatypes.temperature( nc.variables['high_tmpk'][offset1:offset2, j, i], 'K').value("F") high12temp = datatypes.temperature( nc.variables['high_tmpk_12z'][offset1:offset2, j, i], 'K').value("F") lowtemp = datatypes.temperature( nc.variables['low_tmpk'][offset1:offset2, j, i], 'K').value("F") low12temp = datatypes.temperature( nc.variables['low_tmpk_12z'][offset1:offset2, j, i], 'K').value("F") precip = nc.variables['p01d'][offset1:offset2, j, i] / 25.4 precip12 = nc.variables['p01d_12z'][offset1:offset2, j, i] / 25.4 # Get our climatology vars c2000 = ts1.replace(year=2000) coffset1 = iemre.daily_offset(c2000) c2000 = ts2.replace(year=2000) coffset2 = iemre.daily_offset(c2000) + 1 cnc = ncopen(iemre.get_dailyc_ncname()) chigh = datatypes.temperature( cnc.variables['high_tmpk'][coffset1:coffset2, j, i], 'K').value("F") clow = datatypes.temperature( cnc.variables['low_tmpk'][coffset1:coffset2, j, i], 'K').value("F") cprecip = cnc.variables['p01d'][coffset1:coffset2, j, i] / 25.4 cnc.close() if ts1.year > 1980: nc = ncopen("/mesonet/data/prism/%s_daily.nc" % (ts1.year, )) i2, j2 = prismutil.find_ij(lon, lat) prism_precip = nc.variables['ppt'][offset1:offset2, j2, i2] / 25.4 nc.close() else: prism_precip = [None] * (offset2 - offset1) if ts1.year > 2010: nc = ncopen(iemre.get_daily_mrms_ncname(ts1.year)) j2 = int((lat - iemre.SOUTH) * 100.0) i2 = int((lon - iemre.WEST) * 100.0) mrms_precip = nc.variables['p01d'][offset1:offset2, j2, i2] / 25.4 nc.close() else: mrms_precip = [None] * (offset2 - offset1) res = { 'data': [], } for i in range(0, offset2 - offset1): now = ts1 + datetime.timedelta(days=i) res['data'].append({ 'date': now.strftime("%Y-%m-%d"), 'mrms_precip_in': clean(mrms_precip[i]), 'prism_precip_in': clean(prism_precip[i]), 'daily_high_f': clean(hightemp[i]), '12z_high_f': clean(high12temp[i]), 'climate_daily_high_f': clean(chigh[i]), 'daily_low_f': clean(lowtemp[i]), '12z_low_f': clean(low12temp[i]), 'climate_daily_low_f': clean(clow[i]), 'daily_precip_in': clean(precip[i]), '12z_precip_in': clean(precip12[i]), 'climate_daily_precip_in': clean(cprecip[i]) }) ssw('Content-type: application/json\n\n') ssw(json.dumps(res))
def main(): """Do Something Fun!""" form = cgi.FieldStorage() ts = datetime.datetime.strptime(form.getfirst("date"), "%Y-%m-%d") lat = float(form.getfirst("lat")) lon = float(form.getfirst("lon")) fmt = form.getfirst("format") if fmt != 'json': ssw("Content-type: text/plain\n\n") ssw("ERROR: Service only emits json at this time") return i, j = iemre.find_ij(lon, lat) offset = iemre.daily_offset(ts) res = { 'data': [], } fn = iemre.get_daily_ncname(ts.year) ssw('Content-type: application/json\n\n') if not os.path.isfile(fn): ssw(json.dumps(res)) sys.exit() if i is None or j is None: ssw(json.dumps({'error': 'Coordinates outside of domain'})) return if ts.year > 1980: ncfn = "/mesonet/data/prism/%s_daily.nc" % (ts.year, ) if not os.path.isfile(ncfn): prism_precip = None else: i2, j2 = prismutil.find_ij(lon, lat) with ncopen(ncfn) as nc: prism_precip = nc.variables['ppt'][offset, j2, i2] / 25.4 else: prism_precip = None if ts.year > 2010: ncfn = iemre.get_daily_mrms_ncname(ts.year) if not os.path.isfile(ncfn): mrms_precip = None else: j2 = int((lat - iemre.SOUTH) * 100.0) i2 = int((lon - iemre.WEST) * 100.0) with ncopen(ncfn) as nc: mrms_precip = nc.variables['p01d'][offset, j2, i2] / 25.4 else: mrms_precip = None nc = ncopen(fn) c2000 = ts.replace(year=2000) coffset = iemre.daily_offset(c2000) cnc = ncopen(iemre.get_dailyc_ncname()) res['data'].append({ 'prism_precip_in': myrounder(prism_precip, 2), 'mrms_precip_in': myrounder(mrms_precip, 2), 'daily_high_f': myrounder( datatypes.temperature(nc.variables['high_tmpk'][offset, j, i], 'K').value('F'), 1), '12z_high_f': myrounder( datatypes.temperature(nc.variables['high_tmpk_12z'][offset, j, i], 'K').value('F'), 1), 'climate_daily_high_f': myrounder( datatypes.temperature(cnc.variables['high_tmpk'][coffset, j, i], 'K').value("F"), 1), 'daily_low_f': myrounder( datatypes.temperature(nc.variables['low_tmpk'][offset, j, i], 'K').value("F"), 1), '12z_low_f': myrounder( datatypes.temperature(nc.variables['low_tmpk_12z'][offset, j, i], 'K').value('F'), 1), 'avg_dewpoint_f': myrounder( datatypes.temperature(nc.variables['avg_dwpk'][offset, j, i], 'K').value('F'), 1), 'climate_daily_low_f': myrounder( datatypes.temperature(cnc.variables['low_tmpk'][coffset, j, i], 'K').value("F"), 1), 'daily_precip_in': myrounder(nc.variables['p01d'][offset, j, i] / 25.4, 2), '12z_precip_in': myrounder(nc.variables['p01d_12z'][offset, j, i] / 25.4, 2), 'climate_daily_precip_in': myrounder(cnc.variables['p01d'][coffset, j, i] / 25.4, 2), 'srad_mj': myrounder(nc.variables['rsds'][offset, j, i] * 86400. / 1000000., 2), 'avg_windspeed_mps': myrounder(nc.variables['wind_speed'][offset, j, i], 2), }) nc.close() cnc.close() ssw(json.dumps(res))
def plotter(fdict): """ Go """ ctx = util.get_autoplot_context(fdict, get_description()) ptype = ctx['ptype'] sdate = ctx['sdate'] edate = ctx['edate'] src = ctx['src'] opt = ctx['opt'] usdm = ctx['usdm'] if sdate.year != edate.year: raise NoDataFound('Sorry, do not support multi-year plots yet!') days = (edate - sdate).days sector = ctx['sector'] if sdate == edate: title = sdate.strftime("%-d %B %Y") else: title = "%s to %s (inclusive)" % (sdate.strftime("%-d %b"), edate.strftime("%-d %b %Y")) x0 = 0 x1 = -1 y0 = 0 y1 = -1 state = None if len(sector) == 2: state = sector sector = 'state' if src == 'mrms': ncfn = iemre.get_daily_mrms_ncname(sdate.year) clncfn = iemre.get_dailyc_mrms_ncname() ncvar = 'p01d' source = 'MRMS Q3' subtitle = 'NOAA MRMS Project, GaugeCorr and RadarOnly' elif src == 'iemre': ncfn = iemre.get_daily_ncname(sdate.year) clncfn = iemre.get_dailyc_ncname() ncvar = 'p01d_12z' source = 'IEM Reanalysis' subtitle = 'IEM Reanalysis is derived from various NOAA datasets' else: ncfn = "/mesonet/data/prism/%s_daily.nc" % (sdate.year, ) clncfn = "/mesonet/data/prism/prism_dailyc.nc" ncvar = 'ppt' source = 'OSU PRISM' subtitle = ('PRISM Climate Group, Oregon State Univ., ' 'http://prism.oregonstate.edu, created 4 Feb 2004.') mp = MapPlot(sector=sector, state=state, axisbg='white', nocaption=True, title='%s:: %s Precip %s' % (source, title, PDICT3[opt]), subtitle='Data from %s' % (subtitle, ), titlefontsize=14) idx0 = iemre.daily_offset(sdate) idx1 = iemre.daily_offset(edate) + 1 if not os.path.isfile(ncfn): raise NoDataFound("No data for that year, sorry.") with util.ncopen(ncfn) as nc: if state is not None: x0, y0, x1, y1 = util.grid_bounds(nc.variables['lon'][:], nc.variables['lat'][:], state_bounds[state]) elif sector in SECTORS: bnds = SECTORS[sector] x0, y0, x1, y1 = util.grid_bounds( nc.variables['lon'][:], nc.variables['lat'][:], [bnds[0], bnds[2], bnds[1], bnds[3]]) lats = nc.variables['lat'][y0:y1] lons = nc.variables['lon'][x0:x1] if sdate == edate: p01d = distance(nc.variables[ncvar][idx0, y0:y1, x0:x1], 'MM').value('IN') elif (idx1 - idx0) < 32: p01d = distance( np.sum(nc.variables[ncvar][idx0:idx1, y0:y1, x0:x1], 0), 'MM').value('IN') else: # Too much data can overwhelm this app, need to chunk it for i in range(idx0, idx1, 10): i2 = min([i + 10, idx1]) if idx0 == i: p01d = distance( np.sum(nc.variables[ncvar][i:i2, y0:y1, x0:x1], 0), 'MM').value('IN') else: p01d += distance( np.sum(nc.variables[ncvar][i:i2, y0:y1, x0:x1], 0), 'MM').value('IN') if np.ma.is_masked(np.max(p01d)): raise NoDataFound("Data Unavailable") units = 'inches' cmap = plt.get_cmap(ctx['cmap']) cmap.set_bad('white') if opt == 'dep': # Do departure work now with util.ncopen(clncfn) as nc: climo = distance( np.sum(nc.variables[ncvar][idx0:idx1, y0:y1, x0:x1], 0), 'MM').value('IN') p01d = p01d - climo [maxv] = np.percentile(np.abs(p01d), [ 99, ]) clevs = np.around(np.linspace(0 - maxv, maxv, 11), decimals=2) elif opt == 'per': with util.ncopen(clncfn) as nc: climo = distance( np.sum(nc.variables[ncvar][idx0:idx1, y0:y1, x0:x1], 0), 'MM').value('IN') p01d = p01d / climo * 100. cmap.set_under('white') cmap.set_over('black') clevs = [1, 10, 25, 50, 75, 100, 125, 150, 200, 300, 500] units = 'percent' else: p01d = np.where(p01d < 0.001, np.nan, p01d) cmap.set_under('white') clevs = [0.01, 0.1, 0.3, 0.5, 1, 1.5, 2, 2.5, 3, 3.5, 4, 5, 6, 8, 10] if days > 6: clevs = [0.01, 0.3, 0.5, 1, 1.5, 2, 3, 4, 5, 6, 7, 8, 10, 15, 20] if days > 29: clevs = [0.01, 0.5, 1, 2, 3, 4, 5, 6, 8, 10, 15, 20, 25, 30, 35] if days > 90: clevs = [0.01, 1, 2, 3, 4, 5, 6, 8, 10, 15, 20, 25, 30, 35, 40] x2d, y2d = np.meshgrid(lons, lats) if ptype == 'c': mp.contourf(x2d, y2d, p01d, clevs, cmap=cmap, units=units, iline=False) else: res = mp.pcolormesh(x2d, y2d, p01d, clevs, cmap=cmap, units=units) res.set_rasterized(True) if sector != 'midwest': mp.drawcounties() mp.drawcities() if usdm == 'yes': mp.draw_usdm(edate, filled=False, hatched=True) return mp.fig
def main(): """Go Main Go""" # Run for a period of 121 days ets = datetime.datetime.now() - datetime.timedelta(days=1) sts = ets - datetime.timedelta(days=121) # Get the normal accumm cnc = ncopen(iemre.get_dailyc_ncname(), "r") lons = cnc.variables["lon"][:] lats = cnc.variables["lat"][:] index0 = iemre.daily_offset(sts) index1 = iemre.daily_offset(ets) if index1 < index0: # Uh oh, we are spanning a year clprecip = np.sum(cnc.variables["p01d"][:index1, :, :], 0) clprecip = clprecip + np.sum(cnc.variables["p01d"][index0:, :, :], 0) else: clprecip = np.sum(cnc.variables["p01d"][index0:index1, :, :], 0) cnc.close() # Get the observed precip if sts.year != ets.year: # spanner, darn onc = ncopen(iemre.get_daily_ncname(sts.year)) obprecip = np.sum(onc.variables["p01d"][index0:, :, :], 0) onc.close() onc = ncopen(iemre.get_daily_ncname(ets.year)) obprecip = obprecip + np.sum(onc.variables["p01d"][:index1, :, :], 0) onc.close() else: ncfn = iemre.get_daily_ncname(sts.year) onc = ncopen(ncfn, "r") obprecip = np.sum(onc.variables["p01d"][index0:index1, :, :], 0) onc.close() lons, lats = np.meshgrid(lons, lats) # Plot departure from normal mp = MapPlot( sector="midwest", title=("Precipitation Departure %s - %s") % (sts.strftime("%b %d %Y"), ets.strftime("%b %d %Y")), subtitle="based on IEM Estimates", ) mp.pcolormesh(lons, lats, (obprecip - clprecip) / 25.4, np.arange(-10, 10, 1)) mp.postprocess(pqstr="plot c 000000000000 summary/4mon_diff.png bogus png") mp.close() # Plot normals mp = MapPlot( sector="midwest", title=("Normal Precipitation:: %s - %s") % (sts.strftime("%b %d %Y"), ets.strftime("%b %d %Y")), subtitle="based on IEM Estimates", ) mp.pcolormesh(lons, lats, (clprecip) / 25.4, np.arange(0, 30, 2)) mp.postprocess( pqstr="plot c 000000000000 summary/4mon_normals.png bogus png") mp.close() # Plot Obs mp = MapPlot( sector="midwest", title=("Estimated Precipitation:: %s - %s") % (sts.strftime("%b %d %Y"), ets.strftime("%b %d %Y")), subtitle="based on IEM Estimates", ) mp.pcolormesh(lons, lats, (obprecip) / 25.4, np.arange(0, 30, 2)) mp.postprocess( pqstr="plot c 000000000000 summary/4mon_stage4obs.png bogus png") mp.close()
def application(environ, start_response): """Do Something Fun!""" form = parse_formvars(environ) ts = datetime.datetime.strptime(form.get("date", "2019-03-01"), "%Y-%m-%d") lat = float(form.get("lat", 41.99)) lon = float(form.get("lon", -95.1)) fmt = form.get("format", "json") if fmt != "json": headers = [("Content-type", "text/plain")] start_response("200 OK", headers) return [b"ERROR: Service only emits json at this time"] i, j = iemre.find_ij(lon, lat) offset = iemre.daily_offset(ts) res = {"data": []} fn = iemre.get_daily_ncname(ts.year) headers = [("Content-type", "application/json")] start_response("200 OK", headers) if not os.path.isfile(fn): return [json.dumps(res).encode("ascii")] if i is None or j is None: data = {"error": "Coordinates outside of domain"} return [json.dumps(data).encode("ascii")] if ts.year > 1980: ncfn = "/mesonet/data/prism/%s_daily.nc" % (ts.year, ) if not os.path.isfile(ncfn): prism_precip = None else: i2, j2 = prismutil.find_ij(lon, lat) with ncopen(ncfn) as nc: prism_precip = nc.variables["ppt"][offset, j2, i2] / 25.4 else: prism_precip = None if ts.year > 2010: ncfn = iemre.get_daily_mrms_ncname(ts.year) if not os.path.isfile(ncfn): mrms_precip = None else: j2 = int((lat - iemre.SOUTH) * 100.0) i2 = int((lon - iemre.WEST) * 100.0) with ncopen(ncfn) as nc: mrms_precip = nc.variables["p01d"][offset, j2, i2] / 25.4 else: mrms_precip = None c2000 = ts.replace(year=2000) coffset = iemre.daily_offset(c2000) with ncopen(fn) as nc: with ncopen(iemre.get_dailyc_ncname()) as cnc: res["data"].append({ "prism_precip_in": myrounder(prism_precip, 2), "mrms_precip_in": myrounder(mrms_precip, 2), "daily_high_f": myrounder( datatypes.temperature( nc.variables["high_tmpk"][offset, j, i], "K").value("F"), 1, ), "12z_high_f": myrounder( datatypes.temperature( nc.variables["high_tmpk_12z"][offset, j, i], "K").value("F"), 1, ), "climate_daily_high_f": myrounder( datatypes.temperature( cnc.variables["high_tmpk"][coffset, j, i], "K").value("F"), 1, ), "daily_low_f": myrounder( datatypes.temperature( nc.variables["low_tmpk"][offset, j, i], "K").value("F"), 1, ), "12z_low_f": myrounder( datatypes.temperature( nc.variables["low_tmpk_12z"][offset, j, i], "K").value("F"), 1, ), "avg_dewpoint_f": myrounder( datatypes.temperature( nc.variables["avg_dwpk"][offset, j, i], "K").value("F"), 1, ), "climate_daily_low_f": myrounder( datatypes.temperature( cnc.variables["low_tmpk"][coffset, j, i], "K").value("F"), 1, ), "daily_precip_in": myrounder(nc.variables["p01d"][offset, j, i] / 25.4, 2), "12z_precip_in": myrounder(nc.variables["p01d_12z"][offset, j, i] / 25.4, 2), "climate_daily_precip_in": myrounder(cnc.variables["p01d"][coffset, j, i] / 25.4, 2), "srad_mj": myrounder( nc.variables["rsds"][offset, j, i] * 86400.0 / 1000000.0, 2, ), "avg_windspeed_mps": myrounder(nc.variables["wind_speed"][offset, j, i], 2), }) return [json.dumps(res).encode("ascii")]
def application(environ, start_response): """Go Main Go""" form = parse_formvars(environ) ts1 = datetime.datetime.strptime(form.get("date1"), "%Y-%m-%d") ts2 = datetime.datetime.strptime(form.get("date2"), "%Y-%m-%d") if ts1 > ts2: return [send_error(start_response, "date1 larger than date2")] if ts1.year != ts2.year: return [ send_error(start_response, "multi-year query not supported yet...") ] # Make sure we aren't in the future tsend = datetime.date.today() if ts2.date() > tsend: ts2 = datetime.datetime.now() - datetime.timedelta(days=1) lat = float(form.get("lat")) lon = float(form.get("lon")) if lon < iemre.WEST or lon > iemre.EAST: return [ send_error( start_response, "lon value outside of bounds: %s to %s" % (iemre.WEST, iemre.EAST), ) ] if lat < iemre.SOUTH or lat > iemre.NORTH: return [ send_error( start_response, "lat value outside of bounds: %s to %s" % (iemre.SOUTH, iemre.NORTH), ) ] # fmt = form["format"][0] i, j = iemre.find_ij(lon, lat) offset1 = iemre.daily_offset(ts1) offset2 = iemre.daily_offset(ts2) + 1 # Get our netCDF vars with ncopen(iemre.get_daily_ncname(ts1.year)) as nc: hightemp = datatypes.temperature( nc.variables["high_tmpk"][offset1:offset2, j, i], "K" ).value("F") high12temp = datatypes.temperature( nc.variables["high_tmpk_12z"][offset1:offset2, j, i], "K" ).value("F") lowtemp = datatypes.temperature( nc.variables["low_tmpk"][offset1:offset2, j, i], "K" ).value("F") low12temp = datatypes.temperature( nc.variables["low_tmpk_12z"][offset1:offset2, j, i], "K" ).value("F") precip = nc.variables["p01d"][offset1:offset2, j, i] / 25.4 precip12 = nc.variables["p01d_12z"][offset1:offset2, j, i] / 25.4 # Get our climatology vars c2000 = ts1.replace(year=2000) coffset1 = iemre.daily_offset(c2000) c2000 = ts2.replace(year=2000) coffset2 = iemre.daily_offset(c2000) + 1 with ncopen(iemre.get_dailyc_ncname()) as cnc: chigh = datatypes.temperature( cnc.variables["high_tmpk"][coffset1:coffset2, j, i], "K" ).value("F") clow = datatypes.temperature( cnc.variables["low_tmpk"][coffset1:coffset2, j, i], "K" ).value("F") cprecip = cnc.variables["p01d"][coffset1:coffset2, j, i] / 25.4 if ts1.year > 1980: i2, j2 = prismutil.find_ij(lon, lat) with ncopen("/mesonet/data/prism/%s_daily.nc" % (ts1.year,)) as nc: prism_precip = nc.variables["ppt"][offset1:offset2, j2, i2] / 25.4 else: prism_precip = [None] * (offset2 - offset1) if ts1.year > 2010: j2 = int((lat - iemre.SOUTH) * 100.0) i2 = int((lon - iemre.WEST) * 100.0) with ncopen(iemre.get_daily_mrms_ncname(ts1.year)) as nc: mrms_precip = nc.variables["p01d"][offset1:offset2, j2, i2] / 25.4 else: mrms_precip = [None] * (offset2 - offset1) res = {"data": []} for i in range(0, offset2 - offset1): now = ts1 + datetime.timedelta(days=i) res["data"].append( { "date": now.strftime("%Y-%m-%d"), "mrms_precip_in": clean(mrms_precip[i]), "prism_precip_in": clean(prism_precip[i]), "daily_high_f": clean(hightemp[i]), "12z_high_f": clean(high12temp[i]), "climate_daily_high_f": clean(chigh[i]), "daily_low_f": clean(lowtemp[i]), "12z_low_f": clean(low12temp[i]), "climate_daily_low_f": clean(clow[i]), "daily_precip_in": clean(precip[i]), "12z_precip_in": clean(precip12[i]), "climate_daily_precip_in": clean(cprecip[i]), } ) start_response("200 OK", [("Content-type", "application/json")]) return [json.dumps(res).encode("ascii")]
def service( fmt: SupportedFormatsNoGeoJSON, sdate: datetime.date = Query(..., description="Start Date."), edate: datetime.date = Query(..., description="End Date."), lon: float = Query(..., description="Longitude of point of interest"), lat: float = Query(..., description="Latitude of point of interest"), ): """Go Main Go""" # Make sure we aren't in the future tsend = datetime.date.today() if edate > tsend: edate = datetime.date.today() - datetime.timedelta(days=1) i, j = iemre.find_ij(lon, lat) offset1 = iemre.daily_offset(sdate) offset2 = iemre.daily_offset(edate) + 1 # Get our netCDF vars with ncopen(iemre.get_daily_ncname(sdate.year)) as nc: hightemp = convert_value( nc.variables["high_tmpk"][offset1:offset2, j, i], "degK", "degF" ) high12temp = convert_value( nc.variables["high_tmpk_12z"][offset1:offset2, j, i], "degK", "degF", ) lowtemp = convert_value( nc.variables["low_tmpk"][offset1:offset2, j, i], "degK", "degF" ) low12temp = convert_value( nc.variables["low_tmpk_12z"][offset1:offset2, j, i], "degK", "degF" ) precip = mm2inch(nc.variables["p01d"][offset1:offset2, j, i]) precip12 = mm2inch(nc.variables["p01d_12z"][offset1:offset2, j, i]) # Get our climatology vars c2000 = sdate.replace(year=2000) coffset1 = iemre.daily_offset(c2000) c2000 = edate.replace(year=2000) coffset2 = iemre.daily_offset(c2000) + 1 with ncopen(iemre.get_dailyc_ncname()) as cnc: chigh = convert_value( cnc.variables["high_tmpk"][coffset1:coffset2, j, i], "degK", "degF" ) clow = convert_value( cnc.variables["low_tmpk"][coffset1:coffset2, j, i], "degK", "degF" ) cprecip = mm2inch( cnc.variables["p01d"][coffset1:coffset2, j, i], ) if sdate.year > 1980: i2, j2 = prismutil.find_ij(lon, lat) with ncopen(f"/mesonet/data/prism/{sdate.year}_daily.nc") as nc: prism_precip = mm2inch( nc.variables["ppt"][offset1:offset2, j2, i2], ) else: prism_precip = [None] * (offset2 - offset1) if sdate.year > 2000: j2 = int((lat - iemre.SOUTH) * 100.0) i2 = int((lon - iemre.WEST) * 100.0) with ncopen(iemre.get_daily_mrms_ncname(sdate.year)) as nc: mrms_precip = mm2inch( nc.variables["p01d"][offset1:offset2, j2, i2], ) else: mrms_precip = [None] * (offset2 - offset1) res = [] for i in range(0, offset2 - offset1): now = sdate + datetime.timedelta(days=i) res.append( { "date": now.strftime("%Y-%m-%d"), "mrms_precip_in": clean(mrms_precip[i]), "prism_precip_in": clean(prism_precip[i]), "daily_high_f": clean(hightemp[i]), "12z_high_f": clean(high12temp[i]), "climate_daily_high_f": clean(chigh[i]), "daily_low_f": clean(lowtemp[i]), "12z_low_f": clean(low12temp[i]), "climate_daily_low_f": clean(clow[i]), "daily_precip_in": clean(precip[i]), "12z_precip_in": clean(precip12[i]), "climate_daily_precip_in": clean(cprecip[i]), } ) return deliver_df(pd.DataFrame(res), fmt)
def service( fmt: SupportedFormatsNoGeoJSON, date: datetime.date = Query(..., description="The date of interest."), lon: float = Query(..., description="Longitude of point of interest"), lat: float = Query(..., description="Latitude of point of interest"), ): """Do Something Fun!""" i, j = iemre.find_ij(lon, lat) offset = iemre.daily_offset(date) res = [] fn = iemre.get_daily_ncname(date.year) if date.year > 1980: ncfn = f"/mesonet/data/prism/{date.year}_daily.nc" if not os.path.isfile(ncfn): prism_precip = None else: i2, j2 = prismutil.find_ij(lon, lat) with ncopen(ncfn) as nc: prism_precip = mm2inch(nc.variables["ppt"][offset, j2, i2]) else: prism_precip = None if date.year > 2000: ncfn = iemre.get_daily_mrms_ncname(date.year) if not os.path.isfile(ncfn): mrms_precip = None else: j2 = int((lat - iemre.SOUTH) * 100.0) i2 = int((lon - iemre.WEST) * 100.0) with ncopen(ncfn) as nc: mrms_precip = mm2inch(nc.variables["p01d"][offset, j2, i2]) else: mrms_precip = None c2000 = date.replace(year=2000) coffset = iemre.daily_offset(c2000) with ncopen(fn) as nc: with ncopen(iemre.get_dailyc_ncname()) as cnc: res.append({ "prism_precip_in": myrounder(prism_precip, 2), "mrms_precip_in": myrounder(mrms_precip, 2), "daily_high_f": myrounder( convert_value( nc.variables["high_tmpk"][offset, j, i], "degK", "degF", ), 1, ), "12z_high_f": myrounder( convert_value( nc.variables["high_tmpk_12z"][offset, j, i], "degK", "degF", ), 1, ), "climate_daily_high_f": myrounder( convert_value( cnc.variables["high_tmpk"][coffset, j, i], "degK", "degF", ), 1, ), "daily_low_f": myrounder( convert_value( nc.variables["low_tmpk"][offset, j, i], "degK", "degF", ), 1, ), "12z_low_f": myrounder( convert_value( nc.variables["low_tmpk_12z"][offset, j, i], "degK", "degF", ), 1, ), "avg_dewpoint_f": myrounder( convert_value( nc.variables["avg_dwpk"][offset, j, i], "degK", "degF", ), 1, ), "climate_daily_low_f": myrounder( convert_value( cnc.variables["low_tmpk"][coffset, j, i], "degK", "degF", ), 1, ), "daily_precip_in": myrounder(mm2inch(nc.variables["p01d"][offset, j, i]), 2), "12z_precip_in": myrounder(mm2inch(nc.variables["p01d_12z"][offset, j, i]), 2), "climate_daily_precip_in": myrounder(mm2inch(cnc.variables["p01d"][coffset, j, i]), 2), "srad_mj": myrounder( nc.variables["rsds"][offset, j, i] * 86400.0 / 1000000.0, 2, ), "avg_windspeed_mps": myrounder(nc.variables["wind_speed"][offset, j, i], 2), }) return deliver_df(pd.DataFrame(res), fmt)