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 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 plotter(fdict): """ Go """ ctx = util.get_autoplot_context(fdict, get_description()) date = ctx['date'] sector = ctx['sector'] days = ctx['trailing'] threshold = ctx['threshold'] window_sts = date - datetime.timedelta(days=days) if window_sts.year != date.year: raise ValueError('Sorry, do not support multi-year plots yet!') if len(sector) != 2: raise ValueError("Sorry, this does not support multi-state plots yet.") idx0 = iemre.daily_offset(window_sts) idx1 = iemre.daily_offset(date) ncfn = iemre.get_daily_mrms_ncname(date.year) ncvar = 'p01d' if not os.path.isfile(ncfn): raise ValueError("No data for that year, sorry.") nc = util.ncopen(ncfn) # Get the state weight df = gpd.GeoDataFrame.from_postgis(""" SELECT the_geom from states where state_abbr = %s """, util.get_dbconn('postgis'), params=(sector, ), index_col=None, geom_col='the_geom') czs = CachingZonalStats(iemre.MRMS_AFFINE) czs.gen_stats( np.zeros((nc.variables['lat'].size, nc.variables['lon'].size)), df['the_geom']) hasdata = None jslice = None islice = None for nav in czs.gridnav: hasdata = np.ones((nav.ysz, nav.xsz)) hasdata[nav.mask] = 0. # careful here as y is flipped in this context jslice = slice(nc.variables['lat'].size - (nav.y0 + nav.ysz), nc.variables['lat'].size - nav.y0) islice = slice(nav.x0, nav.x0 + nav.xsz) hasdata = np.flipud(hasdata) today = distance(nc.variables[ncvar][idx1, jslice, islice], 'MM').value('IN') if (idx1 - idx0) < 32: p01d = distance( np.sum(nc.variables[ncvar][idx0:idx1, jslice, islice], 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, jslice, islice], 0), 'MM').value('IN') else: p01d += distance( np.sum(nc.variables[ncvar][i:i2, jslice, islice], 0), 'MM').value('IN') nc.close() # Get climatology nc = util.ncopen(iemre.get_dailyc_mrms_ncname()) if (idx1 - idx0) < 32: c_p01d = distance( np.sum(nc.variables[ncvar][idx0:idx1, jslice, islice], 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: c_p01d = distance( np.sum(nc.variables[ncvar][i:i2, jslice, islice], 0), 'MM').value('IN') else: c_p01d += distance( np.sum(nc.variables[ncvar][i:i2, jslice, islice], 0), 'MM').value('IN') nc.close() # we actually don't care about weights at this fine of scale cells = np.sum(np.where(hasdata > 0, 1, 0)) departure = p01d - c_p01d # Update departure and today to values unconsidered below when out of state departure = np.where(hasdata > 0, departure, -9999) today = np.where(hasdata > 0, today, 0) ranges = [[-99, -3], [-3, -2], [-2, -1], [-1, 0], [0, 1], [1, 2], [2, 3], [3, 99]] x = [] x2 = [] labels = [] for (minv, maxv) in ranges: labels.append("%.0f to %.0f" % (minv, maxv)) # How many departure cells in this range hits = np.logical_and(departure < maxv, departure > minv) hits2 = np.logical_and(hits, today > threshold) x.append(np.sum(np.where(hits, 1, 0)) / float(cells) * 100.) x2.append(np.sum(np.where(hits2, 1, 0)) / float(cells) * 100.) (fig, ax) = plt.subplots(1, 1) ax.set_title(("%s NOAA MRMS %s %.2f inch Precip Coverage") % (state_names[sector], date.strftime("%-d %b %Y"), threshold)) ax.bar(np.arange(8) - 0.2, x, align='center', width=0.4, label='Trailing %s Day Departure' % (days, )) ax.bar(np.arange(8) + 0.2, x2, align='center', width=0.4, label='%s Coverage (%.1f%% Tot)' % (date.strftime("%-d %b %Y"), sum(x2))) for i, (_x1, _x2) in enumerate(zip(x, x2)): ax.text(i - 0.2, _x1 + 1, "%.1f" % (_x1, ), ha='center') ax.text(i + 0.2, _x2 + 1, "%.1f" % (_x2, ), ha='center') ax.set_xticks(np.arange(8)) ax.set_xticklabels(labels) ax.set_xlabel("Trailing %s Day Precip Departure [in]" % (days, )) ax.set_position([0.1, 0.2, 0.8, 0.7]) ax.legend(loc=(0., -0.2), ncol=2) ax.set_ylabel("Areal Coverage of %s [%%]" % (state_names[sector], )) ax.grid(True) ax.set_xlim(-0.5, 7.5) ax.set_ylim(0, max([max(x2), max(x)]) + 5) return fig
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 init_year(ts): """ Create a new NetCDF file for a year of our specification! """ fn = iemre.get_dailyc_mrms_ncname() nc = ncopen(fn, "w") nc.title = "IEM Daily Reanalysis Climatology %s" % (ts.year, ) nc.platform = "Grided Climatology" nc.description = "IEM daily analysis on a 0.01 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.NORTH - iemre.SOUTH) * 100.0) nc.createDimension("lon", (iemre.EAST - iemre.WEST) * 100.0) ts2 = datetime.datetime(ts.year + 1, 1, 1) days = (ts2 - ts).days nc.createDimension("time", int(days)) nc.createDimension("nv", 2) # Setup Coordinate Variables lat = nc.createVariable("lat", np.float, ("lat", )) lat.units = "degrees_north" lat.long_name = "Latitude" lat.standard_name = "latitude" lat.bounds = "lat_bnds" lat.axis = "Y" # Grid centers lat[:] = np.arange(iemre.SOUTH + 0.005, iemre.NORTH, 0.01) lat_bnds = nc.createVariable("lat_bnds", np.float, ("lat", "nv")) lat_bnds[:, 0] = np.arange(iemre.SOUTH, iemre.NORTH, 0.01) lat_bnds[:, 1] = np.arange(iemre.SOUTH + 0.01, iemre.NORTH + 0.01, 0.01) lon = nc.createVariable("lon", np.float, ("lon", )) lon.units = "degrees_east" lon.long_name = "Longitude" lon.standard_name = "longitude" lon.bounds = "lon_bnds" lon.axis = "X" lon[:] = np.arange(iemre.WEST, iemre.EAST, 0.01) lon_bnds = nc.createVariable("lon_bnds", np.float, ("lon", "nv")) lon_bnds[:, 0] = np.arange(iemre.WEST, iemre.EAST, 0.01) lon_bnds[:, 1] = np.arange(iemre.WEST + 0.01, iemre.EAST + 0.01, 0.01) 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)) p01d = nc.createVariable("p01d", np.uint16, ("time", "lat", "lon"), fill_value=65535) p01d.units = "mm" p01d.scale_factor = 0.01 p01d.long_name = "Precipitation" p01d.standard_name = "Precipitation" p01d.coordinates = "lon lat" p01d.description = "Precipitation accumulation for the day" nc.close()