def test_i_tmin(self): """tests function which computes tmin index""" frac = np.arange(0.0, 1.0, 0.2) tmin = frac * (gsi.TMIN_MAX - gsi.TMIN_MIN) + gsi.TMIN_MIN i_tmin = gsi.calc_i_tmin(tmin) self.assertTrue(np.all(np.abs(i_tmin - frac) < 1e-5))
def test_i_tmin_kelvin(self): """tests behavior when compute_i_tmin is called with kelvin temps""" frac = np.arange(0.0, 1.0, 0.2) tmin = frac * (gsi.TMIN_MAX - gsi.TMIN_MIN) + gsi.TMIN_MIN tmin = tmin.to(u.K, equivalencies=u.temperature()) i_tmin = gsi.calc_i_tmin(tmin) self.assertTrue(np.all(np.abs(i_tmin - frac) < 1e-5))
def indices_year(y, forcing_template, out_template) : """Processes one year. Runs the calculation of indices for one year given an orchidee forcing file for that year.""" # figure out filenames and open dataset. forcing_file = forcing_template % (y,) out_file = out_template % (y,) ds = ForcingDataset(forcing_file, out_file) # register required variables from NetCDF file so they are tracked qair = ds.register_variable("Qair", u.dimensionless_unscaled) tair = ds.register_variable("Tair", u.Kelvin) ds.register_variable("PSurf", u.Pa) rainf = ds.register_variable("Rainf", u.kg / (u.m**2) / u.s ) swdown = ds.register_variable("SWdown", u.W / (u.m**2)) print "NetCDF variables registered" # setup netcdf dimensions in output file ds.copyDimension("land") ds.copyDimension("y") ds.copyDimension("tstep") ds.createDimension("days", 365) # copy basic data ds.copyVariable('nav_lat') ds.copyVariable('nav_lon') print "Variables copied from forcing file" # create netcdf variables to hold indices in output file daylength = ds.create_variable("daylength", ("days","y"), np.float32) daylength.title = "Day Length" daylength.units = "hours" rh = ds.create_variable("rh", ("tstep","land"), np.float32) rh.long_name = "Relative Humidity" rh.units = "fraction" rh_max = ds.create_variable("rh_max", ("days","land"), np.float32) rh_max.long_name = "Maximum RH" rh_max.units = "fraction" rh_min = ds.create_variable("rh_min", ("days","land"), np.float32) rh_min.long_name = "Minimum RH" rh_min.units = "fraction" rh_afternoon = ds.create_variable("rh_afternoon", ('days', 'land'),np.float32) rh_afternoon.long_name = "RH in the afternoon" rh_afternoon.units = "fraction" t_min = ds.create_variable("t_min", ('days','land'), np.float32) t_min.long_name = "minimum temperature for the 24 hours preceeding burning period" t_min.units = "K" t_max = ds.create_variable("t_max", ('days', 'land'), np.float32) t_max.long_name = "maximum temperature for the 24 hours preceeding burning period" t_max.units = "K" t_afternoon = ds.create_variable("t_afternoon", ('days','land'), np.float32) t_afternoon.long_name = "mid-burning-period temperature" t_afternoon.units = "K" i_tmin = ds.create_variable("i_tmin", ('days','land'), np.float32) i_tmin.long_name = "GSI minimum temperature index component" i_tmin.units = 'dimensionless' i_photo = ds.create_variable('i_photo', ('days','land'), np.float32) i_photo.long_name = 'GSI photoperiod index component' i_photo.units = 'dimensionless' i_vpd = ds.create_variable('i_vpd', ('days','land'), np.float32) i_vpd.long_name = 'GSI vapor pressure deficit index component' i_vpd.units = 'dimensionless' i_gsi = ds.create_variable('gsi', ('days','land'), np.float32) i_gsi.long_name = 'GSI Index' i_gsi.units = 'dimensionless' gsi_days = 10 i_gsi_avg = ds.create_variable('gsi_avg', ('days','land'), np.float32) i_gsi_avg.long_name = 'GSI Index (%d day running average)' % gsi_days i_gsi_avg.units = 'dimensionless' precip = ds.create_variable('precip_duration', ('days','land'), np.float32) precip.long_name = "Duration of precipitation" precip.units = 'hours' tot_precip = ds.create_variable('total_precip', ('days','land'), np.float32) tot_precip.long_name = 'total precipitation over last 24 hours' tot_precip.units = 'kg / m^2' dd_days = 30 dd = ds.create_variable('dd', ('days','land'), np.int) dd.long_name = 'dry day weighting (%d day window)' % dd_days dd.units = 'none' eqmc_bar = ds.create_variable('eqmc_bar', ('days','land'), np.float32) eqmc_bar.long_name = 'Weighted daily average equilibrium moisture content' eqmc_bar.units = 'percent' fm1000 = ds.create_variable('fm1000', ('days','land'), np.float32) fm1000.long_name = '1000 hour fuel moisture' fm1000.units = 'percent' fm100 = ds.create_variable('fm100', ('days','land'), np.float32) fm100.long_name = '100 hour fuel moisture' fm100.units = 'percent' fm10 = ds.create_variable('fm10', ('days','land'), np.float32) fm10.long_name = '10 hour fuel moisture' fm10.units = 'percent' fm1 = ds.create_variable('fm1', ('days','land'), np.float32) fm1.long_name = '1 hour fuel moisture' fm1.units = 'percent' print "Output NetCDF variables created" # moving window of GSI data gsi_window = w.MovingWindow(i_gsi.shape, 0, gsi_days) # moving window to compute dry day weights dd_window = w.SequenceWindow(dd.shape, 0, dd_days) # initialize fuel moisture calculators fm1000_calc = fm.ThousandHourFM(fm1000.shape, 0) fm100_calc = fm.HundredHourFM(fm100.shape, 0) # base time time_start = t.Time('%04d:001'%y, format='yday', scale='ut1') if ( (y < 1960) or (y > 2013) ) : time_start.delta_ut1_utc=0 # loop over days # the cur_day property is the index of the next day to read in from the file. # since the netcdf file is 0-based, indices are [0, 365) while qair.cur_day < 365 : i_day = qair.cur_day - 1 print qair.cur_day # calculate daylengths, store as hours day = time_start + (i_day*u.day) if (hasattr(time_start,"delta_ut1_utc")) : day.delta_ut1_utc = time_start.delta_ut1_utc daylength_lut = ds.get_daylength_lookup(day) daylength[i_day,:] = daylength_lut.values # pull out/store minimum, maximum and afternoon temps t_min[i_day,:] = tair.min(unitted=False) t_max[i_day,:] = tair.max(unitted=False) t_afternoon[i_day,:] = tair.ref_val(unitted=False) # calculate RH & store rh_dlts = ds.compute_rh() rh_dlts.store_day(rh) rh_max[i_day,:] = rh_dlts.max(unitted=False) rh_min[i_day,:] = rh_dlts.min(unitted=False) rh_afternoon[i_day,:] = rh_dlts.ref_val(unitted=False) # calculate GSI indices and store i_tmin[i_day,:] = gsi.calc_i_tmin(tair.min()) cell_daylengths = daylength_lut.get(ds.get_latitudes()) i_photo[i_day,:] = gsi.calc_i_photo(cell_daylengths) i_vpd[i_day,:] = gsi.calc_i_vpd(ds.compute_afternoon_vpd()) gsi_vals = i_tmin[i_day,:] * i_photo[i_day,:] * i_vpd[i_day,:] i_gsi[i_day,:] = gsi_vals # calculate running GSI average and store gsi_window.put(gsi_vals) if gsi_window.ready() : i_gsi_avg[i_day,:] = gsi_window.mean() # calculate precipitation duration and store precip_val = ds.compute_precip_duration() precip[i_day,:] = precip_val # calculate total precip over last 24 hours, and dry day flag tot_precip_val = (rainf.sum() * ds.get_timestep()).to(u.kg/(u.m**2)) tot_precip[i_day,:] = tot_precip_val dd_window.put( tot_precip_val < DRY_DAY_PRECIP ) dd[i_day,:] = dd_window.all_runs() # calculate daily avg equilibrium moisture content eqmc_bar_val = ds.compute_eqmc_bar(cell_daylengths) eqmc_bar[i_day,:] = eqmc_bar_val # calculate fuel moisture content fm1000[i_day,:] = fm1000_calc.compute(eqmc_bar_val, precip_val).to(u.percent) fm100_today = fm100_calc.compute(eqmc_bar_val, precip_val) fm100[i_day,:] = fm100_today.to(u.percent) fm1_today, fm10_today = fm.oneten_ofdm( t_afternoon[i_day,:]*u.K, rh_afternoon[i_day,:]*u.dimensionless_unscaled, swdown.ref_val(), fm100_today) fm10[i_day,:] = fm10_today.to(u.percent) fm1[i_day,:] = fm1_today.to(u.percent) # first time through, store the first day's data if i_day == 1 : rh_dlts.store_day(rh, current=False) # load next day for all variables ds.next() ds.close()
def indices_year(y, forcing_template, out_template): """Processes one year. Runs the calculation of indices for one year given an orchidee forcing file for that year.""" # figure out filenames and open dataset. forcing_file = forcing_template % (y, ) out_file = out_template % (y, ) ds = ForcingDataset(forcing_file, out_file) # register required variables from NetCDF file so they are tracked qair = ds.register_variable("Qair", u.dimensionless_unscaled) tair = ds.register_variable("Tair", u.Kelvin) ds.register_variable("PSurf", u.Pa) rainf = ds.register_variable("Rainf", u.kg / (u.m**2) / u.s) swdown = ds.register_variable("SWdown", u.W / (u.m**2)) print "NetCDF variables registered" # setup netcdf dimensions in output file ds.copyDimension("land") ds.copyDimension("y") ds.copyDimension("tstep") ds.createDimension("days", 365) # copy basic data ds.copyVariable('nav_lat') ds.copyVariable('nav_lon') print "Variables copied from forcing file" # create netcdf variables to hold indices in output file daylength = ds.create_variable("daylength", ("days", "y"), np.float32) daylength.title = "Day Length" daylength.units = "hours" rh = ds.create_variable("rh", ("tstep", "land"), np.float32) rh.long_name = "Relative Humidity" rh.units = "fraction" rh_max = ds.create_variable("rh_max", ("days", "land"), np.float32) rh_max.long_name = "Maximum RH" rh_max.units = "fraction" rh_min = ds.create_variable("rh_min", ("days", "land"), np.float32) rh_min.long_name = "Minimum RH" rh_min.units = "fraction" rh_afternoon = ds.create_variable("rh_afternoon", ('days', 'land'), np.float32) rh_afternoon.long_name = "RH in the afternoon" rh_afternoon.units = "fraction" t_min = ds.create_variable("t_min", ('days', 'land'), np.float32) t_min.long_name = "minimum temperature for the 24 hours preceeding burning period" t_min.units = "K" t_max = ds.create_variable("t_max", ('days', 'land'), np.float32) t_max.long_name = "maximum temperature for the 24 hours preceeding burning period" t_max.units = "K" t_afternoon = ds.create_variable("t_afternoon", ('days', 'land'), np.float32) t_afternoon.long_name = "mid-burning-period temperature" t_afternoon.units = "K" i_tmin = ds.create_variable("i_tmin", ('days', 'land'), np.float32) i_tmin.long_name = "GSI minimum temperature index component" i_tmin.units = 'dimensionless' i_photo = ds.create_variable('i_photo', ('days', 'land'), np.float32) i_photo.long_name = 'GSI photoperiod index component' i_photo.units = 'dimensionless' i_vpd = ds.create_variable('i_vpd', ('days', 'land'), np.float32) i_vpd.long_name = 'GSI vapor pressure deficit index component' i_vpd.units = 'dimensionless' i_gsi = ds.create_variable('gsi', ('days', 'land'), np.float32) i_gsi.long_name = 'GSI Index' i_gsi.units = 'dimensionless' gsi_days = 10 i_gsi_avg = ds.create_variable('gsi_avg', ('days', 'land'), np.float32) i_gsi_avg.long_name = 'GSI Index (%d day running average)' % gsi_days i_gsi_avg.units = 'dimensionless' precip = ds.create_variable('precip_duration', ('days', 'land'), np.float32) precip.long_name = "Duration of precipitation" precip.units = 'hours' tot_precip = ds.create_variable('total_precip', ('days', 'land'), np.float32) tot_precip.long_name = 'total precipitation over last 24 hours' tot_precip.units = 'kg / m^2' dd_days = 30 dd = ds.create_variable('dd', ('days', 'land'), np.int) dd.long_name = 'dry day weighting (%d day window)' % dd_days dd.units = 'none' eqmc_bar = ds.create_variable('eqmc_bar', ('days', 'land'), np.float32) eqmc_bar.long_name = 'Weighted daily average equilibrium moisture content' eqmc_bar.units = 'percent' fm1000 = ds.create_variable('fm1000', ('days', 'land'), np.float32) fm1000.long_name = '1000 hour fuel moisture' fm1000.units = 'percent' fm100 = ds.create_variable('fm100', ('days', 'land'), np.float32) fm100.long_name = '100 hour fuel moisture' fm100.units = 'percent' fm10 = ds.create_variable('fm10', ('days', 'land'), np.float32) fm10.long_name = '10 hour fuel moisture' fm10.units = 'percent' fm1 = ds.create_variable('fm1', ('days', 'land'), np.float32) fm1.long_name = '1 hour fuel moisture' fm1.units = 'percent' print "Output NetCDF variables created" # moving window of GSI data gsi_window = w.MovingWindow(i_gsi.shape, 0, gsi_days) # moving window to compute dry day weights dd_window = w.SequenceWindow(dd.shape, 0, dd_days) # initialize fuel moisture calculators fm1000_calc = fm.ThousandHourFM(fm1000.shape, 0) fm100_calc = fm.HundredHourFM(fm100.shape, 0) # base time time_start = t.Time('%04d:001' % y, format='yday', scale='ut1') if ((y < 1960) or (y > 2013)): time_start.delta_ut1_utc = 0 # loop over days # the cur_day property is the index of the next day to read in from the file. # since the netcdf file is 0-based, indices are [0, 365) while qair.cur_day < 365: i_day = qair.cur_day - 1 print qair.cur_day # calculate daylengths, store as hours day = time_start + (i_day * u.day) if (hasattr(time_start, "delta_ut1_utc")): day.delta_ut1_utc = time_start.delta_ut1_utc daylength_lut = ds.get_daylength_lookup(day) daylength[i_day, :] = daylength_lut.values # pull out/store minimum, maximum and afternoon temps t_min[i_day, :] = tair.min(unitted=False) t_max[i_day, :] = tair.max(unitted=False) t_afternoon[i_day, :] = tair.ref_val(unitted=False) # calculate RH & store rh_dlts = ds.compute_rh() rh_dlts.store_day(rh) rh_max[i_day, :] = rh_dlts.max(unitted=False) rh_min[i_day, :] = rh_dlts.min(unitted=False) rh_afternoon[i_day, :] = rh_dlts.ref_val(unitted=False) # calculate GSI indices and store i_tmin[i_day, :] = gsi.calc_i_tmin(tair.min()) cell_daylengths = daylength_lut.get(ds.get_latitudes()) i_photo[i_day, :] = gsi.calc_i_photo(cell_daylengths) i_vpd[i_day, :] = gsi.calc_i_vpd(ds.compute_afternoon_vpd()) gsi_vals = i_tmin[i_day, :] * i_photo[i_day, :] * i_vpd[i_day, :] i_gsi[i_day, :] = gsi_vals # calculate running GSI average and store gsi_window.put(gsi_vals) if gsi_window.ready(): i_gsi_avg[i_day, :] = gsi_window.mean() # calculate precipitation duration and store precip_val = ds.compute_precip_duration() precip[i_day, :] = precip_val # calculate total precip over last 24 hours, and dry day flag tot_precip_val = (rainf.sum() * ds.get_timestep()).to(u.kg / (u.m**2)) tot_precip[i_day, :] = tot_precip_val dd_window.put(tot_precip_val < DRY_DAY_PRECIP) dd[i_day, :] = dd_window.all_runs() # calculate daily avg equilibrium moisture content eqmc_bar_val = ds.compute_eqmc_bar(cell_daylengths) eqmc_bar[i_day, :] = eqmc_bar_val # calculate fuel moisture content fm1000[i_day, :] = fm1000_calc.compute(eqmc_bar_val, precip_val).to(u.percent) fm100_today = fm100_calc.compute(eqmc_bar_val, precip_val) fm100[i_day, :] = fm100_today.to(u.percent) fm1_today, fm10_today = fm.oneten_ofdm( t_afternoon[i_day, :] * u.K, rh_afternoon[i_day, :] * u.dimensionless_unscaled, swdown.ref_val(), fm100_today) fm10[i_day, :] = fm10_today.to(u.percent) fm1[i_day, :] = fm1_today.to(u.percent) # first time through, store the first day's data if i_day == 1: rh_dlts.store_day(rh, current=False) # load next day for all variables ds.next() ds.close()