def test_simple(): """ Get nulls for right and top values """ i, j = iemre.find_ij(iemre.EAST, iemre.NORTH) assert i is None assert j is None i, j = iemre.find_ij(iemre.WEST, iemre.SOUTH) assert i == 0 assert j == 0
def test_simple(self): """ Get nulls for right and top values """ i, j = iemre.find_ij(iemre.EAST, iemre.NORTH) assert i is None assert j is None i, j = iemre.find_ij(iemre.WEST, iemre.SOUTH) self.assertEqual(i, 0) self.assertEqual(j, 0)
def load_table(state, date): """Update the station table""" nt = NetworkTable("%sCLIMATE" % (state, )) rows = [] istoday = (date == datetime.date.today()) for sid in nt.sts: # handled by compute_0000 if sid[2:] == '0000' or sid[2] == 'C': continue if istoday and not nt.sts[sid]['temp24_hour'] in range(3, 12): # print('skipping %s as is_today' % (sid, )) continue i, j = iemre.find_ij(nt.sts[sid]['lon'], nt.sts[sid]['lat']) nt.sts[sid]['gridi'] = i nt.sts[sid]['gridj'] = j rows.append( {'station': sid, 'gridi': i, 'gridj': j, 'temp24_hour': nt.sts[sid]['temp24_hour'], 'precip24_hour': nt.sts[sid]['precip24_hour'], 'tracks': nt.sts[sid]['attributes'].get( 'TRACKS_STATION', '|').split("|")[0]} ) if not rows: return df = pd.DataFrame(rows) df.set_index('station', inplace=True) for key in ['high', 'low', 'precip', 'snow', 'snowd']: df[key] = None return df
def load_table(state, date): """Update the station table""" nt = NetworkTable("%sCLIMATE" % (state, )) rows = [] istoday = date == datetime.date.today() for sid in nt.sts: # handled by compute_0000 if sid[2:] == "0000" or sid[2] == "C": continue if istoday and not nt.sts[sid]["temp24_hour"] in range(3, 12): continue i, j = iemre.find_ij(nt.sts[sid]["lon"], nt.sts[sid]["lat"]) nt.sts[sid]["gridi"] = i nt.sts[sid]["gridj"] = j rows.append({ "station": sid, "gridi": i, "gridj": j, "temp24_hour": nt.sts[sid]["temp24_hour"], "precip24_hour": nt.sts[sid]["precip24_hour"], "tracks": nt.sts[sid]["attributes"].get("TRACKS_STATION", "|").split("|")[0], }) if not rows: return df = pd.DataFrame(rows) df.set_index("station", inplace=True) for key in ["high", "low", "precip", "snow", "snowd"]: df[key] = None return df
def tile_extraction(nc, valid, west, south): """Do our tile extraction""" # update model metadata nc.valid = "CFS model: %s" % (valid.strftime("%Y-%m-%dT%H:%M:%SZ"), ) i, j = iemre.find_ij(west, south) islice = slice(i, i + 16) jslice = slice(j, j + 16) for year in range(1980, valid.year + 1): # Current year IEMRE should be substituted for this year's data today = datetime.date(year, valid.month, valid.day) copy_iemre(nc, valid.year, datetime.date(year, 1, 1), today, islice, jslice) # replace CFS! if year == valid.year: replace_cfs(nc, valid.date(), islice, jslice) else: # replace rest of year with previous year copy_iemre( nc, year, today + datetime.timedelta(days=1), datetime.date(year, 12, 31), islice, jslice, )
def do_var(varname): """ Run our estimator for a given variable """ currentnc = None sql = """select day, station from alldata_%s WHERE %s is null and day >= '1893-01-01' ORDER by day ASC""" % (state.lower(), varname) ccursor.execute(sql) for row in ccursor: day = row[0] station = row[1] if station not in nt.sts: continue sql = """ SELECT station, %s from alldata_%s WHERE %s is not NULL and station in %s and day = '%s' """ % (varname, state, varname, tuple(friends[station]), day) ccursor2.execute(sql) weight = [] value = [] for row2 in ccursor2: idx = friends[station].index(row2[0]) weight.append(weights[station][idx]) value.append(row2[1]) if len(weight) < 3: # Nearest neighbors failed, so lets look at our grided analysis # and sample from it if currentnc is None or currentnc.title.find(str(day.year)) == -1: currentnc = netCDF4.Dataset(("/mesonet/data/iemre/" "%s_mw_daily.nc") % (day.year,)) tidx = iemre.daily_offset(datetime.datetime(day.year, day.month, day.day)) iidx, jidx = iemre.find_ij(nt.sts[station]['lon'], nt.sts[station]['lat']) iemreval = currentnc.variables[vnameconv[varname]][tidx, jidx, iidx] if varname in ('high', 'low'): interp = temperature(iemreval, 'K').value('F') else: interp = distance(iemreval, 'MM').value('IN') print '--> Neighbor failure, %s %s %s' % (station, day, varname) else: mass = sum(weight) interp = np.sum(np.array(weight) * np.array(value) / mass) dataformat = '%.2f' if varname in ['high', 'low']: dataformat = '%.0f' print(('Set station: %s day: %s varname: %s value: %s' ) % (station, day, varname, dataformat % (interp,))) sql = """ UPDATE alldata_%s SET estimated = true, %s = %s WHERE station = '%s' and day = '%s' """ % (state.lower(), varname, dataformat % (interp,), station, day) sql = sql.replace(' nan ', ' null ') ccursor2.execute(sql)
def do_var(varname): """ Run our estimator for a given variable """ currentnc = None sql = """select day, station from alldata_%s WHERE %s is null and day >= '1893-01-01' ORDER by day ASC""" % (state.lower(), varname) ccursor.execute(sql) for row in ccursor: day = row[0] station = row[1] if station not in nt.sts: continue sql = """ SELECT station, %s from alldata_%s WHERE %s is not NULL and station in %s and day = '%s' """ % (varname, state, varname, tuple(friends[station]), day) ccursor2.execute(sql) weight = [] value = [] for row2 in ccursor2: idx = friends[station].index(row2[0]) weight.append(weights[station][idx]) value.append(row2[1]) if len(weight) < 3: # Nearest neighbors failed, so lets look at our grided analysis # and sample from it if currentnc is None or currentnc.title.find(str(day.year)) == -1: currentnc = netCDF4.Dataset(("/mesonet/data/iemre/" "%s_mw_daily.nc") % (day.year, )) tidx = iemre.daily_offset( datetime.datetime(day.year, day.month, day.day)) iidx, jidx = iemre.find_ij(nt.sts[station]['lon'], nt.sts[station]['lat']) iemreval = currentnc.variables[vnameconv[varname]][tidx, jidx, iidx] if varname in ('high', 'low'): interp = temperature(iemreval, 'K').value('F') else: interp = iemreval / 24.5 print '--> Neighbor failure, %s %s %s' % (station, day, varname) else: mass = sum(weight) interp = np.sum(np.array(weight) * np.array(value) / mass) dataformat = '%.2f' if varname in ['high', 'low']: dataformat = '%.0f' print(('Set station: %s day: %s varname: %s value: %s') % (station, day, varname, dataformat % (interp, ))) sql = """ UPDATE alldata_%s SET estimated = true, %s = %s WHERE station = '%s' and day = '%s' """ % (state.lower(), varname, dataformat % (interp, ), station, day) sql = sql.replace(' nan ', ' null ') ccursor2.execute(sql)
def load_table(): """Update the station table""" for sid in nt.sts: i, j = iemre.find_ij(nt.sts[sid]['lon'], nt.sts[sid]['lat']) nt.sts[sid]['gridi'] = i nt.sts[sid]['gridj'] = j for key in ['high', 'low', 'precip', 'snow', 'snowd']: nt.sts[sid][key] = None
def main(): """Do Something Fun!""" form = cgi.FormContent() ts = datetime.datetime.strptime(form["date"][0], "%Y-%m-%d") lat = float(form["lat"][0]) lon = float(form["lon"][0]) fmt = form["format"][0] if fmt != 'json': sys.stdout.write("Content-type: text/plain\n\n") sys.stdout.write("ERROR: Service only emits json at this time") return i, j = iemre.find_ij(lon, lat) offset = iemre.daily_offset(ts) res = {'data': [], } fn = "/mesonet/data/iemre/%s_mw_daily.nc" % (ts.year,) sys.stdout.write('Content-type: application/json\n\n') if not os.path.isfile(fn): sys.stdout.write(json.dumps(res)) sys.exit() if i is None or j is None: sys.stdout.write(json.dumps({'error': 'Coordinates outside of domain'} )) return nc = netCDF4.Dataset(fn, 'r') c2000 = ts.replace(year=2000) coffset = iemre.daily_offset(c2000) cnc = netCDF4.Dataset("/mesonet/data/iemre/mw_dailyc.nc", 'r') res['data'].append({ 'daily_high_f': myrounder( datatypes.temperature( nc.variables['high_tmpk'][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), '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), 'climate_daily_precip_in': myrounder( cnc.variables['p01d'][coffset, j, i] / 25.4, 2), }) nc.close() cnc.close() sys.stdout.write(json.dumps(res))
def tile_extraction(nc, valid, west, south): """Do our tile extraction""" # update model metadata i, j = iemre.find_ij(west, south) islice = slice(i, i + 16) jslice = slice(j, j + 16) for year in range(1980, valid.year + 1): copy_iemre(nc, year, datetime.date(year, 1, 1), datetime.date(year, 12, 31), islice, jslice)
def tile_extraction(nc, valid, west, south): """Do our tile extraction""" # update model metadata i, j = iemre.find_ij(west, south) islice = slice(i, i + 16) jslice = slice(j, j + 16) # Current year IEMRE should be substituted for this year's data copy_iemre(nc, valid.year, datetime.date(valid.year, 1, 1), valid, islice, jslice) replace_cfs(nc, valid, islice, jslice)
def main(argv): """Go Main Go.""" year = int(argv[1]) ets = min([datetime.date(year, 12, 31), datetime.date.today()]) queue = [] for x0 in np.arange(iemre.WEST, iemre.EAST, 5.): for y0 in np.arange(iemre.SOUTH, iemre.NORTH, 5.): queue.append([x0, y0]) for x0, y0 in tqdm(queue, disable=not sys.stdout.isatty()): url = ( "https://power.larc.nasa.gov/cgi-bin/v1/DataAccess.py?" "request=execute&identifier=Regional&" "parameters=ALLSKY_SFC_SW_DWN&" "startDate=%s0101&endDate=%s&userCommunity=SSE&" "tempAverage=DAILY&bbox=%s,%s,%s,%s&user=anonymous&" "outputList=NETCDF" ) % (year, ets.strftime("%Y%m%d"), y0, x0, min([y0 + 5., iemre.NORTH]) - 0.1, min([x0 + 5., iemre.EAST]) - 0.1) req = requests.get(url, timeout=60) js = req.json() if 'outputs' not in js: print(url) print(js) continue fn = js['outputs']['netcdf'] req = requests.get(fn, timeout=60, stream=True) ncfn = '/tmp/power%s.nc' % (year, ) with open(ncfn, 'wb') as fh: for chunk in req.iter_content(chunk_size=1024): if chunk: fh.write(chunk) fh.close() nc = ncopen(ncfn) for day, _ in enumerate(nc.variables['time'][:]): date = datetime.date(year, 1, 1) + datetime.timedelta(days=day) # kwh to MJ/d 3600 * 1000 / 1e6 data = nc.variables['ALLSKY_SFC_SW_DWN'][day, :, :] * 3.6 # Sometimes there are missing values? if np.ma.is_masked(data): data[data.mask] = np.mean(data) i, j = iemre.find_ij(x0, y0) # resample data is 0.5, iemre is 0.125 data = np.repeat(np.repeat(data, 4, axis=0), 4, axis=1) shp = np.shape(data) # print("i: %s j: %s shp: %s" % (i, j, shp)) renc = ncopen(iemre.get_daily_ncname(year), 'a') renc.variables['power_swdn'][ iemre.daily_offset(date), slice(j, j+shp[0]), slice(i, i+shp[1]) ] = data renc.close() nc.close()
def main(): """Go Main Go""" sts = datetime.datetime(2018, 4, 20, 0) sts = sts.replace(tzinfo=pytz.utc) ets = datetime.datetime(2018, 5, 11, 0) ets = ets.replace(tzinfo=pytz.utc) nc = ncopen(iemre.get_hourly_ncname(sts.year)) lons = nc.variables['lon'][:] lats = nc.variables['lat'][:] running = np.zeros((len(nc.dimensions['lat']), len(nc.dimensions['lon']))) maxval = np.zeros((len(nc.dimensions['lat']), len(nc.dimensions['lon']))) interval = datetime.timedelta(hours=1) now = sts i, j = iemre.find_ij(-93.61, 41.99) while now < ets: offset = iemre.hourly_offset(now) p01m = np.sum(nc.variables['p01m'][offset - 24:offset], axis=0) # 0.05in is 1.27 mm this = np.where(p01m > THRESHOLD, 1, 0) running = np.where(this == 1, 0, running + 1) maxval = np.where(running > maxval, running, maxval) print("%s %s %s" % (now, running[j, i], maxval[j, i])) now += interval # maxval = numpy.where(domain == 1, maxval, 1.e20) m = plot.MapPlot(sector='midwest', title=('Max Period ' 'between 24 Hour 0.25+ inch Total Precipitation'), subtitle=('Period of 20 Apr - 11 May 2018, ' 'based on NCEP Stage IV data')) extra = lons[-1] + (lons[-1] - lons[-2]) lons[-1] = extra # lons = np.concatenate([lons, [extra, ]]) extra = lats[-1] + (lats[-1] - lats[-2]) lats[-1] = extra # lats = np.concatenate([lats, [extra, ]]) lons, lats = np.meshgrid(lons, lats) # m.pcolormesh(x, y, maxval / 24.0, numpy.arange(0,25,1), units='days') maxval = np.where(maxval > 800, 73., maxval) cmap = plt.get_cmap('terrain') m.contourf(lons, lats, maxval / 24.0, np.arange(1, 11.1, 1), cmap=cmap, units='days', clip_on=False) m.postprocess(filename='test.png')
def service( fmt: SupportedFormatsNoGeoJSON, date: datetime.date = Query( ..., description="The CST/CDT date of interest.", ), lon: float = Query(..., description="Longitude of point of interest"), lat: float = Query(..., description="Latitude of point of interest"), ): """Do Something Fun!""" sts, ets = get_timerange(date) i, j = iemre.find_ij(lon, lat) df = workflow(sts, ets, i, j) return deliver_df(df, fmt)
def workflow(fn): """Do the copy work""" oldnc = netCDF4.Dataset(fn) newnc = netCDF4.Dataset(iemre.get_daily_ncname(fn[:4]), 'a') newnc.set_auto_scale(True) i, j = iemre.find_ij(oldnc.variables['lon'][0], oldnc.variables['lat'][0]) jslice = slice(j, j + oldnc.dimensions['lat'].size * 2) islice = slice(i, i + oldnc.dimensions['lon'].size * 2) # print("i:%s j:%s %s %s" % (i, j, islice, jslice)) for vname in tqdm(oldnc.variables): if vname in ['time', 'lat', 'lon']: continue for tstep in oldnc.variables['time'][:]: oldgrid = np.repeat(oldnc.variables[vname][tstep, :, :], 2, 0).repeat(2, 1) newnc.variables[vname][tstep, jslice, islice] = oldgrid newnc.close()
def tile_extraction(nc, valid, west, south, isnewfile): """Do our tile extraction""" # update model metadata nc.valid = "CFS model: %s" % (valid.strftime("%Y-%m-%dT%H:%M:%SZ"), ) i, j = iemre.find_ij(west, south) islice = slice(i, i + 16) jslice = slice(j, j + 16) for year in range(1980 if isnewfile else valid.year, valid.year + 1): tidx0 = (datetime.date(year, 1, 1) - datetime.date(1980, 1, 1)).days tidx1 = (datetime.date(year + 1, 1, 1) - datetime.date(1980, 1, 1)).days tslice = slice(tidx0, tidx1) ncfn = iemre.get_daily_ncname(year) if not os.path.isfile(ncfn): continue renc = ncopen(ncfn) # print("tslice: %s jslice: %s islice: %s" % (tslice, jslice, islice)) nc.variables['tmax'][tslice, :, :] = temperature( renc.variables['high_tmpk'][:, jslice, islice], 'K').value('C') nc.variables['tmin'][tslice, :, :] = temperature( renc.variables['low_tmpk'][:, jslice, islice], 'K').value('C') nc.variables['prcp'][tslice, :, :] = (renc.variables['p01d'][:, jslice, islice]) # MJ/d back to average W/m2 nc.variables['srad'][tslice, :, :] = (renc.variables['rsds'][:, jslice, islice]) renc.close() if year != valid.year: continue # replace CFS! renc = ncopen(valid.strftime("/mesonet/data/iemre/cfs_%Y%m%d.nc")) tidx = iemre.daily_offset(valid + datetime.timedelta(days=1)) tslice = slice(tidx0 + tidx, tidx1) nc.variables['srad'][tslice, :, :] = ( renc.variables['srad'][tidx:, jslice, islice] * 1000000. / 86400.) nc.variables['tmax'][tslice, :, :] = temperature( renc.variables['high_tmpk'][tidx:, jslice, islice], 'K').value('C') nc.variables['tmin'][tslice, :, :] = temperature( renc.variables['low_tmpk'][tidx:, jslice, islice], 'K').value('C') nc.variables['prcp'][tslice, :, :] = (renc.variables['p01d'][tidx:, jslice, islice]) renc.close()
def application(environ, start_response): """Do Something Fun!""" form = parse_formvars(environ) sts, ets = get_timerange(form) lat = float(form.get("lat", 41.99)) lon = float(form.get("lon", -95.1)) # fmt = form.get("format", "json") headers = [("Content-type", "application/json")] start_response("200 OK", headers) i, j = iemre.find_ij(lon, lat) mckey = "iemre/hourly/%s/%s/%s" % (sts.strftime("%Y%m%d"), i, j) mc = memcache.Client(["iem-memcached:11211"], debug=0) res = mc.get(mckey) if res is None: res = workflow(sts, ets, i, j) res = json.dumps(res).encode("ascii") mc.set(mckey, res, 3600) else: sys.stderr.write("Using cached %s\n" % (mckey,)) return [res]
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)
# 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["lat"][0]) lon = float(form["lon"][0]) 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 fp = "/mesonet/data/iemre/%s_mw_daily.nc" % (ts1.year, ) nc = netCDF4.Dataset(fp, 'r') hightemp = datatypes.temperature( nc.variables['high_tmpk'][offset1:offset2, j, i], 'K').value("F") lowtemp = datatypes.temperature( nc.variables['low_tmpk'][offset1:offset2, j, i], 'K').value("F") precip = nc.variables['p01d'][offset1:offset2, j, i] / 25.4 nc.close() # Get our climatology vars c2000 = ts1.replace(year=2000)
def plotter(fdict): """ Go """ ctx = get_autoplot_context(fdict, get_description()) ptype = ctx['ptype'] date = ctx['date'] varname = ctx['var'] csector = ctx['csector'] title = date.strftime("%-d %B %Y") mp = MapPlot(sector=('state' if len(csector) == 2 else csector), state=ctx['csector'], axisbg='white', nocaption=True, title='IEM Reanalysis of %s for %s' % (PDICT.get(varname), title), subtitle='Data derived from various NOAA datasets') (west, east, south, north) = mp.ax.get_extent(ccrs.PlateCarree()) i0, j0 = iemre.find_ij(west, south) i1, j1 = iemre.find_ij(east, north) jslice = slice(j0, j1) islice = slice(i0, i1) idx0 = iemre.daily_offset(date) with ncopen(iemre.get_daily_ncname(date.year)) as nc: lats = nc.variables['lat'][jslice] lons = nc.variables['lon'][islice] cmap = ctx['cmap'] if varname in ['rsds', 'power_swdn']: # Value is in W m**-2, we want MJ multi = (86400. / 1000000.) if varname == 'rsds' else 1 data = nc.variables[varname][idx0, jslice, islice] * multi units = 'MJ d-1' clevs = np.arange(0, 37, 3.) clevs[0] = 0.01 clevstride = 1 elif varname in [ 'wind_speed', ]: data = speed(nc.variables[varname][idx0, jslice, islice], 'MPS').value('MPH') units = 'mph' clevs = np.arange(0, 41, 2) clevs[0] = 0.01 clevstride = 2 elif varname in ['p01d', 'p01d_12z', 'snow_12z', 'snowd_12z']: # Value is in W m**-2, we want MJ data = distance(nc.variables[varname][idx0, jslice, islice], 'MM').value('IN') units = 'inch' clevs = np.arange(0, 0.25, 0.05) clevs = np.append(clevs, np.arange(0.25, 3., 0.25)) clevs = np.append(clevs, np.arange(3., 10.0, 1)) clevs[0] = 0.01 clevstride = 1 cmap = stretch_cmap(ctx['cmap'], clevs) elif varname in [ 'high_tmpk', 'low_tmpk', 'high_tmpk_12z', 'low_tmpk_12z', 'avg_dwpk' ]: # Value is in W m**-2, we want MJ data = temperature(nc.variables[varname][idx0, jslice, islice], 'K').value('F') units = 'F' clevs = np.arange(-30, 120, 5) clevstride = 2 elif varname in ['range_tmpk', 'range_tmpk_12z']: vname1 = 'high_tmpk%s' % ('_12z' if varname == 'range_tmpk_12z' else '', ) vname2 = 'low_tmpk%s' % ('_12z' if varname == 'range_tmpk_12z' else '', ) d1 = nc.variables[vname1][idx0, jslice, islice] d2 = nc.variables[vname2][idx0, jslice, islice] data = (temperature(d1, 'K').value('F') - temperature(d2, 'K').value('F')) units = 'F' clevs = np.arange(0, 61, 5) clevstride = 2 if np.ma.is_masked(np.max(data)): raise ValueError("Data Unavailable") x, y = np.meshgrid(lons, lats) if ptype == 'c': # in the case of contour, use the centroids on the grids mp.contourf(x + 0.125, y + 0.125, data, clevs, clevstride=clevstride, units=units, ilabel=True, labelfmt='%.0f', cmap=cmap) else: x, y = np.meshgrid(lons, lats) mp.pcolormesh(x, y, data, clevs, clevstride=clevstride, cmap=cmap, units=units) return mp.fig
'IA2367': 'DBQ', 'IA2723': 'EST', 'IA4106': 'IOW', 'IA4587': 'LWD', 'IA5199': 'MIW', 'IA5235': 'MCW', 'IA6389': 'OTM', 'IA7708': 'SUX', 'IA7844': 'SPW', 'IA8706': 'ALO', } # Pre-compute the grid location of each climate site nt = NetworkTable("%sCLIMATE" % (state.upper(),)) for sid in nt.sts.keys(): i, j = iemre.find_ij(nt.sts[sid]['lon'], nt.sts[sid]['lat']) nt.sts[sid]['gridi'] = i nt.sts[sid]['gridj'] = j for key in ['high', 'low', 'precip', 'snow', 'snowd']: nt.sts[sid][key] = None def estimate_precip(ts): """Estimate precipitation based on IEMRE""" idx = iemre.daily_offset(ts) nc = netCDF4.Dataset("/mesonet/data/iemre/%s_mw_daily.nc" % (ts.year, ), 'r') grid12 = nc.variables['p01d_12z'][idx, :, :] / 25.4 grid00 = nc.variables['p01d'][idx, :, :] / 25.4 nc.close()
def main(): """Go main go""" os.chdir("/tmp") form = cgi.FormContent() ts0 = datetime.datetime.strptime(form["date0"][0], "%Y-%m-%d") ts1 = datetime.datetime.strptime(form["date1"][0], "%Y-%m-%d") base = int(form["base"][0]) ceil = int(form["ceil"][0]) # Make sure we aren't in the future tsend = datetime.date.today() if ts1.date() >= tsend: ts1 = tsend - datetime.timedelta(days=1) ts1 = datetime.datetime(ts1.year, ts1.month, ts1.day) fmt = form["format"][0] offset0 = iemre.daily_offset(ts0) offset1 = iemre.daily_offset(ts1) ncfn = "/mesonet/data/iemre/%s_mw_daily.nc" % (ts0.year, ) nc = netCDF4.Dataset(ncfn, 'r') # 2-D precipitation, inches precip = np.sum(nc.variables['p01d'][offset0:offset1, :, :] / 25.4, axis=0) # GDD H = datatypes.temperature(nc.variables['high_tmpk'][offset0:offset1], 'K').value("F") H = np.where(H < base, base, H) H = np.where(H > ceil, ceil, H) L = datatypes.temperature(nc.variables['low_tmpk'][offset0:offset1], 'K').value("F") L = np.where(L < base, base, L) gdd = np.sum((H + L) / 2.0 - base, axis=0) nc.close() if fmt == 'json': # For example: 19013 ugc = "IAC" + form["county"][0][2:] # Go figure out where this is! postgis = get_dbconn('postgis') pcursor = postgis.cursor() pcursor.execute( """ SELECT ST_x(ST_Centroid(geom)), ST_y(ST_Centroid(geom)) from ugcs WHERE ugc = %s and end_ts is null """, (ugc, )) row = pcursor.fetchone() lat = row[1] lon = row[0] (i, j) = iemre.find_ij(lon, lat) myGDD = gdd[j, i] myPrecip = precip[j, i] res = { 'data': [], } res['data'].append({ 'gdd': "%.0f" % (myGDD, ), 'precip': "%.1f" % (myPrecip, ), 'latitude': "%.4f" % (lat, ), 'longitude': "%.4f" % (lon, ) }) sys.stdout.write('Content-type: application/json\n\n') sys.stdout.write(json.dumps(res)) if fmt == 'shp': # Time to create the shapefiles basefn = "iemre_%s_%s" % (ts0.strftime("%Y%m%d"), ts1.strftime("%Y%m")) w = shapefile.Writer(shapefile.POLYGON) w.field('GDD', 'F', 10, 2) w.field('PREC_IN', 'F', 10, 2) for x in iemre.XAXIS: for y in iemre.YAXIS: w.poly(parts=[[(x, y), (x, y + iemre.DY), (x + iemre.DX, y + iemre.DY), (x + iemre.DX, y), (x, y)]]) for i in range(len(iemre.XAXIS)): for j in range(len(iemre.YAXIS)): w.record(gdd[j, i], precip[j, i]) w.save(basefn) # Create zip file, send it back to the clients shutil.copyfile("/opt/iem/data/gis/meta/4326.prj", "%s.prj" % (basefn, )) z = zipfile.ZipFile("%s.zip" % (basefn, ), 'w', zipfile.ZIP_DEFLATED) for suffix in ['shp', 'shx', 'dbf', 'prj']: z.write("%s.%s" % (basefn, suffix)) z.close() sys.stdout.write("Content-type: application/octet-stream\n") sys.stdout.write( ("Content-Disposition: attachment; filename=%s.zip\n\n") % (basefn, )) sys.stdout.write(file(basefn + ".zip", 'r').read()) for suffix in ['zip', 'shp', 'shx', 'dbf', 'prj']: os.unlink("%s.%s" % (basefn, suffix))
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 main(argv): """Go Main Go.""" year = int(argv[1]) sts = datetime.date(year, 1, 1) ets = min([datetime.date(year, 12, 31), datetime.date.today()]) current = {} now = ets while now >= sts: ds = iemre.get_grids(now, varnames="power_swdn") maxval = ds["power_swdn"].values.max() if np.isnan(maxval) or maxval < 0: LOG.debug("adding %s as currently empty", now) current[now] = {"data": ds, "dirty": False} now -= datetime.timedelta(days=1) sts = min(list(current.keys())) ets = max(list(current.keys())) LOG.debug("running between %s and %s", sts, ets) queue = [] for x0 in np.arange(iemre.WEST, iemre.EAST, 5.0): for y0 in np.arange(iemre.SOUTH, iemre.NORTH, 5.0): queue.append([x0, y0]) for x0, y0 in tqdm(queue, disable=not sys.stdout.isatty()): url = ( "https://power.larc.nasa.gov/cgi-bin/v1/DataAccess.py?" "request=execute&identifier=Regional&" "parameters=ALLSKY_SFC_SW_DWN&" "startDate=%s&endDate=%s&userCommunity=SSE&" "tempAverage=DAILY&bbox=%s,%s,%s,%s&user=anonymous&" "outputList=NETCDF" ) % ( sts.strftime("%Y%m%d"), ets.strftime("%Y%m%d"), y0, x0, min([y0 + 5.0, iemre.NORTH]) - 0.1, min([x0 + 5.0, iemre.EAST]) - 0.1, ) req = exponential_backoff(requests.get, url, timeout=60) js = req.json() if "outputs" not in js: LOG.debug(url) LOG.debug(str(js)) continue fn = js["outputs"]["netcdf"] req = requests.get(fn, timeout=60, stream=True) ncfn = "/tmp/power%s.nc" % (year,) with open(ncfn, "wb") as fh: for chunk in req.iter_content(chunk_size=1024): if chunk: fh.write(chunk) fh.close() with ncopen(ncfn) as nc: for day, _ in enumerate(nc.variables["time"][:]): date = sts + datetime.timedelta(days=day) if date not in current: continue # kwh to MJ/d 3600 * 1000 / 1e6 data = nc.variables["ALLSKY_SFC_SW_DWN"][day, :, :] * 3.6 # Sometimes there are missing values? if np.ma.is_masked(data): data[data.mask] = np.mean(data) i, j = iemre.find_ij(x0, y0) # resample data is 0.5, iemre is 0.125 data = np.repeat(np.repeat(data, 4, axis=0), 4, axis=1) data = np.where(data < 0, np.nan, data) shp = np.shape(data) jslice = slice(j, j + shp[0]) islice = slice(i, i + shp[1]) # get currentdata present = current[date]["data"]["power_swdn"].values[ jslice, islice ] if present.mean() == data.mean(): continue current[date]["data"]["power_swdn"].values[ jslice, islice ] = data current[date]["dirty"] = True for date in current: if not current[date]["dirty"]: continue LOG.debug("saving %s", date) iemre.set_grids(date, current[date]["data"]) subprocess.call( "python ../iemre/db_to_netcdf.py %s" % (date.strftime("%Y %m %d"),), shell=True, )
import pytz sts = datetime.datetime(2013,5,1, 0) sts = sts.replace(tzinfo=pytz.timezone("UTC")) ets = datetime.datetime(2013,6,10, 0) ets = ets.replace(tzinfo=pytz.timezone("UTC")) nc = netCDF4.Dataset('/mesonet/data/iemre/2013_mw_hourly.nc') lons = nc.variables['lon'][:] lats = nc.variables['lat'][:] running = numpy.zeros( (len(nc.dimensions['lat']), len(nc.dimensions['lon']))) maxval = numpy.zeros( (len(nc.dimensions['lat']), len(nc.dimensions['lon']))) interval = datetime.timedelta(hours=1) now = sts i,j = iemre.find_ij(-93.61, 41.99) while now < ets: offset = iemre.hourly_offset(now) p01m = nc.variables['p01m'][offset] # 0.05in is 1.27 mm this = numpy.where(p01m > 1.27, 1, 0) running = numpy.where(this == 1, 0, running + 1) maxval = numpy.where(running > maxval, running, maxval) print now, running[j,i], maxval[j,i] now += interval nc2 = netCDF4.Dataset("/mesonet/data/iemre/state_weights.nc") domain = nc2.variables['domain'][:] nc2.close() maxval = numpy.where(domain == 1, maxval, 1.e20)
def application(environ, start_response): """Go main go""" os.chdir("/tmp") form = parse_formvars(environ) ts0 = datetime.datetime.strptime(form.get("date0"), "%Y-%m-%d") ts1 = datetime.datetime.strptime(form.get("date1"), "%Y-%m-%d") base = int(form.get("base", 50)) ceil = int(form.get("ceil", 86)) # Make sure we aren't in the future tsend = datetime.date.today() if ts1.date() >= tsend: ts1 = tsend - datetime.timedelta(days=1) ts1 = datetime.datetime(ts1.year, ts1.month, ts1.day) fmt = form.get("format") offset0 = iemre.daily_offset(ts0) offset1 = iemre.daily_offset(ts1) with ncopen(iemre.get_daily_ncname(ts0.year)) as nc: # 2-D precipitation, inches precip = np.sum(nc.variables["p01d"][offset0:offset1, :, :] / 25.4, axis=0) # GDD H = datatypes.temperature(nc.variables["high_tmpk"][offset0:offset1], "K").value("F") H = np.where(H < base, base, H) H = np.where(H > ceil, ceil, H) L = datatypes.temperature(nc.variables["low_tmpk"][offset0:offset1], "K").value("F") L = np.where(L < base, base, L) gdd = np.sum((H + L) / 2.0 - base, axis=0) if fmt == "json": # For example: 19013 ugc = "IAC" + form.get("county")[2:] # Go figure out where this is! postgis = get_dbconn("postgis") pcursor = postgis.cursor() pcursor.execute( """ SELECT ST_x(ST_Centroid(geom)), ST_y(ST_Centroid(geom)) from ugcs WHERE ugc = %s and end_ts is null """, (ugc, ), ) row = pcursor.fetchone() lat = row[1] lon = row[0] (i, j) = iemre.find_ij(lon, lat) myGDD = gdd[j, i] myPrecip = precip[j, i] res = {"data": []} res["data"].append({ "gdd": "%.0f" % (myGDD, ), "precip": "%.1f" % (myPrecip, ), "latitude": "%.4f" % (lat, ), "longitude": "%.4f" % (lon, ), }) headers = [("Content-type", "application/json")] start_response("200 OK", headers) return [json.dumps(res).encode("ascii")] # Time to create the shapefiles basefn = "iemre_%s_%s" % (ts0.strftime("%Y%m%d"), ts1.strftime("%Y%m")) w = shapefile.Writer(basefn) w.field("GDD", "F", 10, 2) w.field("PREC_IN", "F", 10, 2) for x in iemre.XAXIS: for y in iemre.YAXIS: w.poly([[ (x, y), (x, y + iemre.DY), (x + iemre.DX, y + iemre.DY), (x + iemre.DX, y), (x, y), ]]) for i in range(len(iemre.XAXIS)): for j in range(len(iemre.YAXIS)): w.record(gdd[j, i], precip[j, i]) w.close() # Create zip file, send it back to the clients shutil.copyfile("/opt/iem/data/gis/meta/4326.prj", "%s.prj" % (basefn, )) z = zipfile.ZipFile("%s.zip" % (basefn, ), "w", zipfile.ZIP_DEFLATED) for suffix in ["shp", "shx", "dbf", "prj"]: z.write("%s.%s" % (basefn, suffix)) z.close() headers = [ ("Content-type", "application/octet-stream"), ("Content-Disposition", "attachment; filename=%s.zip" % (basefn, )), ] start_response("200 OK", headers) content = open(basefn + ".zip", "rb").read() for suffix in ["zip", "shp", "shx", "dbf", "prj"]: os.unlink("%s.%s" % (basefn, suffix)) return [content]
if fmt == 'json': # For example: 19013 ugc = "IAC" + form["county"][0][2:] # Go figure out where this is! postgis = psycopg2.connect(database='postgis', host='iemdb', user='******') pcursor = postgis.cursor() pcursor.execute( """ SELECT ST_x(ST_Centroid(geom)), ST_y(ST_Centroid(geom)) from ugcs WHERE ugc = %s and end_ts is null """, (ugc, )) row = pcursor.fetchone() lat = row[1] lon = row[0] (i, j) = iemre.find_ij(lon, lat) myGDD = gdd[j, i] myPrecip = precip[j, i] res = { 'data': [], } res['data'].append({ 'gdd': "%.0f" % (myGDD, ), 'precip': "%.1f" % (myPrecip, ), 'latitude': "%.4f" % (lat, ), 'longitude': "%.4f" % (lon, ) }) sys.stdout.write('Content-type: application/json\n\n') sys.stdout.write(json.dumps(res)) if fmt == 'shp':
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")]
# 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["lat"][0]) lon = float(form["lon"][0]) 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 fp = "/mesonet/data/iemre/%s_mw_daily.nc" % (ts1.year,) nc = netCDF4.Dataset(fp, 'r') hightemp = datatypes.temperature(nc.variables['high_tmpk'][offset1:offset2, j, i], 'K').value("F") lowtemp = datatypes.temperature(nc.variables['low_tmpk'][offset1:offset2, j, i], 'K').value("F") precip = nc.variables['p01d'][offset1:offset2, j, i] / 25.4 nc.close()
# SD6947 | KUNR | RAPID CITY 4NW | Rapid City # Wisconsin 'WI5479': 'MKE', 'WI3269': 'GRB', 'WI7113': 'RHI', 'WI2428': 'EAU', 'WI4961': 'MSN', 'WI4370': 'LSE', 'WI2428': 'AUW', } # Pre-compute the grid location of each climate site nt = NetworkTable("%sCLIMATE" % (state.upper(),)) for sid in nt.sts.keys(): i, j = iemre.find_ij(nt.sts[sid]['lon'], nt.sts[sid]['lat']) nt.sts[sid]['gridi'] = i nt.sts[sid]['gridj'] = j for key in ['high', 'low', 'precip', 'snow', 'snowd']: nt.sts[sid][key] = None def estimate_precip(ts): """Estimate precipitation based on IEMRE""" idx = iemre.daily_offset(ts) nc = netCDF4.Dataset("/mesonet/data/iemre/%s_mw_daily.nc" % (ts.year, ), 'r') grid12 = nc.variables['p01d_12z'][idx, :, :] / 25.4 grid00 = nc.variables['p01d'][idx, :, :] / 25.4 nc.close()
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))
nc.close() if fmt == 'json': # For example: 19013 ugc = "IAC" + form["county"][0][2:] # Go figure out where this is! postgis = psycopg2.connect(database='postgis', host='iemdb', user='******') pcursor = postgis.cursor() pcursor.execute(""" SELECT ST_x(ST_Centroid(geom)), ST_y(ST_Centroid(geom)) from ugcs WHERE ugc = %s and end_ts is null """, (ugc,)) row = pcursor.fetchone() lat = row[1] lon = row[0] (i, j) = iemre.find_ij(lon, lat) myGDD = gdd[j, i] myPrecip = precip[j, i] res = {'data': [], } res['data'].append({ 'gdd': "%.0f" % (myGDD,), 'precip': "%.1f" % (myPrecip,), 'latitude': "%.4f" % (lat,), 'longitude': "%.4f" % (lon,) }) sys.stdout.write('Content-type: application/json\n\n') sys.stdout.write(json.dumps(res)) if format == 'shp': # Time to create the shapefiles fp = "iemre_%s_%s" % (ts0.strftime("%Y%m%d"), ts1.strftime("%Y%m"))
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.FormContent() ts = datetime.datetime.strptime(form["date"][0], "%Y-%m-%d") lat = float(form["lat"][0]) lon = float(form["lon"][0]) fmt = form["format"][0] if fmt != 'json': sys.stdout.write("Content-type: text/plain\n\n") sys.stdout.write("ERROR: Service only emits json at this time") return i, j = iemre.find_ij(lon, lat) offset = iemre.daily_offset(ts) res = {'data': [], } fn = "/mesonet/data/iemre/%s_mw_daily.nc" % (ts.year,) sys.stdout.write('Content-type: application/json\n\n') if not os.path.isfile(fn): sys.stdout.write(json.dumps(res)) sys.exit() if i is None or j is None: sys.stdout.write(json.dumps({'error': 'Coordinates outside of domain'} )) return nc = netCDF4.Dataset(fn, 'r') c2000 = ts.replace(year=2000) coffset = iemre.daily_offset(c2000) cnc = netCDF4.Dataset("/mesonet/data/iemre/mw_dailyc.nc", 'r') res['data'].append({ '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() sys.stdout.write(json.dumps(res))
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)
def append_cfs(res, lon, lat): """Append on needed CFS data.""" gridx, gridy = find_ij(lon, lat) lastyear = max(res["data"].keys()) thisyear = datetime.date.today().year lastdate = datetime.date(thisyear, 8, 31) if lastyear != thisyear: # We don't have any data yet for this year, so we add some res["data"][thisyear] = {"dates": [], "high": [], "low": [], "rh": []} else: # shrug if res["data"][lastyear]["dates"]: lastdate = datetime.datetime.strptime( res["data"][thisyear]["dates"][-1], "%Y-%m-%d" ).date() # go find the most recent CFS 0z file valid = datetime.date.today() attempt = 0 while True: testfn = valid.strftime("/mesonet/data/iemre/cfs_%Y%m%d00.nc") if os.path.isfile(testfn): break valid -= datetime.timedelta(hours=24) attempt += 1 if attempt > 9: return None try: nc = ncopen(testfn, timeout=NCOPEN_TIMEOUT) except Exception as exp: LOG.error(exp) return None if nc is None: LOG.debug("Failing %s as nc is None", testfn) return None high = ( masked_array(nc.variables["high_tmpk"][:, gridy, gridx], units.degK) .to(units.degF) .m ) low = ( masked_array(nc.variables["low_tmpk"][:, gridy, gridx], units.degK) .to(units.degF) .m ) # RH hack # found ~20% bias with this value, so arb addition for now rh = ( relative_humidity_from_dewpoint( masked_array(high, units.degF), masked_array(low, units.degF) ).m * 100.0 + 20.0 ) rh = np.where(rh > 95, 95, rh) entry = res["data"][thisyear] # lastdate is either August 31 or a date after, so our first forecast # date is i+1 tidx = daily_offset(lastdate + datetime.timedelta(days=1)) for i in range(tidx, 365): lts = datetime.date(thisyear, 1, 1) + datetime.timedelta(days=i) if lts.month in [9, 10, 11]: entry["dates"].append(lts.strftime("%Y-%m-%d")) entry["high"].append(_i(high[i])) entry["low"].append(_i(low[i])) entry["rh"].append(_i(rh[i])) return res
def plotter(fdict): """ Go """ ctx = get_autoplot_context(fdict, get_description()) ptype = ctx["ptype"] date = ctx["date"] varname = ctx["var"] csector = ctx["csector"] title = date.strftime("%-d %B %Y") mp = MapPlot( sector=("state" if len(csector) == 2 else csector), state=ctx["csector"], axisbg="white", nocaption=True, title="IEM Reanalysis of %s for %s" % (PDICT.get(varname), title), subtitle="Data derived from various NOAA datasets", ) (west, east, south, north) = mp.ax.get_extent(ccrs.PlateCarree()) i0, j0 = iemre.find_ij(west, south) i1, j1 = iemre.find_ij(east, north) jslice = slice(j0, j1) islice = slice(i0, i1) idx0 = iemre.daily_offset(date) ncfn = iemre.get_daily_ncname(date.year) if not os.path.isfile(ncfn): raise NoDataFound("No Data Found.") with ncopen(ncfn) as nc: lats = nc.variables["lat"][jslice] lons = nc.variables["lon"][islice] cmap = ctx["cmap"] if varname in ["rsds", "power_swdn"]: # Value is in W m**-2, we want MJ multi = (86400.0 / 1000000.0) if varname == "rsds" else 1 data = nc.variables[varname][idx0, jslice, islice] * multi plot_units = "MJ d-1" clevs = np.arange(0, 37, 3.0) clevs[0] = 0.01 clevstride = 1 elif varname in ["wind_speed"]: data = (masked_array( nc.variables[varname][idx0, jslice, islice], units("meter / second"), ).to(units("mile / hour")).m) plot_units = "mph" clevs = np.arange(0, 41, 2) clevs[0] = 0.01 clevstride = 2 elif varname in ["p01d", "p01d_12z", "snow_12z", "snowd_12z"]: # Value is in W m**-2, we want MJ data = (masked_array(nc.variables[varname][idx0, jslice, islice], units("mm")).to(units("inch")).m) plot_units = "inch" clevs = np.arange(0, 0.25, 0.05) clevs = np.append(clevs, np.arange(0.25, 3.0, 0.25)) clevs = np.append(clevs, np.arange(3.0, 10.0, 1)) clevs[0] = 0.01 clevstride = 1 cmap = stretch_cmap(ctx["cmap"], clevs) elif varname in [ "high_tmpk", "low_tmpk", "high_tmpk_12z", "low_tmpk_12z", "avg_dwpk", ]: # Value is in W m**-2, we want MJ data = (masked_array(nc.variables[varname][idx0, jslice, islice], units("degK")).to(units("degF")).m) plot_units = "F" clevs = np.arange(-30, 120, 5) clevstride = 2 elif varname in ["range_tmpk", "range_tmpk_12z"]: vname1 = "high_tmpk%s" % ("_12z" if varname == "range_tmpk_12z" else "", ) vname2 = "low_tmpk%s" % ("_12z" if varname == "range_tmpk_12z" else "", ) d1 = nc.variables[vname1][idx0, jslice, islice] d2 = nc.variables[vname2][idx0, jslice, islice] data = (masked_array(d1, units("degK")).to(units("degF")).m - masked_array(d2, units("degK")).to(units("degF")).m) plot_units = "F" clevs = np.arange(0, 61, 5) clevstride = 2 if np.ma.is_masked(np.max(data)): raise NoDataFound("Data Unavailable") x, y = np.meshgrid(lons, lats) if ptype == "c": # in the case of contour, use the centroids on the grids mp.contourf( x + 0.125, y + 0.125, data, clevs, clevstride=clevstride, units=plot_units, ilabel=True, labelfmt="%.0f", cmap=cmap, ) else: x, y = np.meshgrid(lons, lats) mp.pcolormesh( x, y, data, clevs, clevstride=clevstride, cmap=cmap, units=plot_units, ) return mp.fig
import pytz sts = datetime.datetime(2015,5,1, 0) sts = sts.replace(tzinfo=pytz.timezone("UTC")) ets = datetime.datetime(2015,6,28, 0) ets = ets.replace(tzinfo=pytz.timezone("UTC")) nc = netCDF4.Dataset('/mesonet/data/iemre/2015_mw_hourly.nc') lons = nc.variables['lon'][:] lats = nc.variables['lat'][:] running = numpy.zeros( (len(nc.dimensions['lat']), len(nc.dimensions['lon']))) maxval = numpy.zeros( (len(nc.dimensions['lat']), len(nc.dimensions['lon']))) interval = datetime.timedelta(hours=1) now = sts i,j = iemre.find_ij(-93.61, 41.99) while now < ets: offset = iemre.hourly_offset(now) p01m = nc.variables['p01m'][offset] # 0.05in is 1.27 mm this = numpy.where(p01m > 1.27, 1, 0) running = numpy.where(this == 1, 0, running + 1) maxval = numpy.where(running > maxval, running, maxval) print now, running[j,i], maxval[j,i] now += interval nc2 = netCDF4.Dataset("/mesonet/data/iemre/state_weights.nc") domain = nc2.variables['domain'][:] nc2.close() #maxval = numpy.where(domain == 1, maxval, 1.e20)