From 1cd21d3f1502a6d734c9d49ede14bcef1d768853 Mon Sep 17 00:00:00 2001
From: "pre-commit-ci[bot]"
<66853113+pre-commit-ci[bot]@users.noreply.github.com>
Date: Mon, 5 Feb 2024 21:13:25 +0000
Subject: [PATCH] [pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
---
carbonplan_forest_risks/__init__.py | 2 +-
carbonplan_forest_risks/collect.py | 12 +-
carbonplan_forest_risks/fit/growth.py | 25 +-
carbonplan_forest_risks/fit/hurdle.py | 13 +-
carbonplan_forest_risks/fit/interp.py | 12 +-
carbonplan_forest_risks/load/cmip.py | 81 +-
carbonplan_forest_risks/load/fia.py | 354 ++--
carbonplan_forest_risks/load/mask.py | 8 +-
carbonplan_forest_risks/load/mtbs.py | 8 +-
carbonplan_forest_risks/load/nftd.py | 31 +-
carbonplan_forest_risks/load/nlcd.py | 35 +-
carbonplan_forest_risks/load/terraclim.py | 80 +-
carbonplan_forest_risks/load/tiff.py | 34 +-
carbonplan_forest_risks/plot/carto.py | 58 +-
carbonplan_forest_risks/plot/fire.py | 197 +-
carbonplan_forest_risks/plot/line.py | 30 +-
carbonplan_forest_risks/plot/paper.py | 54 +-
carbonplan_forest_risks/plot/xy.py | 36 +-
carbonplan_forest_risks/prepare.py | 116 +-
carbonplan_forest_risks/preprocess/fia.py | 271 +--
carbonplan_forest_risks/setup/loading.py | 14 +-
carbonplan_forest_risks/setup/plotting.py | 6 +-
carbonplan_forest_risks/utils.py | 10 +-
notebooks/biomass/biomass_model.ipynb | 510 ++---
notebooks/biomass/biomass_results.ipynb | 410 ++--
notebooks/drought/drought_model.ipynb | 466 ++---
notebooks/drought/drought_results.ipynb | 290 +--
notebooks/fire/figure_foresttype.ipynb | 624 +++---
notebooks/fire/fire_model.ipynb | 1130 +++++------
notebooks/fire/fire_model_redux.ipynb | 1730 ++++++++---------
notebooks/fire/fire_model_supersections.ipynb | 526 ++---
notebooks/insects/insects_model.ipynb | 468 ++---
notebooks/insects/insects_results.ipynb | 308 +--
.../change-factor-calculations.ipynb | 288 +--
notebooks/paper/Figure-1/Figure-1.ipynb | 736 +++----
notebooks/paper/Figure-2/Figure-2.ipynb | 702 +++----
notebooks/paper/Figure-3/Figure-3.ipynb | 656 +++----
notebooks/paper/Figure-4/Figure-4.ipynb | 578 +++---
.../Supplementary-Figure-01.ipynb | 504 ++---
.../Supplementary-Figure-02.ipynb | 156 +-
.../Supplementary-Figure-03.ipynb | 368 ++--
.../Supplementary-Figure-04.ipynb | 208 +-
.../Supplementary-Figure-05.ipynb | 512 ++---
.../Supplementary-Figure-06.ipynb | 172 +-
.../Supplementary-Figure-07.ipynb | 212 +-
.../Supplementary-Figure-08.ipynb | 828 ++++----
.../Supplementary-Figure-09.ipynb | 266 +--
.../Supplementary-Figure-10.ipynb | 340 ++--
.../Supplementary-Figure-11.ipynb | 454 ++---
notebooks/share/fire_risks_counties.ipynb | 432 ++--
scripts/article_prep.py | 178 +-
scripts/biomass.py | 84 +-
scripts/convert.py | 38 +-
scripts/drought.py | 48 +-
scripts/export.py | 64 +-
scripts/fire.py | 171 +-
scripts/insects.py | 48 +-
scripts/package_insects_drought.py | 34 +-
scripts/regrid.py | 51 +-
scripts/regrid_bill.py | 24 +-
scripts/stats.py | 78 +-
scripts/website_prep.py | 36 +-
tests/test_forests.py | 2 +-
63 files changed, 8206 insertions(+), 8011 deletions(-)
diff --git a/carbonplan_forest_risks/__init__.py b/carbonplan_forest_risks/__init__.py
index 916b2ff..052df2e 100644
--- a/carbonplan_forest_risks/__init__.py
+++ b/carbonplan_forest_risks/__init__.py
@@ -5,5 +5,5 @@
try:
version = get_distribution(__name__).version
except DistributionNotFound: # pragma: no cover
- version = '0.0.0' # pragma: no cover
+ version = "0.0.0" # pragma: no cover
__version__ = version
diff --git a/carbonplan_forest_risks/collect.py b/carbonplan_forest_risks/collect.py
index 1d55c67..11b316d 100644
--- a/carbonplan_forest_risks/collect.py
+++ b/carbonplan_forest_risks/collect.py
@@ -4,11 +4,11 @@
def fire(y, src, inds=None):
da = xr.Dataset()
- da['x'] = src.x
- da['y'] = src.y
- da['time'] = src.time
- da['lat'] = (['y', 'x'], src['lat'])
- da['lon'] = (['y', 'x'], src['lon'])
+ da["x"] = src.x
+ da["y"] = src.y
+ da["time"] = src.time
+ da["lat"] = (["y", "x"], src["lat"])
+ da["lon"] = (["y", "x"], src["lon"])
shape = (len(src.time), len(src.y), len(src.x))
if inds is None:
@@ -17,6 +17,6 @@ def fire(y, src, inds=None):
yfull = np.zeros(shape).flatten()
yfull[inds] = y
yfull = yfull.reshape(shape)
- da['prediction'] = (['time', 'y', 'x'], yfull)
+ da["prediction"] = (["time", "y", "x"], yfull)
return da
diff --git a/carbonplan_forest_risks/fit/growth.py b/carbonplan_forest_risks/fit/growth.py
index 475ba22..128b9c6 100644
--- a/carbonplan_forest_risks/fit/growth.py
+++ b/carbonplan_forest_risks/fit/growth.py
@@ -14,13 +14,13 @@ def logistic(x, f, p):
)
-def growth(x, y, f, noise='gamma', init=None):
+def growth(x, y, f, noise="gamma", init=None):
def loglik(x, y, f, p):
a, b, c, w0, w1, scale = p
_mu = logistic(x, f, [a, b, c, w0, w1])
- if noise == 'gamma':
+ if noise == "gamma":
return -np.sum(gamma.logpdf(y, np.maximum(_mu / scale, 1e-12), scale=scale))
- if noise == 'normal':
+ if noise == "normal":
return -np.sum(norm.logpdf(y, loc=_mu, scale=scale))
fx = lambda p: loglik(x, y, f, p)
@@ -33,14 +33,16 @@ def loglik(x, y, f, p):
bounds = Bounds(lb, ub)
if init is None:
init = [np.nanmean(y), 0.1, 10, 0, 0, np.nanstd(y)]
- options_trust = {'maxiter': 10000}
+ options_trust = {"maxiter": 10000}
with warnings.catch_warnings():
- warnings.filterwarnings('ignore', category=UserWarning)
- result = minimize(fx, init, bounds=bounds, method='trust-constr', options=options_trust)
+ warnings.filterwarnings("ignore", category=UserWarning)
+ result = minimize(
+ fx, init, bounds=bounds, method="trust-constr", options=options_trust
+ )
if result.success is False:
- print('optimization failed')
+ print("optimization failed")
return GrowthModel(result, noise, x, y, f)
@@ -63,12 +65,15 @@ def r2(self, x, f, y):
def predict(self, x, f, percentile=None):
if percentile is not None:
- f = [np.nanpercentile(f[0], percentile[0]), np.nanpercentile(f[1], percentile[1])]
+ f = [
+ np.nanpercentile(f[0], percentile[0]),
+ np.nanpercentile(f[1], percentile[1]),
+ ]
return logistic(x, f, self.p)
def sample(self, x, f):
mu = logistic(x, f, self.p)
- if self.noise == 'gamma':
+ if self.noise == "gamma":
return np.random.gamma(mu / self.scale, scale=self.scale)
- if self.noise == 'normal':
+ if self.noise == "normal":
return np.random.normal(mu, scale=self.scale)
diff --git a/carbonplan_forest_risks/fit/hurdle.py b/carbonplan_forest_risks/fit/hurdle.py
index 4a3683e..211fd13 100644
--- a/carbonplan_forest_risks/fit/hurdle.py
+++ b/carbonplan_forest_risks/fit/hurdle.py
@@ -9,11 +9,16 @@ def hurdle(x, y, log=True, max_iter=1000):
x, y = remove_nans(x, y)
n_obs = len(x)
- clf = LogisticRegression(fit_intercept=True, penalty='none', max_iter=max_iter)
+ clf = LogisticRegression(fit_intercept=True, penalty="none", max_iter=max_iter)
if log:
reg = TweedieRegressor(
- fit_intercept=True, power=0, link='log', alpha=0, tol=1e-8, max_iter=max_iter
+ fit_intercept=True,
+ power=0,
+ link="log",
+ alpha=0,
+ tol=1e-8,
+ max_iter=max_iter,
)
else:
reg = LinearRegression(fit_intercept=True)
@@ -31,7 +36,9 @@ def __init__(self, clf, reg, n_obs, log=None, x=None, y=None):
self.log = log
self.n_obs = n_obs
if x is not None and y is not None:
- self.train_r2 = np.corrcoef(self.predict_linear(x)[y > 0], y[y > 0])[0, 1] ** 2
+ self.train_r2 = (
+ np.corrcoef(self.predict_linear(x)[y > 0], y[y > 0])[0, 1] ** 2
+ )
self.train_roc = roc_auc_score(y > 0, self.predict_prob(x))
def __repr__(self):
diff --git a/carbonplan_forest_risks/fit/interp.py b/carbonplan_forest_risks/fit/interp.py
index fc60a3b..c5e4f88 100644
--- a/carbonplan_forest_risks/fit/interp.py
+++ b/carbonplan_forest_risks/fit/interp.py
@@ -8,11 +8,11 @@
def score(y_true, y_pred):
m = ~np.isnan(y_pred)
if len(y_pred) != m.sum():
- print(f'found {len(m) - m.sum()} nans in y_pred')
+ print(f"found {len(m) - m.sum()} nans in y_pred")
return r2_score(y_true[m], y_pred[m])
-def interp(df, mask, var='biomass', spacing=4000):
+def interp(df, mask, var="biomass", spacing=4000):
"""
Grid a set of lat/lon points to a grid defined by mask
@@ -38,7 +38,7 @@ def interp(df, mask, var='biomass', spacing=4000):
# extract the projection and grid info
region = [mask.x.data[0], mask.x.data[-1], mask.y.data[-1], mask.y.data[0]]
- projection = pyproj.Proj(mask.attrs['crs'])
+ projection = pyproj.Proj(mask.attrs["crs"])
coordinates = (df.lon.values, df.lat.values)
@@ -54,8 +54,8 @@ def interp(df, mask, var='biomass', spacing=4000):
# fit the gridder
chain = vd.Chain(
[
- ('mean', vd.BlockReduce(np.mean, spacing=spacing * 0.25, region=region)),
- ('nearest', vd.ScipyGridder(method='linear')),
+ ("mean", vd.BlockReduce(np.mean, spacing=spacing * 0.25, region=region)),
+ ("nearest", vd.ScipyGridder(method="linear")),
]
)
@@ -64,7 +64,7 @@ def interp(df, mask, var='biomass', spacing=4000):
# fit_score = score(test[1][0], y_pred)
# make the grid
- grid = chain.grid(spacing=spacing, region=region, data_names=[var], dims=('y', 'x'))
+ grid = chain.grid(spacing=spacing, region=region, data_names=[var], dims=("y", "x"))
grid = vd.distance_mask(
proj_coords,
maxdist=4 * spacing,
diff --git a/carbonplan_forest_risks/load/cmip.py b/carbonplan_forest_risks/load/cmip.py
index d7dfb85..1fe335e 100644
--- a/carbonplan_forest_risks/load/cmip.py
+++ b/carbonplan_forest_risks/load/cmip.py
@@ -12,74 +12,79 @@
from .. import setup, utils
members = {
- 'CanESM5-CanOE': 'r3i1p2f1',
- 'MIROC-ES2L': 'r1i1p1f2',
- 'ACCESS-CM2': 'r1i1p1f1',
- 'ACCESS-ESM1-5': 'r10i1p1f1',
- 'MRI-ESM2-0': 'r1i1p1f1',
- 'MPI-ESM1-2-LR': 'r10i1p1f1',
+ "CanESM5-CanOE": "r3i1p2f1",
+ "MIROC-ES2L": "r1i1p1f2",
+ "ACCESS-CM2": "r1i1p1f1",
+ "ACCESS-ESM1-5": "r10i1p1f1",
+ "MRI-ESM2-0": "r1i1p1f1",
+ "MPI-ESM1-2-LR": "r10i1p1f1",
}
@retry(stop=stop_after_attempt(5))
def cmip(
- store='az',
+ store="az",
df=None,
tlim=None,
model=None,
scenario=None,
coarsen=None,
- variables=['ppt', 'tmean'],
+ variables=["ppt", "tmean"],
mask=None,
member=None,
- method='bias-corrected',
- sampling='annual',
+ method="bias-corrected",
+ sampling="annual",
historical=False,
remove_nans=False,
):
with warnings.catch_warnings():
- warnings.simplefilter('ignore', category=ResourceWarning)
- warnings.simplefilter('ignore', category=FutureWarning)
- warnings.simplefilter('ignore', category=RuntimeWarning)
+ warnings.simplefilter("ignore", category=ResourceWarning)
+ warnings.simplefilter("ignore", category=FutureWarning)
+ warnings.simplefilter("ignore", category=RuntimeWarning)
if scenario is None:
- raise ValueError('must specify scenario')
+ raise ValueError("must specify scenario")
if model is None:
- raise ValueError('must specify model')
+ raise ValueError("must specify model")
if member is None:
member = members[model]
-
path = setup.loading(store)
- prefix = f'cmip6/{method}/conus/4000m/{sampling}/{model}.{scenario}.{member}.zarr'
+ prefix = (
+ f"cmip6/{method}/conus/4000m/{sampling}/{model}.{scenario}.{member}.zarr"
+ )
- if store == 'az':
+ if store == "az":
mapper = zarr.storage.ABSStore(
- 'carbonplan-downscaling', prefix=prefix, account_name='carbonplan'
+ "carbonplan-downscaling", prefix=prefix, account_name="carbonplan"
)
else:
- mapper = fsspec.get_mapper((path / 'carbonplan-downscaling' / prefix).as_uri())
+ mapper = fsspec.get_mapper(
+ (path / "carbonplan-downscaling" / prefix).as_uri()
+ )
ds = xr.open_zarr(mapper, consolidated=True)
if historical:
- prefix = f'cmip6/{method}/conus/4000m/{sampling}/{model}.historical.{member}.zarr'
+ prefix = f"cmip6/{method}/conus/4000m/{sampling}/{model}.historical.{member}.zarr"
- if store == 'az':
+ if store == "az":
mapper = zarr.storage.ABSStore(
- 'carbonplan-downscaling', prefix=prefix, account_name='carbonplan'
+ "carbonplan-downscaling", prefix=prefix, account_name="carbonplan"
)
else:
- mapper = fsspec.get_mapper((path / 'carbonplan-downscaling' / prefix).as_uri())
+ mapper = fsspec.get_mapper(
+ (path / "carbonplan-downscaling" / prefix).as_uri()
+ )
ds_historical = xr.open_zarr(mapper, consolidated=True)
- ds = xr.concat([ds_historical, ds], 'time')
+ ds = xr.concat([ds_historical, ds], "time")
- ds['cwd'] = ds['def']
- ds['pdsi'] = ds['pdsi'].clip(-16, 16)
+ ds["cwd"] = ds["def"]
+ ds["pdsi"] = ds["pdsi"].clip(-16, 16)
X = xr.Dataset()
keys = variables
@@ -99,29 +104,31 @@ def cmip(
if coarsen:
X_coarse = xr.Dataset()
for key in keys:
- X_coarse[key] = X[key].coarsen(x=coarsen, y=coarsen, boundary='trim').mean()
+ X_coarse[key] = (
+ X[key].coarsen(x=coarsen, y=coarsen, boundary="trim").mean()
+ )
X = X_coarse
if df is not None:
t = Affine(*utils.albers_conus_transform(4000))
p1 = Proj(utils.albers_conus_crs())
- p2 = Proj(proj='latlong', datum='WGS84')
- x, y = transform(p2, p1, df['lon'].values, df['lat'].values)
+ p2 = Proj(proj="latlong", datum="WGS84")
+ x, y = transform(p2, p1, df["lon"].values, df["lat"].values)
rc = rowcol(t, x, y)
- ind_r = xr.DataArray(rc[0], dims=['c'])
- ind_c = xr.DataArray(rc[1], dims=['c'])
+ ind_r = xr.DataArray(rc[0], dims=["c"])
+ ind_c = xr.DataArray(rc[1], dims=["c"])
base = X[keys].isel(y=ind_r, x=ind_c).load()
for key in keys:
- df[key + '_mean'] = base[key].mean('time').values
- df[key + '_min'] = base[key].min('time').values
- df[key + '_max'] = base[key].max('time').values
+ df[key + "_mean"] = base[key].mean("time").values
+ df[key + "_min"] = base[key].min("time").values
+ df[key + "_max"] = base[key].max("time").values
if remove_nans:
for key in keys:
- df = df[~np.isnan(df[key + '_mean'])]
+ df = df[~np.isnan(df[key + "_mean"])]
df = df.reset_index(drop=True)
return df
- X = X.drop(['x', 'y'])
+ X = X.drop(["x", "y"])
X.load(retries=10)
return X
diff --git a/carbonplan_forest_risks/load/fia.py b/carbonplan_forest_risks/load/fia.py
index 4b369a1..6ae986d 100644
--- a/carbonplan_forest_risks/load/fia.py
+++ b/carbonplan_forest_risks/load/fia.py
@@ -179,59 +179,59 @@
}
conus_states = [
- 'AL',
- 'AZ',
- 'AR',
- 'CA',
- 'CO',
- 'CT',
- 'DE',
- 'FL',
- 'GA',
- 'IA',
- 'ID',
- 'IL',
- 'IN',
- 'KS',
- 'KY',
- 'LA',
- 'ME',
- 'MA',
- 'MD',
- 'MI',
- 'MN',
- 'MO',
- 'MS',
- 'MT',
- 'NC',
- 'ND',
- 'NE',
- 'NH',
- 'NJ',
- 'NM',
- 'NV',
- 'NY',
- 'OH',
- 'OK',
- 'OR',
- 'PA',
- 'RI',
- 'SC',
- 'SD',
- 'TN',
- 'TX',
- 'UT',
- 'VT',
- 'VA',
- 'WA',
- 'WV',
- 'WI',
- 'WY',
+ "AL",
+ "AZ",
+ "AR",
+ "CA",
+ "CO",
+ "CT",
+ "DE",
+ "FL",
+ "GA",
+ "IA",
+ "ID",
+ "IL",
+ "IN",
+ "KS",
+ "KY",
+ "LA",
+ "ME",
+ "MA",
+ "MD",
+ "MI",
+ "MN",
+ "MO",
+ "MS",
+ "MT",
+ "NC",
+ "ND",
+ "NE",
+ "NH",
+ "NJ",
+ "NM",
+ "NV",
+ "NY",
+ "OH",
+ "OK",
+ "OR",
+ "PA",
+ "RI",
+ "SC",
+ "SD",
+ "TN",
+ "TX",
+ "UT",
+ "VT",
+ "VA",
+ "WA",
+ "WV",
+ "WI",
+ "WY",
]
-def fia(store='az', states='conus', clean=True, group_repeats=False):
- if states == 'conus':
+def fia(store="az", states="conus", clean=True, group_repeats=False):
+ if states == "conus":
states = conus_states
load_state = fia_state_grouped if group_repeats is True else fia_state
@@ -245,7 +245,7 @@ def fia(store='az', states='conus', clean=True, group_repeats=False):
if group_repeats:
# TODO this is to drop columns added due to missing data
# should maybe handle more cleanly
- remove = ['disturb_animal', 'disturb_fire', 'disturb_disease']
+ remove = ["disturb_animal", "disturb_fire", "disturb_disease"]
for var in remove:
if var in df.columns:
df = df.drop(columns=[var])
@@ -257,82 +257,82 @@ def fia(store='az', states='conus', clean=True, group_repeats=False):
def fia_state(store, state, clean):
path = setup.loading(store)
df = pd.read_parquet(
- path / f'carbonplan-data/processed/fia-states/long/{state.lower()}.parquet'
+ path / f"carbonplan-data/processed/fia-states/long/{state.lower()}.parquet"
)
if clean:
inds = (
- (df['adj_ag_biomass'] > 0)
- & (df['STDAGE'] < 999)
- & (df['STDAGE'] > 0)
- & (~np.isnan(df['FLDTYPCD']))
- & (df['FLDTYPCD'] != 999)
- & (df['FLDTYPCD'] != 950)
- & (df['FLDTYPCD'] <= 983)
- & (df['DSTRBCD1'] == 0)
- & (df['COND_STATUS_CD'] == 1)
- & (df['CONDPROP_UNADJ'] > 0.3)
- & (df['MEASYEAR'] < 9999)
- & (df['MEASYEAR'] > 2000)
- & (df['INVYR'] < 9999)
- & (df['INVYR'] > 2000)
+ (df["adj_ag_biomass"] > 0)
+ & (df["STDAGE"] < 999)
+ & (df["STDAGE"] > 0)
+ & (~np.isnan(df["FLDTYPCD"]))
+ & (df["FLDTYPCD"] != 999)
+ & (df["FLDTYPCD"] != 950)
+ & (df["FLDTYPCD"] <= 983)
+ & (df["DSTRBCD1"] == 0)
+ & (df["COND_STATUS_CD"] == 1)
+ & (df["CONDPROP_UNADJ"] > 0.3)
+ & (df["MEASYEAR"] < 9999)
+ & (df["MEASYEAR"] > 2000)
+ & (df["INVYR"] < 9999)
+ & (df["INVYR"] > 2000)
)
df = df[inds]
else:
inds = (
- (df['MEASYEAR'] < 9999)
- & (df['INVYR'] < 9999)
- & (df['FLDTYPCD'] != 999)
- & (df['FLDTYPCD'] != 950)
- & (df['FLDTYPCD'] <= 983)
+ (df["MEASYEAR"] < 9999)
+ & (df["INVYR"] < 9999)
+ & (df["FLDTYPCD"] != 999)
+ & (df["FLDTYPCD"] != 950)
+ & (df["FLDTYPCD"] <= 983)
)
df = df[inds]
df = df.rename(
columns={
- 'LAT': 'lat',
- 'LON': 'lon',
- 'adj_ag_biomass': 'biomass',
- 'adj_pop_mort': 'mort',
- 'STDAGE': 'age',
- 'ACTUALHT': 'height',
- 'MEASYEAR': 'year',
- 'INVYR': 'inventory_year',
- 'FLDTYPCD': 'type_code',
- 'PHYSCLCD': 'physiographic_code',
- 'ALSTKCD': 'all_stocking_code',
- 'GSSTKCD': 'grow_stocking_code',
- 'ELEV': 'elevation',
- 'SLOPE': 'slope',
- 'ASPECT': 'aspect',
- 'OWNCD': 'owner',
- 'PLT_CN': 'plot_cn',
+ "LAT": "lat",
+ "LON": "lon",
+ "adj_ag_biomass": "biomass",
+ "adj_pop_mort": "mort",
+ "STDAGE": "age",
+ "ACTUALHT": "height",
+ "MEASYEAR": "year",
+ "INVYR": "inventory_year",
+ "FLDTYPCD": "type_code",
+ "PHYSCLCD": "physiographic_code",
+ "ALSTKCD": "all_stocking_code",
+ "GSSTKCD": "grow_stocking_code",
+ "ELEV": "elevation",
+ "SLOPE": "slope",
+ "ASPECT": "aspect",
+ "OWNCD": "owner",
+ "PLT_CN": "plot_cn",
}
).filter(
[
- 'lat',
- 'lon',
- 'age',
- 'biomass',
- 'year',
- 'inventory_year',
- 'type_code',
- 'elevation',
- 'slope',
- 'aspect',
- 'mort',
- 'owner',
- 'plot_cn',
- 'height',
- 'physiographic_code',
- 'all_stocking_code',
- 'grow_stocking_code',
+ "lat",
+ "lon",
+ "age",
+ "biomass",
+ "year",
+ "inventory_year",
+ "type_code",
+ "elevation",
+ "slope",
+ "aspect",
+ "mort",
+ "owner",
+ "plot_cn",
+ "height",
+ "physiographic_code",
+ "all_stocking_code",
+ "grow_stocking_code",
]
)
- df['type_code'] = df['type_code'].map(forest_type_remap)
+ df["type_code"] = df["type_code"].map(forest_type_remap)
- df['state'] = state.upper()
+ df["state"] = state.upper()
return df.reset_index(drop=True)
@@ -345,61 +345,67 @@ def fia_state_grouped(store, state, clean):
"""
path = setup.loading(store)
state_long = pd.read_parquet(
- path / f'carbonplan-data/processed/fia-states/long/{state.lower()}.parquet'
+ path / f"carbonplan-data/processed/fia-states/long/{state.lower()}.parquet"
)
state_long = state_long.rename(
columns={
- 'LAT': 'lat',
- 'LON': 'lon',
- 'FLDTYPCD': 'type_code',
- 'MEASYEAR': 'year',
- 'INVYR': 'inventory_year',
- 'STDAGE': 'age',
- 'ELEV': 'elevation',
- 'SLOPE': 'slope',
- 'ACTUALHT': 'height',
- 'PHYSCLCD': 'physiographic_code',
- 'ALSTKCD': 'all_stocking_code',
- 'GSSTKCD': 'grow_stocking_code',
- 'ASPECT': 'aspect',
- 'OWNCD': 'owner',
- 'CONDPROP_UNADJ': 'condprop',
- 'adj_pop_mort': 'mort',
- 'adj_removal': 'removal',
- 'adj_balive': 'balive',
+ "LAT": "lat",
+ "LON": "lon",
+ "FLDTYPCD": "type_code",
+ "MEASYEAR": "year",
+ "INVYR": "inventory_year",
+ "STDAGE": "age",
+ "ELEV": "elevation",
+ "SLOPE": "slope",
+ "ACTUALHT": "height",
+ "PHYSCLCD": "physiographic_code",
+ "ALSTKCD": "all_stocking_code",
+ "GSSTKCD": "grow_stocking_code",
+ "ASPECT": "aspect",
+ "OWNCD": "owner",
+ "CONDPROP_UNADJ": "condprop",
+ "adj_pop_mort": "mort",
+ "adj_removal": "removal",
+ "adj_balive": "balive",
}
)
- state_long = state_long.sort_values(['plt_uid', 'CONDID', 'year'])
- state_long['wide_idx'] = state_long.groupby(['plt_uid', 'CONDID']).cumcount()
+ state_long = state_long.sort_values(["plt_uid", "CONDID", "year"])
+ state_long["wide_idx"] = state_long.groupby(["plt_uid", "CONDID"]).cumcount()
tmp = []
- missing_vars = [] # append missing vars, then will fill in nan cols after concat the wide df
+ missing_vars = (
+ []
+ ) # append missing vars, then will fill in nan cols after concat the wide df
for var in [
- 'year',
- 'balive',
- 'mort',
- 'frac_pop_mort_insect',
- 'frac_pop_mort_disease',
- 'frac_pop_mort_fire',
- 'frac_pop_mort_animal',
- 'frac_pop_mort_weather',
- 'frac_pop_mort_vegetation',
- 'frac_pop_mort_unknown',
- 'disturb_animal',
- 'disturb_insect',
- 'disturb_disease',
- 'disturb_fire',
- 'disturb_human',
- 'disturb_weather',
- 'treatment_cutting',
- 'treatment_regeneration',
- 'treatment_preparation',
- 'treatment_other',
+ "year",
+ "balive",
+ "mort",
+ "frac_pop_mort_insect",
+ "frac_pop_mort_disease",
+ "frac_pop_mort_fire",
+ "frac_pop_mort_animal",
+ "frac_pop_mort_weather",
+ "frac_pop_mort_vegetation",
+ "frac_pop_mort_unknown",
+ "disturb_animal",
+ "disturb_insect",
+ "disturb_disease",
+ "disturb_fire",
+ "disturb_human",
+ "disturb_weather",
+ "treatment_cutting",
+ "treatment_regeneration",
+ "treatment_preparation",
+ "treatment_other",
]:
- state_long['tmp_idx'] = var + '_' + state_long['wide_idx'].astype(str)
+ state_long["tmp_idx"] = var + "_" + state_long["wide_idx"].astype(str)
if var in state_long.columns:
- tmp.append(state_long.pivot(index=['plt_uid', 'CONDID'], columns='tmp_idx', values=var))
+ tmp.append(
+ state_long.pivot(
+ index=["plt_uid", "CONDID"], columns="tmp_idx", values=var
+ )
+ )
else:
missing_vars.append(var)
wide = pd.concat(tmp, axis=1)
@@ -408,48 +414,48 @@ def fia_state_grouped(store, state, clean):
for missing_var in missing_vars:
wide[missing_var] = np.nan
- attrs = state_long.groupby(['plt_uid', 'CONDID'])[
+ attrs = state_long.groupby(["plt_uid", "CONDID"])[
[
- 'lat',
- 'lon',
- 'age',
- 'type_code',
- 'elevation',
- 'slope',
- 'aspect',
- 'condprop',
- 'owner',
- 'height',
- 'physiographic_code',
- 'all_stocking_code',
- 'grow_stocking_code',
+ "lat",
+ "lon",
+ "age",
+ "type_code",
+ "elevation",
+ "slope",
+ "aspect",
+ "condprop",
+ "owner",
+ "height",
+ "physiographic_code",
+ "all_stocking_code",
+ "grow_stocking_code",
]
].max()
- if 'year_1' not in wide.columns:
+ if "year_1" not in wide.columns:
return None
- df = attrs.join(wide).dropna(subset=['year_1'])
+ df = attrs.join(wide).dropna(subset=["year_1"])
if clean:
inds = (
- (~np.isnan(df['type_code']))
- & (df['type_code'] != 999)
- & (df['type_code'] != 950)
- & (df['type_code'] <= 983)
+ (~np.isnan(df["type_code"]))
+ & (df["type_code"] != 999)
+ & (df["type_code"] != 950)
+ & (df["type_code"] <= 983)
)
df = df[inds]
for year in range(6):
- key = f'year_{year}'
+ key = f"year_{year}"
if key in df.columns:
if clean:
df = df[(df[key] < 9999) | np.isnan((df[key]))]
if sum(np.isnan(df[key])) == len(df):
del df[key]
- df['type_code'] = df['type_code'].map(forest_type_remap)
+ df["type_code"] = df["type_code"].map(forest_type_remap)
- df['state'] = state.upper()
+ df["state"] = state.upper()
return df.reset_index(drop=True)
diff --git a/carbonplan_forest_risks/load/mask.py b/carbonplan_forest_risks/load/mask.py
index dbbd925..dba7f70 100644
--- a/carbonplan_forest_risks/load/mask.py
+++ b/carbonplan_forest_risks/load/mask.py
@@ -1,8 +1,8 @@
from .nlcd import nlcd
-def mask(store='az', year=2001, coarsen=None):
- bands = nlcd(store=store, classes='all', year=year)
+def mask(store="az", year=2001, coarsen=None):
+ bands = nlcd(store=store, classes="all", year=year)
if coarsen:
- bands = bands.coarsen(x=coarsen, y=coarsen, boundary='trim').mean()
- return bands.sum('band')
+ bands = bands.coarsen(x=coarsen, y=coarsen, boundary="trim").mean()
+ return bands.sum("band")
diff --git a/carbonplan_forest_risks/load/mtbs.py b/carbonplan_forest_risks/load/mtbs.py
index fd0a29f..b8213cb 100644
--- a/carbonplan_forest_risks/load/mtbs.py
+++ b/carbonplan_forest_risks/load/mtbs.py
@@ -7,14 +7,14 @@
from .. import setup
-def mtbs(store='az', tlim=(1984, 2018), mask=None, coarsen=None):
+def mtbs(store="az", tlim=(1984, 2018), mask=None, coarsen=None):
path = setup.loading(store)
- prefix = (path / 'carbonplan-data/processed/mtbs/conus/4000m/monthly.zarr').as_uri()
+ prefix = (path / "carbonplan-data/processed/mtbs/conus/4000m/monthly.zarr").as_uri()
mapper = fsspec.get_mapper(prefix)
with warnings.catch_warnings():
- warnings.simplefilter('ignore', category=RuntimeWarning)
+ warnings.simplefilter("ignore", category=RuntimeWarning)
mtbs = xr.open_zarr(mapper, consolidated=True)
@@ -28,7 +28,7 @@ def mtbs(store='az', tlim=(1984, 2018), mask=None, coarsen=None):
mtbs = mtbs * vals
if coarsen:
- mtbs = mtbs.coarsen(x=coarsen, y=coarsen, boundary='trim').mean()
+ mtbs = mtbs.coarsen(x=coarsen, y=coarsen, boundary="trim").mean()
mtbs.load()
return mtbs
diff --git a/carbonplan_forest_risks/load/nftd.py b/carbonplan_forest_risks/load/nftd.py
index 4fb07a6..387ced3 100644
--- a/carbonplan_forest_risks/load/nftd.py
+++ b/carbonplan_forest_risks/load/nftd.py
@@ -10,10 +10,17 @@ def load_rio(f):
return src.read(1)
-def nftd(store='az', groups='all', coarsen=None, append_all=False, mask=None, area_threshold=None):
+def nftd(
+ store="az",
+ groups="all",
+ coarsen=None,
+ append_all=False,
+ mask=None,
+ area_threshold=None,
+):
path = setup.loading(store)
- if groups == 'all':
+ if groups == "all":
groups = [
100,
120,
@@ -45,16 +52,20 @@ def nftd(store='az', groups='all', coarsen=None, append_all=False, mask=None, ar
bands = xr.concat(
[
xr.open_rasterio(
- (path / f'carbonplan-data/processed/nftd/conus/4000m/group_g{g}.tif').as_uri()
+ (
+ path / f"carbonplan-data/processed/nftd/conus/4000m/group_g{g}.tif"
+ ).as_uri()
)[0]
for g in groups
],
- dim=xr.Variable('band', groups),
+ dim=xr.Variable("band", groups),
)
if area_threshold is not None:
- band_inds = bands['band'].values
- areas = np.asarray([bands.sel(band=band).sum(['x', 'y']).item() for band in band_inds])
+ band_inds = bands["band"].values
+ areas = np.asarray(
+ [bands.sel(band=band).sum(["x", "y"]).item() for band in band_inds]
+ )
small_inds = areas < area_threshold
large_inds = areas >= area_threshold
matches = {}
@@ -75,9 +86,9 @@ def nftd(store='az', groups='all', coarsen=None, append_all=False, mask=None, ar
bands = bands[large_inds]
if append_all:
- total = bands.sum('band').values[np.newaxis, :, :]
- total = xr.DataArray(total, dims=['band', 'y', 'x'], coords={'band': [0]})
- bands = xr.concat([bands, total], dim='band')
+ total = bands.sum("band").values[np.newaxis, :, :]
+ total = xr.DataArray(total, dims=["band", "y", "x"], coords={"band": [0]})
+ bands = xr.concat([bands, total], dim="band")
if mask is not None:
vals = mask.values
@@ -85,7 +96,7 @@ def nftd(store='az', groups='all', coarsen=None, append_all=False, mask=None, ar
bands = bands * vals
if coarsen is not None:
- bands = bands.coarsen(x=coarsen, y=coarsen, boundary='trim').mean()
+ bands = bands.coarsen(x=coarsen, y=coarsen, boundary="trim").mean()
bands.load()
return bands
diff --git a/carbonplan_forest_risks/load/nlcd.py b/carbonplan_forest_risks/load/nlcd.py
index af822a0..0e107b0 100644
--- a/carbonplan_forest_risks/load/nlcd.py
+++ b/carbonplan_forest_risks/load/nlcd.py
@@ -4,20 +4,43 @@
from .. import setup
-def nlcd(store='az', classes='all', year=2001, coarsen=None, mask=None):
+def nlcd(store="az", classes="all", year=2001, coarsen=None, mask=None):
path = setup.loading(store)
- if classes == 'all':
- classes = [11, 12, 21, 22, 23, 24, 31, 41, 42, 43, 51, 52, 71, 72, 73, 74, 81, 82, 90, 95]
+ if classes == "all":
+ classes = [
+ 11,
+ 12,
+ 21,
+ 22,
+ 23,
+ 24,
+ 31,
+ 41,
+ 42,
+ 43,
+ 51,
+ 52,
+ 71,
+ 72,
+ 73,
+ 74,
+ 81,
+ 82,
+ 90,
+ 95,
+ ]
bands = xr.concat(
[
xr.open_rasterio(
- (path / f'carbonplan-data/processed/nlcd/conus/4000m/{year}_c{c}.tif').as_uri()
+ (
+ path / f"carbonplan-data/processed/nlcd/conus/4000m/{year}_c{c}.tif"
+ ).as_uri()
)
for c in classes
],
- dim=xr.Variable('band', classes),
+ dim=xr.Variable("band", classes),
)
if mask is not None:
@@ -26,7 +49,7 @@ def nlcd(store='az', classes='all', year=2001, coarsen=None, mask=None):
bands = bands * vals
if coarsen is not None:
- bands = bands.coarsen(x=coarsen, y=coarsen, boundary='trim').mean()
+ bands = bands.coarsen(x=coarsen, y=coarsen, boundary="trim").mean()
bands.load()
return bands
diff --git a/carbonplan_forest_risks/load/terraclim.py b/carbonplan_forest_risks/load/terraclim.py
index e15d557..f975835 100644
--- a/carbonplan_forest_risks/load/terraclim.py
+++ b/carbonplan_forest_risks/load/terraclim.py
@@ -14,36 +14,38 @@
@retry(stop=stop_after_attempt(5))
def terraclim(
- store='az',
+ store="az",
df=None,
tlim=None,
coarsen=None,
- sampling='annual',
- variables=['ppt', 'tmean'],
+ sampling="annual",
+ variables=["ppt", "tmean"],
mask=None,
group_repeats=False,
remove_nans=False,
):
with warnings.catch_warnings():
- warnings.simplefilter('ignore', category=ResourceWarning)
- warnings.simplefilter('ignore', category=FutureWarning)
- warnings.simplefilter('ignore', category=RuntimeWarning)
+ warnings.simplefilter("ignore", category=ResourceWarning)
+ warnings.simplefilter("ignore", category=FutureWarning)
+ warnings.simplefilter("ignore", category=RuntimeWarning)
path = setup.loading(store)
- prefix = f'obs/conus/4000m/{sampling}/terraclimate_plus_v3.zarr'
+ prefix = f"obs/conus/4000m/{sampling}/terraclimate_plus_v3.zarr"
- if store == 'az':
+ if store == "az":
mapper = zarr.storage.ABSStore(
- 'carbonplan-downscaling', prefix=prefix, account_name='carbonplan'
+ "carbonplan-downscaling", prefix=prefix, account_name="carbonplan"
)
else:
- mapper = fsspec.get_mapper((path / 'carbonplan-downscaling' / prefix).as_uri())
+ mapper = fsspec.get_mapper(
+ (path / "carbonplan-downscaling" / prefix).as_uri()
+ )
ds = xr.open_zarr(mapper, consolidated=True)
- ds['cwd'] = ds['pet'] - ds['aet']
- ds['pdsi'] = ds['pdsi'].clip(-16, 16)
+ ds["cwd"] = ds["pet"] - ds["aet"]
+ ds["pdsi"] = ds["pdsi"].clip(-16, 16)
X = xr.Dataset()
@@ -62,69 +64,75 @@ def terraclim(
if coarsen:
X_coarse = xr.Dataset()
for key in variables:
- X_coarse[key] = X[key].coarsen(x=coarsen, y=coarsen, boundary='trim').mean()
+ X_coarse[key] = (
+ X[key].coarsen(x=coarsen, y=coarsen, boundary="trim").mean()
+ )
X = X_coarse
if df is not None:
t = Affine(*utils.albers_conus_transform(4000))
p1 = Proj(utils.albers_conus_crs())
- p2 = Proj(proj='latlong', datum='WGS84')
- x, y = transform(p2, p1, df['lon'].values, df['lat'].values)
+ p2 = Proj(proj="latlong", datum="WGS84")
+ x, y = transform(p2, p1, df["lon"].values, df["lat"].values)
rc = rowcol(t, x, y)
- ind_r = xr.DataArray(rc[0], dims=['c'])
- ind_c = xr.DataArray(rc[1], dims=['c'])
+ ind_r = xr.DataArray(rc[0], dims=["c"])
+ ind_c = xr.DataArray(rc[1], dims=["c"])
if not group_repeats:
base = X[variables].isel(y=ind_r, x=ind_c).load()
for key in variables:
- df[key + '_mean'] = base[key].mean('time').values
- df[key + '_min'] = base[key].min('time').values
- df[key + '_max'] = base[key].max('time').values
+ df[key + "_mean"] = base[key].mean("time").values
+ df[key + "_min"] = base[key].min("time").values
+ df[key + "_max"] = base[key].max("time").values
if remove_nans:
for key in variables:
- df = df[~np.isnan(df[key + '_mean'])]
+ df = df[~np.isnan(df[key + "_mean"])]
df = df.reset_index(drop=True)
return df
else:
base = X[variables].isel(y=ind_r, x=ind_c).load()
for key in variables:
array = base[key].values.T
- time = np.arange(X['time.year'].min(), X['time.year'].max() + 1)
+ time = np.arange(X["time.year"].min(), X["time.year"].max() + 1)
maxyear = max(
map(
- lambda x: int(x.split('_')[1]),
- df.columns[['year' in c for c in df.columns]],
+ lambda x: int(x.split("_")[1]),
+ df.columns[["year" in c for c in df.columns]],
)
)
pairs = [(str(y), str(y + 1)) for y in range(maxyear)]
for pair in pairs:
tlims = [
- (time > tmin) & (time <= tmax)
- if (~np.isnan(tmin) & ~np.isnan(tmax))
- else []
- for (tmin, tmax) in zip(df[f'year_{pair[0]}'], df[f'year_{pair[1]}'])
+ (
+ (time > tmin) & (time <= tmax)
+ if (~np.isnan(tmin) & ~np.isnan(tmax))
+ else []
+ )
+ for (tmin, tmax) in zip(
+ df[f"year_{pair[0]}"], df[f"year_{pair[1]}"]
+ )
]
def get_stats(a, t):
if (len(t) > 0) and (t.sum() > 0):
selection = a[t]
return {
- 'min': selection.min(),
- 'max': selection.max(),
- 'mean': selection.mean(),
+ "min": selection.min(),
+ "max": selection.max(),
+ "mean": selection.mean(),
}
else:
- return {'min': np.NaN, 'max': np.NaN, 'mean': np.NaN}
+ return {"min": np.NaN, "max": np.NaN, "mean": np.NaN}
stats = [get_stats(a, t) for (a, t) in zip(array, tlims)]
- df[key + '_min_' + pair[1]] = [d['min'] for d in stats]
- df[key + '_max_' + pair[1]] = [d['max'] for d in stats]
- df[key + '_mean_' + pair[1]] = [d['mean'] for d in stats]
+ df[key + "_min_" + pair[1]] = [d["min"] for d in stats]
+ df[key + "_max_" + pair[1]] = [d["max"] for d in stats]
+ df[key + "_mean_" + pair[1]] = [d["mean"] for d in stats]
if remove_nans:
for key in variables:
- df = df[~np.isnan(df[key + '_mean_1'])]
+ df = df[~np.isnan(df[key + "_mean_1"])]
df = df.reset_index(drop=True)
return df
else:
diff --git a/carbonplan_forest_risks/load/tiff.py b/carbonplan_forest_risks/load/tiff.py
index 745f8ba..d15e5b1 100644
--- a/carbonplan_forest_risks/load/tiff.py
+++ b/carbonplan_forest_risks/load/tiff.py
@@ -6,11 +6,17 @@
def tiff(url, model_ds, coarsen=1):
- target = nlcd(store='az', year=2001).isel(band=0).drop('band')
+ target = nlcd(store="az", year=2001).isel(band=0).drop("band")
source = xr.open_rasterio(url)
source = source.where(source > -1)
ds = source.rio.reproject_match(target, resampling=Resampling.bilinear)
- ds = ds.where(ds > -1).sel(band=1).drop('band').drop('spatial_ref').astype(np.float64)
+ ds = (
+ ds.where(ds > -1)
+ .sel(band=1)
+ .drop("band")
+ .drop("spatial_ref")
+ .astype(np.float64)
+ )
if coarsen != 1:
ds = ds.coarsen(x=coarsen, y=coarsen, boundary="trim").mean()
# make sure that the coordinates are *exactly* aligned- otherwise you'll have
@@ -27,7 +33,7 @@ def impacts(
period_start=1970,
period_end=2100,
coarsen=1,
- met_data='cmip',
+ met_data="cmip",
):
start_years = np.arange(period_start, period_end, 10)
end_years = np.arange(period_start + 9, period_end + 9, 10)
@@ -43,35 +49,39 @@ def impacts(
("MPI-ESM1-2-LR", "r10i1p1f1"),
("CanESM5-CanOE", "r3i1p2f1"),
]
- if met_data == 'cmip':
+ if met_data == "cmip":
for scenario in scenarios:
impact_ds = xr.Dataset()
- for (gcm, ensemble_member) in gcms:
+ for gcm, ensemble_member in gcms:
year_coords, impact_ds_list = [], []
for start_year, end_year in zip(start_years, end_years):
if start_year < 2005:
url = url_template.format(
- gcm, 'historical', ensemble_member, start_year, end_year
+ gcm, "historical", ensemble_member, start_year, end_year
)
else:
url = url_template.format(
gcm, scenario, ensemble_member, start_year, end_year
)
- impact_ds_list.append(tiff(url, spatial_template, coarsen=coarsen).load())
+ impact_ds_list.append(
+ tiff(url, spatial_template, coarsen=coarsen).load()
+ )
year_coords.append(start_year)
- impact_ds[gcm] = xr.concat(impact_ds_list, 'year').assign_coords(
- {'year': year_coords}
+ impact_ds[gcm] = xr.concat(impact_ds_list, "year").assign_coords(
+ {"year": year_coords}
)
full_ds_list.append(impact_ds)
- full_ds = xr.concat(full_ds_list, 'scenario').assign_coords({'scenario': scenarios})
+ full_ds = xr.concat(full_ds_list, "scenario").assign_coords(
+ {"scenario": scenarios}
+ )
- elif met_data == 'terraclimate':
+ elif met_data == "terraclimate":
year_coords, impact_ds_list = [], []
for start_year, end_year in zip(start_years, end_years):
url = url_template.format(start_year, end_year)
impact_ds_list.append(tiff(url, spatial_template, coarsen=coarsen).load())
year_coords.append(start_year)
- full_ds = xr.concat(impact_ds_list, 'year').assign_coords({'year': year_coords})
+ full_ds = xr.concat(impact_ds_list, "year").assign_coords({"year": year_coords})
if mask is not None:
full_ds = full_ds.where(mask > 0)
return full_ds
diff --git a/carbonplan_forest_risks/plot/carto.py b/carbonplan_forest_risks/plot/carto.py
index 25800a9..b4b366a 100644
--- a/carbonplan_forest_risks/plot/carto.py
+++ b/carbonplan_forest_risks/plot/carto.py
@@ -9,9 +9,9 @@
def carto(
data=None,
- lon='lon',
- lat='lat',
- projection='albersUsa',
+ lon="lon",
+ lat="lat",
+ projection="albersUsa",
color=None,
cmap=None,
clabel=None,
@@ -23,17 +23,17 @@ def carto(
opacity=1,
):
if data is None:
- df = pd.DataFrame({'lon': lon, 'lat': lat})
- if color is not None and hasattr(color, 'name') and clabel is None:
+ df = pd.DataFrame({"lon": lon, "lat": lat})
+ if color is not None and hasattr(color, "name") and clabel is None:
clabel = color.name
if color is not None:
- df['color'] = color
- _color = 'color'
+ df["color"] = color
+ _color = "color"
else:
df = data
_color = color
if clabel is None:
- clabel = 'color'
+ clabel = "color"
clegend = alt.Legend(title=clabel)
@@ -43,24 +43,30 @@ def color_scaled(color):
elif clim is None and cmap is not None:
return alt.Color(color, legend=clegend, scale=alt.Scale(scheme=cmap))
elif clim is not None and cmap is None:
- return alt.Color(color, legend=clegend, scale=alt.Scale(domain=clim, clamp=True))
+ return alt.Color(
+ color, legend=clegend, scale=alt.Scale(domain=clim, clamp=True)
+ )
elif clim is not None and cmap is not None:
if type(cmap) == str:
return alt.Color(
- color, legend=clegend, scale=alt.Scale(domain=clim, scheme=cmap, clamp=True)
+ color,
+ legend=clegend,
+ scale=alt.Scale(domain=clim, scheme=cmap, clamp=True),
)
else:
return alt.Color(
- color, legend=clegend, scale=alt.Scale(domain=clim, range=cmap, clamp=True)
+ color,
+ legend=clegend,
+ scale=alt.Scale(domain=clim, range=cmap, clamp=True),
)
- states = alt.topo_feature(vega_data.us_10m.url, 'states')
+ states = alt.topo_feature(vega_data.us_10m.url, "states")
background = (
alt.Chart(states)
.mark_geoshape(
- fill='white',
- stroke='black',
+ fill="white",
+ stroke="black",
strokeWidth=0.3,
)
.project(projection)
@@ -74,8 +80,8 @@ def color_scaled(color):
if color is None:
geomap = (
alt.Chart(df)
- .mark_square(size=size, color='rgb(150,150,150)', opacity=opacity)
- .encode(longitude='lon:Q', latitude='lat:Q')
+ .mark_square(size=size, color="rgb(150,150,150)", opacity=opacity)
+ .encode(longitude="lon:Q", latitude="lat:Q")
.project(type=projection)
.properties(width=width, height=height)
)
@@ -83,7 +89,7 @@ def color_scaled(color):
geomap = (
alt.Chart(df)
.mark_square(size=size, opacity=opacity)
- .encode(longitude='lon:Q', latitude='lat:Q', color=color_scaled(_color))
+ .encode(longitude="lon:Q", latitude="lat:Q", color=color_scaled(_color))
.project(type=projection)
.properties(width=width, height=height)
)
@@ -91,7 +97,7 @@ def color_scaled(color):
return background + geomap
-def cartopy_proj_albers(region='conus'):
+def cartopy_proj_albers(region="conus"):
return ccrs.AlbersEqualArea(
central_longitude=-96, central_latitude=23, standard_parallels=(29.5, 45.5)
)
@@ -99,21 +105,23 @@ def cartopy_proj_albers(region='conus'):
def cartopy_borders():
states_df = gpd.read_file(
- shapereader.natural_earth('50m', 'cultural', 'admin_1_states_provinces')
+ shapereader.natural_earth("50m", "cultural", "admin_1_states_provinces")
)
states = (
- states_df.loc[states_df['iso_a2'] == 'US']
+ states_df.loc[states_df["iso_a2"] == "US"]
.set_crs(epsg=4326)
- .to_crs(utils.projections('albers', 'conus'))
- .drop([49, 60])['geometry']
+ .to_crs(utils.projections("albers", "conus"))
+ .drop([49, 60])["geometry"]
.values
)
- countries_df = gpd.read_file(shapereader.natural_earth('50m', 'cultural', 'admin_0_countries'))
+ countries_df = gpd.read_file(
+ shapereader.natural_earth("50m", "cultural", "admin_0_countries")
+ )
countries = (
- countries_df[countries_df['ADMIN'] == 'United States of America']
+ countries_df[countries_df["ADMIN"] == "United States of America"]
.set_crs(epsg=4326)
- .to_crs(utils.projections('albers', 'conus'))['geometry']
+ .to_crs(utils.projections("albers", "conus"))["geometry"]
.values
)
return states, countries
diff --git a/carbonplan_forest_risks/plot/fire.py b/carbonplan_forest_risks/plot/fire.py
index 009911c..872192b 100644
--- a/carbonplan_forest_risks/plot/fire.py
+++ b/carbonplan_forest_risks/plot/fire.py
@@ -8,16 +8,23 @@
from . import carto, line
-def monthly(data, data_var='monthly', projection='albersUsa', clim=None, cmap='reds', clabel=None):
- lat = data['lat'].values.flatten()
- lon = data['lon'].values.flatten()
+def monthly(
+ data,
+ data_var="monthly",
+ projection="albersUsa",
+ clim=None,
+ cmap="reds",
+ clabel=None,
+):
+ lat = data["lat"].values.flatten()
+ lon = data["lon"].values.flatten()
- shape = data['lat'].shape
+ shape = data["lat"].shape
size = (170 / shape[0]) * (270 / shape[1]) * 0.9
months = [2, 3, 4, 5, 6, 7, 8, 9, 10]
- months_labels = ['mar', 'apr', 'may', 'jun', 'jul', 'aug', 'sep', 'oct', 'nov']
- fires = data[data_var].groupby('time.month').mean().isel(month=months)
+ months_labels = ["mar", "apr", "may", "jun", "jul", "aug", "sep", "oct", "nov"]
+ fires = data[data_var].groupby("time.month").mean().isel(month=months)
chart = alt.vconcat()
counter = 0
@@ -51,18 +58,18 @@ def simple_map(
data,
data2=None,
clabel=None,
- projection='albersUsa',
+ projection="albersUsa",
clim=None,
- cmap='reds',
+ cmap="reds",
title1=None,
title2=None,
):
- lat = data['lat'].values.flatten()
- lon = data['lon'].values.flatten()
+ lat = data["lat"].values.flatten()
+ lon = data["lon"].values.flatten()
color = data.values.flatten()
inds = color >= clim[0]
- shape = data['lat'].shape
+ shape = data["lat"].shape
size = (250 / shape[0]) * (400 / shape[1]) * 0.9
row = alt.hconcat()
@@ -102,26 +109,32 @@ def simple_map(
return row
-def summary(data, data_var='monthly', projection='albersUsa', clim=None, clabel=None, title=None):
- lat = data['lat'].values.flatten()
- lon = data['lon'].values.flatten()
- color = data.groupby('time.year').sum().mean('year').values.flatten()
+def summary(
+ data, data_var="monthly", projection="albersUsa", clim=None, clabel=None, title=None
+):
+ lat = data["lat"].values.flatten()
+ lon = data["lon"].values.flatten()
+ color = data.groupby("time.year").sum().mean("year").values.flatten()
inds = color > clim[0]
- shape = data['lat'].shape
+ shape = data["lat"].shape
size = (300 / shape[0]) * (500 / shape[1]) * 0.9
column = alt.vconcat()
- x = data.groupby('time.year').sum()['year'].values
- y = data.groupby('time.year').sum().mean(['x', 'y']).values
+ x = data.groupby("time.year").sum()["year"].values
+ y = data.groupby("time.year").sum().mean(["x", "y"]).values
- column &= line(x=x, y=y, width=300, height=122, strokeWidth=2, color='rgb(175,91,92)')
+ column &= line(
+ x=x, y=y, width=300, height=122, strokeWidth=2, color="rgb(175,91,92)"
+ )
- x = data.groupby('time.month').mean()['month'].values
- y = data.groupby('time.month').mean().mean(['x', 'y']).values
+ x = data.groupby("time.month").mean()["month"].values
+ y = data.groupby("time.month").mean().mean(["x", "y"]).values
- column &= line(x=x, y=y, width=300, height=122, strokeWidth=2, color='rgb(175,91,92)')
+ column &= line(
+ x=x, y=y, width=300, height=122, strokeWidth=2, color="rgb(175,91,92)"
+ )
row = alt.hconcat()
@@ -132,7 +145,7 @@ def summary(data, data_var='monthly', projection='albersUsa', clim=None, clabel=
lon=lon[inds],
color=color[inds],
clim=clim,
- cmap='reds',
+ cmap="reds",
clabel=clabel,
size=size,
width=500,
@@ -155,31 +168,35 @@ def evaluation(
data,
model,
mask,
- projection='albersUsa',
+ projection="albersUsa",
clim=None,
- cmap='reds',
+ cmap="reds",
percentage=True,
comparison=True,
add_map=True,
clabel=None,
):
- lat = data['lat'].values.flatten()
- lon = data['lon'].values.flatten()
+ lat = data["lat"].values.flatten()
+ lon = data["lon"].values.flatten()
- color_model = model.groupby('time.year').sum().where(mask).mean('year').values.flatten()
- color_data = data.groupby('time.year').sum().where(mask).mean('year').values.flatten()
+ color_model = (
+ model.groupby("time.year").sum().where(mask).mean("year").values.flatten()
+ )
+ color_data = (
+ data.groupby("time.year").sum().where(mask).mean("year").values.flatten()
+ )
inds_model = color_model >= clim[0]
inds_data = color_data >= clim[0]
- shape = data['lat'].shape
+ shape = data["lat"].shape
size = (300 / shape[0]) * (500 / shape[1]) * 0.85
column = alt.vconcat()
- x = data.groupby('time.year').sum().where(mask)['year'].values
- y = data.groupby('time.year').sum().where(mask).mean(['x', 'y']).values
- yhat = model.groupby('time.year').sum().where(mask).mean(['x', 'y']).values
+ x = data.groupby("time.year").sum().where(mask)["year"].values
+ y = data.groupby("time.year").sum().where(mask).mean(["x", "y"]).values
+ yhat = model.groupby("time.year").sum().where(mask).mean(["x", "y"]).values
column &= line(
x=x,
@@ -188,9 +205,9 @@ def evaluation(
height=233,
strokeWidth=2,
opacity=1,
- color='darkgrey',
- ylabel='Burn area (fraction/year',
- xlabel='Time',
+ color="darkgrey",
+ ylabel="Burn area (fraction/year",
+ xlabel="Time",
) + line(
x=x,
y=yhat,
@@ -198,14 +215,14 @@ def evaluation(
height=233,
strokeWidth=2,
opacity=1,
- color='#D77B40',
- ylabel='Burn area (fraction/year)',
- xlabel='Time',
+ color="#D77B40",
+ ylabel="Burn area (fraction/year)",
+ xlabel="Time",
)
- x = data.groupby('time.month').mean()['month'].values
- y = data.groupby('time.month').mean().mean(['x', 'y']).values
- yhat = model.groupby('time.month').mean().mean(['x', 'y']).values
+ x = data.groupby("time.month").mean()["month"].values
+ y = data.groupby("time.month").mean().mean(["x", "y"]).values
+ yhat = model.groupby("time.month").mean().mean(["x", "y"]).values
column &= line(
x=x,
@@ -214,23 +231,23 @@ def evaluation(
height=233,
strokeWidth=2,
opacity=1,
- color='darkgrey',
- ylabel='Burn area (fraction/month)',
- xlabel='Month',
+ color="darkgrey",
+ ylabel="Burn area (fraction/month)",
+ xlabel="Month",
) + line(
x=x,
y=yhat,
width=450,
height=233,
strokeWidth=2,
- color='#D77B40',
- ylabel='Burn area (fraction/month)',
- xlabel='Month',
+ color="#D77B40",
+ ylabel="Burn area (fraction/month)",
+ xlabel="Month",
)
- x = data['time'].values
- y = data.mean(['x', 'y']).values
- yhat = model.mean(['x', 'y']).values
+ x = data["time"].values
+ y = data.mean(["x", "y"]).values
+ yhat = model.mean(["x", "y"]).values
column &= line(
x=x,
@@ -239,18 +256,18 @@ def evaluation(
height=233,
strokeWidth=2,
opacity=1,
- color='darkgrey',
- ylabel='Burn area (fraction/month)',
- xlabel='Time',
+ color="darkgrey",
+ ylabel="Burn area (fraction/month)",
+ xlabel="Time",
) + line(
x=x,
y=yhat,
width=450,
height=233,
strokeWidth=2,
- color='#D77B40',
- ylabel='Burn area (fraction/month)',
- xlabel='Time',
+ color="#D77B40",
+ ylabel="Burn area (fraction/month)",
+ xlabel="Time",
)
chart = column
@@ -291,11 +308,11 @@ def evaluation(
def full_eval(
data,
model,
- data_var='vlf',
- model_var='prediction',
- projection='albersUsa',
+ data_var="vlf",
+ model_var="prediction",
+ projection="albersUsa",
clim=None,
- cmap='reds',
+ cmap="reds",
percentage=True,
comparison=True,
clabel=None,
@@ -307,21 +324,21 @@ def full_eval(
spatial_corr = np.corrcoef(a[inds], b[inds])[0, 1] ** 2
eval_metrics = {
- 'seasonal': np.corrcoef(
+ "seasonal": np.corrcoef(
data[data_var].groupby("time.month").mean().mean(["x", "y"]),
model[model_var].groupby("time.month").mean().mean(["x", "y"]),
)[0, 1]
** 2,
- 'annual': np.corrcoef(
+ "annual": np.corrcoef(
data[data_var].groupby("time.year").mean().mean(["x", "y"]),
model[model_var].groupby("time.year").mean().mean(["x", "y"]),
)[0, 1]
** 2,
- 'spatial': spatial_corr,
+ "spatial": spatial_corr,
}
for metric, performance in eval_metrics.items():
- print('performance at {} scale is: {}'.format(metric, performance))
+ print("performance at {} scale is: {}".format(metric, performance))
return eval_metrics, evaluation(
data,
@@ -341,7 +358,7 @@ def integrated_risk(p):
return (1 - binom.cdf(0, 100, p)) * 100
-def supersection(data, varname, store='az'):
+def supersection(data, varname, store="az"):
from palettable.colorbrewer.sequential import YlOrRd_9
cmap = YlOrRd_9.mpl_colormap
@@ -350,14 +367,14 @@ def supersection(data, varname, store='az'):
)
masks = rm.mask_3D_geopandas(regions, data)
- groupby = data.groupby('time.year').sum().mean('year')
+ groupby = data.groupby("time.year").sum().mean("year")
risks = np.asarray(
[
- groupby[varname].where(masks.sel(region=i)).mean(['x', 'y']).values.item()
- for i in masks['region']
+ groupby[varname].where(masks.sel(region=i)).mean(["x", "y"]).values.item()
+ for i in masks["region"]
]
)
- regions.to_crs('EPSG:5070').plot(
+ regions.to_crs("EPSG:5070").plot(
integrated_risk(risks),
figsize=[15, 8],
cmap=cmap,
@@ -367,42 +384,50 @@ def supersection(data, varname, store='az'):
vmax=25,
legend=True,
)
- plt.axis('off')
+ plt.axis("off")
def calc_decadal_averages(simulation):
decadal_averages = (
- simulation.sel(time=slice('2020', '2099')).coarsen(time=120).sum().load() / 10
+ simulation.sel(time=slice("2020", "2099")).coarsen(time=120).sum().load() / 10
)
return decadal_averages
def future_ts(decadal_averages, historical=None, domain=(0.0, 0.05)):
- df = decadal_averages.mean(dim=['x', 'y']).to_dataframe()
+ df = decadal_averages.mean(dim=["x", "y"]).to_dataframe()
- df['time'] = df.index
- df_toplot = df.melt('time', var_name='gcm_scenario', value_name='probability')
+ df["time"] = df.index
+ df_toplot = df.melt("time", var_name="gcm_scenario", value_name="probability")
if historical is not None:
- historical['time'] = historical.index
+ historical["time"] = historical.index
# the historical_historical is a hack to make the gcm/scenario splitting below not fail
- historical_df = historical.rename(columns={'historical': 'historical_historical'})
+ historical_df = historical.rename(
+ columns={"historical": "historical_historical"}
+ )
df_toplot = df_toplot.append(
- historical_df.melt('time', var_name='gcm_scenario', value_name='probability'),
+ historical_df.melt(
+ "time", var_name="gcm_scenario", value_name="probability"
+ ),
ignore_index=True,
)
- df_toplot['gcm'] = df_toplot.apply(lambda row: row.gcm_scenario.split('_')[0], axis=1)
- df_toplot['scenario'] = df_toplot.apply(lambda row: row.gcm_scenario.split('_')[1], axis=1)
- scenarios = ['historical', 'ssp245', 'ssp370', 'ssp585']
- colors_ = ['black', '#7eb36a', '#ea9755', '#f07071']
+ df_toplot["gcm"] = df_toplot.apply(
+ lambda row: row.gcm_scenario.split("_")[0], axis=1
+ )
+ df_toplot["scenario"] = df_toplot.apply(
+ lambda row: row.gcm_scenario.split("_")[1], axis=1
+ )
+ scenarios = ["historical", "ssp245", "ssp370", "ssp585"]
+ colors_ = ["black", "#7eb36a", "#ea9755", "#f07071"]
base = alt.Chart(df_toplot).properties(width=550)
line = base.mark_line().encode(
- alt.Y('probability:Q', scale=alt.Scale(domain=domain)),
- x='time',
- color=alt.Color('scenario', scale=alt.Scale(domain=scenarios, range=colors_)),
- strokeDash='gcm',
+ alt.Y("probability:Q", scale=alt.Scale(domain=domain)),
+ x="time",
+ color=alt.Color("scenario", scale=alt.Scale(domain=scenarios, range=colors_)),
+ strokeDash="gcm",
)
return line
diff --git a/carbonplan_forest_risks/plot/line.py b/carbonplan_forest_risks/plot/line.py
index 816f782..43edaa5 100644
--- a/carbonplan_forest_risks/plot/line.py
+++ b/carbonplan_forest_risks/plot/line.py
@@ -22,20 +22,20 @@ def line(
plot two variables optionally colored by some feature
"""
if data is None:
- if hasattr(x, 'name') and xlabel is None:
+ if hasattr(x, "name") and xlabel is None:
xlabel = x.name
- if hasattr(y, 'name') and ylabel is None:
+ if hasattr(y, "name") and ylabel is None:
ylabel = y.name
- df = pd.DataFrame({'x': x, 'y': y})
- _x = 'x'
- _y = 'y'
+ df = pd.DataFrame({"x": x, "y": y})
+ _x = "x"
+ _y = "y"
if color is not None:
- df['color'] = color
- _color = 'color'
+ df["color"] = color
+ _color = "color"
else:
- if hasattr(data[x], 'name') and xlabel is None:
+ if hasattr(data[x], "name") and xlabel is None:
xlabel = data[x].name
- if hasattr(data[y], 'name') and ylabel is None:
+ if hasattr(data[y], "name") and ylabel is None:
ylabel = data[y].name
df = data
_x = x
@@ -43,10 +43,10 @@ def line(
_color = color
if xlabel is None:
- xlabel = 'x'
+ xlabel = "x"
if ylabel is None:
- ylabel = 'y'
+ ylabel = "y"
xaxis = alt.Axis(title=xlabel)
yaxis = alt.Axis(title=ylabel)
@@ -65,16 +65,18 @@ def y_scaled(y):
def color_scaled(color):
if clim is None and cmap is None:
- return alt.Color(color, scale=alt.Scale(scheme='viridis'))
+ return alt.Color(color, scale=alt.Scale(scheme="viridis"))
elif clim is None and cmap is not None:
return alt.Color(color, scale=alt.Scale(scheme=cmap))
elif clim is not None and cmap is None:
return alt.Color(color, scale=alt.Scale(domain=clim))
elif clim is not None and cmap is not None:
- return alt.Color(color, scale=alt.Scale(domain=clim, scheme=cmap, clamp=True))
+ return alt.Color(
+ color, scale=alt.Scale(domain=clim, scheme=cmap, clamp=True)
+ )
if color is None:
- color = '#EA9755'
+ color = "#EA9755"
if type(color) is str:
line = (
diff --git a/carbonplan_forest_risks/plot/paper.py b/carbonplan_forest_risks/plot/paper.py
index e372430..ccb1eeb 100644
--- a/carbonplan_forest_risks/plot/paper.py
+++ b/carbonplan_forest_risks/plot/paper.py
@@ -6,25 +6,25 @@
from . import cartopy_borders, cartopy_proj_albers
-def map_pretty(ax, title=''):
+def map_pretty(ax, title=""):
state_borders, us_border = cartopy_borders()
ax.add_geometries(
state_borders,
- facecolor='none',
- edgecolor='k',
+ facecolor="none",
+ edgecolor="k",
crs=cartopy_proj_albers(),
linewidth=0.3,
zorder=0,
)
ax.add_geometries(
us_border,
- facecolor='none',
- edgecolor='k',
+ facecolor="none",
+ edgecolor="k",
crs=cartopy_proj_albers(),
linewidth=0.3,
zorder=0,
)
- ax.axis('off')
+ ax.axis("off")
ax.set_extent([-125, -70, 20, 50])
ax.text(0.77, 0.96, title, transform=ax.transAxes)
@@ -39,8 +39,8 @@ def add_colorbar(
width=0.018,
vmin=None,
vmax=None,
- cbar_label='',
- cmap='viridis',
+ cbar_label="",
+ cmap="viridis",
):
cax = fig.add_axes([x_location, y_location, width, height])
cax.text(
@@ -48,32 +48,32 @@ def add_colorbar(
-0.08,
vmin,
transform=cax.transAxes,
- horizontalalignment='center',
- verticalalignment='center',
+ horizontalalignment="center",
+ verticalalignment="center",
)
cax.text(
0.5,
1.08,
vmax,
transform=cax.transAxes,
- horizontalalignment='center',
- verticalalignment='center',
+ horizontalalignment="center",
+ verticalalignment="center",
)
cax.text(
1.8,
0.5,
cbar_label,
transform=cax.transAxes,
- verticalalignment='center',
- multialignment='center',
+ verticalalignment="center",
+ multialignment="center",
rotation=-90,
)
if to_plot is not None:
- cbar = fig.colorbar(to_plot, cax=cax, orientation='vertical')
+ cbar = fig.colorbar(to_plot, cax=cax, orientation="vertical")
else:
norm = mpl.colors.Normalize(vmin=vmin, vmax=vmax)
cbar = fig.colorbar(
- mpl.cm.ScalarMappable(norm=norm, cmap=cmap), cax=cax, orientation='vertical'
+ mpl.cm.ScalarMappable(norm=norm, cmap=cmap), cax=cax, orientation="vertical"
)
cbar.outline.set_visible(False)
cbar.set_ticks([])
@@ -119,10 +119,12 @@ def multipanel_ts(results_dict, region_bboxes, fig_path):
ax.add_patch(
mpatches.Rectangle(
- xy=[region_bboxes[region]['x'].start, region_bboxes[region]['y'].start],
- width=region_bboxes[region]['x'].stop - region_bboxes[region]['x'].start,
- height=region_bboxes[region]['y'].stop - region_bboxes[region]['y'].start,
- facecolor='grey',
+ xy=[region_bboxes[region]["x"].start, region_bboxes[region]["y"].start],
+ width=region_bboxes[region]["x"].stop
+ - region_bboxes[region]["x"].start,
+ height=region_bboxes[region]["y"].stop
+ - region_bboxes[region]["y"].start,
+ facecolor="grey",
alpha=0.5,
)
)
@@ -135,9 +137,11 @@ def multipanel_ts(results_dict, region_bboxes, fig_path):
results_dict[impact][region]["historical"].plot(ax=ax, color="k", zorder=60)
for scenario in ["ssp245", "ssp370", "ssp585"]:
impact_axes.append(ax)
- plot_future_ts_traces(ax, results_dict[impact][region]["future"], scenario, gcms)
+ plot_future_ts_traces(
+ ax, results_dict[impact][region]["future"], scenario, gcms
+ )
ts_pretty(ax, impact, ylims[impact])
- if impact != 'insects':
+ if impact != "insects":
ax.set_xticks([])
if len(impact_axes) > 3:
ax.set_yticks([])
@@ -163,8 +167,10 @@ def plot_future_ts_traces(ax, ds, scenario, gcms):
ssp_rename = {"ssp245": "SSP2-4.5", "ssp370": "SSP3-7.0", "ssp585": "SSP5-8.5"}
- for (gcm, location) in gcms:
- ds.sel(gcm=gcm, scenario=scenario).plot(ax=ax, color=scenario_colors_light[scenario])
+ for gcm, location in gcms:
+ ds.sel(gcm=gcm, scenario=scenario).plot(
+ ax=ax, color=scenario_colors_light[scenario]
+ )
ds.sel(scenario=scenario).mean(dim="gcm").plot(
ax=ax, color=scenario_colors[scenario], label=ssp_rename[scenario], zorder=30
diff --git a/carbonplan_forest_risks/plot/xy.py b/carbonplan_forest_risks/plot/xy.py
index 7dcf2ed..5cf61d4 100644
--- a/carbonplan_forest_risks/plot/xy.py
+++ b/carbonplan_forest_risks/plot/xy.py
@@ -22,24 +22,24 @@ def xy(
plot two variables optionally colored by some feature
"""
if data is None:
- if hasattr(x, 'name') and xlabel is None:
+ if hasattr(x, "name") and xlabel is None:
xlabel = x.name
- if hasattr(y, 'name') and ylabel is None:
+ if hasattr(y, "name") and ylabel is None:
ylabel = y.name
- if color is not None and hasattr(color, 'name') and clabel is None:
+ if color is not None and hasattr(color, "name") and clabel is None:
clabel = color.name
- df = pd.DataFrame({'x': x, 'y': y})
- _x = 'x'
- _y = 'y'
+ df = pd.DataFrame({"x": x, "y": y})
+ _x = "x"
+ _y = "y"
if color is not None:
- df['color'] = color
- _color = 'color'
+ df["color"] = color
+ _color = "color"
else:
- if hasattr(data[x], 'name') and xlabel is None:
+ if hasattr(data[x], "name") and xlabel is None:
xlabel = data[x].name
- if hasattr(data[y], 'name') and ylabel is None:
+ if hasattr(data[y], "name") and ylabel is None:
ylabel = data[y].name
- if color is not None and hasattr(data[color], 'name') and clabel is None:
+ if color is not None and hasattr(data[color], "name") and clabel is None:
clabel = color.name
df = data
_x = x
@@ -47,13 +47,13 @@ def xy(
_color = color
if xlabel is None:
- xlabel = 'x'
+ xlabel = "x"
if ylabel is None:
- ylabel = 'y'
+ ylabel = "y"
if clabel is None:
- clabel = 'color'
+ clabel = "color"
xaxis = alt.Axis(title=xlabel)
yaxis = alt.Axis(title=ylabel)
@@ -73,20 +73,22 @@ def y_scaled(y):
def color_scaled(color):
if clim is None and cmap is None:
- return alt.Color(color, legend=clegend, scale=alt.Scale(scheme='viridis'))
+ return alt.Color(color, legend=clegend, scale=alt.Scale(scheme="viridis"))
elif clim is None and cmap is not None:
return alt.Color(color, legend=clegend, scale=alt.Scale(scheme=cmap))
elif clim is not None and cmap is None:
return alt.Color(color, legend=clegend, scale=alt.Scale(domain=clim))
elif clim is not None and cmap is not None:
return alt.Color(
- color, legend=clegend, scale=alt.Scale(domain=clim, scheme=cmap, clamp=True)
+ color,
+ legend=clegend,
+ scale=alt.Scale(domain=clim, scheme=cmap, clamp=True),
)
if color is None:
points = (
alt.Chart(df)
- .mark_circle(size=42, color='black', fill='black', opacity=opacity)
+ .mark_circle(size=42, color="black", fill="black", opacity=opacity)
.encode(
x=x_scaled(_x),
y=y_scaled(_y),
diff --git a/carbonplan_forest_risks/prepare.py b/carbonplan_forest_risks/prepare.py
index dbee1c0..c4173f4 100644
--- a/carbonplan_forest_risks/prepare.py
+++ b/carbonplan_forest_risks/prepare.py
@@ -10,7 +10,7 @@ def annualize(
signal,
climate_prepend=None,
rolling_period=None,
- analysis_tlim=slice('1984', '2018'),
+ analysis_tlim=slice("1984", "2018"),
):
"""
function to aggregate your full spatial
@@ -22,24 +22,24 @@ def annualize(
else:
da = ds[variable]
- if signal == 'global':
- da = da.mean(dim=['x', 'y'])
+ if signal == "global":
+ da = da.mean(dim=["x", "y"])
if climate_prepend is not None:
aggregated = da.rolling(
- dim={'time': rolling_period}, min_periods=rolling_period, center=False
+ dim={"time": rolling_period}, min_periods=rolling_period, center=False
)
else:
- aggregated = da.groupby('time.year')
+ aggregated = da.groupby("time.year")
- if variable == 'tmean':
+ if variable == "tmean":
aggregated = aggregated.max()
- elif variable == 'ppt':
+ elif variable == "ppt":
aggregated = aggregated.max()
- elif variable == 'cwd':
+ elif variable == "cwd":
aggregated = aggregated.max()
else:
- print('{} not implemented'.format(variable))
+ print("{} not implemented".format(variable))
# drop your first year if you were rolling
if climate_prepend is not None:
@@ -47,19 +47,19 @@ def annualize(
return aggregated
-def package_annualized(da, shape, signal='global', climate_prepend=None):
+def package_annualized(da, shape, signal="global", climate_prepend=None):
"""
to get them into the right shapes for the model we need to do some ugly
array reshaping
"""
- if signal == 'global':
+ if signal == "global":
if climate_prepend is not None:
tile_shape = [shape[1], shape[2]]
else:
tile_shape = [12, shape[1], shape[2]]
arr = np.asarray([np.tile(a, tile_shape) for a in da]).flatten()
- if signal == 'local':
+ if signal == "local":
if climate_prepend is not None:
arr = da.values.flatten()
else:
@@ -78,7 +78,7 @@ def fire(
add_global_climate_trends=False,
add_local_climate_trends=False,
climate_prepend=None,
- analysis_tlim=('1970', '2099'),
+ analysis_tlim=("1970", "2099"),
):
"""
Prepare x and y and group variables for fire model fitting
@@ -91,7 +91,7 @@ def fire(
# after you've done your climate packaging you can tack on the earlier year for aggregations
with warnings.catch_warnings():
- warnings.simplefilter('ignore', category=RuntimeWarning)
+ warnings.simplefilter("ignore", category=RuntimeWarning)
if add_global_climate_trends is not None:
arr_list = []
for var, attrs in add_global_climate_trends.items():
@@ -100,14 +100,14 @@ def fire(
annualize(
climate,
var,
- 'global',
- climate_prepend=attrs['climate_prepend'],
- rolling_period=attrs['rolling_period'],
+ "global",
+ climate_prepend=attrs["climate_prepend"],
+ rolling_period=attrs["rolling_period"],
analysis_tlim=analysis_tlim,
),
shape,
- 'global',
- climate_prepend=attrs['climate_prepend'],
+ "global",
+ climate_prepend=attrs["climate_prepend"],
)
)
f2 = np.asarray(arr_list).T
@@ -119,14 +119,14 @@ def fire(
annualize(
climate,
var,
- 'local',
- climate_prepend=attrs['climate_prepend'],
- rolling_period=attrs['rolling_period'],
+ "local",
+ climate_prepend=attrs["climate_prepend"],
+ rolling_period=attrs["rolling_period"],
analysis_tlim=analysis_tlim,
),
shape,
- 'local',
- climate_prepend=attrs['climate_prepend'],
+ "local",
+ climate_prepend=attrs["climate_prepend"],
)
)
@@ -141,7 +141,7 @@ def fire(
return x
else:
- y = mtbs['monthly'].values.flatten()
+ y = mtbs["monthly"].values.flatten()
return x, y
@@ -153,34 +153,40 @@ def drought(df, eval_only=False, duration=10):
df = df.copy()
if eval_only:
- fit_vars = ['ppt_sum_min', 'tavg_mean_max', 'age', 'age_squared', 'duration']
- df['age_squared'] = df['age'] ** 2
- df['duration'] = duration
+ fit_vars = ["ppt_sum_min", "tavg_mean_max", "age", "age_squared", "duration"]
+ df["age_squared"] = df["age"] ** 2
+ df["duration"] = duration
x = df[fit_vars]
x = x.values
- meta = df[['lat', 'lon', 'type_code']].reset_index(drop=True)
+ meta = df[["lat", "lon", "type_code"]].reset_index(drop=True)
return x, meta
else:
- fit_vars = ['ppt_sum_min_1', 'tavg_mean_max_1', 'age', 'age_squared', 'duration']
+ fit_vars = [
+ "ppt_sum_min_1",
+ "tavg_mean_max_1",
+ "age",
+ "age_squared",
+ "duration",
+ ]
# 'pdsi_mean_min_1','cwd_sum_max_1',
# 'pet_mean_max_1', 'vpd_mean_max_1',
inds = (
- (df['condprop'] > 0.3)
- & (not (df['disturb_human_1'] is True))
- & (not (df['disturb_fire_1'] is True))
- & (not (df['treatment_cutting_1'] is True))
+ (df["condprop"] > 0.3)
+ & (df["disturb_human_1"] is not True)
+ & (df["disturb_fire_1"] is not True)
+ & (df["treatment_cutting_1"] is not True)
)
df = df[inds].copy()
- df['age_squared'] = df['age'] ** 2
- df['duration'] = df['year_1'] - df['year_0']
- y = df['mort_1'] / df['balive_0']
+ df["age_squared"] = df["age"] ** 2
+ df["duration"] = df["year_1"] - df["year_0"]
+ y = df["mort_1"] / df["balive_0"]
x = df[fit_vars]
inds = (np.isnan(x).sum(axis=1) == 0) & (~np.isnan(y)) & (y < 1)
- meta = df[inds][['lat', 'lon', 'type_code']].reset_index(drop=True)
+ meta = df[inds][["lat", "lon", "type_code"]].reset_index(drop=True)
x = x[inds].values
y = y[inds].values
@@ -196,40 +202,40 @@ def insects(df, eval_only=False, duration=10):
df = df.copy()
if eval_only:
- fit_vars = ['ppt_sum_min', 'tavg_mean_max', 'age', 'age_squared', 'duration']
- df['age_squared'] = df['age'] ** 2
- df['duration'] = duration
+ fit_vars = ["ppt_sum_min", "tavg_mean_max", "age", "age_squared", "duration"]
+ df["age_squared"] = df["age"] ** 2
+ df["duration"] = duration
x = df[fit_vars]
x = x.values
- meta = df[['lat', 'lon', 'type_code']].reset_index(drop=True)
+ meta = df[["lat", "lon", "type_code"]].reset_index(drop=True)
return x, meta
else:
fit_vars = [
- 'ppt_sum_min_1',
- 'tavg_mean_max_1',
- 'age',
- 'age_squared',
- 'duration',
+ "ppt_sum_min_1",
+ "tavg_mean_max_1",
+ "age",
+ "age_squared",
+ "duration",
]
inds = (
- (df['condprop'] > 0.3)
- & (not (df['disturb_human_1'] is True))
- & (not (df['disturb_fire_1'] is True))
- & (not (df['treatment_cutting_1'] is True))
+ (df["condprop"] > 0.3)
+ & (df["disturb_human_1"] is not True)
+ & (df["disturb_fire_1"] is not True)
+ & (df["treatment_cutting_1"] is not True)
)
df = df[inds].copy()
- df['age_squared'] = df['age'] ** 2
- df['duration'] = df['year_1'] - df['year_0']
- y = df['fraction_insect_1'] * (df['mort_1'] / df['balive_0'])
+ df["age_squared"] = df["age"] ** 2
+ df["duration"] = df["year_1"] - df["year_0"]
+ y = df["fraction_insect_1"] * (df["mort_1"] / df["balive_0"])
x = df[fit_vars]
inds = (np.isnan(x).sum(axis=1) == 0) & (~np.isnan(y)) & (y < 1)
- meta = df[inds][['lat', 'lon', 'type_code']].reset_index(drop=True)
+ meta = df[inds][["lat", "lon", "type_code"]].reset_index(drop=True)
x = x[inds].values
y = y[inds].values
diff --git a/carbonplan_forest_risks/preprocess/fia.py b/carbonplan_forest_risks/preprocess/fia.py
index 22eaad3..347682e 100644
--- a/carbonplan_forest_risks/preprocess/fia.py
+++ b/carbonplan_forest_risks/preprocess/fia.py
@@ -8,22 +8,22 @@
def fia(states, save=True):
if type(states) is str:
- if states == 'all':
- df = pd.read_csv('gs://carbonplan-data/raw/fia/REF_RESEARCH_STATION.csv')
- return [preprocess_state(state, save=save) for state in df['STATE_ABBR']]
+ if states == "all":
+ df = pd.read_csv("gs://carbonplan-data/raw/fia/REF_RESEARCH_STATION.csv")
+ return [preprocess_state(state, save=save) for state in df["STATE_ABBR"]]
else:
return preprocess_state(states, save=save)
else:
return [preprocess_state(state, save=save) for state in states]
-def generate_uids(data, prev_cn_var='PREV_PLT_CN'):
+def generate_uids(data, prev_cn_var="PREV_PLT_CN"):
"""
Generate dict mapping ever CN to a unique group, allows tracking single plot/tree through time
Can change `prev_cn_var` to apply to tree (etc)
"""
g = nx.Graph()
- for _, row in data[['CN', prev_cn_var]].iterrows():
+ for _, row in data[["CN", prev_cn_var]].iterrows():
if ~np.isnan(row[prev_cn_var]): # has ancestor, add nodes + edge
g.add_edge(row.CN, row[prev_cn_var])
else:
@@ -44,21 +44,23 @@ def get_mort_removal_df(tree_df):
mort_df = mort_df.reset_index(drop=True)
# 10 is minimum code - 0s are legacy and we assume anything < 10 is legacy as well.
- mort_df = mort_df[(mort_df['AGENTCD'] >= 10) & (mort_df['AGENTCD'] < 90)]
+ mort_df = mort_df[(mort_df["AGENTCD"] >= 10) & (mort_df["AGENTCD"] < 90)]
# fill in missing TPA_UNADJ with TPAGROW_UNADJ - this is totally off list but JS approved
- mort_df.loc[np.isnan(mort_df['TPA_UNADJ']), 'TPA_UNADJ'] = mort_df['TPAGROW_UNADJ']
- mort_df['unadj_basal_area'] = math.pi * (mort_df['DIA'] / (2 * 12)) ** 2 * mort_df['TPA_UNADJ']
+ mort_df.loc[np.isnan(mort_df["TPA_UNADJ"]), "TPA_UNADJ"] = mort_df["TPAGROW_UNADJ"]
+ mort_df["unadj_basal_area"] = (
+ math.pi * (mort_df["DIA"] / (2 * 12)) ** 2 * mort_df["TPA_UNADJ"]
+ )
# drop trees where TPA_UNADJ == 0 -- we have no way of using these data
# This is rare, but I interpret this to mean that tree cannot be reliably scaled to acre-1 measurement -- for whatever reason
- mort_df = mort_df[mort_df['TPA_UNADJ'] > 0]
+ mort_df = mort_df[mort_df["TPA_UNADJ"] > 0]
# smaller-ish trees with agent code somtimes lack a DIA, but have a DIACALC -- back-fill. JS approved!
- mort_df.loc[np.isnan(mort_df['DIA']), 'unadj_basal_area'] = (
+ mort_df.loc[np.isnan(mort_df["DIA"]), "unadj_basal_area"] = (
math.pi
- * (mort_df[np.isnan(mort_df['DIA'])]['DIACALC'] / (2 * 12)) ** 2
- * mort_df[np.isnan(mort_df['DIA'])]['TPA_UNADJ']
+ * (mort_df[np.isnan(mort_df["DIA"])]["DIACALC"] / (2 * 12)) ** 2
+ * mort_df[np.isnan(mort_df["DIA"])]["TPA_UNADJ"]
)
# TODO: There is another pot of trees we can access if we impute old diameters
@@ -69,81 +71,96 @@ def get_mort_removal_df(tree_df):
# These would allow recovery a handful of conditions, primarily in region 8 (i think)
# do not return records without unadj_basal_area -- see above TODO.
- return mort_df[mort_df['unadj_basal_area'] > 0]
+ return mort_df[mort_df["unadj_basal_area"] > 0]
def preprocess_state(state_abbr, save=True):
state_abbr = state_abbr.lower()
tree_df = pd.read_parquet(
- f'gs://carbonplan-data/raw/fia-states/tree_{state_abbr}.parquet',
+ f"gs://carbonplan-data/raw/fia-states/tree_{state_abbr}.parquet",
columns=[
- 'CN',
- 'PLT_CN',
- 'DIA',
- 'DIACALC',
- 'HT',
- 'ACTUALHT',
- 'STATUSCD',
- 'CONDID',
- 'TPA_UNADJ',
- 'AGENTCD',
- 'TPAGROW_UNADJ',
- 'TPAMORT_UNADJ',
- 'TPAREMV_UNADJ',
- 'DIACHECK',
- 'CARBON_AG',
- 'CARBON_BG',
+ "CN",
+ "PLT_CN",
+ "DIA",
+ "DIACALC",
+ "HT",
+ "ACTUALHT",
+ "STATUSCD",
+ "CONDID",
+ "TPA_UNADJ",
+ "AGENTCD",
+ "TPAGROW_UNADJ",
+ "TPAMORT_UNADJ",
+ "TPAREMV_UNADJ",
+ "DIACHECK",
+ "CARBON_AG",
+ "CARBON_BG",
],
)
# calculate tree-level statistics that will sum later.
- tree_df['unadj_basal_area'] = math.pi * (tree_df['DIA'] / (2 * 12)) ** 2 * tree_df['TPA_UNADJ']
+ tree_df["unadj_basal_area"] = (
+ math.pi * (tree_df["DIA"] / (2 * 12)) ** 2 * tree_df["TPA_UNADJ"]
+ )
# 892.179 converts lbs/acre to t/ha
- tree_df['unadj_ag_biomass'] = (
- tree_df['CARBON_AG'] * tree_df['TPA_UNADJ'] * 2 / 892.1791216197013
+ tree_df["unadj_ag_biomass"] = (
+ tree_df["CARBON_AG"] * tree_df["TPA_UNADJ"] * 2 / 892.1791216197013
)
- tree_df['unadj_bg_biomass'] = (
- tree_df['CARBON_BG'] * tree_df['TPA_UNADJ'] * 2 / 892.1791216197013
+ tree_df["unadj_bg_biomass"] = (
+ tree_df["CARBON_BG"] * tree_df["TPA_UNADJ"] * 2 / 892.1791216197013
)
- plot_df = pd.read_parquet(f'gs://carbonplan-data/raw/fia-states/plot_{state_abbr}.parquet')
- cond_df = pd.read_parquet(f'gs://carbonplan-data/raw/fia-states/cond_{state_abbr}.parquet')
+ plot_df = pd.read_parquet(
+ f"gs://carbonplan-data/raw/fia-states/plot_{state_abbr}.parquet"
+ )
+ cond_df = pd.read_parquet(
+ f"gs://carbonplan-data/raw/fia-states/cond_{state_abbr}.parquet"
+ )
cond_vars = [
- 'STDAGE',
- 'BALIVE',
- 'SICOND',
- 'SISP',
- 'OWNCD',
- 'SITECLCD',
- 'PHYSCLCD',
- 'ALSTK',
- 'ALSTKCD',
- 'GSSTK',
- 'GSSTKCD',
- 'FORTYPCD',
- 'FLDTYPCD',
- 'DSTRBCD1',
- 'DSTRBCD2',
- 'DSTRBCD3',
- 'TRTCD1',
- 'TRTCD2',
- 'TRTCD3',
- 'CONDPROP_UNADJ',
- 'COND_STATUS_CD',
- 'COND_NONSAMPLE_REASN_CD',
- 'SLOPE',
- 'ASPECT',
- 'INVYR',
- 'CN',
+ "STDAGE",
+ "BALIVE",
+ "SICOND",
+ "SISP",
+ "OWNCD",
+ "SITECLCD",
+ "PHYSCLCD",
+ "ALSTK",
+ "ALSTKCD",
+ "GSSTK",
+ "GSSTKCD",
+ "FORTYPCD",
+ "FLDTYPCD",
+ "DSTRBCD1",
+ "DSTRBCD2",
+ "DSTRBCD3",
+ "TRTCD1",
+ "TRTCD2",
+ "TRTCD3",
+ "CONDPROP_UNADJ",
+ "COND_STATUS_CD",
+ "COND_NONSAMPLE_REASN_CD",
+ "SLOPE",
+ "ASPECT",
+ "INVYR",
+ "CN",
]
- cond_agg = cond_df.groupby(['PLT_CN', 'CONDID'])[cond_vars].max()
+ cond_agg = cond_df.groupby(["PLT_CN", "CONDID"])[cond_vars].max()
cond_agg = cond_agg.join(
- plot_df[plot_df['PLOT_STATUS_CD'] != 2].set_index('CN')[
- ['LAT', 'LON', 'ELEV', 'KINDCD', 'MEASYEAR', 'REMPER', 'RDDISTCD', 'ECOSUBCD']
+ plot_df[plot_df["PLOT_STATUS_CD"] != 2].set_index("CN")[
+ [
+ "LAT",
+ "LON",
+ "ELEV",
+ "KINDCD",
+ "MEASYEAR",
+ "REMPER",
+ "RDDISTCD",
+ "ECOSUBCD",
+ ]
],
- on='PLT_CN',
+ on="PLT_CN",
)
def dstrbcd_to_disturb_class(dstrbcd):
@@ -151,29 +168,32 @@ def dstrbcd_to_disturb_class(dstrbcd):
Transforms dstrbcd (int 0-90) to bulk disturbance class (bugs, fires, weather, etc)
"""
disturb_class_map = {
- 10: 'insect',
- 12: 'insect',
- 20: 'insect',
- 22: 'insect',
- 30: 'fire',
- 32: 'fire',
- 50: 'weather',
- 51: 'weather',
- 52: 'weather',
- 53: 'weather',
- 54: 'drought',
- 80: 'human',
+ 10: "insect",
+ 12: "insect",
+ 20: "insect",
+ 22: "insect",
+ 30: "fire",
+ 32: "fire",
+ 50: "weather",
+ 51: "weather",
+ 52: "weather",
+ 53: "weather",
+ 54: "drought",
+ 80: "human",
}
return (dstrbcd).map(disturb_class_map)
dstrb_hot_encodings = [
- pd.get_dummies(dstrbcd_to_disturb_class(cond_agg[k]), prefix='disturb')
- for k in ['DSTRBCD1', 'DSTRBCD2', 'DSTRBCD3']
+ pd.get_dummies(dstrbcd_to_disturb_class(cond_agg[k]), prefix="disturb")
+ for k in ["DSTRBCD1", "DSTRBCD2", "DSTRBCD3"]
]
# sum all disturb codes, then cast to bool so we know if 0/1 disturbance type occurred
# https://stackoverflow.com/questions/13078751/combine-duplicated-columns-within-a-dataframe
disturb_flags = (
- (pd.concat(dstrb_hot_encodings, axis=1)).groupby(level=0, axis=1).sum().astype(bool)
+ (pd.concat(dstrb_hot_encodings, axis=1))
+ .groupby(level=0, axis=1)
+ .sum()
+ .astype(bool)
)
def trtcd_to_treatment_class(trtcd):
@@ -181,51 +201,58 @@ def trtcd_to_treatment_class(trtcd):
Transforms trtcd (int 00-30) to bulk treatment class (bugs, fires, weather, etc)
"""
treatment_class_map = {
- 10: 'cutting',
- 20: 'preparation',
- 30: 'regeneration',
- 40: 'regeneration',
- 50: 'other',
+ 10: "cutting",
+ 20: "preparation",
+ 30: "regeneration",
+ 40: "regeneration",
+ 50: "other",
}
return (trtcd).map(treatment_class_map)
trt_hot_encodings = [
- pd.get_dummies(trtcd_to_treatment_class(cond_agg[k]), prefix='treatment')
- for k in ['TRTCD1', 'TRTCD2', 'TRTCD3']
+ pd.get_dummies(trtcd_to_treatment_class(cond_agg[k]), prefix="treatment")
+ for k in ["TRTCD1", "TRTCD2", "TRTCD3"]
]
# sum all treatment codes, then cast to bool so we know if 0/1 treatment type occurred
# https://stackoverflow.com/questions/13078751/combine-duplicated-columns-within-a-dataframe
treatment_flags = (
- (pd.concat(trt_hot_encodings, axis=1)).groupby(level=0, axis=1).sum().astype(bool)
+ (pd.concat(trt_hot_encodings, axis=1))
+ .groupby(level=0, axis=1)
+ .sum()
+ .astype(bool)
)
# per-tree variables that need to sum per condition
- alive_sum_vars = ['unadj_ag_biomass', 'unadj_bg_biomass', 'unadj_basal_area']
+ alive_sum_vars = ["unadj_ag_biomass", "unadj_bg_biomass", "unadj_basal_area"]
condition_alive_sums = (
- tree_df.loc[tree_df['STATUSCD'] == 1].groupby(['PLT_CN', 'CONDID'])[alive_sum_vars].sum()
+ tree_df.loc[tree_df["STATUSCD"] == 1]
+ .groupby(["PLT_CN", "CONDID"])[alive_sum_vars]
+ .sum()
)
- alive_mean_vars = ['HT', 'ACTUALHT']
+ alive_mean_vars = ["HT", "ACTUALHT"]
condition_alive_means = (
- tree_df.loc[tree_df['STATUSCD'] == 1].groupby(['PLT_CN', 'CONDID'])[alive_mean_vars].mean()
+ tree_df.loc[tree_df["STATUSCD"] == 1]
+ .groupby(["PLT_CN", "CONDID"])[alive_mean_vars]
+ .mean()
)
mort_removal_trees = get_mort_removal_df(tree_df)
# define queries -- we then subset mort_removal_trees and aggregate separately to prevent zeros from sneaking in
mort_removal_queries = {
- 'unadj_full_mort': (mort_removal_trees['AGENTCD'] < 80),
- 'unadj_pop_mort': (mort_removal_trees['TPAMORT_UNADJ'] > 0)
- & (mort_removal_trees['AGENTCD'] >= 10)
- & (mort_removal_trees['AGENTCD'] < 80),
- 'unadj_removal': (mort_removal_trees['AGENTCD'] == 80)
+ "unadj_full_mort": (mort_removal_trees["AGENTCD"] < 80),
+ "unadj_pop_mort": (mort_removal_trees["TPAMORT_UNADJ"] > 0)
+ & (mort_removal_trees["AGENTCD"] >= 10)
+ & (mort_removal_trees["AGENTCD"] < 80),
+ "unadj_removal": (mort_removal_trees["AGENTCD"] == 80),
# & (mort_removal_trees['TPAREMV_UNADJ'] > 0),
}
condition_mort_removal = pd.concat(
[
mort_removal_trees[idx]
- .groupby(['PLT_CN', 'CONDID'])['unadj_basal_area']
+ .groupby(["PLT_CN", "CONDID"])["unadj_basal_area"]
.sum()
.rename(k)
for k, idx in mort_removal_queries.items()
@@ -234,23 +261,23 @@ def trtcd_to_treatment_class(trtcd):
)
# rerun aggregation with AGENTCD to get fraction mortality on pop estimates
- pop_mort_trees = mort_removal_trees[mort_removal_queries['unadj_pop_mort']]
+ pop_mort_trees = mort_removal_trees[mort_removal_queries["unadj_pop_mort"]]
pop_mort_by_agent = (
- pop_mort_trees.groupby(['PLT_CN', 'CONDID', pop_mort_trees['AGENTCD'] // 10])[
- 'unadj_basal_area'
+ pop_mort_trees.groupby(["PLT_CN", "CONDID", pop_mort_trees["AGENTCD"] // 10])[
+ "unadj_basal_area"
]
.sum()
.unstack(2) # agents to col
)
BULK_AGENT_MAP = {
- 1: 'frac_pop_mort_insect',
- 2: 'frac_pop_mort_disease',
- 3: 'frac_pop_mort_fire',
- 4: 'frac_pop_mort_animal',
- 5: 'frac_pop_mort_weather',
- 6: 'frac_pop_mort_vegetation',
- 7: 'frac_pop_mort_unknown',
+ 1: "frac_pop_mort_insect",
+ 2: "frac_pop_mort_disease",
+ 3: "frac_pop_mort_fire",
+ 4: "frac_pop_mort_animal",
+ 5: "frac_pop_mort_weather",
+ 6: "frac_pop_mort_vegetation",
+ 7: "frac_pop_mort_unknown",
}
# convert to fraction
@@ -271,25 +298,25 @@ def trtcd_to_treatment_class(trtcd):
full = full.join(fraction_pop_mort)
full = full.reset_index()
- full.loc[:, 'adj_full_mort'] = full.unadj_full_mort / full.CONDPROP_UNADJ
- full.loc[:, 'adj_pop_mort'] = full.unadj_pop_mort / full.CONDPROP_UNADJ
+ full.loc[:, "adj_full_mort"] = full.unadj_full_mort / full.CONDPROP_UNADJ
+ full.loc[:, "adj_pop_mort"] = full.unadj_pop_mort / full.CONDPROP_UNADJ
- full.loc[:, 'adj_removal'] = full.unadj_removal / full.CONDPROP_UNADJ
- full.loc[:, 'adj_balive'] = full.unadj_basal_area / full.CONDPROP_UNADJ
- full.loc[:, 'adj_bg_biomass'] = full.unadj_bg_biomass / full.CONDPROP_UNADJ
- full.loc[:, 'adj_ag_biomass'] = full.unadj_ag_biomass / full.CONDPROP_UNADJ
+ full.loc[:, "adj_removal"] = full.unadj_removal / full.CONDPROP_UNADJ
+ full.loc[:, "adj_balive"] = full.unadj_basal_area / full.CONDPROP_UNADJ
+ full.loc[:, "adj_bg_biomass"] = full.unadj_bg_biomass / full.CONDPROP_UNADJ
+ full.loc[:, "adj_ag_biomass"] = full.unadj_ag_biomass / full.CONDPROP_UNADJ
- full['adj_sapling_mort'] = (
- full['adj_full_mort'] - full['adj_pop_mort']
+ full["adj_sapling_mort"] = (
+ full["adj_full_mort"] - full["adj_pop_mort"]
) # diff out mort due to saplings
plt_uids = generate_uids(plot_df)
- full['plt_uid'] = full['PLT_CN'].map(plt_uids)
+ full["plt_uid"] = full["PLT_CN"].map(plt_uids)
if save:
full.to_parquet(
- f'gs://carbonplan-data/processed/fia-states/long/{state_abbr}.parquet',
- compression='gzip',
- engine='fastparquet',
+ f"gs://carbonplan-data/processed/fia-states/long/{state_abbr}.parquet",
+ compression="gzip",
+ engine="fastparquet",
)
return full
diff --git a/carbonplan_forest_risks/setup/loading.py b/carbonplan_forest_risks/setup/loading.py
index aadbf2b..1128242 100644
--- a/carbonplan_forest_risks/setup/loading.py
+++ b/carbonplan_forest_risks/setup/loading.py
@@ -5,12 +5,12 @@
def loading(store=None):
if store is None:
- raise ValueError('data store not specified')
- if store == 'gs':
- base = urlpath.URL('gs://')
- elif store == 'az':
- base = urlpath.URL('https://carbonplan.blob.core.windows.net')
- elif store == 'local':
- base = pathlib.Path(pathlib.Path.home() / 'workdir')
+ raise ValueError("data store not specified")
+ if store == "gs":
+ base = urlpath.URL("gs://")
+ elif store == "az":
+ base = urlpath.URL("https://carbonplan.blob.core.windows.net")
+ elif store == "local":
+ base = pathlib.Path(pathlib.Path.home() / "workdir")
return base
diff --git a/carbonplan_forest_risks/setup/plotting.py b/carbonplan_forest_risks/setup/plotting.py
index 1fe85da..1d3868c 100644
--- a/carbonplan_forest_risks/setup/plotting.py
+++ b/carbonplan_forest_risks/setup/plotting.py
@@ -2,9 +2,9 @@
def plotting(remote=False):
- alt.renderers.enable('default', embed_options={'actions': False})
+ alt.renderers.enable("default", embed_options={"actions": False})
if remote:
- alt.data_transformers.enable('data_server_proxied', urlpath='/user-redirect')
+ alt.data_transformers.enable("data_server_proxied", urlpath="/user-redirect")
else:
- alt.data_transformers.enable('data_server')
+ alt.data_transformers.enable("data_server")
alt.data_transformers.disable_max_rows()
diff --git a/carbonplan_forest_risks/utils.py b/carbonplan_forest_risks/utils.py
index 42d687d..7c0eb7c 100644
--- a/carbonplan_forest_risks/utils.py
+++ b/carbonplan_forest_risks/utils.py
@@ -69,7 +69,7 @@ def rowcol_to_latlon(row, col, res=250):
col = np.asarray(col) if type(col) is list else col
x, y = xy(Affine(*albers_conus_transform(res)), row, col)
p1 = Proj(CRS.from_wkt(albers_conus_crs()))
- p2 = Proj(proj='latlong', datum='WGS84')
+ p2 = Proj(proj="latlong", datum="WGS84")
lon, lat = transform(p1, p2, x, y)
return lat, lon
@@ -84,7 +84,7 @@ def latlon_to_rowcol(lat, lon, res=250):
def latlon_to_xy(lat, lon, base_crs=albers_conus_crs()):
p1 = Proj(base_crs)
- p2 = Proj(proj='latlong', datum='WGS84')
+ p2 = Proj(proj="latlong", datum="WGS84")
x, y = transform(p2, p1, np.asarray(lon), np.asarray(lat))
return x, y
@@ -124,14 +124,14 @@ def remove_nans(x, y=None, return_inds=False):
def weighted_mean(ds, *args, **kwargs):
weights = ds.time.dt.days_in_month
- return ds.weighted(weights).mean(dim='time')
+ return ds.weighted(weights).mean(dim="time")
def get_store(bucket, prefix, account_key=None):
- ''' helper function to create a zarr store'''
+ """helper function to create a zarr store"""
if account_key is None:
- account_key = os.environ.get('BLOB_ACCOUNT_KEY', None)
+ account_key = os.environ.get("BLOB_ACCOUNT_KEY", None)
store = zarr.storage.ABSStore(
bucket,
diff --git a/notebooks/biomass/biomass_model.ipynb b/notebooks/biomass/biomass_model.ipynb
index 04d5e61..42d62c9 100644
--- a/notebooks/biomass/biomass_model.ipynb
+++ b/notebooks/biomass/biomass_model.ipynb
@@ -1,258 +1,258 @@
{
- "cells": [
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "\n",
- "# FIA Biomass Model\n",
- "\n",
- "_by Jeremy Freeman (CarbonPlan), September 19, 2020_\n",
- "\n",
- "This notebook show examples of fitting predictive biomass growth curves from FIA\n",
- "data\n"
- ]
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "\n",
+ "# FIA Biomass Model\n",
+ "\n",
+ "_by Jeremy Freeman (CarbonPlan), September 19, 2020_\n",
+ "\n",
+ "This notebook show examples of fitting predictive biomass growth curves from FIA\n",
+ "data\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import numpy as np\n",
+ "import pandas as pd\n",
+ "from carbonplan_forest_risks import load, setup, plot, fit"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "setup.plotting(remote=True)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "First we load the data. To speed things up, we'll just load data from\n",
+ "California. We load the raw FIA data, as well as two climatic variables `tavg`\n",
+ "and `ppt` from the terraclim dataset.\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "df = load.fia(store=\"az\", states=\"CA\")\n",
+ "df = load.terraclim(\n",
+ " store=\"az\",\n",
+ " tlim=(2000, 2020),\n",
+ " variables=[\"tmean\", \"ppt\"],\n",
+ " df=df,\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "We'll now pick a single forest type and plot biomass vs age colored by our\n",
+ "climatic variables\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "inds = df[\"type_code\"] == 221\n",
+ "x = df[inds][\"age\"]\n",
+ "y = df[inds][\"biomass\"]\n",
+ "f = [df[inds][\"tmean_mean\"], df[inds][\"ppt_mean\"]]\n",
+ "(\n",
+ " plot.xy(x=x, y=y, color=f[0], cmap=\"magma\", xlim=[0, 250], ylim=[0, 600])\n",
+ " | plot.xy(\n",
+ " x=x, y=y, color=f[1], cmap=\"viridis\", xlim=[0, 250], ylim=[0, 600]\n",
+ " )\n",
+ ").resolve_scale(color=\"independent\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "To fit the model to these data we use the `fit.biomass` method\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "model = fit.biomass(x=x, y=y, f=f, noise=\"gamma\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "We can evaluate `r2` on the training data\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "model.r2(x, f, y)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "And we can plot the fitted curves. When plotting, we show curves for different\n",
+ "levels of the climatic variables, to show the form of dependency.\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "xlim = [0, 250]\n",
+ "ylim = [0, 700]\n",
+ "(\n",
+ " (\n",
+ " plot.xy(x=x, y=y, color=f[0], cmap=\"magma\", xlim=xlim, ylim=ylim)\n",
+ " + plot.line(\n",
+ " x=x,\n",
+ " y=model.predict(x, f, [90, 50]),\n",
+ " color=np.nanpercentile(f[0], 90),\n",
+ " )\n",
+ " + plot.line(\n",
+ " x=x,\n",
+ " y=model.predict(x, f, [10, 50]),\n",
+ " color=np.nanpercentile(f[0], 10),\n",
+ " )\n",
+ " )\n",
+ " | (\n",
+ " plot.xy(x=x, y=y, color=f[1], cmap=\"viridis\", xlim=xlim, ylim=ylim)\n",
+ " + plot.line(\n",
+ " x=x,\n",
+ " y=model.predict(x, f, [50, 10]),\n",
+ " color=np.nanpercentile(f[1], 10),\n",
+ " )\n",
+ " + plot.line(\n",
+ " x=x,\n",
+ " y=model.predict(x, f, [50, 90]),\n",
+ " color=np.nanpercentile(f[1], 90),\n",
+ " )\n",
+ " )\n",
+ ").resolve_scale(color=\"independent\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "As an inspection of model validity, we can plot the raw data and a sample from\n",
+ "the generative process underlying the model using the fitted parameters\n",
+ "(specifically, the fitted growth curve, and the Gamma noise model). It should\n",
+ "look qualatatively similar to the actual data. In particular, note how the noise\n",
+ "grows with age, and there are no negative values.\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "xlim = [0, 250]\n",
+ "ylim = [-200, 700]\n",
+ "(\n",
+ " (\n",
+ " plot.xy(x=x, y=y, xlim=xlim, ylim=ylim)\n",
+ " + plot.line(x=x, y=model.predict(x, f, [50, 50]))\n",
+ " )\n",
+ " | (\n",
+ " plot.xy(x=x, y=model.sample(x, f), xlim=xlim, ylim=ylim)\n",
+ " + plot.line(x=x, y=model.predict(x, f, [50, 50]))\n",
+ " )\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "We can set the noise to `'normal'` instead of `'gamma'` and see that the sampled\n",
+ "data no longer matches the real data. While the fitted curve is similar, the\n",
+ "variability is too high for low ages, and there are negative predictions where\n",
+ "there shouldn't be! These behaviors help justify the choice of Gamma\n",
+ "distribution.\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "model = fit.biomass(x=x, y=y, f=f, noise=\"normal\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "xlim = [0, 250]\n",
+ "ylim = [-200, 700]\n",
+ "(\n",
+ " (\n",
+ " plot.xy(x=x, y=y, xlim=xlim, ylim=ylim)\n",
+ " + plot.line(x=x, y=model.predict(x, f, [50, 50]))\n",
+ " )\n",
+ " | (\n",
+ " plot.xy(x=x, y=model.sample(x, f), xlim=xlim, ylim=ylim)\n",
+ " + plot.line(x=x, y=model.predict(x, f, [50, 50]))\n",
+ " )\n",
+ ")"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.8.8"
+ }
},
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "import numpy as np\n",
- "import pandas as pd\n",
- "from carbonplan_forest_risks import load, setup, plot, fit"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "setup.plotting(remote=True)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "First we load the data. To speed things up, we'll just load data from\n",
- "California. We load the raw FIA data, as well as two climatic variables `tavg`\n",
- "and `ppt` from the terraclim dataset.\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "df = load.fia(store=\"az\", states=\"CA\")\n",
- "df = load.terraclim(\n",
- " store=\"az\",\n",
- " tlim=(2000, 2020),\n",
- " variables=[\"tmean\", \"ppt\"],\n",
- " df=df,\n",
- ")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "We'll now pick a single forest type and plot biomass vs age colored by our\n",
- "climatic variables\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "inds = df[\"type_code\"] == 221\n",
- "x = df[inds][\"age\"]\n",
- "y = df[inds][\"biomass\"]\n",
- "f = [df[inds][\"tmean_mean\"], df[inds][\"ppt_mean\"]]\n",
- "(\n",
- " plot.xy(x=x, y=y, color=f[0], cmap=\"magma\", xlim=[0, 250], ylim=[0, 600])\n",
- " | plot.xy(\n",
- " x=x, y=y, color=f[1], cmap=\"viridis\", xlim=[0, 250], ylim=[0, 600]\n",
- " )\n",
- ").resolve_scale(color=\"independent\")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "To fit the model to these data we use the `fit.biomass` method\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "model = fit.biomass(x=x, y=y, f=f, noise=\"gamma\")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "We can evaluate `r2` on the training data\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "model.r2(x, f, y)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "And we can plot the fitted curves. When plotting, we show curves for different\n",
- "levels of the climatic variables, to show the form of dependency.\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "xlim = [0, 250]\n",
- "ylim = [0, 700]\n",
- "(\n",
- " (\n",
- " plot.xy(x=x, y=y, color=f[0], cmap=\"magma\", xlim=xlim, ylim=ylim)\n",
- " + plot.line(\n",
- " x=x,\n",
- " y=model.predict(x, f, [90, 50]),\n",
- " color=np.nanpercentile(f[0], 90),\n",
- " )\n",
- " + plot.line(\n",
- " x=x,\n",
- " y=model.predict(x, f, [10, 50]),\n",
- " color=np.nanpercentile(f[0], 10),\n",
- " )\n",
- " )\n",
- " | (\n",
- " plot.xy(x=x, y=y, color=f[1], cmap=\"viridis\", xlim=xlim, ylim=ylim)\n",
- " + plot.line(\n",
- " x=x,\n",
- " y=model.predict(x, f, [50, 10]),\n",
- " color=np.nanpercentile(f[1], 10),\n",
- " )\n",
- " + plot.line(\n",
- " x=x,\n",
- " y=model.predict(x, f, [50, 90]),\n",
- " color=np.nanpercentile(f[1], 90),\n",
- " )\n",
- " )\n",
- ").resolve_scale(color=\"independent\")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "As an inspection of model validity, we can plot the raw data and a sample from\n",
- "the generative process underlying the model using the fitted parameters\n",
- "(specifically, the fitted growth curve, and the Gamma noise model). It should\n",
- "look qualatatively similar to the actual data. In particular, note how the noise\n",
- "grows with age, and there are no negative values.\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "xlim = [0, 250]\n",
- "ylim = [-200, 700]\n",
- "(\n",
- " (\n",
- " plot.xy(x=x, y=y, xlim=xlim, ylim=ylim)\n",
- " + plot.line(x=x, y=model.predict(x, f, [50, 50]))\n",
- " )\n",
- " | (\n",
- " plot.xy(x=x, y=model.sample(x, f), xlim=xlim, ylim=ylim)\n",
- " + plot.line(x=x, y=model.predict(x, f, [50, 50]))\n",
- " )\n",
- ")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "We can set the noise to `'normal'` instead of `'gamma'` and see that the sampled\n",
- "data no longer matches the real data. While the fitted curve is similar, the\n",
- "variability is too high for low ages, and there are negative predictions where\n",
- "there shouldn't be! These behaviors help justify the choice of Gamma\n",
- "distribution.\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "model = fit.biomass(x=x, y=y, f=f, noise=\"normal\")"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "xlim = [0, 250]\n",
- "ylim = [-200, 700]\n",
- "(\n",
- " (\n",
- " plot.xy(x=x, y=y, xlim=xlim, ylim=ylim)\n",
- " + plot.line(x=x, y=model.predict(x, f, [50, 50]))\n",
- " )\n",
- " | (\n",
- " plot.xy(x=x, y=model.sample(x, f), xlim=xlim, ylim=ylim)\n",
- " + plot.line(x=x, y=model.predict(x, f, [50, 50]))\n",
- " )\n",
- ")"
- ]
- }
- ],
- "metadata": {
- "kernelspec": {
- "display_name": "Python 3",
- "language": "python",
- "name": "python3"
- },
- "language_info": {
- "codemirror_mode": {
- "name": "ipython",
- "version": 3
- },
- "file_extension": ".py",
- "mimetype": "text/x-python",
- "name": "python",
- "nbconvert_exporter": "python",
- "pygments_lexer": "ipython3",
- "version": "3.8.8"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 4
+ "nbformat": 4,
+ "nbformat_minor": 4
}
diff --git a/notebooks/biomass/biomass_results.ipynb b/notebooks/biomass/biomass_results.ipynb
index 3eba209..ee97605 100644
--- a/notebooks/biomass/biomass_results.ipynb
+++ b/notebooks/biomass/biomass_results.ipynb
@@ -1,207 +1,207 @@
{
- "cells": [
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "\n",
- "# FIA Biomass Results\n",
- "\n",
- "_by Jeremy Freeman (CarbonPlan), October 25, 2020_\n",
- "\n",
- "This notebook extracts and summarizes results from fitting biomass growth\n",
- "curves. See the notebook `biomass_modeling` for how the model is fit. This\n",
- "notebook assumes the model has been run and results have been saved using the\n",
- "script `biomass.py`.\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "import pickle\n",
- "import numpy as np\n",
- "import pandas as pd\n",
- "from carbonplan_forest_risks import setup, plot, load"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "setup.plotting(remote=True)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "First we load our model results. This assumes the model has been run and results\n",
- "have been saved using the script `biomass.py`.\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "pf = pd.read_parquet(\"~/forest-risks/data/biomass.parquet\")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Filter out bad values\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "badinds = np.isnan(pf[\"historical\"])\n",
- "for key in pf.columns:\n",
- " if key not in [\"lat\", \"lon\", \"type_code\", \"r2\"]:\n",
- " badinds = badinds | np.isnan(pf[key])\n",
- "pf = pf[~badinds]"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "We can plot the results from the model, evaluting on the same climate as used\n",
- "for fitting\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "plot.carto(\n",
- " lat=pf[\"lat\"],\n",
- " lon=pf[\"lon\"],\n",
- " color=pf[\"historical\"],\n",
- " cmap=\"yellowgreen\",\n",
- " clim=(0, 250),\n",
- " size=1,\n",
- ")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "We can also use other columns to look at future scenarios. For example, here's\n",
- "the difference in biomass from 2020 to 2100.\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "plot.carto(\n",
- " lat=pf[\"lat\"],\n",
- " lon=pf[\"lon\"],\n",
- " color=pf[\"ACCESS-ESM1-5_ssp245_2095\"] - pf[\"ACCESS-ESM1-5_ssp245_2025\"],\n",
- " cmap=\"yellowgreen\",\n",
- " clim=(0, 100),\n",
- ")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Make a time series of spatially averaged projections\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "years = np.arange(2015, 2105, 10)\n",
- "y1 = [pf[\"CanESM5-CanOE_ssp245_\" + str(year)].mean() for year in years]\n",
- "y2 = [pf[\"CanESM5-CanOE_ssp370_\" + str(year)].mean() for year in years]\n",
- "y3 = [pf[\"CanESM5-CanOE_ssp585_\" + str(year)].mean() for year in years]\n",
- "opts = {\"color\": \"rgb(75,128,97)\", \"ylabel\": \"biomass\", \"xlabel\": \"year\"}\n",
- "(\n",
- " plot.line(x=years, y=y1, opacity=0.5, ylim=[100, 175], **opts)\n",
- " + plot.line(x=years, y=y2, opacity=0.75, **opts)\n",
- " + plot.line(x=years, y=y3, opacity=1, **opts)\n",
- ")"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "from showit import image"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "import xarray as xr"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "ds = xr.open_zarr(\"~/forest-risks/data/biomass.zarr\")"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "image(ds[\"ssp245\"][0], clim=[0, 200], size=15)"
- ]
- }
- ],
- "metadata": {
- "kernelspec": {
- "display_name": "Python 3",
- "language": "python",
- "name": "python3"
- },
- "language_info": {
- "codemirror_mode": {
- "name": "ipython",
- "version": 3
- },
- "file_extension": ".py",
- "mimetype": "text/x-python",
- "name": "python",
- "nbconvert_exporter": "python",
- "pygments_lexer": "ipython3",
- "version": "3.8.8"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 4
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "\n",
+ "# FIA Biomass Results\n",
+ "\n",
+ "_by Jeremy Freeman (CarbonPlan), October 25, 2020_\n",
+ "\n",
+ "This notebook extracts and summarizes results from fitting biomass growth\n",
+ "curves. See the notebook `biomass_modeling` for how the model is fit. This\n",
+ "notebook assumes the model has been run and results have been saved using the\n",
+ "script `biomass.py`.\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import pickle\n",
+ "import numpy as np\n",
+ "import pandas as pd\n",
+ "from carbonplan_forest_risks import setup, plot, load"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "setup.plotting(remote=True)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "First we load our model results. This assumes the model has been run and results\n",
+ "have been saved using the script `biomass.py`.\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "pf = pd.read_parquet(\"~/forest-risks/data/biomass.parquet\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Filter out bad values\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "badinds = np.isnan(pf[\"historical\"])\n",
+ "for key in pf.columns:\n",
+ " if key not in [\"lat\", \"lon\", \"type_code\", \"r2\"]:\n",
+ " badinds = badinds | np.isnan(pf[key])\n",
+ "pf = pf[~badinds]"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "We can plot the results from the model, evaluting on the same climate as used\n",
+ "for fitting\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "plot.carto(\n",
+ " lat=pf[\"lat\"],\n",
+ " lon=pf[\"lon\"],\n",
+ " color=pf[\"historical\"],\n",
+ " cmap=\"yellowgreen\",\n",
+ " clim=(0, 250),\n",
+ " size=1,\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "We can also use other columns to look at future scenarios. For example, here's\n",
+ "the difference in biomass from 2020 to 2100.\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "plot.carto(\n",
+ " lat=pf[\"lat\"],\n",
+ " lon=pf[\"lon\"],\n",
+ " color=pf[\"ACCESS-ESM1-5_ssp245_2095\"] - pf[\"ACCESS-ESM1-5_ssp245_2025\"],\n",
+ " cmap=\"yellowgreen\",\n",
+ " clim=(0, 100),\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Make a time series of spatially averaged projections\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "years = np.arange(2015, 2105, 10)\n",
+ "y1 = [pf[\"CanESM5-CanOE_ssp245_\" + str(year)].mean() for year in years]\n",
+ "y2 = [pf[\"CanESM5-CanOE_ssp370_\" + str(year)].mean() for year in years]\n",
+ "y3 = [pf[\"CanESM5-CanOE_ssp585_\" + str(year)].mean() for year in years]\n",
+ "opts = {\"color\": \"rgb(75,128,97)\", \"ylabel\": \"biomass\", \"xlabel\": \"year\"}\n",
+ "(\n",
+ " plot.line(x=years, y=y1, opacity=0.5, ylim=[100, 175], **opts)\n",
+ " + plot.line(x=years, y=y2, opacity=0.75, **opts)\n",
+ " + plot.line(x=years, y=y3, opacity=1, **opts)\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from showit import image"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import xarray as xr"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "ds = xr.open_zarr(\"~/forest-risks/data/biomass.zarr\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "image(ds[\"ssp245\"][0], clim=[0, 200], size=15)"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.8.8"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 4
}
diff --git a/notebooks/drought/drought_model.ipynb b/notebooks/drought/drought_model.ipynb
index bea2739..3b08c6b 100644
--- a/notebooks/drought/drought_model.ipynb
+++ b/notebooks/drought/drought_model.ipynb
@@ -1,235 +1,235 @@
{
- "cells": [
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "\n",
- "# FIA Drought Model\n",
- "\n",
- "_by Jeremy Freeman (CarbonPlan), October 26, 2020_\n",
- "\n",
- "This notebook demos drought modelling.\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "import numpy as np\n",
- "import pandas as pd\n",
- "from carbonplan_forests import setup, plot, load, fit, utils, prepare"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "setup.plotting(remote=False)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Load the raw FIA data grouped by repeated inventories\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "df = load.fia(store=\"local\", states=\"conus\", group_repeats=True)\n",
- "df = load.terraclim(\n",
- " store=\"local\",\n",
- " tlim=(int(df[\"year_0\"].min()), 2020),\n",
- " data_vars=[\"ppt\", \"tavg\", \"pdsi\", \"pet\"],\n",
- " data_aggs=[\"sum\", \"mean\", \"mean\", \"mean\"],\n",
- " df=df,\n",
- " group_repeats=True,\n",
- ")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Prepare data for model fitting\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "x, y, meta = prepare.drought(df)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "x_z, x_mean, x_std = utils.zscore_2d(x)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Fit models\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "pf = meta.copy()\n",
- "pf[\"observed\"] = y\n",
- "pf[\"predicted\"] = np.NaN\n",
- "\n",
- "models = {}\n",
- "for code in pf[\"type_code\"].unique():\n",
- " inds = pf[\"type_code\"] == code\n",
- " model = fit.hurdle(x=x_z[inds], y=y[inds])\n",
- " models[code] = model\n",
- " pf.loc[inds, \"predicted\"] = model.predict(x=x_z[inds])\n",
- "\n",
- "pf = pf[pf[\"predicted\"] < 1]"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Compute simple score metrics (on all data and just on the values where mortality\n",
- "was positive)\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "pf[[\"observed\", \"predicted\"]].corr().iloc[0, 1] ** 2"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "pf[pf[\"observed\"] > 0][[\"observed\", \"predicted\"]].corr().iloc[0, 1] ** 2"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Plot observed vs predicted\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "plot.xy(\n",
- " x=pf[\"observed\"],\n",
- " y=pf[\"predicted\"],\n",
- " xlabel=\"measured mort ratio\",\n",
- " ylabel=\"predicted mort ratio\",\n",
- " xlim=(0, 1),\n",
- " ylim=(0, 1),\n",
- " width=300,\n",
- " height=300,\n",
- " opacity=0.1,\n",
- ")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Make a map of actual mortality ratios\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "plot.carto(\n",
- " lat=pf[\"lat\"],\n",
- " lon=pf[\"lon\"],\n",
- " color=pf[\"observed\"],\n",
- " cmap=\"blues\",\n",
- " clim=(0, 0.1),\n",
- " size=2,\n",
- " opacity=0.75,\n",
- ")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Make a map of predicted mortality ratios\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "plot.carto(\n",
- " lat=pf[\"lat\"],\n",
- " lon=pf[\"lon\"],\n",
- " color=pf[\"predicted\"],\n",
- " clabel=\"mortality\",\n",
- " cmap=\"blues\",\n",
- " clim=(0, 0.1),\n",
- " size=2,\n",
- " opacity=0.75,\n",
- ")"
- ]
- }
- ],
- "metadata": {
- "kernelspec": {
- "display_name": "Python 3",
- "language": "python",
- "name": "python3"
- },
- "language_info": {
- "codemirror_mode": {
- "name": "ipython",
- "version": 3
- },
- "file_extension": ".py",
- "mimetype": "text/x-python",
- "name": "python",
- "nbconvert_exporter": "python",
- "pygments_lexer": "ipython3",
- "version": "3.8.5"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 4
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "\n",
+ "# FIA Drought Model\n",
+ "\n",
+ "_by Jeremy Freeman (CarbonPlan), October 26, 2020_\n",
+ "\n",
+ "This notebook demos drought modelling.\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import numpy as np\n",
+ "import pandas as pd\n",
+ "from carbonplan_forests import setup, plot, load, fit, utils, prepare"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "setup.plotting(remote=False)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Load the raw FIA data grouped by repeated inventories\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "df = load.fia(store=\"local\", states=\"conus\", group_repeats=True)\n",
+ "df = load.terraclim(\n",
+ " store=\"local\",\n",
+ " tlim=(int(df[\"year_0\"].min()), 2020),\n",
+ " data_vars=[\"ppt\", \"tavg\", \"pdsi\", \"pet\"],\n",
+ " data_aggs=[\"sum\", \"mean\", \"mean\", \"mean\"],\n",
+ " df=df,\n",
+ " group_repeats=True,\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Prepare data for model fitting\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "x, y, meta = prepare.drought(df)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "x_z, x_mean, x_std = utils.zscore_2d(x)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Fit models\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "pf = meta.copy()\n",
+ "pf[\"observed\"] = y\n",
+ "pf[\"predicted\"] = np.NaN\n",
+ "\n",
+ "models = {}\n",
+ "for code in pf[\"type_code\"].unique():\n",
+ " inds = pf[\"type_code\"] == code\n",
+ " model = fit.hurdle(x=x_z[inds], y=y[inds])\n",
+ " models[code] = model\n",
+ " pf.loc[inds, \"predicted\"] = model.predict(x=x_z[inds])\n",
+ "\n",
+ "pf = pf[pf[\"predicted\"] < 1]"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Compute simple score metrics (on all data and just on the values where mortality\n",
+ "was positive)\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "pf[[\"observed\", \"predicted\"]].corr().iloc[0, 1] ** 2"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "pf[pf[\"observed\"] > 0][[\"observed\", \"predicted\"]].corr().iloc[0, 1] ** 2"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Plot observed vs predicted\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "plot.xy(\n",
+ " x=pf[\"observed\"],\n",
+ " y=pf[\"predicted\"],\n",
+ " xlabel=\"measured mort ratio\",\n",
+ " ylabel=\"predicted mort ratio\",\n",
+ " xlim=(0, 1),\n",
+ " ylim=(0, 1),\n",
+ " width=300,\n",
+ " height=300,\n",
+ " opacity=0.1,\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Make a map of actual mortality ratios\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "plot.carto(\n",
+ " lat=pf[\"lat\"],\n",
+ " lon=pf[\"lon\"],\n",
+ " color=pf[\"observed\"],\n",
+ " cmap=\"blues\",\n",
+ " clim=(0, 0.1),\n",
+ " size=2,\n",
+ " opacity=0.75,\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Make a map of predicted mortality ratios\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "plot.carto(\n",
+ " lat=pf[\"lat\"],\n",
+ " lon=pf[\"lon\"],\n",
+ " color=pf[\"predicted\"],\n",
+ " clabel=\"mortality\",\n",
+ " cmap=\"blues\",\n",
+ " clim=(0, 0.1),\n",
+ " size=2,\n",
+ " opacity=0.75,\n",
+ ")"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.8.5"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 4
}
diff --git a/notebooks/drought/drought_results.ipynb b/notebooks/drought/drought_results.ipynb
index 27eba43..8ee6cfb 100644
--- a/notebooks/drought/drought_results.ipynb
+++ b/notebooks/drought/drought_results.ipynb
@@ -1,148 +1,148 @@
{
- "cells": [
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "\n",
- "# FIA Drought Results\n",
- "\n",
- "_by Jeremy Freeman (CarbonPlan), October 26, 2020_\n",
- "\n",
- "This notebook loads drought results.\n"
- ]
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "\n",
+ "# FIA Drought Results\n",
+ "\n",
+ "_by Jeremy Freeman (CarbonPlan), October 26, 2020_\n",
+ "\n",
+ "This notebook loads drought results.\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import numpy as np\n",
+ "import pandas as pd\n",
+ "from carbonplan_forests import setup, plot, load, fit, utils, prepare"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "setup.plotting(remote=False)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Load the results\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "pf = pd.read_parquet(\n",
+ " \"/Users/freeman/github/carbonplan/forests/scripts/data/drought.parquet\"\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Filter out bad values\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "badinds = (pf[\"historical\"] > 1) | (np.isnan(pf[\"historical\"]))\n",
+ "for key in pf.columns:\n",
+ " if key not in [\"lat\", \"lon\", \"type_code\", \"r2\"]:\n",
+ " badinds = badinds | ((pf[key] > 1) | (np.isnan(pf[key])))\n",
+ "pf = pf[~badinds]"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Make a map of the historical prediction (from the period used for fitting)\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "plot.carto(\n",
+ " lat=pf[\"lat\"],\n",
+ " lon=pf[\"lon\"],\n",
+ " color=pf[\"historical\"],\n",
+ " cmap=\"blues\",\n",
+ " clim=(0, 0.3),\n",
+ " size=2,\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Make a time series of spatially averaged projections\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "years = np.arange(2020, 2120, 20)\n",
+ "y1 = [pf[\"BCC-CSM2-MR_ssp245_\" + str(year)].mean() for year in years]\n",
+ "y2 = [pf[\"BCC-CSM2-MR_ssp370_\" + str(year)].mean() for year in years]\n",
+ "y3 = [pf[\"BCC-CSM2-MR_ssp585_\" + str(year)].mean() for year in years]\n",
+ "opts = {\n",
+ " \"color\": \"rgb(70,112,164)\",\n",
+ " \"ylabel\": \"fractional mortality\",\n",
+ " \"xlabel\": \"year\",\n",
+ "}\n",
+ "(\n",
+ " plot.line(x=years, y=y1, opacity=0.5, ylim=[0.06, 0.07], **opts)\n",
+ " + plot.line(x=years, y=y2, opacity=0.75, **opts)\n",
+ " + plot.line(x=years, y=y3, opacity=1, **opts)\n",
+ ")"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.8.5"
+ }
},
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "import numpy as np\n",
- "import pandas as pd\n",
- "from carbonplan_forests import setup, plot, load, fit, utils, prepare"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "setup.plotting(remote=False)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Load the results\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "pf = pd.read_parquet(\n",
- " \"/Users/freeman/github/carbonplan/forests/scripts/data/drought.parquet\"\n",
- ")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Filter out bad values\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "badinds = (pf[\"historical\"] > 1) | (np.isnan(pf[\"historical\"]))\n",
- "for key in pf.columns:\n",
- " if key not in [\"lat\", \"lon\", \"type_code\", \"r2\"]:\n",
- " badinds = badinds | ((pf[key] > 1) | (np.isnan(pf[key])))\n",
- "pf = pf[~badinds]"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Make a map of the historical prediction (from the period used for fitting)\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "plot.carto(\n",
- " lat=pf[\"lat\"],\n",
- " lon=pf[\"lon\"],\n",
- " color=pf[\"historical\"],\n",
- " cmap=\"blues\",\n",
- " clim=(0, 0.3),\n",
- " size=2,\n",
- ")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Make a time series of spatially averaged projections\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "years = np.arange(2020, 2120, 20)\n",
- "y1 = [pf[\"BCC-CSM2-MR_ssp245_\" + str(year)].mean() for year in years]\n",
- "y2 = [pf[\"BCC-CSM2-MR_ssp370_\" + str(year)].mean() for year in years]\n",
- "y3 = [pf[\"BCC-CSM2-MR_ssp585_\" + str(year)].mean() for year in years]\n",
- "opts = {\n",
- " \"color\": \"rgb(70,112,164)\",\n",
- " \"ylabel\": \"fractional mortality\",\n",
- " \"xlabel\": \"year\",\n",
- "}\n",
- "(\n",
- " plot.line(x=years, y=y1, opacity=0.5, ylim=[0.06, 0.07], **opts)\n",
- " + plot.line(x=years, y=y2, opacity=0.75, **opts)\n",
- " + plot.line(x=years, y=y3, opacity=1, **opts)\n",
- ")"
- ]
- }
- ],
- "metadata": {
- "kernelspec": {
- "display_name": "Python 3",
- "language": "python",
- "name": "python3"
- },
- "language_info": {
- "codemirror_mode": {
- "name": "ipython",
- "version": 3
- },
- "file_extension": ".py",
- "mimetype": "text/x-python",
- "name": "python",
- "nbconvert_exporter": "python",
- "pygments_lexer": "ipython3",
- "version": "3.8.5"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 4
+ "nbformat": 4,
+ "nbformat_minor": 4
}
diff --git a/notebooks/fire/figure_foresttype.ipynb b/notebooks/fire/figure_foresttype.ipynb
index b92668a..788ed43 100644
--- a/notebooks/fire/figure_foresttype.ipynb
+++ b/notebooks/fire/figure_foresttype.ipynb
@@ -1,315 +1,315 @@
{
- "cells": [
- {
- "cell_type": "markdown",
- "id": "connected-collaboration",
- "metadata": {},
- "source": [
- "\n",
- "\n",
- "# Figure 3: Dependence of model performance on forest type\n",
- "\n",
- "_Authors: Oriana Chegwidden and Jeremy Freeman_\n",
- "\n",
- "The methods below conduct the analyses to recreate Figure 3 included the\n",
- "manuscript <<< insert doi >>>. In this analysis we mean forest group type.\n"
- ]
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "id": "connected-collaboration",
+ "metadata": {},
+ "source": [
+ "\n",
+ "\n",
+ "# Figure 3: Dependence of model performance on forest type\n",
+ "\n",
+ "_Authors: Oriana Chegwidden and Jeremy Freeman_\n",
+ "\n",
+ "The methods below conduct the analyses to recreate Figure 3 included the\n",
+ "manuscript <<< insert doi >>>. In this analysis we mean forest group type.\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "rough-geneva",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "%load_ext autoreload\n",
+ "%autoreload 2\n",
+ "\n",
+ "import numpy as np\n",
+ "import pandas as pd\n",
+ "import scipy as sp\n",
+ "from carbonplan_forests import load, setup, plot, fit, utils, prepare, collect\n",
+ "import xarray as xr\n",
+ "from carbonplan_forests.utils import get_store\n",
+ "import warnings\n",
+ "warnings.filterwarnings('ignore')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "regional-accreditation",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "%matplotlib inline\n",
+ "import matplotlib.pyplot as plt\n",
+ "from carbonplan_forests import load, setup, plot, fit, utils, prepare, collect\n",
+ "from showit import image\n",
+ "import scipy as sp\n",
+ "import numpy as np\n",
+ "import pandas as pd\n",
+ "import xarray as xr\n",
+ "import geopandas as gpd\n",
+ "import regionmask as rm\n",
+ "from scipy.stats import binom\n",
+ "import altair as alt\n",
+ "\n",
+ "from palettable.colorbrewer.sequential import YlOrRd_9"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "charming-worship",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "coarsen = 4\n",
+ "store = \"az\"\n",
+ "tlim = (\"1984\", \"2018\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "amber-deviation",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "mask = (\n",
+ " load.nlcd(store=store, year=2001).sel(band=[41, 42, 43, 90]).sum(\"band\")\n",
+ " > 0.25\n",
+ ").astype(\"float\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "aerial-apartment",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "nlcd = load.nlcd(store=store, year=2001, coarsen=coarsen, mask=mask)\n",
+ "nftd = load.nftd(store=store, area_threshold=1500, coarsen=coarsen, mask=mask)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "opposite-quebec",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "mtbs = load.mtbs(store=store, coarsen=coarsen, tlim=tlim, mask=mask)\n",
+ "# give it the same x/y coords as nftd (and nlcd and climate)\n",
+ "# this re-assignment will help us with some masking lower down\n",
+ "mtbs = mtbs.assign_coords({\"x\": nftd.x, \"y\": nftd.y})"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "operating-directory",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "historical_ds = xr.open_zarr(\n",
+ " get_store(\"carbonplan-scratch\", \"data/fire_historical_final.zarr\")\n",
+ ").assign_coords({\"y\": mtbs.y, \"x\": mtbs.x})"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "breathing-internet",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "alt.data_transformers.disable_max_rows()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "outer-calcium",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "all_evals = []\n",
+ "all_stats = []\n",
+ "for band in nftd.band.values:\n",
+ " stats = plot.fire.full_eval(\n",
+ " mtbs * nftd.sel(band=band),\n",
+ " historical_ds * nftd.sel(band=band),\n",
+ " data_var=\"monthly\",\n",
+ " model_var=\"historical\",\n",
+ " clim=(-0.001, 0.001),\n",
+ " cmap=\"purplegreen\",\n",
+ " percentage=False,\n",
+ " clabel=\"Diff (Mod-Obs) [-]\",\n",
+ " )\n",
+ " all_stats.append(stats)\n",
+ "# all_evals.append(chart)\n",
+ "# alt.vconcat(*all_evals)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "false-momentum",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "performances"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "pharmaceutical-polymer",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "test = (mtbs.groupby(\"time.year\").sum().mean(dim=\"year\") * nftd).mean(\n",
+ " [\"x\", \"y\"]\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "existing-split",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "mtbs_band_probs = test.mean([\"x\", \"y\"]).to_dataframe()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "fancy-relations",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "df_stats = pd.DataFrame(\n",
+ " columns=[\n",
+ " \"Forest group type\",\n",
+ " \"Annual correlation\",\n",
+ " \"Seasonal correlation\",\n",
+ " \"Spatial correlation\",\n",
+ " \"Burn area (fraction/year)\",\n",
+ " ]\n",
+ ")\n",
+ "for row, (band, (performances)) in enumerate(zip(nftd.band.values, all_stats)):\n",
+ " df_stats.loc[row] = [\n",
+ " str(band),\n",
+ " performances[0][\"annual\"],\n",
+ " performances[0][\"seasonal\"],\n",
+ " performances[0][\"spatial\"],\n",
+ " mtbs_band_probs.loc[band][\"monthly\"],\n",
+ " ]"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "bridal-spyware",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "df_stats"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "center-chicken",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "alt.Chart(df_stats).mark_bar().encode(\n",
+ " alt.Y(\"Annual correlation\", scale=alt.Scale(domain=(0, 1), scheme='greys')),\n",
+ " x=\"Forest group type\",\n",
+ " color=\"Burn area (fraction/year)\"\n",
+ ") | alt.Chart(df_stats).mark_bar().encode(\n",
+ " scale=alt.Scale(domain=(0, 1), scheme='greys')),\n",
+ " x='Forest group type',\n",
+ " \n",
+ " y=\"Seasonal correlation\", color=\"Burn area (fraction/year):Q\"\n",
+ ") | alt.Chart(\n",
+ " df_stats\n",
+ ").mark_bar().encode(\n",
+ " alt.X(\"Forest group type\",\n",
+ " scale=alt.Scale(domain=(0, 1), scheme='greys')), y=\"Spatial correlation\", color=\"Burn area (fraction/year)\"\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "certain-memphis",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "df_stats"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "novel-chase",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "alt.Chart(df_stats, height=150, width=200).mark_bar().encode(\n",
+ " alt.Y(\"Annual correlation\", scale=alt.Scale(domain=(0, 1))),\n",
+ " x=\"Forest group type\",\n",
+ " color=\"Burn area (fraction/year):Q\",\n",
+ ") | alt.Chart(df_stats, height=150, width=200).mark_bar().encode(\n",
+ " alt.Y(\"Seasonal correlation\", scale=alt.Scale(domain=(0, 1))),\n",
+ " x=\"Forest group type\",\n",
+ " color=\"Burn area (fraction/year):Q\",\n",
+ ") | alt.Chart(\n",
+ " df_stats, height=150, width=200\n",
+ ").mark_bar().encode(\n",
+ " alt.Y(\"Spatial correlation\", scale=alt.Scale(domain=(0, 1))),\n",
+ " alt.Color(\"Burn area (fraction/year):Q\", scale=alt.Scale(scheme=\"greys\")),\n",
+ " x=\"Forest group type\",\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "progressive-enemy",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "final.configure(fontSize=20)"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python [conda env:notebook] *",
+ "language": "python",
+ "name": "conda-env-notebook-py"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.8.8"
+ }
},
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "rough-geneva",
- "metadata": {},
- "outputs": [],
- "source": [
- "%load_ext autoreload\n",
- "%autoreload 2\n",
- "\n",
- "import numpy as np\n",
- "import pandas as pd\n",
- "import scipy as sp\n",
- "from carbonplan_forests import load, setup, plot, fit, utils, prepare, collect\n",
- "import xarray as xr\n",
- "from carbonplan_forests.utils import get_store\n",
- "import warnings\n",
- "warnings.filterwarnings('ignore')"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "regional-accreditation",
- "metadata": {},
- "outputs": [],
- "source": [
- "%matplotlib inline\n",
- "import matplotlib.pyplot as plt\n",
- "from carbonplan_forests import load, setup, plot, fit, utils, prepare, collect\n",
- "from showit import image\n",
- "import scipy as sp\n",
- "import numpy as np\n",
- "import pandas as pd\n",
- "import xarray as xr\n",
- "import geopandas as gpd\n",
- "import regionmask as rm\n",
- "from scipy.stats import binom\n",
- "import altair as alt\n",
- "\n",
- "from palettable.colorbrewer.sequential import YlOrRd_9"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "charming-worship",
- "metadata": {},
- "outputs": [],
- "source": [
- "coarsen = 4\n",
- "store = \"az\"\n",
- "tlim = (\"1984\", \"2018\")"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "amber-deviation",
- "metadata": {},
- "outputs": [],
- "source": [
- "mask = (\n",
- " load.nlcd(store=store, year=2001).sel(band=[41, 42, 43, 90]).sum(\"band\")\n",
- " > 0.25\n",
- ").astype(\"float\")"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "aerial-apartment",
- "metadata": {},
- "outputs": [],
- "source": [
- "nlcd = load.nlcd(store=store, year=2001, coarsen=coarsen, mask=mask)\n",
- "nftd = load.nftd(store=store, area_threshold=1500, coarsen=coarsen, mask=mask)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "opposite-quebec",
- "metadata": {},
- "outputs": [],
- "source": [
- "mtbs = load.mtbs(store=store, coarsen=coarsen, tlim=tlim, mask=mask)\n",
- "# give it the same x/y coords as nftd (and nlcd and climate)\n",
- "# this re-assignment will help us with some masking lower down\n",
- "mtbs = mtbs.assign_coords({\"x\": nftd.x, \"y\": nftd.y})"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "operating-directory",
- "metadata": {},
- "outputs": [],
- "source": [
- "historical_ds = xr.open_zarr(\n",
- " get_store(\"carbonplan-scratch\", \"data/fire_historical_final.zarr\")\n",
- ").assign_coords({\"y\": mtbs.y, \"x\": mtbs.x})"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "breathing-internet",
- "metadata": {},
- "outputs": [],
- "source": [
- "alt.data_transformers.disable_max_rows()"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "outer-calcium",
- "metadata": {},
- "outputs": [],
- "source": [
- "all_evals = []\n",
- "all_stats = []\n",
- "for band in nftd.band.values:\n",
- " stats = plot.fire.full_eval(\n",
- " mtbs * nftd.sel(band=band),\n",
- " historical_ds * nftd.sel(band=band),\n",
- " data_var=\"monthly\",\n",
- " model_var=\"historical\",\n",
- " clim=(-0.001, 0.001),\n",
- " cmap=\"purplegreen\",\n",
- " percentage=False,\n",
- " clabel=\"Diff (Mod-Obs) [-]\",\n",
- " )\n",
- " all_stats.append(stats)\n",
- "# all_evals.append(chart)\n",
- "# alt.vconcat(*all_evals)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "false-momentum",
- "metadata": {},
- "outputs": [],
- "source": [
- "performances"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "pharmaceutical-polymer",
- "metadata": {},
- "outputs": [],
- "source": [
- "test = (mtbs.groupby(\"time.year\").sum().mean(dim=\"year\") * nftd).mean(\n",
- " [\"x\", \"y\"]\n",
- ")"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "existing-split",
- "metadata": {},
- "outputs": [],
- "source": [
- "mtbs_band_probs = test.mean([\"x\", \"y\"]).to_dataframe()"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "fancy-relations",
- "metadata": {},
- "outputs": [],
- "source": [
- "df_stats = pd.DataFrame(\n",
- " columns=[\n",
- " \"Forest group type\",\n",
- " \"Annual correlation\",\n",
- " \"Seasonal correlation\",\n",
- " \"Spatial correlation\",\n",
- " \"Burn area (fraction/year)\",\n",
- " ]\n",
- ")\n",
- "for row, (band, (performances)) in enumerate(zip(nftd.band.values, all_stats)):\n",
- " df_stats.loc[row] = [\n",
- " str(band),\n",
- " performances[0][\"annual\"],\n",
- " performances[0][\"seasonal\"],\n",
- " performances[0][\"spatial\"],\n",
- " mtbs_band_probs.loc[band][\"monthly\"],\n",
- " ]"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "bridal-spyware",
- "metadata": {},
- "outputs": [],
- "source": [
- "df_stats"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "center-chicken",
- "metadata": {},
- "outputs": [],
- "source": [
- "alt.Chart(df_stats).mark_bar().encode(\n",
- " alt.Y(\"Annual correlation\", scale=alt.Scale(domain=(0, 1), scheme='greys')),\n",
- " x=\"Forest group type\",\n",
- " color=\"Burn area (fraction/year)\"\n",
- ") | alt.Chart(df_stats).mark_bar().encode(\n",
- " scale=alt.Scale(domain=(0, 1), scheme='greys')),\n",
- " x='Forest group type',\n",
- " \n",
- " y=\"Seasonal correlation\", color=\"Burn area (fraction/year):Q\"\n",
- ") | alt.Chart(\n",
- " df_stats\n",
- ").mark_bar().encode(\n",
- " alt.X(\"Forest group type\",\n",
- " scale=alt.Scale(domain=(0, 1), scheme='greys')), y=\"Spatial correlation\", color=\"Burn area (fraction/year)\"\n",
- ")"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "certain-memphis",
- "metadata": {},
- "outputs": [],
- "source": [
- "df_stats"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "novel-chase",
- "metadata": {},
- "outputs": [],
- "source": [
- "alt.Chart(df_stats, height=150, width=200).mark_bar().encode(\n",
- " alt.Y(\"Annual correlation\", scale=alt.Scale(domain=(0, 1))),\n",
- " x=\"Forest group type\",\n",
- " color=\"Burn area (fraction/year):Q\",\n",
- ") | alt.Chart(df_stats, height=150, width=200).mark_bar().encode(\n",
- " alt.Y(\"Seasonal correlation\", scale=alt.Scale(domain=(0, 1))),\n",
- " x=\"Forest group type\",\n",
- " color=\"Burn area (fraction/year):Q\",\n",
- ") | alt.Chart(\n",
- " df_stats, height=150, width=200\n",
- ").mark_bar().encode(\n",
- " alt.Y(\"Spatial correlation\", scale=alt.Scale(domain=(0, 1))),\n",
- " alt.Color(\"Burn area (fraction/year):Q\", scale=alt.Scale(scheme=\"greys\")),\n",
- " x=\"Forest group type\",\n",
- ")"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "progressive-enemy",
- "metadata": {},
- "outputs": [],
- "source": [
- "final.configure(fontSize=20)"
- ]
- }
- ],
- "metadata": {
- "kernelspec": {
- "display_name": "Python [conda env:notebook] *",
- "language": "python",
- "name": "conda-env-notebook-py"
- },
- "language_info": {
- "codemirror_mode": {
- "name": "ipython",
- "version": 3
- },
- "file_extension": ".py",
- "mimetype": "text/x-python",
- "name": "python",
- "nbconvert_exporter": "python",
- "pygments_lexer": "ipython3",
- "version": "3.8.8"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 5
+ "nbformat": 4,
+ "nbformat_minor": 5
}
diff --git a/notebooks/fire/fire_model.ipynb b/notebooks/fire/fire_model.ipynb
index b132a9f..9e45563 100644
--- a/notebooks/fire/fire_model.ipynb
+++ b/notebooks/fire/fire_model.ipynb
@@ -1,567 +1,567 @@
{
- "cells": [
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "\n",
- "# MTBS Fire Model\n",
- "\n",
- "_by Jeremy Freeman (CarbonPlan), September 19, 2020_\n",
- "\n",
- "This notebook loads downsampled MTBS fire data and TerraClimate climate data and\n",
- "fits a logistical regression model.\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "import numpy as np\n",
- "import pandas as pd\n",
- "import scipy as sp\n",
- "from carbonplan_forests import load, setup, plot, fit"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "setup.plotting(remote=False)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "%load_ext autoreload\n",
- "%autoreload 2"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "First we set some top-level parameters: the level of spatial coarsening (which\n",
- "can speed up fitting substantially, especially useful when testing), the time\n",
- "range (MTBS spans 1984 to 2018), and the climatic variables we'll use in the\n",
- "model.\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "coarsen = 16\n",
- "tlim = (1984, 2018)\n",
- "data_vars = [\"ppt\", \"tavg\"]"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "First we load data from `nlcd` which we will use to mask out non-land areas and\n",
- "data from `nftd` to use a regressors for forest type groups.\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "mask = load.nlcd(store=\"local\", classes=\"all\", year=2001)\n",
- "groups = load.nftd(\n",
- " store=\"local\", groups=\"all\", coarsen=coarsen, mask=mask, area_threshold=1500\n",
- ")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Now we load the `terraclim` data from the same time range.\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "scrolled": true
- },
- "outputs": [],
- "source": [
- "climate = load.terraclim(\n",
- " store=\"local\", tlim=tlim, coarsen=coarsen, data_vars=data_vars, mask=mask\n",
- ")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "And finally load the `mtbs` data, setting all non-zero values to 1 as setup for\n",
- "our logistic model.\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "mtbs = load.mtbs(store=\"local\", coarsen=0, tlim=tlim)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "%matplotlib inline"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "from showit import image"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "from scipy.stats import binom"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "def integrated_risk(p):\n",
- " return 1 - binom.cdf(0, 100, p)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "image(\n",
- " (mtbs[\"vlf\"].sel(time=slice(\"2006\", \"2006\")).sum(\"time\")),\n",
- " size=12,\n",
- " clim=(0, 1),\n",
- ")"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "import rasterio"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "r = rasterio.open(\n",
- " \"/Users/freeman/workdir/carbonplan-data/processed/mtbs/conus/30m/2006.tif\"\n",
- ")"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "im = r.read(1)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "%gui qt"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "import napari"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "napari.view_image(im == 1)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Inspecting the data\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "We can plot the `mtbs` data for a specific year to get a sense of the raw data.\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "plot.fire.summary(mtbs, clim=(0, 0.1))"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "plot.fire.monthly(mtbs.sel(time=\"2016\"), \"vlf\", clim=(0, 1))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Here is the same thing but averaged over all years\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "mtbs.groupby(\"time.month\").mean()[\"vlf\"].max().values"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "plot.fire.monthly(mtbs, \"vlf\", clim=(0, 0.2))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "We can plot spatially averaged data over time to see both seasonable trends, and\n",
- "the fact that fire frequency and magnitude has increased over time.\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "x = mtbs[\"time\"]\n",
- "y = mtbs[\"vlf\"].mean([\"x\", \"y\"])\n",
- "\n",
- "plot.line(\n",
- " x=x, y=y, width=900, height=200, color=\"rgb(175,91,92)\", strokeWidth=2\n",
- ")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "We can summarize the data by plotting annual, seasonal, and spatial trends by\n",
- "averaging across different groupings and dimensions.\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "plot.fire.summary(mtbs, \"vlf\", clim=(0, 0.05))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "As a motivation for fitting fires as functions of climatic variables, we can\n",
- "look at spatially averaged climatic variables alongside fires, e.g. average\n",
- "tempreature, and see that there is a clear relationship (in this case a positive\n",
- "correlation).\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "x = mtbs.groupby(\"time.year\").mean()[\"year\"]\n",
- "y1 = mtbs[\"vlf\"].groupby(\"time.year\").mean().mean([\"x\", \"y\"])\n",
- "y2 = climate[\"tavg\"].groupby(\"time.year\").mean().mean([\"x\", \"y\"])\n",
- "\n",
- "(\n",
- " plot.line(x=x, y=sp.stats.zscore(y1), color=\"rgb(175,91,92)\")\n",
- " + plot.line(x=x, y=sp.stats.zscore(y2), color=\"rgb(175,91,92)\", opacity=0.5)\n",
- ")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Fitting the model\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "We'll define the variables to use in the model\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "fit_vars = [\"tavg\", \"ppt\"]"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Then we fit it by providing both the climate variables and the forest type\n",
- "groups. We distinguish the two sets of input variables because the climate\n",
- "variables change over time by the groups do not.\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "model = fit.fire(x=climate[fit_vars], y=mtbs[\"vlf\"], f=groups)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "We can evaluate the fitting model on arbitrary new inputs. In this case, we\n",
- "evaluate on the data we used to fit.\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "prediction = model.predict(x=climate[fit_vars], f=groups)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "We can plot the predictions monthly just as we plotted the real data.\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "plot.fire.monthly(prediction, \"prob\", clim=(0, 0.01))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "And we can plot the same summary of trends but now with both data and model\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "plot.fire.evaluation(mtbs, prediction, \"vlf\", \"prob\", clim=(0.002, 0.02))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "We can also compare the predicted and real probabilities over time.\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "x = mtbs[\"time\"]\n",
- "y1 = mtbs[\"vlf\"].mean([\"x\", \"y\"])\n",
- "y2 = prediction[\"prob\"].mean([\"x\", \"y\"])\n",
- "\n",
- "(\n",
- " plot.line(\n",
- " x=x,\n",
- " y=y1,\n",
- " width=900,\n",
- " height=200,\n",
- " opacity=0.5,\n",
- " color=\"rgb(175,91,92)\",\n",
- " strokeWidth=2,\n",
- " )\n",
- " + plot.line(\n",
- " x=x, y=y2, width=900, height=200, color=\"rgb(175,91,92)\", strokeWidth=2\n",
- " )\n",
- ")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Given that we fit a logistic regression, the natural model performance metric is\n",
- "area under the ROC curve, which we computed on the training data (you can use\n",
- "the variable `crossval` to repeat the model fit and compute a score on 25% held\n",
- "out data).\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "model.train_roc"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Finally, we can compute correlations between model and prediction for annual,\n",
- "seasonal, and spatial trends. Note that these were not metrics used to\n",
- "explicitly fit the model, but in general a better fitting model ought to\n",
- "reproduce at least some of these trends.\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "print(\"correlation of annual trends\")\n",
- "np.corrcoef(\n",
- " mtbs[\"vlf\"].groupby(\"time.year\").mean().mean([\"x\", \"y\"]),\n",
- " prediction[\"prob\"].groupby(\"time.year\").mean().mean([\"x\", \"y\"]),\n",
- ")[0, 1]"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "print(\"correlation of monthly trends\")\n",
- "np.corrcoef(\n",
- " mtbs[\"vlf\"].groupby(\"time.month\").mean().mean([\"x\", \"y\"]),\n",
- " prediction[\"prob\"].groupby(\"time.month\").mean().mean([\"x\", \"y\"]),\n",
- ")[0, 1]"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "print(\"correlation of spatial trends\")\n",
- "np.corrcoef(\n",
- " mtbs[\"vlf\"].mean(\"time\").values.flatten(),\n",
- " prediction[\"prob\"].mean(\"time\").values.flatten(),\n",
- ")[0, 1]"
- ]
- }
- ],
- "metadata": {
- "kernelspec": {
- "display_name": "Python 3",
- "language": "python",
- "name": "python3"
- },
- "language_info": {
- "codemirror_mode": {
- "name": "ipython",
- "version": 3
- },
- "file_extension": ".py",
- "mimetype": "text/x-python",
- "name": "python",
- "nbconvert_exporter": "python",
- "pygments_lexer": "ipython3",
- "version": "3.9.2"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 4
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "\n",
+ "# MTBS Fire Model\n",
+ "\n",
+ "_by Jeremy Freeman (CarbonPlan), September 19, 2020_\n",
+ "\n",
+ "This notebook loads downsampled MTBS fire data and TerraClimate climate data and\n",
+ "fits a logistical regression model.\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import numpy as np\n",
+ "import pandas as pd\n",
+ "import scipy as sp\n",
+ "from carbonplan_forests import load, setup, plot, fit"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "setup.plotting(remote=False)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "%load_ext autoreload\n",
+ "%autoreload 2"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "First we set some top-level parameters: the level of spatial coarsening (which\n",
+ "can speed up fitting substantially, especially useful when testing), the time\n",
+ "range (MTBS spans 1984 to 2018), and the climatic variables we'll use in the\n",
+ "model.\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "coarsen = 16\n",
+ "tlim = (1984, 2018)\n",
+ "data_vars = [\"ppt\", \"tavg\"]"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "First we load data from `nlcd` which we will use to mask out non-land areas and\n",
+ "data from `nftd` to use a regressors for forest type groups.\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "mask = load.nlcd(store=\"local\", classes=\"all\", year=2001)\n",
+ "groups = load.nftd(\n",
+ " store=\"local\", groups=\"all\", coarsen=coarsen, mask=mask, area_threshold=1500\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Now we load the `terraclim` data from the same time range.\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "scrolled": true
+ },
+ "outputs": [],
+ "source": [
+ "climate = load.terraclim(\n",
+ " store=\"local\", tlim=tlim, coarsen=coarsen, data_vars=data_vars, mask=mask\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "And finally load the `mtbs` data, setting all non-zero values to 1 as setup for\n",
+ "our logistic model.\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "mtbs = load.mtbs(store=\"local\", coarsen=0, tlim=tlim)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "%matplotlib inline"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from showit import image"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from scipy.stats import binom"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def integrated_risk(p):\n",
+ " return 1 - binom.cdf(0, 100, p)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "image(\n",
+ " (mtbs[\"vlf\"].sel(time=slice(\"2006\", \"2006\")).sum(\"time\")),\n",
+ " size=12,\n",
+ " clim=(0, 1),\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import rasterio"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "r = rasterio.open(\n",
+ " \"/Users/freeman/workdir/carbonplan-data/processed/mtbs/conus/30m/2006.tif\"\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "im = r.read(1)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "%gui qt"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import napari"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "napari.view_image(im == 1)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Inspecting the data\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "We can plot the `mtbs` data for a specific year to get a sense of the raw data.\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "plot.fire.summary(mtbs, clim=(0, 0.1))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "plot.fire.monthly(mtbs.sel(time=\"2016\"), \"vlf\", clim=(0, 1))"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Here is the same thing but averaged over all years\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "mtbs.groupby(\"time.month\").mean()[\"vlf\"].max().values"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "plot.fire.monthly(mtbs, \"vlf\", clim=(0, 0.2))"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "We can plot spatially averaged data over time to see both seasonable trends, and\n",
+ "the fact that fire frequency and magnitude has increased over time.\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "x = mtbs[\"time\"]\n",
+ "y = mtbs[\"vlf\"].mean([\"x\", \"y\"])\n",
+ "\n",
+ "plot.line(\n",
+ " x=x, y=y, width=900, height=200, color=\"rgb(175,91,92)\", strokeWidth=2\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "We can summarize the data by plotting annual, seasonal, and spatial trends by\n",
+ "averaging across different groupings and dimensions.\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "plot.fire.summary(mtbs, \"vlf\", clim=(0, 0.05))"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "As a motivation for fitting fires as functions of climatic variables, we can\n",
+ "look at spatially averaged climatic variables alongside fires, e.g. average\n",
+ "tempreature, and see that there is a clear relationship (in this case a positive\n",
+ "correlation).\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "x = mtbs.groupby(\"time.year\").mean()[\"year\"]\n",
+ "y1 = mtbs[\"vlf\"].groupby(\"time.year\").mean().mean([\"x\", \"y\"])\n",
+ "y2 = climate[\"tavg\"].groupby(\"time.year\").mean().mean([\"x\", \"y\"])\n",
+ "\n",
+ "(\n",
+ " plot.line(x=x, y=sp.stats.zscore(y1), color=\"rgb(175,91,92)\")\n",
+ " + plot.line(x=x, y=sp.stats.zscore(y2), color=\"rgb(175,91,92)\", opacity=0.5)\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Fitting the model\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "We'll define the variables to use in the model\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "fit_vars = [\"tavg\", \"ppt\"]"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Then we fit it by providing both the climate variables and the forest type\n",
+ "groups. We distinguish the two sets of input variables because the climate\n",
+ "variables change over time by the groups do not.\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "model = fit.fire(x=climate[fit_vars], y=mtbs[\"vlf\"], f=groups)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "We can evaluate the fitting model on arbitrary new inputs. In this case, we\n",
+ "evaluate on the data we used to fit.\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "prediction = model.predict(x=climate[fit_vars], f=groups)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "We can plot the predictions monthly just as we plotted the real data.\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "plot.fire.monthly(prediction, \"prob\", clim=(0, 0.01))"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "And we can plot the same summary of trends but now with both data and model\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "plot.fire.evaluation(mtbs, prediction, \"vlf\", \"prob\", clim=(0.002, 0.02))"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "We can also compare the predicted and real probabilities over time.\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "x = mtbs[\"time\"]\n",
+ "y1 = mtbs[\"vlf\"].mean([\"x\", \"y\"])\n",
+ "y2 = prediction[\"prob\"].mean([\"x\", \"y\"])\n",
+ "\n",
+ "(\n",
+ " plot.line(\n",
+ " x=x,\n",
+ " y=y1,\n",
+ " width=900,\n",
+ " height=200,\n",
+ " opacity=0.5,\n",
+ " color=\"rgb(175,91,92)\",\n",
+ " strokeWidth=2,\n",
+ " )\n",
+ " + plot.line(\n",
+ " x=x, y=y2, width=900, height=200, color=\"rgb(175,91,92)\", strokeWidth=2\n",
+ " )\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Given that we fit a logistic regression, the natural model performance metric is\n",
+ "area under the ROC curve, which we computed on the training data (you can use\n",
+ "the variable `crossval` to repeat the model fit and compute a score on 25% held\n",
+ "out data).\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "model.train_roc"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Finally, we can compute correlations between model and prediction for annual,\n",
+ "seasonal, and spatial trends. Note that these were not metrics used to\n",
+ "explicitly fit the model, but in general a better fitting model ought to\n",
+ "reproduce at least some of these trends.\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "print(\"correlation of annual trends\")\n",
+ "np.corrcoef(\n",
+ " mtbs[\"vlf\"].groupby(\"time.year\").mean().mean([\"x\", \"y\"]),\n",
+ " prediction[\"prob\"].groupby(\"time.year\").mean().mean([\"x\", \"y\"]),\n",
+ ")[0, 1]"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "print(\"correlation of monthly trends\")\n",
+ "np.corrcoef(\n",
+ " mtbs[\"vlf\"].groupby(\"time.month\").mean().mean([\"x\", \"y\"]),\n",
+ " prediction[\"prob\"].groupby(\"time.month\").mean().mean([\"x\", \"y\"]),\n",
+ ")[0, 1]"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "print(\"correlation of spatial trends\")\n",
+ "np.corrcoef(\n",
+ " mtbs[\"vlf\"].mean(\"time\").values.flatten(),\n",
+ " prediction[\"prob\"].mean(\"time\").values.flatten(),\n",
+ ")[0, 1]"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.9.2"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 4
}
diff --git a/notebooks/fire/fire_model_redux.ipynb b/notebooks/fire/fire_model_redux.ipynb
index b5d7852..29a0938 100644
--- a/notebooks/fire/fire_model_redux.ipynb
+++ b/notebooks/fire/fire_model_redux.ipynb
@@ -1,867 +1,867 @@
{
- "cells": [
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "\n",
- "# MTBS Fire Model\n",
- "\n",
- "_by Jeremy Freeman (CarbonPlan), September 19, 2020_\n",
- "\n",
- "This notebook loads downsampled MTBS fire data and TerraClimate climate data and\n",
- "fits a logistical regression model.\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "import numpy as np\n",
- "import pandas as pd\n",
- "import scipy as sp\n",
- "from carbonplan_forests import load, setup, plot, fit, utils, prepare, collect"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "%matplotlib inline\n",
- "import matplotlib.pyplot as plt\n",
- "from showit import image, tile\n",
- "import xarray as xr\n",
- "from astropy.convolution import Gaussian2DKernel\n",
- "from astropy.convolution import convolve, convolve_fft\n",
- "import altair as alt"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "setup.plotting(remote=True)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "%load_ext autoreload\n",
- "%autoreload 2"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "First we set some top-level parameters: the level of spatial coarsening (which\n",
- "can speed up fitting substantially, especially useful when testing), the time\n",
- "range (MTBS spans 1984 to 2018), and the climatic variables we'll use in the\n",
- "model.\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "coarsen = 4\n",
- "full_climate_period = (1983, 2018)\n",
- "analysis_tlim = (1984, 2018)\n",
- "variables = [\"ppt\", \"tmean\", \"cwd\"] # , \"tmax\", \"tmin\"]\n",
- "store = \"az\""
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "First we load data from `nlcd` which we will use to mask out non-land areas and\n",
- "data from `nftd` to use a regressors for forest type groups.\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "mask = (\n",
- " load.nlcd(store=store, year=2001).sel(band=[41, 42, 43, 90]).sum(\"band\")\n",
- " > 0.25\n",
- ").astype(\"float\")"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "nlcd = load.nlcd(store=store, year=2001, coarsen=coarsen, mask=mask)\n",
- "nftd = load.nftd(store=store, area_threshold=1500, coarsen=coarsen, mask=mask)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "coarsened_conus_domain = load.mask(coarsen=coarsen)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Now we load the `terraclim` data from the same time range.\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "scrolled": true
- },
- "outputs": [],
- "source": [
- "climate = load.terraclim(\n",
- " store=store,\n",
- " tlim=full_climate_period,\n",
- " coarsen=coarsen,\n",
- " variables=variables,\n",
- " mask=mask,\n",
- " sampling=\"monthly\",\n",
- ")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "And finally load the `mtbs` data\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "mtbs = load.mtbs(store=store, coarsen=coarsen, tlim=analysis_tlim, mask=mask)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Inspecting the data\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "We can plot the `mtbs` data for a specific year to get a sense of the raw data.\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "plot.fire.monthly(mtbs.sel(time=\"2018\"), clim=(0, 0.2))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Here is the same thing but averaged over all years\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "plot.fire.monthly(mtbs, clim=(0.00005, 0.0015))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## We can plot spatially averaged data over time to see both seasonable trends, and\n",
- "\n",
- "the fact that fire frequency and magnitude has increased over time.\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "x = mtbs[\"time\"]\n",
- "y = mtbs[\"monthly\"].mean([\"x\", \"y\"])\n",
- "\n",
- "plot.line(\n",
- " x=x, y=y, width=900, height=200, color=\"rgb(175,91,92)\", strokeWidth=2\n",
- ")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "We can summarize the data by plotting annual, seasonal, and spatial trends by\n",
- "averaging across different groupings and dimensions.\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "plot.fire.summary(mtbs, clim=(0, 0.005))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "As a motivation for fitting fires as functions of climatic variables, we can\n",
- "look at spatially averaged climatic variables alongside fires, e.g. average\n",
- "tempreature, and see that there is a clear relationship (in this case a positive\n",
- "correlation).\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "x = mtbs.groupby(\"time.year\").mean()[\"year\"]\n",
- "y1 = mtbs[\"monthly\"].groupby(\"time.year\").sum().mean([\"x\", \"y\"])\n",
- "y2 = climate[\"tmean\"].groupby(\"time.year\").max().mean([\"x\", \"y\"])\n",
- "\n",
- "(\n",
- " plot.line(x=x, y=sp.stats.zscore(y1), color=\"rgb(175,91,92)\")\n",
- " + plot.line(x=x, y=sp.stats.zscore(y2), color=\"rgb(175,91,92)\", opacity=0.5)\n",
- ")\n",
- "\n",
- "# np.corrcoef(y1,y2)[0,1]"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "# Tmean precip comparisons\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "sl = slice(\"1984\", \"2008\")"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "single_pixel = climate.isel(x=25, y=25)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "plt.figure(figsize=(15, 8))\n",
- "xr.DataArray(\n",
- " np.repeat(\n",
- " single_pixel[\"tmean\"].sel(time=sl).groupby(\"time.year\").max().values, 12\n",
- " ),\n",
- " coords=single_pixel.sel(time=sl).coords,\n",
- ").plot(label=\"groupby\")\n",
- "single_pixel[\"tmean\"].rolling(time=12).max().sel(time=sl).plot(label=\"rolling\")\n",
- "single_pixel[\"tmean\"].sel(time=sl).plot(label=\"raw\", alpha=0.5)\n",
- "plt.legend()\n",
- "plt.ylim(0, 18)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "ts = climate[\"tmean\"].groupby(\"time.year\").max().mean(dim=[\"x\", \"y\"]).values\n",
- "groupby_global_max_then_mean = xr.DataArray(\n",
- " np.repeat(ts, 12), coords=single_pixel.coords\n",
- ")\n",
- "ts = climate[\"tmean\"].mean(dim=[\"x\", \"y\"]).groupby(\"time.year\").max().values\n",
- "groupby_global_mean_then_max = xr.DataArray(\n",
- " np.repeat(ts, 12), coords=single_pixel.coords\n",
- ")"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "groupby_global_mean_then_max.plot(label=\"mean then max\")\n",
- "groupby_global_max_then_mean.plot(label=\"max then mean\")\n",
- "plt.legend()"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "rolling_global_max = (\n",
- " climate[\"tmean\"]\n",
- " .mean(dim=[\"x\", \"y\"])\n",
- " .rolling(dim={\"time\": 12}, min_periods=8, center=False)\n",
- " .max()\n",
- " .sel(time=inspection_slice)\n",
- ")"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "plt.figure(figsize=(10, 8))\n",
- "inspection_slice = slice(\"1984\", \"1990\")\n",
- "rolling_global_max.sel(time=inspection_slice).plot(label=\"rolling\")\n",
- "# groupby_global_max_annual.sel(time=inspection_slice).plot(label='groupby')\n",
- "\n",
- "groupby_global_mean_then_max.sel(time=inspection_slice).plot(label=\"groupby\")\n",
- "climate[\"tmean\"].sel(time=inspection_slice).mean(dim=[\"x\", \"y\"]).plot(\n",
- " label=\"raw\"\n",
- ")\n",
- "plt.ylim(16, 24)\n",
- "plt.legend()"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "climate[\"ppt\"].rolling(time=12, center=False).sum().mean(dim=[\"x\", \"y\"]).plot()"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "climate[\"tmean\"].rolling(time=12, center=False).max().isel(time=30).plot()"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "climate[\"ppt\"].resample(time=\"AS\").mean().isel(time=3).plot()"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "climate[\"ppt\"].groupby(\"time.year\").sum().mean(dim=[\"x\", \"y\"]).plot()"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "rolling = (\n",
- " climate[\"ppt\"]\n",
- " .rolling(time=12, center=False)\n",
- " .sum()\n",
- " .mean(dim=[\"x\", \"y\"])\n",
- " .sel(time=inspection_slice)\n",
- ")\n",
- "rolling.plot(label=\"rolling\")\n",
- "xr.DataArray(\n",
- " np.repeat(\n",
- " climate[\"ppt\"]\n",
- " .sel(time=inspection_slice)\n",
- " .groupby(\"time.year\")\n",
- " .sum()\n",
- " .mean(dim=[\"x\", \"y\"])\n",
- " .values,\n",
- " 12,\n",
- " ),\n",
- " coords=rolling.coords,\n",
- ").plot(label=\"groupby\")\n",
- "plt.legend()"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "# Original\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "climate.isel(time=3).tmean.plot()"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "rolling_period = slice(\"1984\", \"2018\")"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "climate_prepend = climate.sel(time=slice(\"1983\", \"1983\"))\n",
- "x, y = prepare.fire(\n",
- " climate.sel(time=slice(*[str(t) for t in analysis_tlim])), #\n",
- " nftd,\n",
- " mtbs,\n",
- " add_global_climate_trends={\n",
- " \"tmean\": {\"climate_prepend\": None, \"gaussian_kernel_size\": None},\n",
- " \"ppt\": {\"climate_prepend\": None, \"gaussian_kernel_size\": None},\n",
- " },\n",
- " add_local_climate_trends=None,\n",
- ")\n",
- "# {'tmean': {'climate_prepend': None,\n",
- "# 'gaussian_kernel_size': None},\n",
- "# 'ppt': {'climate_prepend': None,\n",
- "# 'gaussian_kernel_size': None}},)\n",
- "# rolling_period=12)\n",
- "x_z, x_mean, x_std = utils.zscore_2d(x)\n",
- "model = fit.hurdle(x_z, y, log=False)\n",
- "yhat = model.predict(x_z)\n",
- "prediction_original = collect.fire(yhat, mtbs)\n",
- "metrics, chart = plot.fire.full_eval(\n",
- " mtbs,\n",
- " prediction_original,\n",
- " \"monthly\",\n",
- " \"prediction\",\n",
- " clim=(-0.08, 0.08),\n",
- " cmap=\"purplegreen\",\n",
- ")\n",
- "chart"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "climate_prepend = climate.sel(time=slice(\"1983\", \"1983\"))\n",
- "x, y = prepare.fire(\n",
- " climate.sel(time=slice(*[str(t) for t in analysis_tlim])), #\n",
- " nftd,\n",
- " mtbs,\n",
- " add_global_climate_trends={\n",
- " \"tmean\": {\n",
- " \"climate_prepend\": climate_prepend,\n",
- " \"gaussian_kernel_size\": None,\n",
- " },\n",
- " \"ppt\": {\n",
- " \"climate_prepend\": climate_prepend,\n",
- " \"gaussian_kernel_size\": None,\n",
- " },\n",
- " },\n",
- " add_local_climate_trends=None,\n",
- " # {'tmean': {'climate_prepend': None,\n",
- " # 'gaussian_kernel_size': None},\n",
- " # 'ppt': {'climate_prepend': None,\n",
- " # 'gaussian_kernel_size': None}},)\n",
- " rolling_period=8,\n",
- ")\n",
- "x_z, x_mean, x_std = utils.zscore_2d(x)\n",
- "model = fit.hurdle(x_z, y, log=False)\n",
- "yhat = model.predict(x_z)\n",
- "prediction_original = collect.fire(yhat, mtbs)\n",
- "metrics, chart = plot.fire.full_eval(\n",
- " mtbs,\n",
- " prediction_original,\n",
- " \"monthly\",\n",
- " \"prediction\",\n",
- " clim=(-0.08, 0.08),\n",
- " cmap=\"purplegreen\",\n",
- ")\n",
- "chart"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "climate_prepend = climate.sel(time=slice(\"1983\", \"1983\"))\n",
- "x, y = prepare.fire(\n",
- " climate.sel(time=slice(*[str(t) for t in analysis_tlim])), #\n",
- " nftd,\n",
- " mtbs,\n",
- " add_global_climate_trends={\n",
- " \"tmean\": {\n",
- " \"climate_prepend\": climate_prepend,\n",
- " \"gaussian_kernel_size\": None,\n",
- " },\n",
- " \"ppt\": {\n",
- " \"climate_prepend\": climate_prepend,\n",
- " \"gaussian_kernel_size\": None,\n",
- " },\n",
- " },\n",
- " add_local_climate_trends=None,\n",
- " # {'tmean': {'climate_prepend': None,\n",
- " # 'gaussian_kernel_size': None},\n",
- " # 'ppt': {'climate_prepend': None,\n",
- " # 'gaussian_kernel_size': None}},)\n",
- " rolling_period=11,\n",
- ")\n",
- "x_z, x_mean, x_std = utils.zscore_2d(x)\n",
- "model = fit.hurdle(x_z, y, log=False)\n",
- "yhat = model.predict(x_z)\n",
- "prediction = collect.fire(yhat, mtbs)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "plot.fire.monthly(prediction, \"prediction\", clim=(0.00005, 0.0015))"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "plot.fire.evaluation(mtbs, prediction, \"monthly\", \"prediction\", clim=(0, 0.005))"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "x_mean"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "We can also compare the predicted and real probabilities over time.\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "x = mtbs[\"time\"]\n",
- "y1 = mtbs[\"monthly\"].mean([\"x\", \"y\"])\n",
- "y2 = prediction[\"prediction\"].mean([\"x\", \"y\"])\n",
- "\n",
- "(\n",
- " plot.line(\n",
- " x=x,\n",
- " y=y1,\n",
- " width=900,\n",
- " height=200,\n",
- " opacity=0.5,\n",
- " color=\"rgb(175,91,92)\",\n",
- " strokeWidth=2,\n",
- " )\n",
- " + plot.line(\n",
- " x=x, y=y2, width=900, height=200, color=\"rgb(175,91,92)\", strokeWidth=2\n",
- " )\n",
- ")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Given that we fit a logistic regression, the natural model performance metric is\n",
- "area under the ROC curve, which we computed on the training data (you can use\n",
- "the variable `crossval` to repeat the model fit and compute a score on 25% held\n",
- "out data).\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Finally, we can compute correlations between model and prediction for annual,\n",
- "seasonal, and spatial trends. Note that these were not metrics used to\n",
- "explicitly fit the model, but in general a better fitting model ought to\n",
- "reproduce at least some of these trends.\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "print(\"correlation of annual trends\")\n",
- "np.corrcoef(\n",
- " mtbs[\"monthly\"].groupby(\"time.year\").mean().mean([\"x\", \"y\"]),\n",
- " prediction[\"prediction\"].groupby(\"time.year\").mean().mean([\"x\", \"y\"]),\n",
- ")[0, 1]"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "print(\"correlation of monthly trends\")\n",
- "np.corrcoef(\n",
- " mtbs[\"monthly\"].groupby(\"time.month\").mean().mean([\"x\", \"y\"]),\n",
- " prediction[\"prediction\"].groupby(\"time.month\").mean().mean([\"x\", \"y\"]),\n",
- ")[0, 1]"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "print(\"correlation of spatial trends\")\n",
- "a = mtbs[\"monthly\"].mean(\"time\").values.flatten()\n",
- "b = prediction[\"prediction\"].mean(\"time\").values.flatten()\n",
- "inds = ~np.isnan(a) & ~np.isnan(b)\n",
- "np.corrcoef(a[inds], b[inds])[0, 1]"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Prediction on future climate data\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "cmip_model = \"CanESM5\"\n",
- "scenario = \"ssp245\"\n",
- "target = 2025"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "cmip_models = [\n",
- " (\"CanESM5-CanOE\", \"r3i1p2f1\"),\n",
- " (\"MIROC-ES2L\", \"r1i1p1f2\"), #\n",
- " (\"ACCESS-CM2\", \"r1i1p1f1\"), #\n",
- " (\"ACCESS-ESM1-5\", \"r10i1p1f1\"),\n",
- " (\"MRI-ESM2-0\", \"r1i1p1f1\"),\n",
- " (\"MPI-ESM1-2-LR\", \"r10i1p1f1\"),\n",
- "]"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "import zarr"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "downscaling = \"bias-corrected\"\n",
- "sampling = \"monthly\"\n",
- "model = \"CanESM5-CanOE\"\n",
- "scenario = \"ssp245\"\n",
- "member = \"r3i1p2f1\"\n",
- "store = \"az\""
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "downscaling = \"quantile-mapping\"\n",
- "sampling = \"monthly\"\n",
- "for (model, member) in cmip_models:\n",
- " for scenario in [\"historical\", \"ssp245\", \"ssp370\", \"ssp585\"]:\n",
- "\n",
- " prefix = f\"cmip6/{downscaling}/conus/4000m/{sampling}/{model}.{scenario}.{member}.zarr\".format()\n",
- "\n",
- " if store == \"az\":\n",
- " mapper = zarr.storage.ABSStore(\n",
- " \"carbonplan-downscaling\",\n",
- " prefix=prefix,\n",
- " account_name=\"carbonplan\",\n",
- " )\n",
- " ds = xr.open_zarr(mapper, consolidated=True)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "model = \"ACCESS-CM2\"\n",
- "scenario = \"ssp370\" #'r1i1p1f1'\n",
- "future_climate = load.cmip(\n",
- " store=store,\n",
- " model=cmip_model,\n",
- " coarsen=16,\n",
- " scenario=scenario,\n",
- " tlim=(2020, 2100),\n",
- " variables=variables,\n",
- " mask=mask,\n",
- " sampling=\"monthly\",\n",
- ")"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "x = prepare.fire(future_climate, nftd, eval_only=True)\n",
- "x_z = utils.zscore_2d(x, mean=x_mean, std=x_std)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "yhat = model.predict(x_z)\n",
- "prediction = collect.fire(yhat, future_climate)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "plot.fire.summary(prediction, \"prediction\", clim=(0.0006, 0.008))"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "x = prediction[\"time\"]\n",
- "y2 = prediction[\"prediction\"].mean([\"x\", \"y\"])\n",
- "\n",
- "(\n",
- " plot.line(\n",
- " x=x, y=y2, width=900, height=200, color=\"rgb(175,91,92)\", strokeWidth=2\n",
- " )\n",
- ")"
- ]
- }
- ],
- "metadata": {
- "kernelspec": {
- "display_name": "Python 3",
- "language": "python",
- "name": "python3"
- },
- "language_info": {
- "codemirror_mode": {
- "name": "ipython",
- "version": 3
- },
- "file_extension": ".py",
- "mimetype": "text/x-python",
- "name": "python",
- "nbconvert_exporter": "python",
- "pygments_lexer": "ipython3",
- "version": "3.9.2"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 4
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "\n",
+ "# MTBS Fire Model\n",
+ "\n",
+ "_by Jeremy Freeman (CarbonPlan), September 19, 2020_\n",
+ "\n",
+ "This notebook loads downsampled MTBS fire data and TerraClimate climate data and\n",
+ "fits a logistical regression model.\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import numpy as np\n",
+ "import pandas as pd\n",
+ "import scipy as sp\n",
+ "from carbonplan_forests import load, setup, plot, fit, utils, prepare, collect"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "%matplotlib inline\n",
+ "import matplotlib.pyplot as plt\n",
+ "from showit import image, tile\n",
+ "import xarray as xr\n",
+ "from astropy.convolution import Gaussian2DKernel\n",
+ "from astropy.convolution import convolve, convolve_fft\n",
+ "import altair as alt"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "setup.plotting(remote=True)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "%load_ext autoreload\n",
+ "%autoreload 2"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "First we set some top-level parameters: the level of spatial coarsening (which\n",
+ "can speed up fitting substantially, especially useful when testing), the time\n",
+ "range (MTBS spans 1984 to 2018), and the climatic variables we'll use in the\n",
+ "model.\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "coarsen = 4\n",
+ "full_climate_period = (1983, 2018)\n",
+ "analysis_tlim = (1984, 2018)\n",
+ "variables = [\"ppt\", \"tmean\", \"cwd\"] # , \"tmax\", \"tmin\"]\n",
+ "store = \"az\""
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "First we load data from `nlcd` which we will use to mask out non-land areas and\n",
+ "data from `nftd` to use a regressors for forest type groups.\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "mask = (\n",
+ " load.nlcd(store=store, year=2001).sel(band=[41, 42, 43, 90]).sum(\"band\")\n",
+ " > 0.25\n",
+ ").astype(\"float\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "nlcd = load.nlcd(store=store, year=2001, coarsen=coarsen, mask=mask)\n",
+ "nftd = load.nftd(store=store, area_threshold=1500, coarsen=coarsen, mask=mask)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "coarsened_conus_domain = load.mask(coarsen=coarsen)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Now we load the `terraclim` data from the same time range.\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "scrolled": true
+ },
+ "outputs": [],
+ "source": [
+ "climate = load.terraclim(\n",
+ " store=store,\n",
+ " tlim=full_climate_period,\n",
+ " coarsen=coarsen,\n",
+ " variables=variables,\n",
+ " mask=mask,\n",
+ " sampling=\"monthly\",\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "And finally load the `mtbs` data\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "mtbs = load.mtbs(store=store, coarsen=coarsen, tlim=analysis_tlim, mask=mask)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Inspecting the data\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "We can plot the `mtbs` data for a specific year to get a sense of the raw data.\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "plot.fire.monthly(mtbs.sel(time=\"2018\"), clim=(0, 0.2))"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Here is the same thing but averaged over all years\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "plot.fire.monthly(mtbs, clim=(0.00005, 0.0015))"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## We can plot spatially averaged data over time to see both seasonable trends, and\n",
+ "\n",
+ "the fact that fire frequency and magnitude has increased over time.\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "x = mtbs[\"time\"]\n",
+ "y = mtbs[\"monthly\"].mean([\"x\", \"y\"])\n",
+ "\n",
+ "plot.line(\n",
+ " x=x, y=y, width=900, height=200, color=\"rgb(175,91,92)\", strokeWidth=2\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "We can summarize the data by plotting annual, seasonal, and spatial trends by\n",
+ "averaging across different groupings and dimensions.\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "plot.fire.summary(mtbs, clim=(0, 0.005))"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "As a motivation for fitting fires as functions of climatic variables, we can\n",
+ "look at spatially averaged climatic variables alongside fires, e.g. average\n",
+ "tempreature, and see that there is a clear relationship (in this case a positive\n",
+ "correlation).\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "x = mtbs.groupby(\"time.year\").mean()[\"year\"]\n",
+ "y1 = mtbs[\"monthly\"].groupby(\"time.year\").sum().mean([\"x\", \"y\"])\n",
+ "y2 = climate[\"tmean\"].groupby(\"time.year\").max().mean([\"x\", \"y\"])\n",
+ "\n",
+ "(\n",
+ " plot.line(x=x, y=sp.stats.zscore(y1), color=\"rgb(175,91,92)\")\n",
+ " + plot.line(x=x, y=sp.stats.zscore(y2), color=\"rgb(175,91,92)\", opacity=0.5)\n",
+ ")\n",
+ "\n",
+ "# np.corrcoef(y1,y2)[0,1]"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# Tmean precip comparisons\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "sl = slice(\"1984\", \"2008\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "single_pixel = climate.isel(x=25, y=25)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "plt.figure(figsize=(15, 8))\n",
+ "xr.DataArray(\n",
+ " np.repeat(\n",
+ " single_pixel[\"tmean\"].sel(time=sl).groupby(\"time.year\").max().values, 12\n",
+ " ),\n",
+ " coords=single_pixel.sel(time=sl).coords,\n",
+ ").plot(label=\"groupby\")\n",
+ "single_pixel[\"tmean\"].rolling(time=12).max().sel(time=sl).plot(label=\"rolling\")\n",
+ "single_pixel[\"tmean\"].sel(time=sl).plot(label=\"raw\", alpha=0.5)\n",
+ "plt.legend()\n",
+ "plt.ylim(0, 18)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "ts = climate[\"tmean\"].groupby(\"time.year\").max().mean(dim=[\"x\", \"y\"]).values\n",
+ "groupby_global_max_then_mean = xr.DataArray(\n",
+ " np.repeat(ts, 12), coords=single_pixel.coords\n",
+ ")\n",
+ "ts = climate[\"tmean\"].mean(dim=[\"x\", \"y\"]).groupby(\"time.year\").max().values\n",
+ "groupby_global_mean_then_max = xr.DataArray(\n",
+ " np.repeat(ts, 12), coords=single_pixel.coords\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "groupby_global_mean_then_max.plot(label=\"mean then max\")\n",
+ "groupby_global_max_then_mean.plot(label=\"max then mean\")\n",
+ "plt.legend()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "rolling_global_max = (\n",
+ " climate[\"tmean\"]\n",
+ " .mean(dim=[\"x\", \"y\"])\n",
+ " .rolling(dim={\"time\": 12}, min_periods=8, center=False)\n",
+ " .max()\n",
+ " .sel(time=inspection_slice)\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "plt.figure(figsize=(10, 8))\n",
+ "inspection_slice = slice(\"1984\", \"1990\")\n",
+ "rolling_global_max.sel(time=inspection_slice).plot(label=\"rolling\")\n",
+ "# groupby_global_max_annual.sel(time=inspection_slice).plot(label='groupby')\n",
+ "\n",
+ "groupby_global_mean_then_max.sel(time=inspection_slice).plot(label=\"groupby\")\n",
+ "climate[\"tmean\"].sel(time=inspection_slice).mean(dim=[\"x\", \"y\"]).plot(\n",
+ " label=\"raw\"\n",
+ ")\n",
+ "plt.ylim(16, 24)\n",
+ "plt.legend()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "climate[\"ppt\"].rolling(time=12, center=False).sum().mean(dim=[\"x\", \"y\"]).plot()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "climate[\"tmean\"].rolling(time=12, center=False).max().isel(time=30).plot()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "climate[\"ppt\"].resample(time=\"AS\").mean().isel(time=3).plot()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "climate[\"ppt\"].groupby(\"time.year\").sum().mean(dim=[\"x\", \"y\"]).plot()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "rolling = (\n",
+ " climate[\"ppt\"]\n",
+ " .rolling(time=12, center=False)\n",
+ " .sum()\n",
+ " .mean(dim=[\"x\", \"y\"])\n",
+ " .sel(time=inspection_slice)\n",
+ ")\n",
+ "rolling.plot(label=\"rolling\")\n",
+ "xr.DataArray(\n",
+ " np.repeat(\n",
+ " climate[\"ppt\"]\n",
+ " .sel(time=inspection_slice)\n",
+ " .groupby(\"time.year\")\n",
+ " .sum()\n",
+ " .mean(dim=[\"x\", \"y\"])\n",
+ " .values,\n",
+ " 12,\n",
+ " ),\n",
+ " coords=rolling.coords,\n",
+ ").plot(label=\"groupby\")\n",
+ "plt.legend()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# Original\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "climate.isel(time=3).tmean.plot()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "rolling_period = slice(\"1984\", \"2018\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "climate_prepend = climate.sel(time=slice(\"1983\", \"1983\"))\n",
+ "x, y = prepare.fire(\n",
+ " climate.sel(time=slice(*[str(t) for t in analysis_tlim])), #\n",
+ " nftd,\n",
+ " mtbs,\n",
+ " add_global_climate_trends={\n",
+ " \"tmean\": {\"climate_prepend\": None, \"gaussian_kernel_size\": None},\n",
+ " \"ppt\": {\"climate_prepend\": None, \"gaussian_kernel_size\": None},\n",
+ " },\n",
+ " add_local_climate_trends=None,\n",
+ ")\n",
+ "# {'tmean': {'climate_prepend': None,\n",
+ "# 'gaussian_kernel_size': None},\n",
+ "# 'ppt': {'climate_prepend': None,\n",
+ "# 'gaussian_kernel_size': None}},)\n",
+ "# rolling_period=12)\n",
+ "x_z, x_mean, x_std = utils.zscore_2d(x)\n",
+ "model = fit.hurdle(x_z, y, log=False)\n",
+ "yhat = model.predict(x_z)\n",
+ "prediction_original = collect.fire(yhat, mtbs)\n",
+ "metrics, chart = plot.fire.full_eval(\n",
+ " mtbs,\n",
+ " prediction_original,\n",
+ " \"monthly\",\n",
+ " \"prediction\",\n",
+ " clim=(-0.08, 0.08),\n",
+ " cmap=\"purplegreen\",\n",
+ ")\n",
+ "chart"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "climate_prepend = climate.sel(time=slice(\"1983\", \"1983\"))\n",
+ "x, y = prepare.fire(\n",
+ " climate.sel(time=slice(*[str(t) for t in analysis_tlim])), #\n",
+ " nftd,\n",
+ " mtbs,\n",
+ " add_global_climate_trends={\n",
+ " \"tmean\": {\n",
+ " \"climate_prepend\": climate_prepend,\n",
+ " \"gaussian_kernel_size\": None,\n",
+ " },\n",
+ " \"ppt\": {\n",
+ " \"climate_prepend\": climate_prepend,\n",
+ " \"gaussian_kernel_size\": None,\n",
+ " },\n",
+ " },\n",
+ " add_local_climate_trends=None,\n",
+ " # {'tmean': {'climate_prepend': None,\n",
+ " # 'gaussian_kernel_size': None},\n",
+ " # 'ppt': {'climate_prepend': None,\n",
+ " # 'gaussian_kernel_size': None}},)\n",
+ " rolling_period=8,\n",
+ ")\n",
+ "x_z, x_mean, x_std = utils.zscore_2d(x)\n",
+ "model = fit.hurdle(x_z, y, log=False)\n",
+ "yhat = model.predict(x_z)\n",
+ "prediction_original = collect.fire(yhat, mtbs)\n",
+ "metrics, chart = plot.fire.full_eval(\n",
+ " mtbs,\n",
+ " prediction_original,\n",
+ " \"monthly\",\n",
+ " \"prediction\",\n",
+ " clim=(-0.08, 0.08),\n",
+ " cmap=\"purplegreen\",\n",
+ ")\n",
+ "chart"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "climate_prepend = climate.sel(time=slice(\"1983\", \"1983\"))\n",
+ "x, y = prepare.fire(\n",
+ " climate.sel(time=slice(*[str(t) for t in analysis_tlim])), #\n",
+ " nftd,\n",
+ " mtbs,\n",
+ " add_global_climate_trends={\n",
+ " \"tmean\": {\n",
+ " \"climate_prepend\": climate_prepend,\n",
+ " \"gaussian_kernel_size\": None,\n",
+ " },\n",
+ " \"ppt\": {\n",
+ " \"climate_prepend\": climate_prepend,\n",
+ " \"gaussian_kernel_size\": None,\n",
+ " },\n",
+ " },\n",
+ " add_local_climate_trends=None,\n",
+ " # {'tmean': {'climate_prepend': None,\n",
+ " # 'gaussian_kernel_size': None},\n",
+ " # 'ppt': {'climate_prepend': None,\n",
+ " # 'gaussian_kernel_size': None}},)\n",
+ " rolling_period=11,\n",
+ ")\n",
+ "x_z, x_mean, x_std = utils.zscore_2d(x)\n",
+ "model = fit.hurdle(x_z, y, log=False)\n",
+ "yhat = model.predict(x_z)\n",
+ "prediction = collect.fire(yhat, mtbs)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "plot.fire.monthly(prediction, \"prediction\", clim=(0.00005, 0.0015))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "plot.fire.evaluation(mtbs, prediction, \"monthly\", \"prediction\", clim=(0, 0.005))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "x_mean"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "We can also compare the predicted and real probabilities over time.\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "x = mtbs[\"time\"]\n",
+ "y1 = mtbs[\"monthly\"].mean([\"x\", \"y\"])\n",
+ "y2 = prediction[\"prediction\"].mean([\"x\", \"y\"])\n",
+ "\n",
+ "(\n",
+ " plot.line(\n",
+ " x=x,\n",
+ " y=y1,\n",
+ " width=900,\n",
+ " height=200,\n",
+ " opacity=0.5,\n",
+ " color=\"rgb(175,91,92)\",\n",
+ " strokeWidth=2,\n",
+ " )\n",
+ " + plot.line(\n",
+ " x=x, y=y2, width=900, height=200, color=\"rgb(175,91,92)\", strokeWidth=2\n",
+ " )\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Given that we fit a logistic regression, the natural model performance metric is\n",
+ "area under the ROC curve, which we computed on the training data (you can use\n",
+ "the variable `crossval` to repeat the model fit and compute a score on 25% held\n",
+ "out data).\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Finally, we can compute correlations between model and prediction for annual,\n",
+ "seasonal, and spatial trends. Note that these were not metrics used to\n",
+ "explicitly fit the model, but in general a better fitting model ought to\n",
+ "reproduce at least some of these trends.\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "print(\"correlation of annual trends\")\n",
+ "np.corrcoef(\n",
+ " mtbs[\"monthly\"].groupby(\"time.year\").mean().mean([\"x\", \"y\"]),\n",
+ " prediction[\"prediction\"].groupby(\"time.year\").mean().mean([\"x\", \"y\"]),\n",
+ ")[0, 1]"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "print(\"correlation of monthly trends\")\n",
+ "np.corrcoef(\n",
+ " mtbs[\"monthly\"].groupby(\"time.month\").mean().mean([\"x\", \"y\"]),\n",
+ " prediction[\"prediction\"].groupby(\"time.month\").mean().mean([\"x\", \"y\"]),\n",
+ ")[0, 1]"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "print(\"correlation of spatial trends\")\n",
+ "a = mtbs[\"monthly\"].mean(\"time\").values.flatten()\n",
+ "b = prediction[\"prediction\"].mean(\"time\").values.flatten()\n",
+ "inds = ~np.isnan(a) & ~np.isnan(b)\n",
+ "np.corrcoef(a[inds], b[inds])[0, 1]"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Prediction on future climate data\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "cmip_model = \"CanESM5\"\n",
+ "scenario = \"ssp245\"\n",
+ "target = 2025"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "cmip_models = [\n",
+ " (\"CanESM5-CanOE\", \"r3i1p2f1\"),\n",
+ " (\"MIROC-ES2L\", \"r1i1p1f2\"), #\n",
+ " (\"ACCESS-CM2\", \"r1i1p1f1\"), #\n",
+ " (\"ACCESS-ESM1-5\", \"r10i1p1f1\"),\n",
+ " (\"MRI-ESM2-0\", \"r1i1p1f1\"),\n",
+ " (\"MPI-ESM1-2-LR\", \"r10i1p1f1\"),\n",
+ "]"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import zarr"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "downscaling = \"bias-corrected\"\n",
+ "sampling = \"monthly\"\n",
+ "model = \"CanESM5-CanOE\"\n",
+ "scenario = \"ssp245\"\n",
+ "member = \"r3i1p2f1\"\n",
+ "store = \"az\""
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "downscaling = \"quantile-mapping\"\n",
+ "sampling = \"monthly\"\n",
+ "for (model, member) in cmip_models:\n",
+ " for scenario in [\"historical\", \"ssp245\", \"ssp370\", \"ssp585\"]:\n",
+ "\n",
+ " prefix = f\"cmip6/{downscaling}/conus/4000m/{sampling}/{model}.{scenario}.{member}.zarr\".format()\n",
+ "\n",
+ " if store == \"az\":\n",
+ " mapper = zarr.storage.ABSStore(\n",
+ " \"carbonplan-downscaling\",\n",
+ " prefix=prefix,\n",
+ " account_name=\"carbonplan\",\n",
+ " )\n",
+ " ds = xr.open_zarr(mapper, consolidated=True)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "model = \"ACCESS-CM2\"\n",
+ "scenario = \"ssp370\" #'r1i1p1f1'\n",
+ "future_climate = load.cmip(\n",
+ " store=store,\n",
+ " model=cmip_model,\n",
+ " coarsen=16,\n",
+ " scenario=scenario,\n",
+ " tlim=(2020, 2100),\n",
+ " variables=variables,\n",
+ " mask=mask,\n",
+ " sampling=\"monthly\",\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "x = prepare.fire(future_climate, nftd, eval_only=True)\n",
+ "x_z = utils.zscore_2d(x, mean=x_mean, std=x_std)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "yhat = model.predict(x_z)\n",
+ "prediction = collect.fire(yhat, future_climate)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "plot.fire.summary(prediction, \"prediction\", clim=(0.0006, 0.008))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "x = prediction[\"time\"]\n",
+ "y2 = prediction[\"prediction\"].mean([\"x\", \"y\"])\n",
+ "\n",
+ "(\n",
+ " plot.line(\n",
+ " x=x, y=y2, width=900, height=200, color=\"rgb(175,91,92)\", strokeWidth=2\n",
+ " )\n",
+ ")"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.9.2"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 4
}
diff --git a/notebooks/fire/fire_model_supersections.ipynb b/notebooks/fire/fire_model_supersections.ipynb
index 0edf389..b4be3e1 100644
--- a/notebooks/fire/fire_model_supersections.ipynb
+++ b/notebooks/fire/fire_model_supersections.ipynb
@@ -1,266 +1,266 @@
{
- "cells": [
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "\n",
- "# MTBS Fire Supersection Averages\n",
- "\n",
- "_by Jeremy Freeman (CarbonPlan), Januyar 13, 2020_\n",
- "\n",
- "This notebook loads downsampled MTBS fire data and shows avearges within\n",
- "supersections.\n"
- ]
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "\n",
+ "# MTBS Fire Supersection Averages\n",
+ "\n",
+ "_by Jeremy Freeman (CarbonPlan), Januyar 13, 2020_\n",
+ "\n",
+ "This notebook loads downsampled MTBS fire data and shows avearges within\n",
+ "supersections.\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import numpy as np\n",
+ "import pandas as pd\n",
+ "import scipy as sp\n",
+ "import geopandas as gpd\n",
+ "import regionmask as rm\n",
+ "from carbonplan_forests import load, setup, plot, fit, utils, prepare, collect"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "%matplotlib inline\n",
+ "import matplotlib.pyplot as plt\n",
+ "from showit import image, tile"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from palettable.colorbrewer.sequential import YlOrRd_9\n",
+ "import matplotlib.pyplot as plt\n",
+ "\n",
+ "cmap = YlOrRd_9.mpl_colormap"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "setup.plotting(remote=False)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "%load_ext autoreload\n",
+ "%autoreload 2"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Set variables\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "coarsen = 16\n",
+ "tlim = (1984, 2018)\n",
+ "store = \"local\""
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Load the mask from `nlcd`\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "mask = load.mask(store=store, year=2001)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Load the `mtbs` data\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "mtbs = load.mtbs(store=store, coarsen=coarsen, tlim=tlim, mask=mask)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Load the supersections\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "regions = gpd.read_file(\n",
+ " \"https://storage.googleapis.com/carbonplan-data/raw/ecoregions/supersections.geojson\"\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "masks = rm.mask_3D_geopandas(regions, mtbs)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Create integrated risk function\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from scipy.stats import binom\n",
+ "\n",
+ "\n",
+ "def integrated_risk(p):\n",
+ " return (1 - binom.cdf(0, 100, p)) * 100"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Make map before 2000\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "before_2000 = (\n",
+ " mtbs.sel(time=slice(\"1984\", \"2000\")).groupby(\"time.year\").sum().mean(\"year\")\n",
+ ")\n",
+ "risks_before_2000 = np.asarray(\n",
+ " [\n",
+ " before_2000.monthly.where(masks.sel(region=i))\n",
+ " .mean([\"x\", \"y\"])\n",
+ " .values.item()\n",
+ " for i in masks[\"region\"]\n",
+ " ]\n",
+ ")\n",
+ "regions.to_crs(\"EPSG:5070\").plot(\n",
+ " integrated_risk(risks_before_2000),\n",
+ " figsize=[15, 8],\n",
+ " cmap=cmap,\n",
+ " edgecolor=[0, 0, 0],\n",
+ " linewidth=0.3,\n",
+ " vmin=0,\n",
+ " vmax=50,\n",
+ " legend=True,\n",
+ ")\n",
+ "plt.axis(\"off\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Make map after 2000\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "after_2000 = (\n",
+ " mtbs.sel(time=slice(\"2001\", \"2018\")).groupby(\"time.year\").sum().mean(\"year\")\n",
+ ")\n",
+ "risks_after_2000 = np.asarray(\n",
+ " [\n",
+ " after_2000.monthly.where(masks.sel(region=i))\n",
+ " .mean([\"x\", \"y\"])\n",
+ " .values.item()\n",
+ " for i in masks[\"region\"]\n",
+ " ]\n",
+ ")\n",
+ "regions.to_crs(\"EPSG:5070\").plot(\n",
+ " integrated_risk(risks_after_2000),\n",
+ " figsize=[15, 8],\n",
+ " cmap=cmap,\n",
+ " edgecolor=[0, 0, 0],\n",
+ " linewidth=0.3,\n",
+ " vmin=0,\n",
+ " vmax=50,\n",
+ " legend=True,\n",
+ ")\n",
+ "plt.axis(\"off\")"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.8.6"
+ }
},
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "import numpy as np\n",
- "import pandas as pd\n",
- "import scipy as sp\n",
- "import geopandas as gpd\n",
- "import regionmask as rm\n",
- "from carbonplan_forests import load, setup, plot, fit, utils, prepare, collect"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "%matplotlib inline\n",
- "import matplotlib.pyplot as plt\n",
- "from showit import image, tile"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "from palettable.colorbrewer.sequential import YlOrRd_9\n",
- "import matplotlib.pyplot as plt\n",
- "\n",
- "cmap = YlOrRd_9.mpl_colormap"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "setup.plotting(remote=False)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "%load_ext autoreload\n",
- "%autoreload 2"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Set variables\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "coarsen = 16\n",
- "tlim = (1984, 2018)\n",
- "store = \"local\""
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Load the mask from `nlcd`\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "mask = load.mask(store=store, year=2001)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Load the `mtbs` data\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "mtbs = load.mtbs(store=store, coarsen=coarsen, tlim=tlim, mask=mask)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Load the supersections\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "regions = gpd.read_file(\n",
- " \"https://storage.googleapis.com/carbonplan-data/raw/ecoregions/supersections.geojson\"\n",
- ")"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "masks = rm.mask_3D_geopandas(regions, mtbs)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Create integrated risk function\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "from scipy.stats import binom\n",
- "\n",
- "\n",
- "def integrated_risk(p):\n",
- " return (1 - binom.cdf(0, 100, p)) * 100"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Make map before 2000\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "before_2000 = (\n",
- " mtbs.sel(time=slice(\"1984\", \"2000\")).groupby(\"time.year\").sum().mean(\"year\")\n",
- ")\n",
- "risks_before_2000 = np.asarray(\n",
- " [\n",
- " before_2000.monthly.where(masks.sel(region=i))\n",
- " .mean([\"x\", \"y\"])\n",
- " .values.item()\n",
- " for i in masks[\"region\"]\n",
- " ]\n",
- ")\n",
- "regions.to_crs(\"EPSG:5070\").plot(\n",
- " integrated_risk(risks_before_2000),\n",
- " figsize=[15, 8],\n",
- " cmap=cmap,\n",
- " edgecolor=[0, 0, 0],\n",
- " linewidth=0.3,\n",
- " vmin=0,\n",
- " vmax=50,\n",
- " legend=True,\n",
- ")\n",
- "plt.axis(\"off\")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Make map after 2000\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "after_2000 = (\n",
- " mtbs.sel(time=slice(\"2001\", \"2018\")).groupby(\"time.year\").sum().mean(\"year\")\n",
- ")\n",
- "risks_after_2000 = np.asarray(\n",
- " [\n",
- " after_2000.monthly.where(masks.sel(region=i))\n",
- " .mean([\"x\", \"y\"])\n",
- " .values.item()\n",
- " for i in masks[\"region\"]\n",
- " ]\n",
- ")\n",
- "regions.to_crs(\"EPSG:5070\").plot(\n",
- " integrated_risk(risks_after_2000),\n",
- " figsize=[15, 8],\n",
- " cmap=cmap,\n",
- " edgecolor=[0, 0, 0],\n",
- " linewidth=0.3,\n",
- " vmin=0,\n",
- " vmax=50,\n",
- " legend=True,\n",
- ")\n",
- "plt.axis(\"off\")"
- ]
- }
- ],
- "metadata": {
- "kernelspec": {
- "display_name": "Python 3",
- "language": "python",
- "name": "python3"
- },
- "language_info": {
- "codemirror_mode": {
- "name": "ipython",
- "version": 3
- },
- "file_extension": ".py",
- "mimetype": "text/x-python",
- "name": "python",
- "nbconvert_exporter": "python",
- "pygments_lexer": "ipython3",
- "version": "3.8.6"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 4
+ "nbformat": 4,
+ "nbformat_minor": 4
}
diff --git a/notebooks/insects/insects_model.ipynb b/notebooks/insects/insects_model.ipynb
index 995831e..368093a 100644
--- a/notebooks/insects/insects_model.ipynb
+++ b/notebooks/insects/insects_model.ipynb
@@ -1,236 +1,236 @@
{
- "cells": [
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "\n",
- "# FIA Insect Model\n",
- "\n",
- "_by Jeremy Freeman (CarbonPlan), October 26, 2020_\n",
- "\n",
- "This notebook demos insect modelling.\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "import numpy as np\n",
- "import pandas as pd\n",
- "from carbonplan_forests import setup, plot, load, fit, utils, prepare"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "setup.plotting(remote=False)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Load the raw FIA data grouped by repeated inventories\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "df = load.fia(store=\"local\", states=\"conus\", group_repeats=True)\n",
- "df = load.terraclim(\n",
- " store=\"local\",\n",
- " tlim=(int(df[\"year_0\"].min()), 2020),\n",
- " data_vars=[\"ppt\", \"tavg\", \"pdsi\", \"cwd\", \"pet\", \"vpd\"],\n",
- " data_aggs=[\"sum\", \"mean\", \"mean\", \"sum\", \"mean\", \"mean\"],\n",
- " df=df,\n",
- " group_repeats=True,\n",
- ")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Prepare data for model fitting\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "x, y, meta = prepare.insects(df)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "x_z, x_mean, x_std = utils.zscore_2d(x)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Fit models\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "pf = meta.copy()\n",
- "pf[\"observed\"] = y\n",
- "pf[\"predicted\"] = np.NaN\n",
- "\n",
- "models = {}\n",
- "for code in pf[\"type_code\"].unique():\n",
- " inds = pf[\"type_code\"] == code\n",
- " if (y[inds].sum() > 1) & (y[inds].sum() > 1):\n",
- " model = fit.hurdle(x=x_z[inds], y=y[inds])\n",
- " models[code] = model\n",
- " pf.loc[inds, \"predicted\"] = model.predict(x=x_z[inds])\n",
- "\n",
- "pf = pf[pf[\"predicted\"] < 1]"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Compute simple score metrics (on all data and just on the values where fraction\n",
- "insects was positive)\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "pf[[\"observed\", \"predicted\"]].corr().iloc[0, 1] ** 2"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "pf[pf[\"observed\"] > 0][[\"observed\", \"predicted\"]].corr().iloc[0, 1] ** 2"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Plot observed vs predicted\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "plot.xy(\n",
- " x=pf[\"observed\"],\n",
- " y=pf[\"predicted\"],\n",
- " xlabel=\"measured fraction insects\",\n",
- " ylabel=\"predicted fraction insects\",\n",
- " xlim=(0, 1),\n",
- " ylim=(0, 1),\n",
- " width=300,\n",
- " height=300,\n",
- " opacity=0.1,\n",
- ")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Make a map of actual fraction insects\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "plot.carto(\n",
- " lat=pf[\"lat\"],\n",
- " lon=pf[\"lon\"],\n",
- " color=pf[\"observed\"],\n",
- " cmap=\"reds\",\n",
- " clim=(0, 0.2),\n",
- " size=5,\n",
- " opacity=0.75,\n",
- ")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Make a map of predicted fraction insects\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "plot.carto(\n",
- " lat=pf[\"lat\"],\n",
- " lon=pf[\"lon\"],\n",
- " color=pf[\"predicted\"],\n",
- " clabel=\"fraction_insects * mortality\",\n",
- " cmap=\"reds\",\n",
- " clim=(0, 0.2),\n",
- " size=2,\n",
- " opacity=0.75,\n",
- ")"
- ]
- }
- ],
- "metadata": {
- "kernelspec": {
- "display_name": "Python 3",
- "language": "python",
- "name": "python3"
- },
- "language_info": {
- "codemirror_mode": {
- "name": "ipython",
- "version": 3
- },
- "file_extension": ".py",
- "mimetype": "text/x-python",
- "name": "python",
- "nbconvert_exporter": "python",
- "pygments_lexer": "ipython3",
- "version": "3.8.5"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 4
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "\n",
+ "# FIA Insect Model\n",
+ "\n",
+ "_by Jeremy Freeman (CarbonPlan), October 26, 2020_\n",
+ "\n",
+ "This notebook demos insect modelling.\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import numpy as np\n",
+ "import pandas as pd\n",
+ "from carbonplan_forests import setup, plot, load, fit, utils, prepare"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "setup.plotting(remote=False)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Load the raw FIA data grouped by repeated inventories\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "df = load.fia(store=\"local\", states=\"conus\", group_repeats=True)\n",
+ "df = load.terraclim(\n",
+ " store=\"local\",\n",
+ " tlim=(int(df[\"year_0\"].min()), 2020),\n",
+ " data_vars=[\"ppt\", \"tavg\", \"pdsi\", \"cwd\", \"pet\", \"vpd\"],\n",
+ " data_aggs=[\"sum\", \"mean\", \"mean\", \"sum\", \"mean\", \"mean\"],\n",
+ " df=df,\n",
+ " group_repeats=True,\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Prepare data for model fitting\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "x, y, meta = prepare.insects(df)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "x_z, x_mean, x_std = utils.zscore_2d(x)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Fit models\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "pf = meta.copy()\n",
+ "pf[\"observed\"] = y\n",
+ "pf[\"predicted\"] = np.NaN\n",
+ "\n",
+ "models = {}\n",
+ "for code in pf[\"type_code\"].unique():\n",
+ " inds = pf[\"type_code\"] == code\n",
+ " if (y[inds].sum() > 1) & (y[inds].sum() > 1):\n",
+ " model = fit.hurdle(x=x_z[inds], y=y[inds])\n",
+ " models[code] = model\n",
+ " pf.loc[inds, \"predicted\"] = model.predict(x=x_z[inds])\n",
+ "\n",
+ "pf = pf[pf[\"predicted\"] < 1]"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Compute simple score metrics (on all data and just on the values where fraction\n",
+ "insects was positive)\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "pf[[\"observed\", \"predicted\"]].corr().iloc[0, 1] ** 2"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "pf[pf[\"observed\"] > 0][[\"observed\", \"predicted\"]].corr().iloc[0, 1] ** 2"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Plot observed vs predicted\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "plot.xy(\n",
+ " x=pf[\"observed\"],\n",
+ " y=pf[\"predicted\"],\n",
+ " xlabel=\"measured fraction insects\",\n",
+ " ylabel=\"predicted fraction insects\",\n",
+ " xlim=(0, 1),\n",
+ " ylim=(0, 1),\n",
+ " width=300,\n",
+ " height=300,\n",
+ " opacity=0.1,\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Make a map of actual fraction insects\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "plot.carto(\n",
+ " lat=pf[\"lat\"],\n",
+ " lon=pf[\"lon\"],\n",
+ " color=pf[\"observed\"],\n",
+ " cmap=\"reds\",\n",
+ " clim=(0, 0.2),\n",
+ " size=5,\n",
+ " opacity=0.75,\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Make a map of predicted fraction insects\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "plot.carto(\n",
+ " lat=pf[\"lat\"],\n",
+ " lon=pf[\"lon\"],\n",
+ " color=pf[\"predicted\"],\n",
+ " clabel=\"fraction_insects * mortality\",\n",
+ " cmap=\"reds\",\n",
+ " clim=(0, 0.2),\n",
+ " size=2,\n",
+ " opacity=0.75,\n",
+ ")"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.8.5"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 4
}
diff --git a/notebooks/insects/insects_results.ipynb b/notebooks/insects/insects_results.ipynb
index cf79568..1a2c765 100644
--- a/notebooks/insects/insects_results.ipynb
+++ b/notebooks/insects/insects_results.ipynb
@@ -1,157 +1,157 @@
{
- "cells": [
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "\n",
- "# FIA Insects Results\n",
- "\n",
- "_by Jeremy Freeman (CarbonPlan), October 26, 2020_\n",
- "\n",
- "This notebook loads insects results.\n"
- ]
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "\n",
+ "# FIA Insects Results\n",
+ "\n",
+ "_by Jeremy Freeman (CarbonPlan), October 26, 2020_\n",
+ "\n",
+ "This notebook loads insects results.\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import numpy as np\n",
+ "import pandas as pd\n",
+ "from carbonplan_forests import setup, plot, load, fit, utils, prepare"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "setup.plotting(remote=False)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Load the raw FIA grouped data\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "pf = pd.read_parquet(\n",
+ " \"/Users/freeman/github/carbonplan/forests/scripts/data/insects.parquet\"\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Filter out bad values\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "badinds = (pf[\"historical\"] > 1) | (np.isnan(pf[\"historical\"]))\n",
+ "for key in pf.columns:\n",
+ " if key not in [\"lat\", \"lon\", \"type_code\", \"r2\"]:\n",
+ " badinds = badinds | ((pf[key] > 1) | (np.isnan(pf[key])))\n",
+ "pf = pf[~badinds]"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "pf.columns"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Make a map of the historical prediction (from the period used for fitting)\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "plot.carto(\n",
+ " lat=pf[\"lat\"],\n",
+ " lon=pf[\"lon\"],\n",
+ " color=pf[\"historical\"],\n",
+ " cmap=\"reds\",\n",
+ " clim=(0, 0.3),\n",
+ " size=2,\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Make a time series of spatially averaged projections\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "years = np.arange(2020, 2120, 20)\n",
+ "y1 = [pf[\"BCC-CSM2-MR_ssp245_\" + str(year)].mean() for year in years]\n",
+ "y2 = [pf[\"BCC-CSM2-MR_ssp370_\" + str(year)].mean() for year in years]\n",
+ "y3 = [pf[\"BCC-CSM2-MR_ssp585_\" + str(year)].mean() for year in years]\n",
+ "opts = {\n",
+ " \"color\": \"rgb(164,69,70)\",\n",
+ " \"ylabel\": \"fraction insects\",\n",
+ " \"xlabel\": \"year\",\n",
+ "}\n",
+ "(\n",
+ " plot.line(x=years, y=y1, opacity=0.5, ylim=[0, 0.02], **opts)\n",
+ " + plot.line(x=years, y=y2, opacity=0.75, **opts)\n",
+ " + plot.line(x=years, y=y3, opacity=1, **opts)\n",
+ ")"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.8.5"
+ }
},
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "import numpy as np\n",
- "import pandas as pd\n",
- "from carbonplan_forests import setup, plot, load, fit, utils, prepare"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "setup.plotting(remote=False)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Load the raw FIA grouped data\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "pf = pd.read_parquet(\n",
- " \"/Users/freeman/github/carbonplan/forests/scripts/data/insects.parquet\"\n",
- ")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Filter out bad values\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "badinds = (pf[\"historical\"] > 1) | (np.isnan(pf[\"historical\"]))\n",
- "for key in pf.columns:\n",
- " if key not in [\"lat\", \"lon\", \"type_code\", \"r2\"]:\n",
- " badinds = badinds | ((pf[key] > 1) | (np.isnan(pf[key])))\n",
- "pf = pf[~badinds]"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "pf.columns"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Make a map of the historical prediction (from the period used for fitting)\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "plot.carto(\n",
- " lat=pf[\"lat\"],\n",
- " lon=pf[\"lon\"],\n",
- " color=pf[\"historical\"],\n",
- " cmap=\"reds\",\n",
- " clim=(0, 0.3),\n",
- " size=2,\n",
- ")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Make a time series of spatially averaged projections\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "years = np.arange(2020, 2120, 20)\n",
- "y1 = [pf[\"BCC-CSM2-MR_ssp245_\" + str(year)].mean() for year in years]\n",
- "y2 = [pf[\"BCC-CSM2-MR_ssp370_\" + str(year)].mean() for year in years]\n",
- "y3 = [pf[\"BCC-CSM2-MR_ssp585_\" + str(year)].mean() for year in years]\n",
- "opts = {\n",
- " \"color\": \"rgb(164,69,70)\",\n",
- " \"ylabel\": \"fraction insects\",\n",
- " \"xlabel\": \"year\",\n",
- "}\n",
- "(\n",
- " plot.line(x=years, y=y1, opacity=0.5, ylim=[0, 0.02], **opts)\n",
- " + plot.line(x=years, y=y2, opacity=0.75, **opts)\n",
- " + plot.line(x=years, y=y3, opacity=1, **opts)\n",
- ")"
- ]
- }
- ],
- "metadata": {
- "kernelspec": {
- "display_name": "Python 3",
- "language": "python",
- "name": "python3"
- },
- "language_info": {
- "codemirror_mode": {
- "name": "ipython",
- "version": 3
- },
- "file_extension": ".py",
- "mimetype": "text/x-python",
- "name": "python",
- "nbconvert_exporter": "python",
- "pygments_lexer": "ipython3",
- "version": "3.8.5"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 4
+ "nbformat": 4,
+ "nbformat_minor": 4
}
diff --git a/notebooks/paper/Calculations/change-factor-calculations.ipynb b/notebooks/paper/Calculations/change-factor-calculations.ipynb
index 053a96b..807c0c7 100644
--- a/notebooks/paper/Calculations/change-factor-calculations.ipynb
+++ b/notebooks/paper/Calculations/change-factor-calculations.ipynb
@@ -1,147 +1,147 @@
{
- "cells": [
- {
- "cell_type": "markdown",
- "id": "incident-friday",
- "metadata": {},
- "source": [
- "\n",
- "\n",
- "# Figure 3: Future projections for each impact\n",
- "\n",
- "_Author: Oriana Chegwidden_\n",
- "\n",
- "The methods below conduct the analyses to calculate the fire risk change factors\n",
- "included the manuscript <<< insert doi >>>.\n"
- ]
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "id": "incident-friday",
+ "metadata": {},
+ "source": [
+ "\n",
+ "\n",
+ "# Figure 3: Future projections for each impact\n",
+ "\n",
+ "_Author: Oriana Chegwidden_\n",
+ "\n",
+ "The methods below conduct the analyses to calculate the fire risk change factors\n",
+ "included the manuscript <<< insert doi >>>.\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "static-italy",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "%load_ext autoreload\n",
+ "%autoreload 2\n",
+ "\n",
+ "from carbonplan_forest_risks import load, setup, plot, fit, utils, prepare, collect\n",
+ "import xarray as xr\n",
+ "import numpy as np\n",
+ "from carbonplan_forest_risks.utils import get_store"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "driving-print",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "coarsen = 4"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "underlying-genealogy",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "mask = (\n",
+ " (\n",
+ " load.nlcd(store=\"az\", year=2001).sel(band=[41, 42, 43, 90]).sum(\"band\")\n",
+ " > 0.25\n",
+ " )\n",
+ " .astype(\"float\")\n",
+ " .coarsen(x=coarsen, y=coarsen, boundary=\"trim\")\n",
+ " .mean()\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "major-compilation",
+ "metadata": {},
+ "source": [
+ "# Load in fire data\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "armed-penguin",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "historical_fire = xr.open_zarr(\n",
+ " get_store(\n",
+ " \"carbonplan-forests\", \"risks/results/paper/fire_terraclimate_v6.zarr\"\n",
+ " )\n",
+ ").load()\n",
+ "fire_mask = ~np.isnan(historical_fire.historical.isel(time=0).drop(\"time\"))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "virgin-scheduling",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "ds = (\n",
+ " xr.open_zarr(\n",
+ " get_store(\"carbonplan-forests\", \"risks/results/paper/fire_cmip.zarr\")\n",
+ " )\n",
+ " .assign_coords({\"x\": mask.x, \"y\": mask.y})\n",
+ " .where(fire_mask)\n",
+ " .groupby(\"time.year\")\n",
+ " .sum()\n",
+ " .where(fire_mask)\n",
+ " .mean(dim=[\"x\", \"y\"])\n",
+ " .probability.mean(dim=\"gcm\")\n",
+ " .compute()\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "hybrid-shooting",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "for scenario in [\"ssp245\", \"ssp370\", \"ssp585\"]:\n",
+ " ts = ds.sel(scenario=scenario)\n",
+ " hist_slice = slice(1990, 2019)\n",
+ " fut_slice = slice(2080, 2099)\n",
+ " change = (\n",
+ " ts.sel(year=fut_slice).mean(dim=\"year\")\n",
+ " / ts.sel(year=hist_slice).mean(dim=\"year\").values\n",
+ " )\n",
+ " print(\"change factor for {} is {}\".format(scenario, change.values))"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python [conda env:notebook] *",
+ "language": "python",
+ "name": "conda-env-notebook-py"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.8.8"
+ }
},
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "static-italy",
- "metadata": {},
- "outputs": [],
- "source": [
- "%load_ext autoreload\n",
- "%autoreload 2\n",
- "\n",
- "from carbonplan_forest_risks import load, setup, plot, fit, utils, prepare, collect\n",
- "import xarray as xr\n",
- "import numpy as np\n",
- "from carbonplan_forest_risks.utils import get_store"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "driving-print",
- "metadata": {},
- "outputs": [],
- "source": [
- "coarsen = 4"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "underlying-genealogy",
- "metadata": {},
- "outputs": [],
- "source": [
- "mask = (\n",
- " (\n",
- " load.nlcd(store=\"az\", year=2001).sel(band=[41, 42, 43, 90]).sum(\"band\")\n",
- " > 0.25\n",
- " )\n",
- " .astype(\"float\")\n",
- " .coarsen(x=coarsen, y=coarsen, boundary=\"trim\")\n",
- " .mean()\n",
- ")"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "major-compilation",
- "metadata": {},
- "source": [
- "# Load in fire data\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "armed-penguin",
- "metadata": {},
- "outputs": [],
- "source": [
- "historical_fire = xr.open_zarr(\n",
- " get_store(\n",
- " \"carbonplan-forests\", \"risks/results/paper/fire_terraclimate_v6.zarr\"\n",
- " )\n",
- ").load()\n",
- "fire_mask = ~np.isnan(historical_fire.historical.isel(time=0).drop(\"time\"))"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "virgin-scheduling",
- "metadata": {},
- "outputs": [],
- "source": [
- "ds = (\n",
- " xr.open_zarr(\n",
- " get_store(\"carbonplan-forests\", \"risks/results/paper/fire_cmip.zarr\")\n",
- " )\n",
- " .assign_coords({\"x\": mask.x, \"y\": mask.y})\n",
- " .where(fire_mask)\n",
- " .groupby(\"time.year\")\n",
- " .sum()\n",
- " .where(fire_mask)\n",
- " .mean(dim=[\"x\", \"y\"])\n",
- " .probability.mean(dim=\"gcm\")\n",
- " .compute()\n",
- ")"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "hybrid-shooting",
- "metadata": {},
- "outputs": [],
- "source": [
- "for scenario in [\"ssp245\", \"ssp370\", \"ssp585\"]:\n",
- " ts = ds.sel(scenario=scenario)\n",
- " hist_slice = slice(1990, 2019)\n",
- " fut_slice = slice(2080, 2099)\n",
- " change = (\n",
- " ts.sel(year=fut_slice).mean(dim=\"year\")\n",
- " / ts.sel(year=hist_slice).mean(dim=\"year\").values\n",
- " )\n",
- " print(\"change factor for {} is {}\".format(scenario, change.values))"
- ]
- }
- ],
- "metadata": {
- "kernelspec": {
- "display_name": "Python [conda env:notebook] *",
- "language": "python",
- "name": "conda-env-notebook-py"
- },
- "language_info": {
- "codemirror_mode": {
- "name": "ipython",
- "version": 3
- },
- "file_extension": ".py",
- "mimetype": "text/x-python",
- "name": "python",
- "nbconvert_exporter": "python",
- "pygments_lexer": "ipython3",
- "version": "3.8.8"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 5
+ "nbformat": 4,
+ "nbformat_minor": 5
}
diff --git a/notebooks/paper/Figure-1/Figure-1.ipynb b/notebooks/paper/Figure-1/Figure-1.ipynb
index e9d652e..60ad77f 100644
--- a/notebooks/paper/Figure-1/Figure-1.ipynb
+++ b/notebooks/paper/Figure-1/Figure-1.ipynb
@@ -1,371 +1,371 @@
{
- "cells": [
- {
- "cell_type": "markdown",
- "id": "alternate-hunter",
- "metadata": {},
- "source": [
- "\n",
- "\n",
- "# Figure 1: Observed and modelled forest risks\n",
- "\n",
- "_Authors: Oriana Chegwidden and Jeremy Freeman_\n",
- "\n",
- "The methods below conduct the analyses to recreate Figure 1 included the\n",
- "manuscript <<< insert doi >>>. They draw from a model data produced by running\n",
- "`../../../scripts/fire.py` to create a the file located at\n",
- "`az:carbonplan-scratch/data/fire.zarr`.\n"
- ]
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "id": "alternate-hunter",
+ "metadata": {},
+ "source": [
+ "\n",
+ "\n",
+ "# Figure 1: Observed and modelled forest risks\n",
+ "\n",
+ "_Authors: Oriana Chegwidden and Jeremy Freeman_\n",
+ "\n",
+ "The methods below conduct the analyses to recreate Figure 1 included the\n",
+ "manuscript <<< insert doi >>>. They draw from a model data produced by running\n",
+ "`../../../scripts/fire.py` to create a the file located at\n",
+ "`az:carbonplan-scratch/data/fire.zarr`.\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "impressed-ribbon",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "%load_ext autoreload\n",
+ "%autoreload 2\n",
+ "\n",
+ "import numpy as np\n",
+ "import pandas as pd\n",
+ "import scipy as sp\n",
+ "from carbonplan_forest_risks import load, setup, plot, fit, utils, prepare, collect\n",
+ "import xarray as xr\n",
+ "from carbonplan_forest_risks.utils import get_store\n",
+ "import altair as alt\n",
+ "import rioxarray\n",
+ "from carbonplan.data import cat\n",
+ "from carbonplan_styles.mpl import get_colormap\n",
+ "import cartopy.crs as ccrs\n",
+ "import cartopy\n",
+ "import cartopy.feature as cfeature\n",
+ "import matplotlib.pyplot as plt\n",
+ "import matplotlib\n",
+ "from mpl_toolkits.axes_grid1 import make_axes_locatable\n",
+ "\n",
+ "from carbonplan_data import utils\n",
+ "alt.data_transformers.disable_max_rows()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "secondary-falls",
+ "metadata": {},
+ "source": [
+ "### Initialize the dictionary where you'll store all of your datasets.\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "australian-privacy",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "ds_dict = {}"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "champion-florist",
+ "metadata": {},
+ "source": [
+ "## Load in the fire data\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "recreational-modern",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "coarsen = 4\n",
+ "store = \"az\"\n",
+ "tlim = (\"1984\", \"2018\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "indirect-remark",
+ "metadata": {},
+ "source": [
+ "#### Historical simulation\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "representative-locking",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "historical_fire = xr.open_zarr(\n",
+ " \"https://carbonplan.blob.core.windows.net/carbonplan-forests/risks/results/paper/fire_terraclimate.zarr\"\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "smaller-interference",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "fire_mask = ~np.isnan(historical_fire.historical.isel(time=0).drop(\"time\"))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "alert-laptop",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "ds_dict[\"Fire_modeled\"] = (\n",
+ " historical_fire.groupby(\"time.year\").sum().where(fire_mask).mean(dim=\"year\")\n",
+ ").compute()[\n",
+ " \"historical\"\n",
+ "] * 100 # cast into percent"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "informal-running",
+ "metadata": {},
+ "source": [
+ "#### Observations\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "soviet-contributor",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "mask = (\n",
+ " load.nlcd(store=store, year=2001).sel(band=[41, 42, 43, 90]).sum(\"band\")\n",
+ " > 0.25\n",
+ ").astype(\"float\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "internal-adapter",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "ds_dict[\"Fire_observed\"] = load.mtbs(\n",
+ " store=store, coarsen=coarsen, tlim=tlim, mask=mask\n",
+ ")\n",
+ "ds_dict[\"Fire_observed\"] = (\n",
+ " ds_dict[\"Fire_observed\"]\n",
+ " .assign_coords(\n",
+ " {\"x\": ds_dict[\"Fire_modeled\"].x, \"y\": ds_dict[\"Fire_modeled\"].y}\n",
+ " )\n",
+ " .assign_coords(\n",
+ " {\n",
+ " \"lat\": ds_dict[\"Fire_modeled\"].lat,\n",
+ " \"lon\": ds_dict[\"Fire_modeled\"].lon,\n",
+ " }\n",
+ " )\n",
+ " .groupby(\"time.year\")\n",
+ " .sum()\n",
+ " .where(fire_mask)\n",
+ " .mean(dim=\"year\")\n",
+ ").compute()[\n",
+ " \"monthly\"\n",
+ "] * 100 # cast into percent"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "national-address",
+ "metadata": {},
+ "source": [
+ "### Load in insect and drought data\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "static-madonna",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "base_url_tempate = \"https://carbonplan.blob.core.windows.net/carbonplan-forests/risks/results/paper/insects_and_drought_eval/{}\"\n",
+ "dataset_urls = {\n",
+ " \"Drought\": {\n",
+ " \"modeled\": base_url_tempate.format(\n",
+ " \"Fig1D_DroughtModel_ModeledFIAlongEnsembleHistMort_04-22-2021.tiff\"\n",
+ " ),\n",
+ " \"observed\": base_url_tempate.format(\n",
+ " \"Fig1C_DroughtModel_FIAwide-ObsMort_05-08-2021.tiff\"\n",
+ " ),\n",
+ " },\n",
+ " \"Insects\": {\n",
+ " \"modeled\": base_url_tempate.format(\n",
+ " \"Fig1F_InsectModel_ModeledFIAlongEnsembleHistMort_04-22-2021.tiff\"\n",
+ " ),\n",
+ " \"observed\": base_url_tempate.format(\n",
+ " # \"Fig1E_InsectModel_ObservedHistMort_3-30-2021.tif\"\n",
+ " # \"Fig1E_InsectModel_ObservedHistMort_04-09-2021.tif\"\n",
+ " \"Fig1E_InsectModel_FIAwide-ObsMort_05-08-2021.tiff\"\n",
+ " ),\n",
+ " },\n",
+ "}"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "seventh-scope",
+ "metadata": {},
+ "source": [
+ "## Load in the drought and insect data\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "overall-cincinnati",
+ "metadata": {},
+ "source": [
+ "#### Observations and Historical simulations\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "pressing-rwanda",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "for mechanism, url_dict in dataset_urls.items():\n",
+ " for setup, url in url_dict.items():\n",
+ " print(url)\n",
+ " ds_dict[mechanism + \"_\" + setup] = load.tiff(url, mask, coarsen=1) * 100"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "charming-spencer",
+ "metadata": {},
+ "source": [
+ "## Plot the figure for all three impacts\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "impressive-election",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "plot_params = {\n",
+ " \"Fire\": {\n",
+ " \"cmap\": get_colormap(\"reds\"),\n",
+ " \"var_lims\": (0, 0.4),\n",
+ " \"label\": \"Burn area\\n(%/year)\",\n",
+ " \"panel\": [\"A\", \"B\"],\n",
+ " \"cbar_ylocation\": 0.76,\n",
+ " },\n",
+ " \"Drought\": {\n",
+ " \"cmap\": get_colormap(\"pinks\"),\n",
+ " \"var_lims\": (0, 2),\n",
+ " \"label\": \"Drought-related\\nmortality (%/year)\",\n",
+ " \"panel\": [\"C\", \"D\"],\n",
+ " \"cbar_ylocation\": 0.4,\n",
+ " },\n",
+ " \"Insects\": {\n",
+ " \"cmap\": get_colormap(\"blues\"),\n",
+ " \"var_lims\": (0, 0.4),\n",
+ " \"label\": \"Insect-related\\nmortality (%/year)\",\n",
+ " \"panel\": [\"E\", \"F\"],\n",
+ " \"cbar_ylocation\": 0.04,\n",
+ " },\n",
+ "}"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "optical-athens",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "matplotlib.rc(\"font\", family=\"sans-serif\")\n",
+ "matplotlib.rc(\"font\", serif=\"Helvetica Neue\")\n",
+ "matplotlib.rc(\"text\", usetex=\"false\")\n",
+ "matplotlib.rcParams.update({\"font.size\": 14, \"svg.fonttype\": \"none\"})"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "impressive-finnish",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "fig, axarr = plt.subplots(\n",
+ " nrows=3,\n",
+ " ncols=2,\n",
+ " figsize=(10, 12),\n",
+ " subplot_kw={\"projection\": plot.cartopy_proj_albers()},\n",
+ ")\n",
+ "for row, impact in enumerate([\"Fire\", \"Drought\", \"Insects\"]):\n",
+ " for column, setup in enumerate([\"observed\", \"modeled\"]):\n",
+ " vmin, vmax = (\n",
+ " plot_params[impact][\"var_lims\"][0],\n",
+ " plot_params[impact][\"var_lims\"][1],\n",
+ " )\n",
+ " map_plot = ds_dict[\"{}_{}\".format(impact, setup)].plot.imshow(\n",
+ " ax=axarr[row, column],\n",
+ " cmap=plot_params[impact][\"cmap\"],\n",
+ " vmin=vmin,\n",
+ " vmax=vmax,\n",
+ " add_colorbar=False,\n",
+ " )\n",
+ " plot.map_pretty(axarr[row, column], title=setup.capitalize())\n",
+ " axarr[row, column].text(\n",
+ " 0.12,\n",
+ " 1.05,\n",
+ " plot_params[impact][\"panel\"][column],\n",
+ " transform=axarr[row, column].transAxes,\n",
+ " fontsize=18,\n",
+ " )\n",
+ " plot.add_colorbar(\n",
+ " fig,\n",
+ " to_plot=map_plot,\n",
+ " y_location=plot_params[impact][\"cbar_ylocation\"],\n",
+ " vmin=plot_params[impact][\"var_lims\"][0],\n",
+ " vmax=plot_params[impact][\"var_lims\"][1],\n",
+ " cbar_label=plot_params[impact][\"label\"],\n",
+ " )\n",
+ "plt.tight_layout(pad=-6)"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python [conda env:notebook] *",
+ "language": "python",
+ "name": "conda-env-notebook-py"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.9.12"
+ }
},
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "impressed-ribbon",
- "metadata": {},
- "outputs": [],
- "source": [
- "%load_ext autoreload\n",
- "%autoreload 2\n",
- "\n",
- "import numpy as np\n",
- "import pandas as pd\n",
- "import scipy as sp\n",
- "from carbonplan_forest_risks import load, setup, plot, fit, utils, prepare, collect\n",
- "import xarray as xr\n",
- "from carbonplan_forest_risks.utils import get_store\n",
- "import altair as alt\n",
- "import rioxarray\n",
- "from carbonplan.data import cat\n",
- "from carbonplan_styles.mpl import get_colormap\n",
- "import cartopy.crs as ccrs\n",
- "import cartopy\n",
- "import cartopy.feature as cfeature\n",
- "import matplotlib.pyplot as plt\n",
- "import matplotlib\n",
- "from mpl_toolkits.axes_grid1 import make_axes_locatable\n",
- "\n",
- "from carbonplan_data import utils\n",
- "alt.data_transformers.disable_max_rows()"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "secondary-falls",
- "metadata": {},
- "source": [
- "### Initialize the dictionary where you'll store all of your datasets.\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "australian-privacy",
- "metadata": {},
- "outputs": [],
- "source": [
- "ds_dict = {}"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "champion-florist",
- "metadata": {},
- "source": [
- "## Load in the fire data\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "recreational-modern",
- "metadata": {},
- "outputs": [],
- "source": [
- "coarsen = 4\n",
- "store = \"az\"\n",
- "tlim = (\"1984\", \"2018\")"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "indirect-remark",
- "metadata": {},
- "source": [
- "#### Historical simulation\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "representative-locking",
- "metadata": {},
- "outputs": [],
- "source": [
- "historical_fire = xr.open_zarr(\n",
- " \"https://carbonplan.blob.core.windows.net/carbonplan-forests/risks/results/paper/fire_terraclimate.zarr\"\n",
- ")"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "smaller-interference",
- "metadata": {},
- "outputs": [],
- "source": [
- "fire_mask = ~np.isnan(historical_fire.historical.isel(time=0).drop(\"time\"))"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "alert-laptop",
- "metadata": {},
- "outputs": [],
- "source": [
- "ds_dict[\"Fire_modeled\"] = (\n",
- " historical_fire.groupby(\"time.year\").sum().where(fire_mask).mean(dim=\"year\")\n",
- ").compute()[\n",
- " \"historical\"\n",
- "] * 100 # cast into percent"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "informal-running",
- "metadata": {},
- "source": [
- "#### Observations\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "soviet-contributor",
- "metadata": {},
- "outputs": [],
- "source": [
- "mask = (\n",
- " load.nlcd(store=store, year=2001).sel(band=[41, 42, 43, 90]).sum(\"band\")\n",
- " > 0.25\n",
- ").astype(\"float\")"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "internal-adapter",
- "metadata": {},
- "outputs": [],
- "source": [
- "ds_dict[\"Fire_observed\"] = load.mtbs(\n",
- " store=store, coarsen=coarsen, tlim=tlim, mask=mask\n",
- ")\n",
- "ds_dict[\"Fire_observed\"] = (\n",
- " ds_dict[\"Fire_observed\"]\n",
- " .assign_coords(\n",
- " {\"x\": ds_dict[\"Fire_modeled\"].x, \"y\": ds_dict[\"Fire_modeled\"].y}\n",
- " )\n",
- " .assign_coords(\n",
- " {\n",
- " \"lat\": ds_dict[\"Fire_modeled\"].lat,\n",
- " \"lon\": ds_dict[\"Fire_modeled\"].lon,\n",
- " }\n",
- " )\n",
- " .groupby(\"time.year\")\n",
- " .sum()\n",
- " .where(fire_mask)\n",
- " .mean(dim=\"year\")\n",
- ").compute()[\n",
- " \"monthly\"\n",
- "] * 100 # cast into percent"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "national-address",
- "metadata": {},
- "source": [
- "### Load in insect and drought data\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "static-madonna",
- "metadata": {},
- "outputs": [],
- "source": [
- "base_url_tempate = \"https://carbonplan.blob.core.windows.net/carbonplan-forests/risks/results/paper/insects_and_drought_eval/{}\"\n",
- "dataset_urls = {\n",
- " \"Drought\": {\n",
- " \"modeled\": base_url_tempate.format(\n",
- " \"Fig1D_DroughtModel_ModeledFIAlongEnsembleHistMort_04-22-2021.tiff\"\n",
- " ),\n",
- " \"observed\": base_url_tempate.format(\n",
- " \"Fig1C_DroughtModel_FIAwide-ObsMort_05-08-2021.tiff\"\n",
- " ),\n",
- " },\n",
- " \"Insects\": {\n",
- " \"modeled\": base_url_tempate.format(\n",
- " \"Fig1F_InsectModel_ModeledFIAlongEnsembleHistMort_04-22-2021.tiff\"\n",
- " ),\n",
- " \"observed\": base_url_tempate.format(\n",
- " # \"Fig1E_InsectModel_ObservedHistMort_3-30-2021.tif\"\n",
- " # \"Fig1E_InsectModel_ObservedHistMort_04-09-2021.tif\"\n",
- " \"Fig1E_InsectModel_FIAwide-ObsMort_05-08-2021.tiff\"\n",
- " ),\n",
- " },\n",
- "}"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "seventh-scope",
- "metadata": {},
- "source": [
- "## Load in the drought and insect data\n"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "overall-cincinnati",
- "metadata": {},
- "source": [
- "#### Observations and Historical simulations\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "pressing-rwanda",
- "metadata": {},
- "outputs": [],
- "source": [
- "for mechanism, url_dict in dataset_urls.items():\n",
- " for setup, url in url_dict.items():\n",
- " print(url)\n",
- " ds_dict[mechanism + \"_\" + setup] = load.tiff(url, mask, coarsen=1) * 100"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "charming-spencer",
- "metadata": {},
- "source": [
- "## Plot the figure for all three impacts\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "impressive-election",
- "metadata": {},
- "outputs": [],
- "source": [
- "plot_params = {\n",
- " \"Fire\": {\n",
- " \"cmap\": get_colormap(\"reds\"),\n",
- " \"var_lims\": (0, 0.4),\n",
- " \"label\": \"Burn area\\n(%/year)\",\n",
- " \"panel\": [\"A\", \"B\"],\n",
- " \"cbar_ylocation\": 0.76,\n",
- " },\n",
- " \"Drought\": {\n",
- " \"cmap\": get_colormap(\"pinks\"),\n",
- " \"var_lims\": (0, 2),\n",
- " \"label\": \"Drought-related\\nmortality (%/year)\",\n",
- " \"panel\": [\"C\", \"D\"],\n",
- " \"cbar_ylocation\": 0.4,\n",
- " },\n",
- " \"Insects\": {\n",
- " \"cmap\": get_colormap(\"blues\"),\n",
- " \"var_lims\": (0, 0.4),\n",
- " \"label\": \"Insect-related\\nmortality (%/year)\",\n",
- " \"panel\": [\"E\", \"F\"],\n",
- " \"cbar_ylocation\": 0.04,\n",
- " },\n",
- "}"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "optical-athens",
- "metadata": {},
- "outputs": [],
- "source": [
- "matplotlib.rc(\"font\", family=\"sans-serif\")\n",
- "matplotlib.rc(\"font\", serif=\"Helvetica Neue\")\n",
- "matplotlib.rc(\"text\", usetex=\"false\")\n",
- "matplotlib.rcParams.update({\"font.size\": 14, \"svg.fonttype\": \"none\"})"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "impressive-finnish",
- "metadata": {},
- "outputs": [],
- "source": [
- "fig, axarr = plt.subplots(\n",
- " nrows=3,\n",
- " ncols=2,\n",
- " figsize=(10, 12),\n",
- " subplot_kw={\"projection\": plot.cartopy_proj_albers()},\n",
- ")\n",
- "for row, impact in enumerate([\"Fire\", \"Drought\", \"Insects\"]):\n",
- " for column, setup in enumerate([\"observed\", \"modeled\"]):\n",
- " vmin, vmax = (\n",
- " plot_params[impact][\"var_lims\"][0],\n",
- " plot_params[impact][\"var_lims\"][1],\n",
- " )\n",
- " map_plot = ds_dict[\"{}_{}\".format(impact, setup)].plot.imshow(\n",
- " ax=axarr[row, column],\n",
- " cmap=plot_params[impact][\"cmap\"],\n",
- " vmin=vmin,\n",
- " vmax=vmax,\n",
- " add_colorbar=False,\n",
- " )\n",
- " plot.map_pretty(axarr[row, column], title=setup.capitalize())\n",
- " axarr[row, column].text(\n",
- " 0.12,\n",
- " 1.05,\n",
- " plot_params[impact][\"panel\"][column],\n",
- " transform=axarr[row, column].transAxes,\n",
- " fontsize=18,\n",
- " )\n",
- " plot.add_colorbar(\n",
- " fig,\n",
- " to_plot=map_plot,\n",
- " y_location=plot_params[impact][\"cbar_ylocation\"],\n",
- " vmin=plot_params[impact][\"var_lims\"][0],\n",
- " vmax=plot_params[impact][\"var_lims\"][1],\n",
- " cbar_label=plot_params[impact][\"label\"],\n",
- " )\n",
- "plt.tight_layout(pad=-6)"
- ]
- }
- ],
- "metadata": {
- "kernelspec": {
- "display_name": "Python [conda env:notebook] *",
- "language": "python",
- "name": "conda-env-notebook-py"
- },
- "language_info": {
- "codemirror_mode": {
- "name": "ipython",
- "version": 3
- },
- "file_extension": ".py",
- "mimetype": "text/x-python",
- "name": "python",
- "nbconvert_exporter": "python",
- "pygments_lexer": "ipython3",
- "version": "3.9.12"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 5
+ "nbformat": 4,
+ "nbformat_minor": 5
}
diff --git a/notebooks/paper/Figure-2/Figure-2.ipynb b/notebooks/paper/Figure-2/Figure-2.ipynb
index 27d2431..b6ce1ef 100644
--- a/notebooks/paper/Figure-2/Figure-2.ipynb
+++ b/notebooks/paper/Figure-2/Figure-2.ipynb
@@ -1,354 +1,354 @@
{
- "cells": [
- {
- "cell_type": "markdown",
- "id": "dietary-return",
- "metadata": {},
- "source": [
- "\n",
- "\n",
- "# Figure 2: Future projections for each impact\n",
- "\n",
- "_Authors: Oriana Chegwidden and Jeremy Freeman_\n",
- "\n",
- "The methods below conduct the analyses to recreate Figure 2 included the\n",
- "manuscript <<< insert doi >>>. Future risks for fire. We show median changes in\n",
- "risk with respect to the historic.\n"
- ]
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "id": "dietary-return",
+ "metadata": {},
+ "source": [
+ "\n",
+ "\n",
+ "# Figure 2: Future projections for each impact\n",
+ "\n",
+ "_Authors: Oriana Chegwidden and Jeremy Freeman_\n",
+ "\n",
+ "The methods below conduct the analyses to recreate Figure 2 included the\n",
+ "manuscript <<< insert doi >>>. Future risks for fire. We show median changes in\n",
+ "risk with respect to the historic.\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "naughty-madison",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "%load_ext autoreload\n",
+ "%autoreload 2\n",
+ "\n",
+ "import numpy as np\n",
+ "import pandas as pd\n",
+ "import scipy as sp\n",
+ "from carbonplan_forest_risks import load, setup, plot, fit, utils, prepare, collect\n",
+ "import xarray as xr\n",
+ "from carbonplan_forest_risks.utils import get_store\n",
+ "import rioxarray\n",
+ "from carbonplan.data import cat\n",
+ "%matplotlib inline\n",
+ "import matplotlib.pyplot as plt\n",
+ "import scipy as sp\n",
+ "import geopandas as gpd\n",
+ "import regionmask as rm\n",
+ "import altair as alt\n",
+ "alt.themes.enable(\"carbonplan_light\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "careful-boston",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import warnings\n",
+ "\n",
+ "warnings.filterwarnings(\"ignore\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "defensive-maldives",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "alt.data_transformers.disable_max_rows()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "wicked-father",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "coarsen = 4"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "dutch-acrobat",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "mask = (\n",
+ " (\n",
+ " load.nlcd(store=\"az\", year=2001).sel(band=[41, 42, 43, 90]).sum(\"band\")\n",
+ " > 0.25\n",
+ " )\n",
+ " .astype(\"float\")\n",
+ " .coarsen(x=coarsen, y=coarsen, boundary=\"trim\")\n",
+ " .mean()\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "august-namibia",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Load in fire data"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "clean-glenn",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "historical_fire = xr.open_zarr(\n",
+ " \"https://carbonplan.blob.core.windows.net/carbonplan-forests/risks/results/paper/fire_terraclimate.zarr\"\n",
+ ")\n",
+ "fire_mask = ~np.isnan(historical_fire.historical.isel(time=0).drop(\"time\"))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "horizontal-cinema",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "ds = (\n",
+ " xr.open_zarr(\n",
+ " \"https://carbonplan.blob.core.windows.net/carbonplan-forests/risks/results/paper/fire_cmip.zarr\"\n",
+ " )\n",
+ " .assign_coords({\"x\": mask.x, \"y\": mask.y})\n",
+ " .where(fire_mask)\n",
+ " .groupby(\"time.year\")\n",
+ " .sum()\n",
+ " .where(fire_mask)\n",
+ " .compute()\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "conscious-career",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "historical_annual = (\n",
+ " historical_fire.assign_coords({\"x\": mask.x, \"y\": mask.y})\n",
+ " .groupby(\"time.year\")\n",
+ " .sum()\n",
+ " .where(fire_mask)\n",
+ " .mean(dim=[\"x\", \"y\"])\n",
+ " .compute()\n",
+ ") * 100 # cast to percent"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "surprising-discovery",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "future_ts = {}\n",
+ "future_ts[\"fire\"] = (\n",
+ " ds.mean(dim=[\"x\", \"y\"]).rolling(dim={\"year\": 10}).mean().compute()\n",
+ ") * 100 # cast to percent"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "unexpected-stanford",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "gcms = [\n",
+ " (\"ACCESS-CM2\", \"r1i1p1f1\"),\n",
+ " (\"ACCESS-ESM1-5\", \"r10i1p1f1\"),\n",
+ " (\"MRI-ESM2-0\", \"r1i1p1f1\"),\n",
+ " (\"MIROC-ES2L\", \"r1i1p1f2\"),\n",
+ " (\"MPI-ESM1-2-LR\", \"r10i1p1f1\"),\n",
+ " (\"CanESM5-CanOE\", \"r3i1p2f1\"),\n",
+ "]"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "downtown-feature",
+ "metadata": {},
+ "source": [
+ "### Load in insect and drought data\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "manual-candle",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "historical_ts = {}\n",
+ "for impact in [\"drought\", \"insects\"]:\n",
+ " historical_ts[impact] = (\n",
+ " xr.open_zarr(\n",
+ " \"https://carbonplan.blob.core.windows.net/carbonplan-forests/risks/results/paper/{}_terraclimate.zarr\".format(\n",
+ " impact\n",
+ " )\n",
+ " )\n",
+ " .assign_coords({\"year\": np.arange(1995, 2020, 10)})\n",
+ " .mean(dim=[\"x\", \"y\"])\n",
+ " .compute()\n",
+ " )\n",
+ " future_ts[impact] = (\n",
+ " xr.open_zarr(\n",
+ " \"https://carbonplan.blob.core.windows.net/carbonplan-forests/risks/results/paper/{}_cmip.zarr\".format(\n",
+ " impact\n",
+ " )\n",
+ " )\n",
+ " .assign_coords({\"year\": np.arange(1975, 2100, 10)})\n",
+ " .mean(dim=[\"x\", \"y\"])\n",
+ " .compute()\n",
+ " )"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "inclusive-roulette",
+ "metadata": {},
+ "source": [
+ "## Plot the figure\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "miniature-valley",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "gcms = [\n",
+ " (\"MRI-ESM2-0\", (0, 0)),\n",
+ " (\"MIROC-ES2L\", (1, 0)),\n",
+ " (\"MPI-ESM1-2-LR\", (2, 0)),\n",
+ " (\"ACCESS-ESM1-5\", (3, 0)),\n",
+ " (\"ACCESS-CM2\", (4, 0)),\n",
+ " (\"CanESM5-CanOE\", (5, 0)),\n",
+ "]\n",
+ "scenario_colors = {\n",
+ " \"ssp245\": \"#59A82F\",\n",
+ " \"ssp370\": \"#D8B525\",\n",
+ " \"ssp585\": \"#D83232\",\n",
+ "}\n",
+ "scenario_colors_light = {\n",
+ " \"ssp245\": \"#DEEED5\",\n",
+ " \"ssp370\": \"#F7F0D3\",\n",
+ " \"ssp585\": \"#F7D6D6\",\n",
+ "}\n",
+ "titles = {\n",
+ " \"fire\": \"Burn area\\n(%/year)\",\n",
+ " \"drought\": \"Drought-related\\nmortality (%/year)\",\n",
+ " \"insects\": \"Insect-related\\nmortality (%/year)\",\n",
+ "}\n",
+ "ylims = {\n",
+ " \"fire\": (0, 1.5),\n",
+ " \"drought\": (0, 3),\n",
+ " \"insects\": (0, 0.5),\n",
+ "}\n",
+ "ssp_rename = {\"ssp245\": \"SSP2-4.5\", \"ssp370\": \"SSP3-7.0\", \"ssp585\": \"SSP5-8.5\"}"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "august-audio",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "plt.rcParams.update({\"font.size\": 14, \"svg.fonttype\": \"none\"})\n",
+ "\n",
+ "fig, axarr = plt.subplots(nrows=3, figsize=(6, 10), sharex=True)\n",
+ "\n",
+ "## Fire\n",
+ "\n",
+ "for scenario in [\"ssp245\", \"ssp370\", \"ssp585\"]:\n",
+ " for (gcm, location) in gcms:\n",
+ " future_ts[\"fire\"].probability.sel(gcm=gcm, scenario=scenario).sel(\n",
+ " year=slice(\"1970\", \"2099\")\n",
+ " ).plot(ax=axarr[0], color=scenario_colors_light[scenario], alpha=1)\n",
+ "\n",
+ "for scenario in [\"ssp245\", \"ssp370\", \"ssp585\"]:\n",
+ " future_ts[\"fire\"].probability.sel(scenario=scenario).mean(dim=\"gcm\").plot(\n",
+ " ax=axarr[0], color=scenario_colors[scenario], label=ssp_rename[scenario]\n",
+ " )\n",
+ "historical_annual[\"historical\"].rolling(dim={\"year\": 10}).mean().plot(\n",
+ " ax=axarr[0], color=\"k\", linestyle=\"-\", label=\"Historical\"\n",
+ ")\n",
+ "\n",
+ "axarr[0].legend()\n",
+ "## Drought and insects\n",
+ "for i, impact in enumerate([\"drought\", \"insects\"]):\n",
+ " historical_ts[impact].probability.plot(\n",
+ " ax=axarr[i + 1], color=\"k\", zorder=50\n",
+ " )\n",
+ "\n",
+ " for scenario in [\"ssp245\", \"ssp370\", \"ssp585\"]:\n",
+ " for (gcm, location) in gcms:\n",
+ " future_ts[impact].probability.sel(scenario=scenario, gcm=gcm).sel(\n",
+ " year=slice(1970, 2099)\n",
+ " ).plot(\n",
+ " ax=axarr[i + 1],\n",
+ " color=scenario_colors_light[scenario],\n",
+ " )\n",
+ "\n",
+ " for scenario in [\"ssp245\", \"ssp370\", \"ssp585\"]:\n",
+ " future_ts[impact].probability.sel(scenario=scenario).mean(\n",
+ " dim=\"gcm\"\n",
+ " ).plot(\n",
+ " ax=axarr[i + 1],\n",
+ " color=scenario_colors[scenario],\n",
+ " label=ssp_rename[scenario],\n",
+ " )\n",
+ "for i, (impact, title) in enumerate(titles.items()):\n",
+ " axarr[i].set_ylabel(title)\n",
+ " axarr[i].set_xlabel(\"\")\n",
+ " axarr[i].set_ylim(ylims[impact])\n",
+ " axarr[i].set_title(\"\")\n",
+ "plt.tight_layout()\n",
+ "# for format_string in [\"svg\", \"png\"]:\n",
+ "# plt.savefig(\"Figure-2.\" + format_string, format=format_string)"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python [conda env:notebook] *",
+ "language": "python",
+ "name": "conda-env-notebook-py"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.9.12"
+ }
},
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "naughty-madison",
- "metadata": {},
- "outputs": [],
- "source": [
- "%load_ext autoreload\n",
- "%autoreload 2\n",
- "\n",
- "import numpy as np\n",
- "import pandas as pd\n",
- "import scipy as sp\n",
- "from carbonplan_forest_risks import load, setup, plot, fit, utils, prepare, collect\n",
- "import xarray as xr\n",
- "from carbonplan_forest_risks.utils import get_store\n",
- "import rioxarray\n",
- "from carbonplan.data import cat\n",
- "%matplotlib inline\n",
- "import matplotlib.pyplot as plt\n",
- "import scipy as sp\n",
- "import geopandas as gpd\n",
- "import regionmask as rm\n",
- "import altair as alt\n",
- "alt.themes.enable(\"carbonplan_light\")"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "careful-boston",
- "metadata": {},
- "outputs": [],
- "source": [
- "import warnings\n",
- "\n",
- "warnings.filterwarnings(\"ignore\")"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "defensive-maldives",
- "metadata": {},
- "outputs": [],
- "source": [
- "alt.data_transformers.disable_max_rows()"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "wicked-father",
- "metadata": {},
- "outputs": [],
- "source": [
- "coarsen = 4"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "dutch-acrobat",
- "metadata": {},
- "outputs": [],
- "source": [
- "mask = (\n",
- " (\n",
- " load.nlcd(store=\"az\", year=2001).sel(band=[41, 42, 43, 90]).sum(\"band\")\n",
- " > 0.25\n",
- " )\n",
- " .astype(\"float\")\n",
- " .coarsen(x=coarsen, y=coarsen, boundary=\"trim\")\n",
- " .mean()\n",
- ")"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "august-namibia",
- "metadata": {},
- "outputs": [],
- "source": [
- "# Load in fire data"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "clean-glenn",
- "metadata": {},
- "outputs": [],
- "source": [
- "historical_fire = xr.open_zarr(\n",
- " \"https://carbonplan.blob.core.windows.net/carbonplan-forests/risks/results/paper/fire_terraclimate.zarr\"\n",
- ")\n",
- "fire_mask = ~np.isnan(historical_fire.historical.isel(time=0).drop(\"time\"))"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "horizontal-cinema",
- "metadata": {},
- "outputs": [],
- "source": [
- "ds = (\n",
- " xr.open_zarr(\n",
- " \"https://carbonplan.blob.core.windows.net/carbonplan-forests/risks/results/paper/fire_cmip.zarr\"\n",
- " )\n",
- " .assign_coords({\"x\": mask.x, \"y\": mask.y})\n",
- " .where(fire_mask)\n",
- " .groupby(\"time.year\")\n",
- " .sum()\n",
- " .where(fire_mask)\n",
- " .compute()\n",
- ")"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "conscious-career",
- "metadata": {},
- "outputs": [],
- "source": [
- "historical_annual = (\n",
- " historical_fire.assign_coords({\"x\": mask.x, \"y\": mask.y})\n",
- " .groupby(\"time.year\")\n",
- " .sum()\n",
- " .where(fire_mask)\n",
- " .mean(dim=[\"x\", \"y\"])\n",
- " .compute()\n",
- ") * 100 # cast to percent"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "surprising-discovery",
- "metadata": {},
- "outputs": [],
- "source": [
- "future_ts = {}\n",
- "future_ts[\"fire\"] = (\n",
- " ds.mean(dim=[\"x\", \"y\"]).rolling(dim={\"year\": 10}).mean().compute()\n",
- ") * 100 # cast to percent"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "unexpected-stanford",
- "metadata": {},
- "outputs": [],
- "source": [
- "gcms = [\n",
- " (\"ACCESS-CM2\", \"r1i1p1f1\"),\n",
- " (\"ACCESS-ESM1-5\", \"r10i1p1f1\"),\n",
- " (\"MRI-ESM2-0\", \"r1i1p1f1\"),\n",
- " (\"MIROC-ES2L\", \"r1i1p1f2\"),\n",
- " (\"MPI-ESM1-2-LR\", \"r10i1p1f1\"),\n",
- " (\"CanESM5-CanOE\", \"r3i1p2f1\"),\n",
- "]"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "downtown-feature",
- "metadata": {},
- "source": [
- "### Load in insect and drought data\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "manual-candle",
- "metadata": {},
- "outputs": [],
- "source": [
- "historical_ts = {}\n",
- "for impact in [\"drought\", \"insects\"]:\n",
- " historical_ts[impact] = (\n",
- " xr.open_zarr(\n",
- " \"https://carbonplan.blob.core.windows.net/carbonplan-forests/risks/results/paper/{}_terraclimate.zarr\".format(\n",
- " impact\n",
- " )\n",
- " )\n",
- " .assign_coords({\"year\": np.arange(1995, 2020, 10)})\n",
- " .mean(dim=[\"x\", \"y\"])\n",
- " .compute()\n",
- " )\n",
- " future_ts[impact] = (\n",
- " xr.open_zarr(\n",
- " \"https://carbonplan.blob.core.windows.net/carbonplan-forests/risks/results/paper/{}_cmip.zarr\".format(\n",
- " impact\n",
- " )\n",
- " )\n",
- " .assign_coords({\"year\": np.arange(1975, 2100, 10)})\n",
- " .mean(dim=[\"x\", \"y\"])\n",
- " .compute()\n",
- " )"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "inclusive-roulette",
- "metadata": {},
- "source": [
- "## Plot the figure\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "miniature-valley",
- "metadata": {},
- "outputs": [],
- "source": [
- "gcms = [\n",
- " (\"MRI-ESM2-0\", (0, 0)),\n",
- " (\"MIROC-ES2L\", (1, 0)),\n",
- " (\"MPI-ESM1-2-LR\", (2, 0)),\n",
- " (\"ACCESS-ESM1-5\", (3, 0)),\n",
- " (\"ACCESS-CM2\", (4, 0)),\n",
- " (\"CanESM5-CanOE\", (5, 0)),\n",
- "]\n",
- "scenario_colors = {\n",
- " \"ssp245\": \"#59A82F\",\n",
- " \"ssp370\": \"#D8B525\",\n",
- " \"ssp585\": \"#D83232\",\n",
- "}\n",
- "scenario_colors_light = {\n",
- " \"ssp245\": \"#DEEED5\",\n",
- " \"ssp370\": \"#F7F0D3\",\n",
- " \"ssp585\": \"#F7D6D6\",\n",
- "}\n",
- "titles = {\n",
- " \"fire\": \"Burn area\\n(%/year)\",\n",
- " \"drought\": \"Drought-related\\nmortality (%/year)\",\n",
- " \"insects\": \"Insect-related\\nmortality (%/year)\",\n",
- "}\n",
- "ylims = {\n",
- " \"fire\": (0, 1.5),\n",
- " \"drought\": (0, 3),\n",
- " \"insects\": (0, 0.5),\n",
- "}\n",
- "ssp_rename = {\"ssp245\": \"SSP2-4.5\", \"ssp370\": \"SSP3-7.0\", \"ssp585\": \"SSP5-8.5\"}"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "august-audio",
- "metadata": {},
- "outputs": [],
- "source": [
- "plt.rcParams.update({\"font.size\": 14, \"svg.fonttype\": \"none\"})\n",
- "\n",
- "fig, axarr = plt.subplots(nrows=3, figsize=(6, 10), sharex=True)\n",
- "\n",
- "## Fire\n",
- "\n",
- "for scenario in [\"ssp245\", \"ssp370\", \"ssp585\"]:\n",
- " for (gcm, location) in gcms:\n",
- " future_ts[\"fire\"].probability.sel(gcm=gcm, scenario=scenario).sel(\n",
- " year=slice(\"1970\", \"2099\")\n",
- " ).plot(ax=axarr[0], color=scenario_colors_light[scenario], alpha=1)\n",
- "\n",
- "for scenario in [\"ssp245\", \"ssp370\", \"ssp585\"]:\n",
- " future_ts[\"fire\"].probability.sel(scenario=scenario).mean(dim=\"gcm\").plot(\n",
- " ax=axarr[0], color=scenario_colors[scenario], label=ssp_rename[scenario]\n",
- " )\n",
- "historical_annual[\"historical\"].rolling(dim={\"year\": 10}).mean().plot(\n",
- " ax=axarr[0], color=\"k\", linestyle=\"-\", label=\"Historical\"\n",
- ")\n",
- "\n",
- "axarr[0].legend()\n",
- "## Drought and insects\n",
- "for i, impact in enumerate([\"drought\", \"insects\"]):\n",
- " historical_ts[impact].probability.plot(\n",
- " ax=axarr[i + 1], color=\"k\", zorder=50\n",
- " )\n",
- "\n",
- " for scenario in [\"ssp245\", \"ssp370\", \"ssp585\"]:\n",
- " for (gcm, location) in gcms:\n",
- " future_ts[impact].probability.sel(scenario=scenario, gcm=gcm).sel(\n",
- " year=slice(1970, 2099)\n",
- " ).plot(\n",
- " ax=axarr[i + 1],\n",
- " color=scenario_colors_light[scenario],\n",
- " )\n",
- "\n",
- " for scenario in [\"ssp245\", \"ssp370\", \"ssp585\"]:\n",
- " future_ts[impact].probability.sel(scenario=scenario).mean(\n",
- " dim=\"gcm\"\n",
- " ).plot(\n",
- " ax=axarr[i + 1],\n",
- " color=scenario_colors[scenario],\n",
- " label=ssp_rename[scenario],\n",
- " )\n",
- "for i, (impact, title) in enumerate(titles.items()):\n",
- " axarr[i].set_ylabel(title)\n",
- " axarr[i].set_xlabel(\"\")\n",
- " axarr[i].set_ylim(ylims[impact])\n",
- " axarr[i].set_title(\"\")\n",
- "plt.tight_layout()\n",
- "# for format_string in [\"svg\", \"png\"]:\n",
- "# plt.savefig(\"Figure-2.\" + format_string, format=format_string)"
- ]
- }
- ],
- "metadata": {
- "kernelspec": {
- "display_name": "Python [conda env:notebook] *",
- "language": "python",
- "name": "conda-env-notebook-py"
- },
- "language_info": {
- "codemirror_mode": {
- "name": "ipython",
- "version": 3
- },
- "file_extension": ".py",
- "mimetype": "text/x-python",
- "name": "python",
- "nbconvert_exporter": "python",
- "pygments_lexer": "ipython3",
- "version": "3.9.12"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 5
+ "nbformat": 4,
+ "nbformat_minor": 5
}
diff --git a/notebooks/paper/Figure-3/Figure-3.ipynb b/notebooks/paper/Figure-3/Figure-3.ipynb
index bc6bc05..a71f798 100644
--- a/notebooks/paper/Figure-3/Figure-3.ipynb
+++ b/notebooks/paper/Figure-3/Figure-3.ipynb
@@ -1,331 +1,331 @@
{
- "cells": [
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "sustained-barrier",
- "metadata": {},
- "outputs": [],
- "source": [
- "%load_ext autoreload\n",
- "%autoreload 2\n",
- "\n",
- "import numpy as np\n",
- "import pandas as pd\n",
- "import scipy as sp\n",
- "from carbonplan_forest_risks import load, setup, plot, fit, utils, prepare, collect\n",
- "import xarray as xr\n",
- "from carbonplan_forest_risks.utils import get_store\n",
- "import altair as alt\n",
- "from carbonplan.data import cat\n",
- "import rioxarray\n",
- "import cartopy.crs as ccrs\n",
- "import cartopy\n",
- "import cartopy.feature as cfeature\n",
- "import matplotlib.pyplot as plt\n",
- "from carbonplan_styles.mpl import get_colormap\n",
- "import warnings\n",
- "warnings.filterwarnings('ignore')\n",
- "import matplotlib\n",
- "from carbonplan_data import utils\n",
- "\n",
- "alt.themes.enable(\"carbonplan_light\")"
- ]
+ "cells": [
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "sustained-barrier",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "%load_ext autoreload\n",
+ "%autoreload 2\n",
+ "\n",
+ "import numpy as np\n",
+ "import pandas as pd\n",
+ "import scipy as sp\n",
+ "from carbonplan_forest_risks import load, setup, plot, fit, utils, prepare, collect\n",
+ "import xarray as xr\n",
+ "from carbonplan_forest_risks.utils import get_store\n",
+ "import altair as alt\n",
+ "from carbonplan.data import cat\n",
+ "import rioxarray\n",
+ "import cartopy.crs as ccrs\n",
+ "import cartopy\n",
+ "import cartopy.feature as cfeature\n",
+ "import matplotlib.pyplot as plt\n",
+ "from carbonplan_styles.mpl import get_colormap\n",
+ "import warnings\n",
+ "warnings.filterwarnings('ignore')\n",
+ "import matplotlib\n",
+ "from carbonplan_data import utils\n",
+ "\n",
+ "alt.themes.enable(\"carbonplan_light\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "bizarre-semester",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "alt.data_transformers.disable_max_rows()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "administrative-tours",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "coarsen = 4\n",
+ "mask = (\n",
+ " (\n",
+ " load.nlcd(store=\"az\", year=2001).sel(band=[41, 42, 43, 90]).sum(\"band\")\n",
+ " > 0.25\n",
+ " )\n",
+ " .astype(\"float\")\n",
+ " .coarsen(x=coarsen, y=coarsen, boundary=\"trim\")\n",
+ " .mean()\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "black-michigan",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "historical_fire = xr.open_zarr(\n",
+ " \"https://carbonplan.blob.core.windows.net/carbonplan-forests/risks/results/paper/fire_terraclimate.zarr\"\n",
+ ").load()\n",
+ "fire_mask = ~np.isnan(historical_fire.historical.isel(time=0).drop(\"time\"))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "legendary-module",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "ds = (\n",
+ " xr.open_zarr(\n",
+ " \"https://carbonplan.blob.core.windows.net/carbonplan-forests/risks/results/paper/fire_cmip.zarr\"\n",
+ " )\n",
+ " .assign_coords({\"x\": mask.x, \"y\": mask.y})\n",
+ " .where(fire_mask)\n",
+ " .groupby(\"time.year\")\n",
+ " .sum()\n",
+ " .where(fire_mask)\n",
+ " .compute()\n",
+ ") * 100 # scale to percent"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "invalid-navigator",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "future_maps = {}\n",
+ "future_maps[\"Fire\"] = (\n",
+ " ds.sel(year=slice(\"2080\", \"2099\")).mean(dim=\"year\").compute()\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "focused-quest",
+ "metadata": {},
+ "source": [
+ "### load insects and drought\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "final-bailey",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "for impact in [\"drought\", \"insects\"]:\n",
+ " future_maps[impact.capitalize()] = (\n",
+ " xr.open_zarr(\n",
+ " \"https://carbonplan.blob.core.windows.net/carbonplan-forests/risks/results/paper/{}_cmip.zarr\".format(\n",
+ " impact\n",
+ " )\n",
+ " )\n",
+ " .assign_coords({\"year\": np.arange(1975, 2100, 10)})\n",
+ " .sel(year=slice(2080, 2099))\n",
+ " .mean(dim=\"year\")\n",
+ " )"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "photographic-label",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "gcms = [\n",
+ " (\"MRI-ESM2-0\", (0, 0)),\n",
+ " (\"MIROC-ES2L\", (1, 0)),\n",
+ " (\"MPI-ESM1-2-LR\", (2, 0)),\n",
+ " (\"ACCESS-ESM1-5\", (3, 0)),\n",
+ " (\"ACCESS-CM2\", (4, 0)),\n",
+ " (\"CanESM5-CanOE\", (5, 0)),\n",
+ "]\n",
+ "titles = [\n",
+ " \"Burn area\\n[%/year]\",\n",
+ " \"Drought mortality\\n[]\",\n",
+ " \"Biotic agent mortality\\n[]\",\n",
+ "]"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "deadly-newman",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "scenario_dict = {}\n",
+ "for risk in [\"Fire\", \"Insects\", \"Drought\"]:\n",
+ " scenario_dict[risk] = {}\n",
+ " for scenario in [\"ssp245\", \"ssp370\", \"ssp585\"]:\n",
+ " scenario_dict[risk][scenario] = (\n",
+ " future_maps[risk]\n",
+ " .probability.sel(scenario=scenario)\n",
+ " .mean(dim=\"gcm\")\n",
+ " .drop(\"scenario\")\n",
+ " )"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "absent-concern",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "plot_params = {\n",
+ " \"Fire\": {\n",
+ " \"cmap\": get_colormap(\"reds\"),\n",
+ " \"var_lims\": (0, 3),\n",
+ " \"label\": \"Burn area\\n(%/year)\",\n",
+ " \"panel\": [\"A\", \"B\", \"C\"],\n",
+ " \"cbar_ylocation\": 0.76,\n",
+ " },\n",
+ " \"Drought\": {\n",
+ " \"cmap\": get_colormap(\"pinks\"),\n",
+ " \"var_lims\": (0, 4),\n",
+ " \"label\": \"Drought-related\\nmortality (%/year)\",\n",
+ " \"panel\": [\"D\", \"E\", \"F\"],\n",
+ " \"cbar_ylocation\": 0.4,\n",
+ " },\n",
+ " \"Insects\": {\n",
+ " \"cmap\": get_colormap(\"blues\"),\n",
+ " \"var_lims\": (0, 0.8),\n",
+ " \"label\": \"Insect-related\\nmortality (%/year)\",\n",
+ " \"panel\": [\"G\", \"H\", \"I\"],\n",
+ " \"cbar_ylocation\": 0.04,\n",
+ " },\n",
+ "}"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "sweet-arena",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "matplotlib.rc(\"font\", family=\"sans-serif\")\n",
+ "matplotlib.rc(\"font\", serif=\"Helvetica Neue\")\n",
+ "matplotlib.rc(\"text\", usetex=\"false\")\n",
+ "matplotlib.rcParams.update({\"font.size\": 14, \"svg.fonttype\": \"none\"})"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "critical-indicator",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "ssp_rename = {\"ssp245\": \"SSP2-4.5\", \"ssp370\": \"SSP3-7.0\", \"ssp585\": \"SSP5-8.5\"}"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "headed-employee",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "state_borders, us_border = plot.cartopy_borders()\n",
+ "fig, axarr = plt.subplots(\n",
+ " nrows=3,\n",
+ " ncols=3,\n",
+ " figsize=(15, 12),\n",
+ " subplot_kw={\"projection\": plot.cartopy_proj_albers()},\n",
+ ")\n",
+ "from mpl_toolkits.axes_grid1 import make_axes_locatable\n",
+ "\n",
+ "for row, impact in enumerate([\"Fire\", \"Drought\", \"Insects\"]):\n",
+ " for column, scenario in enumerate([\"ssp245\", \"ssp370\", \"ssp585\"]):\n",
+ " vmin, vmax = (\n",
+ " plot_params[impact][\"var_lims\"][0],\n",
+ " plot_params[impact][\"var_lims\"][1],\n",
+ " )\n",
+ "\n",
+ " map_plot = scenario_dict[impact][scenario].plot.imshow(\n",
+ " ax=axarr[row, column],\n",
+ " cmap=plot_params[impact][\"cmap\"],\n",
+ " vmin=vmin,\n",
+ " vmax=vmax,\n",
+ " add_colorbar=False,\n",
+ " )\n",
+ "\n",
+ " plot.map_pretty(axarr[row, column], title=ssp_rename[scenario])\n",
+ " axarr[row, column].text(\n",
+ " 0.12,\n",
+ " 1.05,\n",
+ " plot_params[impact][\"panel\"][column],\n",
+ " transform=axarr[row, column].transAxes,\n",
+ " fontsize=18,\n",
+ " )\n",
+ " cax = fig.add_axes(\n",
+ " [1.03, plot_params[impact][\"cbar_ylocation\"], 0.018, 0.12]\n",
+ " )\n",
+ " cax.text(\n",
+ " 0.5,\n",
+ " -0.12,\n",
+ " plot_params[impact][\"var_lims\"][0],\n",
+ " transform=cax.transAxes,\n",
+ " horizontalalignment=\"center\",\n",
+ " )\n",
+ " cax.text(\n",
+ " 0.5,\n",
+ " 1.05,\n",
+ " plot_params[impact][\"var_lims\"][1],\n",
+ " transform=cax.transAxes,\n",
+ " horizontalalignment=\"center\",\n",
+ " )\n",
+ " cax.text(\n",
+ " 1.8,\n",
+ " 0.5,\n",
+ " plot_params[impact][\"label\"],\n",
+ " transform=cax.transAxes,\n",
+ " verticalalignment=\"center\",\n",
+ " multialignment=\"center\",\n",
+ " rotation=-90,\n",
+ " )\n",
+ " cbar = fig.colorbar(map_plot, cax=cax, orientation=\"vertical\")\n",
+ " cbar.outline.set_visible(False)\n",
+ " cbar.set_ticks([])\n",
+ "plt.tight_layout(pad=-6)\n",
+ "# for format_string in [\"svg\", \"png\"]:\n",
+ "# fig.savefig(\n",
+ "# \"Figure-3.\" + format_string, format=format_string, bbox_inches=\"tight\"\n",
+ "# )"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python [conda env:notebook] *",
+ "language": "python",
+ "name": "conda-env-notebook-py"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.9.12"
+ }
},
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "bizarre-semester",
- "metadata": {},
- "outputs": [],
- "source": [
- "alt.data_transformers.disable_max_rows()"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "administrative-tours",
- "metadata": {},
- "outputs": [],
- "source": [
- "coarsen = 4\n",
- "mask = (\n",
- " (\n",
- " load.nlcd(store=\"az\", year=2001).sel(band=[41, 42, 43, 90]).sum(\"band\")\n",
- " > 0.25\n",
- " )\n",
- " .astype(\"float\")\n",
- " .coarsen(x=coarsen, y=coarsen, boundary=\"trim\")\n",
- " .mean()\n",
- ")"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "black-michigan",
- "metadata": {},
- "outputs": [],
- "source": [
- "historical_fire = xr.open_zarr(\n",
- " \"https://carbonplan.blob.core.windows.net/carbonplan-forests/risks/results/paper/fire_terraclimate.zarr\"\n",
- ").load()\n",
- "fire_mask = ~np.isnan(historical_fire.historical.isel(time=0).drop(\"time\"))"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "legendary-module",
- "metadata": {},
- "outputs": [],
- "source": [
- "ds = (\n",
- " xr.open_zarr(\n",
- " \"https://carbonplan.blob.core.windows.net/carbonplan-forests/risks/results/paper/fire_cmip.zarr\"\n",
- " )\n",
- " .assign_coords({\"x\": mask.x, \"y\": mask.y})\n",
- " .where(fire_mask)\n",
- " .groupby(\"time.year\")\n",
- " .sum()\n",
- " .where(fire_mask)\n",
- " .compute()\n",
- ") * 100 # scale to percent"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "invalid-navigator",
- "metadata": {},
- "outputs": [],
- "source": [
- "future_maps = {}\n",
- "future_maps[\"Fire\"] = (\n",
- " ds.sel(year=slice(\"2080\", \"2099\")).mean(dim=\"year\").compute()\n",
- ")"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "focused-quest",
- "metadata": {},
- "source": [
- "### load insects and drought\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "final-bailey",
- "metadata": {},
- "outputs": [],
- "source": [
- "for impact in [\"drought\", \"insects\"]:\n",
- " future_maps[impact.capitalize()] = (\n",
- " xr.open_zarr(\n",
- " \"https://carbonplan.blob.core.windows.net/carbonplan-forests/risks/results/paper/{}_cmip.zarr\".format(\n",
- " impact\n",
- " )\n",
- " )\n",
- " .assign_coords({\"year\": np.arange(1975, 2100, 10)})\n",
- " .sel(year=slice(2080, 2099))\n",
- " .mean(dim=\"year\")\n",
- " )"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "photographic-label",
- "metadata": {},
- "outputs": [],
- "source": [
- "gcms = [\n",
- " (\"MRI-ESM2-0\", (0, 0)),\n",
- " (\"MIROC-ES2L\", (1, 0)),\n",
- " (\"MPI-ESM1-2-LR\", (2, 0)),\n",
- " (\"ACCESS-ESM1-5\", (3, 0)),\n",
- " (\"ACCESS-CM2\", (4, 0)),\n",
- " (\"CanESM5-CanOE\", (5, 0)),\n",
- "]\n",
- "titles = [\n",
- " \"Burn area\\n[%/year]\",\n",
- " \"Drought mortality\\n[]\",\n",
- " \"Biotic agent mortality\\n[]\",\n",
- "]"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "deadly-newman",
- "metadata": {},
- "outputs": [],
- "source": [
- "scenario_dict = {}\n",
- "for risk in [\"Fire\", \"Insects\", \"Drought\"]:\n",
- " scenario_dict[risk] = {}\n",
- " for scenario in [\"ssp245\", \"ssp370\", \"ssp585\"]:\n",
- " scenario_dict[risk][scenario] = (\n",
- " future_maps[risk]\n",
- " .probability.sel(scenario=scenario)\n",
- " .mean(dim=\"gcm\")\n",
- " .drop(\"scenario\")\n",
- " )"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "absent-concern",
- "metadata": {},
- "outputs": [],
- "source": [
- "plot_params = {\n",
- " \"Fire\": {\n",
- " \"cmap\": get_colormap(\"reds\"),\n",
- " \"var_lims\": (0, 3),\n",
- " \"label\": \"Burn area\\n(%/year)\",\n",
- " \"panel\": [\"A\", \"B\", \"C\"],\n",
- " \"cbar_ylocation\": 0.76,\n",
- " },\n",
- " \"Drought\": {\n",
- " \"cmap\": get_colormap(\"pinks\"),\n",
- " \"var_lims\": (0, 4),\n",
- " \"label\": \"Drought-related\\nmortality (%/year)\",\n",
- " \"panel\": [\"D\", \"E\", \"F\"],\n",
- " \"cbar_ylocation\": 0.4,\n",
- " },\n",
- " \"Insects\": {\n",
- " \"cmap\": get_colormap(\"blues\"),\n",
- " \"var_lims\": (0, 0.8),\n",
- " \"label\": \"Insect-related\\nmortality (%/year)\",\n",
- " \"panel\": [\"G\", \"H\", \"I\"],\n",
- " \"cbar_ylocation\": 0.04,\n",
- " },\n",
- "}"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "sweet-arena",
- "metadata": {},
- "outputs": [],
- "source": [
- "matplotlib.rc(\"font\", family=\"sans-serif\")\n",
- "matplotlib.rc(\"font\", serif=\"Helvetica Neue\")\n",
- "matplotlib.rc(\"text\", usetex=\"false\")\n",
- "matplotlib.rcParams.update({\"font.size\": 14, \"svg.fonttype\": \"none\"})"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "critical-indicator",
- "metadata": {},
- "outputs": [],
- "source": [
- "ssp_rename = {\"ssp245\": \"SSP2-4.5\", \"ssp370\": \"SSP3-7.0\", \"ssp585\": \"SSP5-8.5\"}"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "headed-employee",
- "metadata": {},
- "outputs": [],
- "source": [
- "state_borders, us_border = plot.cartopy_borders()\n",
- "fig, axarr = plt.subplots(\n",
- " nrows=3,\n",
- " ncols=3,\n",
- " figsize=(15, 12),\n",
- " subplot_kw={\"projection\": plot.cartopy_proj_albers()},\n",
- ")\n",
- "from mpl_toolkits.axes_grid1 import make_axes_locatable\n",
- "\n",
- "for row, impact in enumerate([\"Fire\", \"Drought\", \"Insects\"]):\n",
- " for column, scenario in enumerate([\"ssp245\", \"ssp370\", \"ssp585\"]):\n",
- " vmin, vmax = (\n",
- " plot_params[impact][\"var_lims\"][0],\n",
- " plot_params[impact][\"var_lims\"][1],\n",
- " )\n",
- "\n",
- " map_plot = scenario_dict[impact][scenario].plot.imshow(\n",
- " ax=axarr[row, column],\n",
- " cmap=plot_params[impact][\"cmap\"],\n",
- " vmin=vmin,\n",
- " vmax=vmax,\n",
- " add_colorbar=False,\n",
- " )\n",
- "\n",
- " plot.map_pretty(axarr[row, column], title=ssp_rename[scenario])\n",
- " axarr[row, column].text(\n",
- " 0.12,\n",
- " 1.05,\n",
- " plot_params[impact][\"panel\"][column],\n",
- " transform=axarr[row, column].transAxes,\n",
- " fontsize=18,\n",
- " )\n",
- " cax = fig.add_axes(\n",
- " [1.03, plot_params[impact][\"cbar_ylocation\"], 0.018, 0.12]\n",
- " )\n",
- " cax.text(\n",
- " 0.5,\n",
- " -0.12,\n",
- " plot_params[impact][\"var_lims\"][0],\n",
- " transform=cax.transAxes,\n",
- " horizontalalignment=\"center\",\n",
- " )\n",
- " cax.text(\n",
- " 0.5,\n",
- " 1.05,\n",
- " plot_params[impact][\"var_lims\"][1],\n",
- " transform=cax.transAxes,\n",
- " horizontalalignment=\"center\",\n",
- " )\n",
- " cax.text(\n",
- " 1.8,\n",
- " 0.5,\n",
- " plot_params[impact][\"label\"],\n",
- " transform=cax.transAxes,\n",
- " verticalalignment=\"center\",\n",
- " multialignment=\"center\",\n",
- " rotation=-90,\n",
- " )\n",
- " cbar = fig.colorbar(map_plot, cax=cax, orientation=\"vertical\")\n",
- " cbar.outline.set_visible(False)\n",
- " cbar.set_ticks([])\n",
- "plt.tight_layout(pad=-6)\n",
- "# for format_string in [\"svg\", \"png\"]:\n",
- "# fig.savefig(\n",
- "# \"Figure-3.\" + format_string, format=format_string, bbox_inches=\"tight\"\n",
- "# )"
- ]
- }
- ],
- "metadata": {
- "kernelspec": {
- "display_name": "Python [conda env:notebook] *",
- "language": "python",
- "name": "conda-env-notebook-py"
- },
- "language_info": {
- "codemirror_mode": {
- "name": "ipython",
- "version": 3
- },
- "file_extension": ".py",
- "mimetype": "text/x-python",
- "name": "python",
- "nbconvert_exporter": "python",
- "pygments_lexer": "ipython3",
- "version": "3.9.12"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 5
+ "nbformat": 4,
+ "nbformat_minor": 5
}
diff --git a/notebooks/paper/Figure-4/Figure-4.ipynb b/notebooks/paper/Figure-4/Figure-4.ipynb
index 1ffe63c..4e020ef 100644
--- a/notebooks/paper/Figure-4/Figure-4.ipynb
+++ b/notebooks/paper/Figure-4/Figure-4.ipynb
@@ -1,292 +1,292 @@
{
- "cells": [
- {
- "cell_type": "markdown",
- "id": "surface-novel",
- "metadata": {},
- "source": [
- "\n",
- "\n",
- "# Figure 4: Future projections for each impact\n",
- "\n",
- "_Authors: Oriana Chegwidden and Jeremy Freeman_\n",
- "\n",
- "The methods below conduct the analyses to recreate Figure 4 included the\n",
- "manuscript <<< insert doi >>>. Future risks for fire. We show median changes in\n",
- "risk with respect to the historic.\n"
- ]
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "id": "surface-novel",
+ "metadata": {},
+ "source": [
+ "\n",
+ "\n",
+ "# Figure 4: Future projections for each impact\n",
+ "\n",
+ "_Authors: Oriana Chegwidden and Jeremy Freeman_\n",
+ "\n",
+ "The methods below conduct the analyses to recreate Figure 4 included the\n",
+ "manuscript <<< insert doi >>>. Future risks for fire. We show median changes in\n",
+ "risk with respect to the historic.\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "worth-convergence",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "%load_ext autoreload\n",
+ "%autoreload 2\n",
+ "%matplotlib inline\n",
+ "import matplotlib.pyplot as plt\n",
+ "import numpy as np\n",
+ "import pandas as pd\n",
+ "import scipy as sp\n",
+ "from carbonplan_forest_risks import load, setup, plot, fit, utils, prepare, collect\n",
+ "import xarray as xr\n",
+ "from carbonplan_forest_risks.utils import get_store\n",
+ "import rioxarray\n",
+ "from carbonplan.data import cat\n",
+ "import matplotlib.gridspec as gridspec"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "optical-vinyl",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import warnings\n",
+ "\n",
+ "warnings.filterwarnings(\"ignore\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "forbidden-claim",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "coarsen = 4"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "arabic-intelligence",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "mask = (\n",
+ " (\n",
+ " load.nlcd(store=\"az\", year=2001).sel(band=[41, 42, 43, 90]).sum(\"band\")\n",
+ " > 0.25\n",
+ " )\n",
+ " .astype(\"float\")\n",
+ " .coarsen(x=coarsen, y=coarsen, boundary=\"trim\")\n",
+ " .mean()\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "advised-biodiversity",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "region_bboxes = {\n",
+ " \"PNW\": {\"x\": slice(-2.5e6, -1e6), \"y\": slice(3.5e6, 2.4e6)},\n",
+ " \"Southwest\": {\"x\": slice(-1.8e6, -0.9e6), \"y\": slice(1.8e6, 0.9e6)},\n",
+ " \"California\": {\"x\": slice(-2.3e6, -1.8e6), \"y\": slice(2.5e6, 1.2e6)},\n",
+ " \"Southeast\": {\"x\": slice(0.6e6, 1.8e6), \"y\": slice(1.6e6, 0.3e6)},\n",
+ "}"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "heated-revelation",
+ "metadata": {},
+ "source": [
+ "# Load in fire data\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "loaded-supervisor",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "historical_fire = xr.open_zarr(\n",
+ " \"https://carbonplan.blob.core.windows.net/carbonplan-forests/risks/results/paper/fire_terraclimate.zarr\"\n",
+ ").load()\n",
+ "fire_mask = ~np.isnan(historical_fire.historical.isel(time=0).drop(\"time\"))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "little-injury",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "ds = (\n",
+ " xr.open_zarr(\n",
+ " \"https://carbonplan.blob.core.windows.net/carbonplan-forests/risks/results/paper/fire_cmip.zarr\"\n",
+ " )\n",
+ " .assign_coords({\"x\": mask.x, \"y\": mask.y})\n",
+ " .where(fire_mask)\n",
+ " .groupby(\"time.year\")\n",
+ " .sum()\n",
+ " .where(fire_mask)\n",
+ " .compute()\n",
+ ") * 100"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "further-smile",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "historical_annual = (\n",
+ " xr.open_zarr(\n",
+ " \"https://carbonplan.blob.core.windows.net/carbonplan-forests/risks/results/paper/fire_terraclimate.zarr\"\n",
+ " )\n",
+ " .assign_coords({\"x\": mask.x, \"y\": mask.y})\n",
+ " .groupby(\"time.year\")\n",
+ " .sum()\n",
+ " .where(fire_mask)\n",
+ " .compute()\n",
+ ") * 100"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "modified-entrepreneur",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def load_regional_results(ds, timestep, region):\n",
+ " selected = ds.sel(**region)\n",
+ " if timestep == \"annual\":\n",
+ " return (\n",
+ " selected.mean(dim=[\"x\", \"y\"])\n",
+ " .rolling(dim={\"year\": 10})\n",
+ " .mean()\n",
+ " .compute()\n",
+ " )\n",
+ " elif timestep == \"decadal\":\n",
+ " return selected.mean(dim=[\"x\", \"y\"]).compute()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "settled-plaza",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "results_dict = {\"fire\": {}, \"insects\": {}, \"drought\": {}}"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "clear-commodity",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "for region, bbox in region_bboxes.items():\n",
+ " results_dict[\"fire\"][region] = {}\n",
+ " results_dict[\"fire\"][region][\"future\"] = (\n",
+ " load_regional_results(ds, \"annual\", region_bboxes[region])\n",
+ " .sel(year=slice(1970, 2099))\n",
+ " .probability\n",
+ " )\n",
+ " results_dict[\"fire\"][region][\"historical\"] = load_regional_results(\n",
+ " historical_annual, \"annual\", region_bboxes[region]\n",
+ " ).historical"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "combined-millennium",
+ "metadata": {},
+ "source": [
+ "### Load in insect and drought data\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "comic-third",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "for impact in [\"insects\", \"drought\"]:\n",
+ " historical_ds = (\n",
+ " xr.open_zarr(\n",
+ " \"https://carbonplan.blob.core.windows.net/carbonplan-forests/risks/results/paper/{}_terraclimate.zarr\".format(\n",
+ " impact\n",
+ " )\n",
+ " )\n",
+ " .assign_coords({\"year\": np.arange(1995, 2020, 10)})\n",
+ " .compute()\n",
+ " )\n",
+ " future_ds = (\n",
+ " xr.open_zarr(\n",
+ " \"https://carbonplan.blob.core.windows.net/carbonplan-forests/risks/results/paper/{}_cmip.zarr\".format(\n",
+ " impact\n",
+ " )\n",
+ " )\n",
+ " .assign_coords({\"year\": np.arange(1975, 2100, 10)})\n",
+ " .compute()\n",
+ " )\n",
+ "\n",
+ " for region, bbox in region_bboxes.items():\n",
+ " results_dict[impact][region] = {}\n",
+ " results_dict[impact][region][\"future\"] = (\n",
+ " load_regional_results(future_ds, \"decadal\", region_bboxes[region])\n",
+ " .sel(year=slice(1970, 2099))\n",
+ " .probability\n",
+ " )\n",
+ " results_dict[impact][region][\"historical\"] = load_regional_results(\n",
+ " historical_ds, \"decadal\", region_bboxes[region]\n",
+ " ).probability"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "decent-baltimore",
+ "metadata": {},
+ "source": [
+ "## Plot the figure\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "obvious-thursday",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "plot.multipanel_ts(results_dict, region_bboxes, \"Figure-4\")"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python [conda env:notebook] *",
+ "language": "python",
+ "name": "conda-env-notebook-py"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.9.12"
+ }
},
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "worth-convergence",
- "metadata": {},
- "outputs": [],
- "source": [
- "%load_ext autoreload\n",
- "%autoreload 2\n",
- "%matplotlib inline\n",
- "import matplotlib.pyplot as plt\n",
- "import numpy as np\n",
- "import pandas as pd\n",
- "import scipy as sp\n",
- "from carbonplan_forest_risks import load, setup, plot, fit, utils, prepare, collect\n",
- "import xarray as xr\n",
- "from carbonplan_forest_risks.utils import get_store\n",
- "import rioxarray\n",
- "from carbonplan.data import cat\n",
- "import matplotlib.gridspec as gridspec"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "optical-vinyl",
- "metadata": {},
- "outputs": [],
- "source": [
- "import warnings\n",
- "\n",
- "warnings.filterwarnings(\"ignore\")"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "forbidden-claim",
- "metadata": {},
- "outputs": [],
- "source": [
- "coarsen = 4"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "arabic-intelligence",
- "metadata": {},
- "outputs": [],
- "source": [
- "mask = (\n",
- " (\n",
- " load.nlcd(store=\"az\", year=2001).sel(band=[41, 42, 43, 90]).sum(\"band\")\n",
- " > 0.25\n",
- " )\n",
- " .astype(\"float\")\n",
- " .coarsen(x=coarsen, y=coarsen, boundary=\"trim\")\n",
- " .mean()\n",
- ")"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "advised-biodiversity",
- "metadata": {},
- "outputs": [],
- "source": [
- "region_bboxes = {\n",
- " \"PNW\": {\"x\": slice(-2.5e6, -1e6), \"y\": slice(3.5e6, 2.4e6)},\n",
- " \"Southwest\": {\"x\": slice(-1.8e6, -0.9e6), \"y\": slice(1.8e6, 0.9e6)},\n",
- " \"California\": {\"x\": slice(-2.3e6, -1.8e6), \"y\": slice(2.5e6, 1.2e6)},\n",
- " \"Southeast\": {\"x\": slice(0.6e6, 1.8e6), \"y\": slice(1.6e6, 0.3e6)},\n",
- "}"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "heated-revelation",
- "metadata": {},
- "source": [
- "# Load in fire data\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "loaded-supervisor",
- "metadata": {},
- "outputs": [],
- "source": [
- "historical_fire = xr.open_zarr(\n",
- " \"https://carbonplan.blob.core.windows.net/carbonplan-forests/risks/results/paper/fire_terraclimate.zarr\"\n",
- ").load()\n",
- "fire_mask = ~np.isnan(historical_fire.historical.isel(time=0).drop(\"time\"))"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "little-injury",
- "metadata": {},
- "outputs": [],
- "source": [
- "ds = (\n",
- " xr.open_zarr(\n",
- " \"https://carbonplan.blob.core.windows.net/carbonplan-forests/risks/results/paper/fire_cmip.zarr\"\n",
- " )\n",
- " .assign_coords({\"x\": mask.x, \"y\": mask.y})\n",
- " .where(fire_mask)\n",
- " .groupby(\"time.year\")\n",
- " .sum()\n",
- " .where(fire_mask)\n",
- " .compute()\n",
- ") * 100"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "further-smile",
- "metadata": {},
- "outputs": [],
- "source": [
- "historical_annual = (\n",
- " xr.open_zarr(\n",
- " \"https://carbonplan.blob.core.windows.net/carbonplan-forests/risks/results/paper/fire_terraclimate.zarr\"\n",
- " )\n",
- " .assign_coords({\"x\": mask.x, \"y\": mask.y})\n",
- " .groupby(\"time.year\")\n",
- " .sum()\n",
- " .where(fire_mask)\n",
- " .compute()\n",
- ") * 100"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "modified-entrepreneur",
- "metadata": {},
- "outputs": [],
- "source": [
- "def load_regional_results(ds, timestep, region):\n",
- " selected = ds.sel(**region)\n",
- " if timestep == \"annual\":\n",
- " return (\n",
- " selected.mean(dim=[\"x\", \"y\"])\n",
- " .rolling(dim={\"year\": 10})\n",
- " .mean()\n",
- " .compute()\n",
- " )\n",
- " elif timestep == \"decadal\":\n",
- " return selected.mean(dim=[\"x\", \"y\"]).compute()"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "settled-plaza",
- "metadata": {},
- "outputs": [],
- "source": [
- "results_dict = {\"fire\": {}, \"insects\": {}, \"drought\": {}}"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "clear-commodity",
- "metadata": {},
- "outputs": [],
- "source": [
- "for region, bbox in region_bboxes.items():\n",
- " results_dict[\"fire\"][region] = {}\n",
- " results_dict[\"fire\"][region][\"future\"] = (\n",
- " load_regional_results(ds, \"annual\", region_bboxes[region])\n",
- " .sel(year=slice(1970, 2099))\n",
- " .probability\n",
- " )\n",
- " results_dict[\"fire\"][region][\"historical\"] = load_regional_results(\n",
- " historical_annual, \"annual\", region_bboxes[region]\n",
- " ).historical"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "combined-millennium",
- "metadata": {},
- "source": [
- "### Load in insect and drought data\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "comic-third",
- "metadata": {},
- "outputs": [],
- "source": [
- "for impact in [\"insects\", \"drought\"]:\n",
- " historical_ds = (\n",
- " xr.open_zarr(\n",
- " \"https://carbonplan.blob.core.windows.net/carbonplan-forests/risks/results/paper/{}_terraclimate.zarr\".format(\n",
- " impact\n",
- " )\n",
- " )\n",
- " .assign_coords({\"year\": np.arange(1995, 2020, 10)})\n",
- " .compute()\n",
- " )\n",
- " future_ds = (\n",
- " xr.open_zarr(\n",
- " \"https://carbonplan.blob.core.windows.net/carbonplan-forests/risks/results/paper/{}_cmip.zarr\".format(\n",
- " impact\n",
- " )\n",
- " )\n",
- " .assign_coords({\"year\": np.arange(1975, 2100, 10)})\n",
- " .compute()\n",
- " )\n",
- "\n",
- " for region, bbox in region_bboxes.items():\n",
- " results_dict[impact][region] = {}\n",
- " results_dict[impact][region][\"future\"] = (\n",
- " load_regional_results(future_ds, \"decadal\", region_bboxes[region])\n",
- " .sel(year=slice(1970, 2099))\n",
- " .probability\n",
- " )\n",
- " results_dict[impact][region][\"historical\"] = load_regional_results(\n",
- " historical_ds, \"decadal\", region_bboxes[region]\n",
- " ).probability"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "decent-baltimore",
- "metadata": {},
- "source": [
- "## Plot the figure\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "obvious-thursday",
- "metadata": {},
- "outputs": [],
- "source": [
- "plot.multipanel_ts(results_dict, region_bboxes, \"Figure-4\")"
- ]
- }
- ],
- "metadata": {
- "kernelspec": {
- "display_name": "Python [conda env:notebook] *",
- "language": "python",
- "name": "conda-env-notebook-py"
- },
- "language_info": {
- "codemirror_mode": {
- "name": "ipython",
- "version": 3
- },
- "file_extension": ".py",
- "mimetype": "text/x-python",
- "name": "python",
- "nbconvert_exporter": "python",
- "pygments_lexer": "ipython3",
- "version": "3.9.12"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 5
+ "nbformat": 4,
+ "nbformat_minor": 5
}
diff --git a/notebooks/paper/Supplementary-Figure-01/Supplementary-Figure-01.ipynb b/notebooks/paper/Supplementary-Figure-01/Supplementary-Figure-01.ipynb
index cd3f1f9..17428e7 100644
--- a/notebooks/paper/Supplementary-Figure-01/Supplementary-Figure-01.ipynb
+++ b/notebooks/paper/Supplementary-Figure-01/Supplementary-Figure-01.ipynb
@@ -1,254 +1,254 @@
{
- "cells": [
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "muslim-proof",
- "metadata": {},
- "outputs": [],
- "source": [
- "import numpy as np\n",
- "import pandas as pd\n",
- "import matplotlib.pyplot as plt"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "brave-southwest",
- "metadata": {},
- "outputs": [],
- "source": [
- "df = pd.read_csv(\"fire_stats.csv\")"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "sunset-bruce",
- "metadata": {},
- "outputs": [],
- "source": [
- "df"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "municipal-rachel",
- "metadata": {},
- "outputs": [],
- "source": [
- "df[df[\"method\"].str.contains(\"split_halves\")][\"roc\"].mean()"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "subjective-mobile",
- "metadata": {},
- "outputs": [],
- "source": [
- "df[df[\"method\"].str.contains(\"split_halves\")][\"r2\"].mean()"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "loose-empty",
- "metadata": {},
- "outputs": [],
- "source": [
- "df[df[\"method\"].str.contains(\"split_halves\")][\"annual_r2\"].mean()"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "quantitative-launch",
- "metadata": {},
- "outputs": [],
- "source": [
- "df[df[\"method\"].str.contains(\"split_halves\")][\"seasonal_r2\"].mean()"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "personalized-binding",
- "metadata": {},
- "outputs": [],
- "source": [
- "df[df[\"method\"].str.contains(\"split_halves\")][\"spatial_r2\"].mean()"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "dab131fe",
- "metadata": {},
- "outputs": [],
- "source": [
- "df[df[\"method\"].str.contains(\"split_halves\")][\"spatial_auc\"].mean()"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "mobile-affiliate",
- "metadata": {},
- "outputs": [],
- "source": [
- "results = {}\n",
- "results[\"null\"] = df[df[\"method\"].str.contains(\"shuffle_all\")]\n",
- "results[\"split\"] = df[df[\"method\"].str.contains(\"split_halves\")]\n",
- "results[\"extrap\"] = df[df[\"method\"].str.contains(\"extrapolate\")]"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "neutral-primary",
- "metadata": {},
- "outputs": [],
- "source": [
- "plt.rcParams.update({\"font.size\": 14, \"svg.fonttype\": \"none\"})"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "burning-pixel",
- "metadata": {},
- "outputs": [],
- "source": [
- "plot_params = {\n",
- " \"roc\": {\n",
- " \"ylim\": [0.5, 0.95],\n",
- " \"ylabel\": \"Hurdle ROC\",\n",
- " \"yticks\": [0.5, 0.6, 0.7, 0.8, 0.9],\n",
- " },\n",
- " \"r2\": {\"ylim\": [-0.02, 0.08], \"ylabel\": \"Hurdle R2\"},\n",
- " \"annual_r2\": {\"ylim\": [-0.1, 0.95], \"ylabel\": \"Annual R2\"},\n",
- " \"seasonal_r2\": {\"ylim\": [-0.1, 0.95], \"ylabel\": \"Seasonal R2\"},\n",
- " \"spatial_auc\": {\"ylim\": [0.4, 0.95], \"ylabel\": \"Spatial ROC\"},\n",
- "}"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "drawn-telephone",
- "metadata": {},
- "outputs": [],
- "source": [
- "def style(ax, params):\n",
- " ax.spines[\"top\"].set_visible(False)\n",
- " ax.spines[\"right\"].set_visible(False)\n",
- " ax.spines[\"bottom\"].set_visible(False)\n",
- " ax.set_xticks([])\n",
- " if \"ylim\" in params.keys():\n",
- " ax.set_ylim(params[\"ylim\"])\n",
- " if \"yticks\" in params.keys():\n",
- " ax.set_yticks(params[\"yticks\"])\n",
- " if \"ylabel\" in params.keys():\n",
- " ax.set_ylabel(params[\"ylabel\"])\n",
- "\n",
- "\n",
- "def plot_lines(ax, field):\n",
- " ax.hlines(\n",
- " [\n",
- " results[\"null\"][field].min(),\n",
- " results[\"null\"][field].median(),\n",
- " results[\"null\"][field].max(),\n",
- " ],\n",
- " 0,\n",
- " 1,\n",
- " color=\"gray\",\n",
- " )\n",
- "\n",
- "\n",
- "def plot_dots(ax, field):\n",
- " ax.plot(\n",
- " [0.25],\n",
- " [results[\"split\"][field].median()],\n",
- " \".\",\n",
- " color=\"black\",\n",
- " markersize=15,\n",
- " )\n",
- " ax.plot(\n",
- " [0.75],\n",
- " [results[\"extrap\"][field].median()],\n",
- " \".\",\n",
- " color=\"gray\",\n",
- " markersize=15,\n",
- " )"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "typical-moscow",
- "metadata": {},
- "outputs": [],
- "source": [
- "fig, axs = plt.subplots(\n",
- " nrows=1,\n",
- " ncols=5,\n",
- " figsize=(12, 5),\n",
- ")\n",
- "\n",
- "for i, field in enumerate(\n",
- " [\"roc\", \"r2\", \"spatial_auc\", \"annual_r2\", \"seasonal_r2\"]\n",
- "):\n",
- " plot_lines(axs[i], field)\n",
- " plot_dots(axs[i], field)\n",
- " style(axs[i], plot_params[field])\n",
- "\n",
- "plt.tight_layout()\n",
- "plt.savefig(\"Supplementary-Figure-01.svg\")"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "aggressive-distributor",
- "metadata": {},
- "outputs": [],
- "source": [
- "df[df[\"method\"].str.contains(\"split_halves\")][\"bias\"].median()"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "changed-charity",
- "metadata": {},
- "outputs": [],
- "source": [
- "df[df[\"method\"].str.contains(\"extrapolate\")][\"bias\"].median()"
- ]
- }
- ],
- "metadata": {
- "kernelspec": {
- "display_name": "Python 3 (ipykernel)",
- "language": "python",
- "name": "python3"
- },
- "language_info": {
- "codemirror_mode": {
- "name": "ipython",
- "version": 3
- },
- "file_extension": ".py",
- "mimetype": "text/x-python",
- "name": "python",
- "nbconvert_exporter": "python",
- "pygments_lexer": "ipython3",
- "version": "3.8.6"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 5
+ "cells": [
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "muslim-proof",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import numpy as np\n",
+ "import pandas as pd\n",
+ "import matplotlib.pyplot as plt"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "brave-southwest",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "df = pd.read_csv(\"fire_stats.csv\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "sunset-bruce",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "df"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "municipal-rachel",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "df[df[\"method\"].str.contains(\"split_halves\")][\"roc\"].mean()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "subjective-mobile",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "df[df[\"method\"].str.contains(\"split_halves\")][\"r2\"].mean()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "loose-empty",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "df[df[\"method\"].str.contains(\"split_halves\")][\"annual_r2\"].mean()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "quantitative-launch",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "df[df[\"method\"].str.contains(\"split_halves\")][\"seasonal_r2\"].mean()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "personalized-binding",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "df[df[\"method\"].str.contains(\"split_halves\")][\"spatial_r2\"].mean()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "dab131fe",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "df[df[\"method\"].str.contains(\"split_halves\")][\"spatial_auc\"].mean()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "mobile-affiliate",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "results = {}\n",
+ "results[\"null\"] = df[df[\"method\"].str.contains(\"shuffle_all\")]\n",
+ "results[\"split\"] = df[df[\"method\"].str.contains(\"split_halves\")]\n",
+ "results[\"extrap\"] = df[df[\"method\"].str.contains(\"extrapolate\")]"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "neutral-primary",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "plt.rcParams.update({\"font.size\": 14, \"svg.fonttype\": \"none\"})"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "burning-pixel",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "plot_params = {\n",
+ " \"roc\": {\n",
+ " \"ylim\": [0.5, 0.95],\n",
+ " \"ylabel\": \"Hurdle ROC\",\n",
+ " \"yticks\": [0.5, 0.6, 0.7, 0.8, 0.9],\n",
+ " },\n",
+ " \"r2\": {\"ylim\": [-0.02, 0.08], \"ylabel\": \"Hurdle R2\"},\n",
+ " \"annual_r2\": {\"ylim\": [-0.1, 0.95], \"ylabel\": \"Annual R2\"},\n",
+ " \"seasonal_r2\": {\"ylim\": [-0.1, 0.95], \"ylabel\": \"Seasonal R2\"},\n",
+ " \"spatial_auc\": {\"ylim\": [0.4, 0.95], \"ylabel\": \"Spatial ROC\"},\n",
+ "}"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "drawn-telephone",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def style(ax, params):\n",
+ " ax.spines[\"top\"].set_visible(False)\n",
+ " ax.spines[\"right\"].set_visible(False)\n",
+ " ax.spines[\"bottom\"].set_visible(False)\n",
+ " ax.set_xticks([])\n",
+ " if \"ylim\" in params.keys():\n",
+ " ax.set_ylim(params[\"ylim\"])\n",
+ " if \"yticks\" in params.keys():\n",
+ " ax.set_yticks(params[\"yticks\"])\n",
+ " if \"ylabel\" in params.keys():\n",
+ " ax.set_ylabel(params[\"ylabel\"])\n",
+ "\n",
+ "\n",
+ "def plot_lines(ax, field):\n",
+ " ax.hlines(\n",
+ " [\n",
+ " results[\"null\"][field].min(),\n",
+ " results[\"null\"][field].median(),\n",
+ " results[\"null\"][field].max(),\n",
+ " ],\n",
+ " 0,\n",
+ " 1,\n",
+ " color=\"gray\",\n",
+ " )\n",
+ "\n",
+ "\n",
+ "def plot_dots(ax, field):\n",
+ " ax.plot(\n",
+ " [0.25],\n",
+ " [results[\"split\"][field].median()],\n",
+ " \".\",\n",
+ " color=\"black\",\n",
+ " markersize=15,\n",
+ " )\n",
+ " ax.plot(\n",
+ " [0.75],\n",
+ " [results[\"extrap\"][field].median()],\n",
+ " \".\",\n",
+ " color=\"gray\",\n",
+ " markersize=15,\n",
+ " )"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "typical-moscow",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "fig, axs = plt.subplots(\n",
+ " nrows=1,\n",
+ " ncols=5,\n",
+ " figsize=(12, 5),\n",
+ ")\n",
+ "\n",
+ "for i, field in enumerate(\n",
+ " [\"roc\", \"r2\", \"spatial_auc\", \"annual_r2\", \"seasonal_r2\"]\n",
+ "):\n",
+ " plot_lines(axs[i], field)\n",
+ " plot_dots(axs[i], field)\n",
+ " style(axs[i], plot_params[field])\n",
+ "\n",
+ "plt.tight_layout()\n",
+ "plt.savefig(\"Supplementary-Figure-01.svg\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "aggressive-distributor",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "df[df[\"method\"].str.contains(\"split_halves\")][\"bias\"].median()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "changed-charity",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "df[df[\"method\"].str.contains(\"extrapolate\")][\"bias\"].median()"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3 (ipykernel)",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.8.6"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
}
diff --git a/notebooks/paper/Supplementary-Figure-02/Supplementary-Figure-02.ipynb b/notebooks/paper/Supplementary-Figure-02/Supplementary-Figure-02.ipynb
index eacfa86..c547c75 100644
--- a/notebooks/paper/Supplementary-Figure-02/Supplementary-Figure-02.ipynb
+++ b/notebooks/paper/Supplementary-Figure-02/Supplementary-Figure-02.ipynb
@@ -1,81 +1,81 @@
{
- "cells": [
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "geological-bedroom",
- "metadata": {},
- "outputs": [],
- "source": [
- "import numpy as np\n",
- "import pandas as pd\n",
- "import matplotlib.pyplot as plt"
- ]
+ "cells": [
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "geological-bedroom",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import numpy as np\n",
+ "import pandas as pd\n",
+ "import matplotlib.pyplot as plt"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "initial-bonus",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "plt.rcParams.update({\"font.size\": 14, \"svg.fonttype\": \"none\"})"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "helpful-enough",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "df = pd.read_csv(\"StankeSFigData.csv\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "industrial-oasis",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "fig, ax = plt.subplots(1, 1, figsize=(4, 4))\n",
+ "ax.plot(df[\"StankeFSI\"], df[\"DrtMort\"], \"k.\", markersize=12)\n",
+ "ax.spines[\"top\"].set_visible(False)\n",
+ "ax.spines[\"right\"].set_visible(False)\n",
+ "ax.set_xlim(-2.25, 1.25)\n",
+ "ax.set_xticks([-2, -1, 0, 1])\n",
+ "ax.set_ylim([0, 0.025])\n",
+ "ax.set_yticks([0, 0.01, 0.02])\n",
+ "ax.set_ylabel(\"Mortality (%/year)\")\n",
+ "ax.set_xlabel(\"Forest stability index\")\n",
+ "m, b = np.polyfit(df[\"StankeFSI\"], df[\"DrtMort\"], 1)\n",
+ "plt.plot(df[\"StankeFSI\"], m * df[\"StankeFSI\"] + b, \"gray\")\n",
+ "for i, code in enumerate(df[\"SP.CD\"]):\n",
+ " ax.annotate(code, (df[\"StankeFSI\"][i] - 0.25, df[\"DrtMort\"][i] + 0.001))\n",
+ "plt.savefig(\"Supplementary-Figure-02.svg\")"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.8.6"
+ }
},
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "initial-bonus",
- "metadata": {},
- "outputs": [],
- "source": [
- "plt.rcParams.update({\"font.size\": 14, \"svg.fonttype\": \"none\"})"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "helpful-enough",
- "metadata": {},
- "outputs": [],
- "source": [
- "df = pd.read_csv(\"StankeSFigData.csv\")"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "industrial-oasis",
- "metadata": {},
- "outputs": [],
- "source": [
- "fig, ax = plt.subplots(1, 1, figsize=(4, 4))\n",
- "ax.plot(df[\"StankeFSI\"], df[\"DrtMort\"], \"k.\", markersize=12)\n",
- "ax.spines[\"top\"].set_visible(False)\n",
- "ax.spines[\"right\"].set_visible(False)\n",
- "ax.set_xlim(-2.25, 1.25)\n",
- "ax.set_xticks([-2, -1, 0, 1])\n",
- "ax.set_ylim([0, 0.025])\n",
- "ax.set_yticks([0, 0.01, 0.02])\n",
- "ax.set_ylabel(\"Mortality (%/year)\")\n",
- "ax.set_xlabel(\"Forest stability index\")\n",
- "m, b = np.polyfit(df[\"StankeFSI\"], df[\"DrtMort\"], 1)\n",
- "plt.plot(df[\"StankeFSI\"], m * df[\"StankeFSI\"] + b, \"gray\")\n",
- "for i, code in enumerate(df[\"SP.CD\"]):\n",
- " ax.annotate(code, (df[\"StankeFSI\"][i] - 0.25, df[\"DrtMort\"][i] + 0.001))\n",
- "plt.savefig(\"Supplementary-Figure-02.svg\")"
- ]
- }
- ],
- "metadata": {
- "kernelspec": {
- "display_name": "Python 3",
- "language": "python",
- "name": "python3"
- },
- "language_info": {
- "codemirror_mode": {
- "name": "ipython",
- "version": 3
- },
- "file_extension": ".py",
- "mimetype": "text/x-python",
- "name": "python",
- "nbconvert_exporter": "python",
- "pygments_lexer": "ipython3",
- "version": "3.8.6"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 5
+ "nbformat": 4,
+ "nbformat_minor": 5
}
diff --git a/notebooks/paper/Supplementary-Figure-03/Supplementary-Figure-03.ipynb b/notebooks/paper/Supplementary-Figure-03/Supplementary-Figure-03.ipynb
index 22584e2..19e0375 100644
--- a/notebooks/paper/Supplementary-Figure-03/Supplementary-Figure-03.ipynb
+++ b/notebooks/paper/Supplementary-Figure-03/Supplementary-Figure-03.ipynb
@@ -1,187 +1,187 @@
{
- "cells": [
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "unlike-defendant",
- "metadata": {},
- "outputs": [],
- "source": [
- "import numpy as np\n",
- "import pandas as pd\n",
- "import xarray as xr\n",
- "import rioxarray\n",
- "import matplotlib\n",
- "import matplotlib.pyplot as plt\n",
- "from rasterio.enums import Resampling\n",
- "from carbonplan_forest_risks import (\n",
- " load,\n",
- " setup,\n",
- " plot,\n",
- " fit,\n",
- " utils,\n",
- " prepare,\n",
- " collect,\n",
- ")\n",
- "from carbonplan.data import cat\n",
- "from carbonplan_styles.mpl import get_colormap"
- ]
+ "cells": [
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "unlike-defendant",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import numpy as np\n",
+ "import pandas as pd\n",
+ "import xarray as xr\n",
+ "import rioxarray\n",
+ "import matplotlib\n",
+ "import matplotlib.pyplot as plt\n",
+ "from rasterio.enums import Resampling\n",
+ "from carbonplan_forest_risks import (\n",
+ " load,\n",
+ " setup,\n",
+ " plot,\n",
+ " fit,\n",
+ " utils,\n",
+ " prepare,\n",
+ " collect,\n",
+ ")\n",
+ "from carbonplan.data import cat\n",
+ "from carbonplan_styles.mpl import get_colormap"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "drawn-thirty",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def load_bill(url):\n",
+ " target = cat.nlcd.raster.to_dask()\n",
+ " source = xr.open_rasterio(url)\n",
+ " source = source.where(source > -1)\n",
+ " ds = source.rio.reproject_match(target, resampling=Resampling.bilinear)\n",
+ " ds = ds.where(ds > -1).sel(band=1)\n",
+ "\n",
+ " return ds"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "sophisticated-uganda",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "base_url_tempate = \"https://carbonplan.blob.core.windows.net/carbonplan-scratch/from-bill-05-03-2021/Fig1_4-22-21/{}\"\n",
+ "dataset_urls = {\n",
+ " \"Insects\": {\n",
+ " \"modeled\": base_url_tempate.format(\n",
+ " \"Fig1F_InsectModel_ModeledFIAlongEnsembleHistMort_04-22-2021.tif\"\n",
+ " ),\n",
+ " \"observed\": base_url_tempate.format(\n",
+ " \"Fig1E_InsectModel_FIAwide-ObsMort_05-08-2021.tif\"\n",
+ " ),\n",
+ " \"reference\": \"SuppFig_Williamsetal2016_BarkBeetleOccurrenceMap_04-19-2021.tif\",\n",
+ " },\n",
+ "}"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "dominican-conviction",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "ds_dict = {}\n",
+ "ds_dict[\"modeled\"] = load_bill(dataset_urls[\"Insects\"][\"modeled\"]) * 100\n",
+ "ds_dict[\"observed\"] = load_bill(dataset_urls[\"Insects\"][\"observed\"]) * 100\n",
+ "ds_dict[\"reference\"] = load_bill(dataset_urls[\"Insects\"][\"reference\"])"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "royal-prairie",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "plot_params = {\n",
+ " \"modeled\": {\n",
+ " \"cmap\": get_colormap(\"blues\"),\n",
+ " \"var_lims\": (0, 0.4),\n",
+ " \"label\": \"Insect-related\\nmortality (%/year)\",\n",
+ " \"panel\": [\"E\", \"F\"],\n",
+ " \"cbar_ylocation\": 0.76,\n",
+ " },\n",
+ " \"observed\": {\n",
+ " \"cmap\": get_colormap(\"blues\"),\n",
+ " \"var_lims\": (0, 0.4),\n",
+ " \"label\": \"Insect-related\\nmortality (%/year)\",\n",
+ " \"panel\": [\"E\", \"F\"],\n",
+ " \"cbar_ylocation\": 0.4,\n",
+ " },\n",
+ " \"reference\": {\n",
+ " \"cmap\": get_colormap(\"blues\"),\n",
+ " \"var_lims\": (0, 0.5),\n",
+ " \"label\": \"Area affected\\n(% grid cell/year)\",\n",
+ " \"panel\": [\"E\", \"F\"],\n",
+ " \"cbar_ylocation\": 0.04,\n",
+ " },\n",
+ "}"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "together-enlargement",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "matplotlib.rc(\"font\", family=\"sans-serif\")\n",
+ "matplotlib.rc(\"font\", serif=\"Helvetica Neue\")\n",
+ "matplotlib.rc(\"text\", usetex=\"false\")\n",
+ "matplotlib.rcParams.update({\"font.size\": 14, \"svg.fonttype\": \"none\"})"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "prescribed-overhead",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "fig, axarr = plt.subplots(\n",
+ " nrows=3,\n",
+ " ncols=1,\n",
+ " figsize=(5, 12),\n",
+ " subplot_kw={\"projection\": plot.cartopy_proj_albers()},\n",
+ ")\n",
+ "for row, setup in enumerate([\"observed\", \"modeled\", \"reference\"]):\n",
+ " vmin, vmax = (\n",
+ " plot_params[setup][\"var_lims\"][0],\n",
+ " plot_params[setup][\"var_lims\"][1],\n",
+ " )\n",
+ " map_plot = ds_dict[\"{}\".format(setup)].plot.imshow(\n",
+ " ax=axarr[row],\n",
+ " cmap=plot_params[setup][\"cmap\"],\n",
+ " vmin=vmin,\n",
+ " vmax=vmax,\n",
+ " add_colorbar=False,\n",
+ " add_labels=False,\n",
+ " )\n",
+ " plot.map_pretty(axarr[row], title=setup.capitalize())\n",
+ " plot.add_colorbar(\n",
+ " fig,\n",
+ " to_plot=map_plot,\n",
+ " y_location=plot_params[setup][\"cbar_ylocation\"],\n",
+ " vmin=plot_params[setup][\"var_lims\"][0],\n",
+ " vmax=plot_params[setup][\"var_lims\"][1],\n",
+ " cbar_label=plot_params[setup][\"label\"],\n",
+ " )\n",
+ "plt.tight_layout(pad=-6)\n",
+ "fig.savefig(\"Supplementary-Figure-03.svg\", format=\"svg\", bbox_inches=\"tight\")"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.8.8"
+ }
},
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "drawn-thirty",
- "metadata": {},
- "outputs": [],
- "source": [
- "def load_bill(url):\n",
- " target = cat.nlcd.raster.to_dask()\n",
- " source = xr.open_rasterio(url)\n",
- " source = source.where(source > -1)\n",
- " ds = source.rio.reproject_match(target, resampling=Resampling.bilinear)\n",
- " ds = ds.where(ds > -1).sel(band=1)\n",
- "\n",
- " return ds"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "sophisticated-uganda",
- "metadata": {},
- "outputs": [],
- "source": [
- "base_url_tempate = \"https://carbonplan.blob.core.windows.net/carbonplan-scratch/from-bill-05-03-2021/Fig1_4-22-21/{}\"\n",
- "dataset_urls = {\n",
- " \"Insects\": {\n",
- " \"modeled\": base_url_tempate.format(\n",
- " \"Fig1F_InsectModel_ModeledFIAlongEnsembleHistMort_04-22-2021.tif\"\n",
- " ),\n",
- " \"observed\": base_url_tempate.format(\n",
- " \"Fig1E_InsectModel_FIAwide-ObsMort_05-08-2021.tif\"\n",
- " ),\n",
- " \"reference\": \"SuppFig_Williamsetal2016_BarkBeetleOccurrenceMap_04-19-2021.tif\",\n",
- " },\n",
- "}"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "dominican-conviction",
- "metadata": {},
- "outputs": [],
- "source": [
- "ds_dict = {}\n",
- "ds_dict[\"modeled\"] = load_bill(dataset_urls[\"Insects\"][\"modeled\"]) * 100\n",
- "ds_dict[\"observed\"] = load_bill(dataset_urls[\"Insects\"][\"observed\"]) * 100\n",
- "ds_dict[\"reference\"] = load_bill(dataset_urls[\"Insects\"][\"reference\"])"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "royal-prairie",
- "metadata": {},
- "outputs": [],
- "source": [
- "plot_params = {\n",
- " \"modeled\": {\n",
- " \"cmap\": get_colormap(\"blues\"),\n",
- " \"var_lims\": (0, 0.4),\n",
- " \"label\": \"Insect-related\\nmortality (%/year)\",\n",
- " \"panel\": [\"E\", \"F\"],\n",
- " \"cbar_ylocation\": 0.76,\n",
- " },\n",
- " \"observed\": {\n",
- " \"cmap\": get_colormap(\"blues\"),\n",
- " \"var_lims\": (0, 0.4),\n",
- " \"label\": \"Insect-related\\nmortality (%/year)\",\n",
- " \"panel\": [\"E\", \"F\"],\n",
- " \"cbar_ylocation\": 0.4,\n",
- " },\n",
- " \"reference\": {\n",
- " \"cmap\": get_colormap(\"blues\"),\n",
- " \"var_lims\": (0, 0.5),\n",
- " \"label\": \"Area affected\\n(% grid cell/year)\",\n",
- " \"panel\": [\"E\", \"F\"],\n",
- " \"cbar_ylocation\": 0.04,\n",
- " },\n",
- "}"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "together-enlargement",
- "metadata": {},
- "outputs": [],
- "source": [
- "matplotlib.rc(\"font\", family=\"sans-serif\")\n",
- "matplotlib.rc(\"font\", serif=\"Helvetica Neue\")\n",
- "matplotlib.rc(\"text\", usetex=\"false\")\n",
- "matplotlib.rcParams.update({\"font.size\": 14, \"svg.fonttype\": \"none\"})"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "prescribed-overhead",
- "metadata": {},
- "outputs": [],
- "source": [
- "fig, axarr = plt.subplots(\n",
- " nrows=3,\n",
- " ncols=1,\n",
- " figsize=(5, 12),\n",
- " subplot_kw={\"projection\": plot.cartopy_proj_albers()},\n",
- ")\n",
- "for row, setup in enumerate([\"observed\", \"modeled\", \"reference\"]):\n",
- " vmin, vmax = (\n",
- " plot_params[setup][\"var_lims\"][0],\n",
- " plot_params[setup][\"var_lims\"][1],\n",
- " )\n",
- " map_plot = ds_dict[\"{}\".format(setup)].plot.imshow(\n",
- " ax=axarr[row],\n",
- " cmap=plot_params[setup][\"cmap\"],\n",
- " vmin=vmin,\n",
- " vmax=vmax,\n",
- " add_colorbar=False,\n",
- " add_labels=False,\n",
- " )\n",
- " plot.map_pretty(axarr[row], title=setup.capitalize())\n",
- " plot.add_colorbar(\n",
- " fig,\n",
- " to_plot=map_plot,\n",
- " y_location=plot_params[setup][\"cbar_ylocation\"],\n",
- " vmin=plot_params[setup][\"var_lims\"][0],\n",
- " vmax=plot_params[setup][\"var_lims\"][1],\n",
- " cbar_label=plot_params[setup][\"label\"],\n",
- " )\n",
- "plt.tight_layout(pad=-6)\n",
- "fig.savefig(\"Supplementary-Figure-03.svg\", format=\"svg\", bbox_inches=\"tight\")"
- ]
- }
- ],
- "metadata": {
- "kernelspec": {
- "display_name": "Python 3",
- "language": "python",
- "name": "python3"
- },
- "language_info": {
- "codemirror_mode": {
- "name": "ipython",
- "version": 3
- },
- "file_extension": ".py",
- "mimetype": "text/x-python",
- "name": "python",
- "nbconvert_exporter": "python",
- "pygments_lexer": "ipython3",
- "version": "3.8.8"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 5
+ "nbformat": 4,
+ "nbformat_minor": 5
}
diff --git a/notebooks/paper/Supplementary-Figure-04/Supplementary-Figure-04.ipynb b/notebooks/paper/Supplementary-Figure-04/Supplementary-Figure-04.ipynb
index 2fb578e..6bbcb56 100644
--- a/notebooks/paper/Supplementary-Figure-04/Supplementary-Figure-04.ipynb
+++ b/notebooks/paper/Supplementary-Figure-04/Supplementary-Figure-04.ipynb
@@ -1,107 +1,107 @@
{
- "cells": [
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "minimal-pittsburgh",
- "metadata": {},
- "outputs": [],
- "source": [
- "import pandas as pd\n",
- "import numpy as np\n",
- "import matplotlib.pyplot as plt"
- ]
+ "cells": [
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "minimal-pittsburgh",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import pandas as pd\n",
+ "import numpy as np\n",
+ "import matplotlib.pyplot as plt"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "comic-engineer",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "plt.rcParams.update({\"font.size\": 14, \"svg.fonttype\": \"none\"})"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "electric-cover",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "df = pd.read_csv(\"Insect2PineFTs_SFigData.csv\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "emerging-ordinance",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "fig, axs = plt.subplots(2, 1, figsize=(12, 6))\n",
+ "width = 0.35\n",
+ "labels = list(df[\"Coefficient\"])\n",
+ "index = np.arange(len(df.index))\n",
+ "rects1a = axs[0].bar(\n",
+ " index - width / 2, df[\"Limber.Binom\"], width, color=\"black\", label=\"Men\"\n",
+ ")\n",
+ "rects1b = axs[0].bar(\n",
+ " index + width / 2, df[\"Limber.Beta\"], width, color=\"gray\", label=\"Women\"\n",
+ ")\n",
+ "rects2a = axs[1].bar(\n",
+ " index - width / 2, df[\"Lodgepole.Binom\"], width, color=\"black\", label=\"Men\"\n",
+ ")\n",
+ "rects2b = axs[1].bar(\n",
+ " index + width / 2, df[\"Lodgepole.Beta\"], width, color=\"gray\", label=\"Women\"\n",
+ ")\n",
+ "axs[0].spines[\"top\"].set_visible(False)\n",
+ "axs[0].spines[\"right\"].set_visible(False)\n",
+ "axs[1].spines[\"top\"].set_visible(False)\n",
+ "axs[1].spines[\"right\"].set_visible(False)\n",
+ "axs[0].set_xticks([])\n",
+ "axs[1].set_xticks(index)\n",
+ "axs[1].set_xticklabels(labels)\n",
+ "axs[0].set_ylim([-25, 24])\n",
+ "axs[1].set_ylim([-7, 3])\n",
+ "axs[0].set_ylabel(\"Coefficient\")\n",
+ "axs[1].set_ylabel(\"Coefficient\")\n",
+ "for i, pval in enumerate(df[\"Limber.Binom.pval\"]):\n",
+ " if pval < 0.05:\n",
+ " axs[0].annotate(\"*\", (index[i] - width / 2 - 0.045, 20))\n",
+ "for i, pval in enumerate(df[\"Limber.Beta.pval\"]):\n",
+ " if pval < 0.05:\n",
+ " axs[0].annotate(\"*\", (index[i] + width / 2 - 0.045, 20), color=\"gray\")\n",
+ "for i, pval in enumerate(df[\"Lodgepole.Binom.pval\"]):\n",
+ " if pval < 0.05:\n",
+ " axs[1].annotate(\"*\", (index[i] - width / 2 - 0.045, 2.5))\n",
+ "for i, pval in enumerate(df[\"Lodgepole.Beta.pval\"]):\n",
+ " if pval < 0.05:\n",
+ " axs[1].annotate(\"*\", (index[i] + width / 2 - 0.045, 2.5), color=\"gray\")\n",
+ "\n",
+ "plt.savefig(\"Supplementary-Figure-04.svg\")"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3 (ipykernel)",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.8.6"
+ }
},
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "comic-engineer",
- "metadata": {},
- "outputs": [],
- "source": [
- "plt.rcParams.update({\"font.size\": 14, \"svg.fonttype\": \"none\"})"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "electric-cover",
- "metadata": {},
- "outputs": [],
- "source": [
- "df = pd.read_csv(\"Insect2PineFTs_SFigData.csv\")"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "emerging-ordinance",
- "metadata": {},
- "outputs": [],
- "source": [
- "fig, axs = plt.subplots(2, 1, figsize=(12, 6))\n",
- "width = 0.35\n",
- "labels = list(df[\"Coefficient\"])\n",
- "index = np.arange(len(df.index))\n",
- "rects1a = axs[0].bar(\n",
- " index - width / 2, df[\"Limber.Binom\"], width, color=\"black\", label=\"Men\"\n",
- ")\n",
- "rects1b = axs[0].bar(\n",
- " index + width / 2, df[\"Limber.Beta\"], width, color=\"gray\", label=\"Women\"\n",
- ")\n",
- "rects2a = axs[1].bar(\n",
- " index - width / 2, df[\"Lodgepole.Binom\"], width, color=\"black\", label=\"Men\"\n",
- ")\n",
- "rects2b = axs[1].bar(\n",
- " index + width / 2, df[\"Lodgepole.Beta\"], width, color=\"gray\", label=\"Women\"\n",
- ")\n",
- "axs[0].spines[\"top\"].set_visible(False)\n",
- "axs[0].spines[\"right\"].set_visible(False)\n",
- "axs[1].spines[\"top\"].set_visible(False)\n",
- "axs[1].spines[\"right\"].set_visible(False)\n",
- "axs[0].set_xticks([])\n",
- "axs[1].set_xticks(index)\n",
- "axs[1].set_xticklabels(labels)\n",
- "axs[0].set_ylim([-25, 24])\n",
- "axs[1].set_ylim([-7, 3])\n",
- "axs[0].set_ylabel(\"Coefficient\")\n",
- "axs[1].set_ylabel(\"Coefficient\")\n",
- "for i, pval in enumerate(df[\"Limber.Binom.pval\"]):\n",
- " if pval < 0.05:\n",
- " axs[0].annotate(\"*\", (index[i] - width / 2 - 0.045, 20))\n",
- "for i, pval in enumerate(df[\"Limber.Beta.pval\"]):\n",
- " if pval < 0.05:\n",
- " axs[0].annotate(\"*\", (index[i] + width / 2 - 0.045, 20), color=\"gray\")\n",
- "for i, pval in enumerate(df[\"Lodgepole.Binom.pval\"]):\n",
- " if pval < 0.05:\n",
- " axs[1].annotate(\"*\", (index[i] - width / 2 - 0.045, 2.5))\n",
- "for i, pval in enumerate(df[\"Lodgepole.Beta.pval\"]):\n",
- " if pval < 0.05:\n",
- " axs[1].annotate(\"*\", (index[i] + width / 2 - 0.045, 2.5), color=\"gray\")\n",
- "\n",
- "plt.savefig(\"Supplementary-Figure-04.svg\")"
- ]
- }
- ],
- "metadata": {
- "kernelspec": {
- "display_name": "Python 3 (ipykernel)",
- "language": "python",
- "name": "python3"
- },
- "language_info": {
- "codemirror_mode": {
- "name": "ipython",
- "version": 3
- },
- "file_extension": ".py",
- "mimetype": "text/x-python",
- "name": "python",
- "nbconvert_exporter": "python",
- "pygments_lexer": "ipython3",
- "version": "3.8.6"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 5
+ "nbformat": 4,
+ "nbformat_minor": 5
}
diff --git a/notebooks/paper/Supplementary-Figure-05/Supplementary-Figure-05.ipynb b/notebooks/paper/Supplementary-Figure-05/Supplementary-Figure-05.ipynb
index 782a63e..4ac393f 100644
--- a/notebooks/paper/Supplementary-Figure-05/Supplementary-Figure-05.ipynb
+++ b/notebooks/paper/Supplementary-Figure-05/Supplementary-Figure-05.ipynb
@@ -1,259 +1,259 @@
{
- "cells": [
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "delayed-nirvana",
- "metadata": {},
- "outputs": [],
- "source": [
- "import numpy as np\n",
- "import pandas as pd\n",
- "import xarray as xr\n",
- "import rioxarray\n",
- "import matplotlib\n",
- "import matplotlib.pyplot as plt\n",
- "from rasterio.enums import Resampling\n",
- "from carbonplan_forest_risks import (\n",
- " load,\n",
- " setup,\n",
- " plot,\n",
- " fit,\n",
- " utils,\n",
- " prepare,\n",
- " collect,\n",
- ")\n",
- "from carbonplan.data import cat\n",
- "from carbonplan_styles.mpl import get_colormap\n",
- "\n",
- "from showit import image"
- ]
+ "cells": [
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "delayed-nirvana",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import numpy as np\n",
+ "import pandas as pd\n",
+ "import xarray as xr\n",
+ "import rioxarray\n",
+ "import matplotlib\n",
+ "import matplotlib.pyplot as plt\n",
+ "from rasterio.enums import Resampling\n",
+ "from carbonplan_forest_risks import (\n",
+ " load,\n",
+ " setup,\n",
+ " plot,\n",
+ " fit,\n",
+ " utils,\n",
+ " prepare,\n",
+ " collect,\n",
+ ")\n",
+ "from carbonplan.data import cat\n",
+ "from carbonplan_styles.mpl import get_colormap\n",
+ "\n",
+ "from showit import image"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "human-introduction",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "coarsen = 4"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "coral-special",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def load_bill(url):\n",
+ " target = cat.nlcd.raster.to_dask()\n",
+ " source = xr.open_rasterio(url)\n",
+ " source = source.where(source > -1)\n",
+ " ds = source.rio.reproject_match(target, resampling=Resampling.bilinear)\n",
+ " ds = (\n",
+ " ds.where(ds > -1)\n",
+ " .coarsen(x=coarsen, y=coarsen, boundary=\"trim\")\n",
+ " .mean()\n",
+ " .sel(band=1)\n",
+ " )\n",
+ "\n",
+ " return ds"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "sustainable-mainland",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "dataset_urls = {\n",
+ " \"insects\": {\n",
+ " \"AUC\": \"SuppFig_InsectModel_CV_AUC_04-22-2021.tif\",\n",
+ " \"R2\": \"SuppFig_InsectModel_CV_nonzeroR2_04-22-2021.tif\",\n",
+ " },\n",
+ " \"drought\": {\n",
+ " \"AUC\": \"SuppFig_DroughtModel_CV_AUC_04-22-2021.tif\",\n",
+ " \"R2\": \"SuppFig_DroughtModel_CV_nonzeroR2_04-22-2021.tif\",\n",
+ " },\n",
+ "}"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "hindu-biography",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "ds_dict = {}\n",
+ "ds_dict[\"insects\"] = {}\n",
+ "ds_dict[\"drought\"] = {}\n",
+ "ds_dict[\"insects\"][\"AUC\"] = load_bill(dataset_urls[\"insects\"][\"AUC\"])\n",
+ "ds_dict[\"insects\"][\"R2\"] = load_bill(dataset_urls[\"insects\"][\"R2\"])\n",
+ "ds_dict[\"drought\"][\"AUC\"] = load_bill(dataset_urls[\"drought\"][\"AUC\"])\n",
+ "ds_dict[\"drought\"][\"R2\"] = load_bill(dataset_urls[\"drought\"][\"R2\"])"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "defensive-tsunami",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "plot_params = {\n",
+ " \"drought_AUC\": {\n",
+ " \"cmap\": get_colormap(\"pinks\"),\n",
+ " \"var_lims\": (0.5, 0.8),\n",
+ " \"label\": \"Drought-related\\nmortality (%/year)\",\n",
+ " \"panel\": [\"C\", \"D\"],\n",
+ " \"cbar_ylocation\": 0.15,\n",
+ " \"cbar_xlocation\": 0.46,\n",
+ " },\n",
+ " \"insects_AUC\": {\n",
+ " \"cmap\": get_colormap(\"blues\"),\n",
+ " \"var_lims\": (0.5, 0.8),\n",
+ " \"label\": \"Insect-related\\nmortality (%/year)\",\n",
+ " \"panel\": [\"E\", \"F\"],\n",
+ " \"cbar_ylocation\": 0.64,\n",
+ " \"cbar_xlocation\": 0.46,\n",
+ " },\n",
+ " \"drought_R2\": {\n",
+ " \"cmap\": get_colormap(\"pinks\"),\n",
+ " \"var_lims\": (0, 0.05),\n",
+ " \"label\": \"Drought-related\\nmortality (%/year)\",\n",
+ " \"panel\": [\"C\", \"D\"],\n",
+ " \"cbar_ylocation\": 0.15,\n",
+ " \"cbar_xlocation\": 1.01,\n",
+ " },\n",
+ " \"insects_R2\": {\n",
+ " \"cmap\": get_colormap(\"blues\"),\n",
+ " \"var_lims\": (0, 0.15),\n",
+ " \"label\": \"Insect-related\\nmortality (%/year)\",\n",
+ " \"panel\": [\"E\", \"F\"],\n",
+ " \"cbar_ylocation\": 0.64,\n",
+ " \"cbar_xlocation\": 1.01,\n",
+ " },\n",
+ "}"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "altered-norwegian",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "matplotlib.rc(\"font\", family=\"sans-serif\")\n",
+ "matplotlib.rc(\"font\", serif=\"Helvetica Neue\")\n",
+ "matplotlib.rc(\"text\", usetex=\"false\")\n",
+ "matplotlib.rcParams.update({\"font.size\": 14, \"svg.fonttype\": \"none\"})"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "biological-alexandria",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "fig, axarr = plt.subplots(\n",
+ " nrows=2,\n",
+ " ncols=2,\n",
+ " figsize=(12, 10),\n",
+ " subplot_kw={\"projection\": plot.cartopy_proj_albers()},\n",
+ ")\n",
+ "for row, dataset in enumerate([\"insects\", \"drought\"]):\n",
+ " for column, metric in enumerate([\"AUC\", \"R2\"]):\n",
+ " vmin, vmax = (\n",
+ " plot_params[\"{}_{}\".format(dataset, metric)][\"var_lims\"][0],\n",
+ " plot_params[\"{}_{}\".format(dataset, metric)][\"var_lims\"][1],\n",
+ " )\n",
+ " map_plot = ds_dict[dataset][metric].plot.imshow(\n",
+ " ax=axarr[row, column],\n",
+ " cmap=plot_params[\"{}_{}\".format(dataset, metric)][\"cmap\"],\n",
+ " vmin=vmin,\n",
+ " vmax=vmax,\n",
+ " add_colorbar=False,\n",
+ " add_labels=False,\n",
+ " )\n",
+ " plot.map_pretty(axarr[row, column], title=metric)\n",
+ " plot.add_colorbar(\n",
+ " fig,\n",
+ " to_plot=map_plot,\n",
+ " y_location=plot_params[\"{}_{}\".format(dataset, metric)][\n",
+ " \"cbar_ylocation\"\n",
+ " ],\n",
+ " x_location=plot_params[\"{}_{}\".format(dataset, metric)][\n",
+ " \"cbar_xlocation\"\n",
+ " ],\n",
+ " vmin=plot_params[\"{}_{}\".format(dataset, metric)][\"var_lims\"][0],\n",
+ " vmax=plot_params[\"{}_{}\".format(dataset, metric)][\"var_lims\"][1],\n",
+ " cbar_label=plot_params[\"{}_{}\".format(dataset, metric)][\"label\"],\n",
+ " )\n",
+ "plt.tight_layout(pad=-6)\n",
+ "fig.savefig(\"Supplementary-Figure-05.svg\", format=\"svg\", bbox_inches=\"tight\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "underlying-correlation",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "df_drought = pd.read_csv(\n",
+ " \"Drought_USwide_CrossValidationR2_4-21-21.csv\", header=None\n",
+ ")\n",
+ "df_insects = pd.read_csv(\n",
+ " \"Insect_USwide_CrossValidationR2_4-21-21.csv\", header=None\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "discrete-qatar",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "print(\"drought: spatial cross validation R2 percentiles\")\n",
+ "print(np.percentile(df_drought[0], [5, 50, 95]))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "bulgarian-bracelet",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "print(\"insects: spatial cross validation R2 percentiles\")\n",
+ "print(np.percentile(df_insects[0], [5, 50, 95]))"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.8.8"
+ }
},
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "human-introduction",
- "metadata": {},
- "outputs": [],
- "source": [
- "coarsen = 4"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "coral-special",
- "metadata": {},
- "outputs": [],
- "source": [
- "def load_bill(url):\n",
- " target = cat.nlcd.raster.to_dask()\n",
- " source = xr.open_rasterio(url)\n",
- " source = source.where(source > -1)\n",
- " ds = source.rio.reproject_match(target, resampling=Resampling.bilinear)\n",
- " ds = (\n",
- " ds.where(ds > -1)\n",
- " .coarsen(x=coarsen, y=coarsen, boundary=\"trim\")\n",
- " .mean()\n",
- " .sel(band=1)\n",
- " )\n",
- "\n",
- " return ds"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "sustainable-mainland",
- "metadata": {},
- "outputs": [],
- "source": [
- "dataset_urls = {\n",
- " \"insects\": {\n",
- " \"AUC\": \"SuppFig_InsectModel_CV_AUC_04-22-2021.tif\",\n",
- " \"R2\": \"SuppFig_InsectModel_CV_nonzeroR2_04-22-2021.tif\",\n",
- " },\n",
- " \"drought\": {\n",
- " \"AUC\": \"SuppFig_DroughtModel_CV_AUC_04-22-2021.tif\",\n",
- " \"R2\": \"SuppFig_DroughtModel_CV_nonzeroR2_04-22-2021.tif\",\n",
- " },\n",
- "}"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "hindu-biography",
- "metadata": {},
- "outputs": [],
- "source": [
- "ds_dict = {}\n",
- "ds_dict[\"insects\"] = {}\n",
- "ds_dict[\"drought\"] = {}\n",
- "ds_dict[\"insects\"][\"AUC\"] = load_bill(dataset_urls[\"insects\"][\"AUC\"])\n",
- "ds_dict[\"insects\"][\"R2\"] = load_bill(dataset_urls[\"insects\"][\"R2\"])\n",
- "ds_dict[\"drought\"][\"AUC\"] = load_bill(dataset_urls[\"drought\"][\"AUC\"])\n",
- "ds_dict[\"drought\"][\"R2\"] = load_bill(dataset_urls[\"drought\"][\"R2\"])"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "defensive-tsunami",
- "metadata": {},
- "outputs": [],
- "source": [
- "plot_params = {\n",
- " \"drought_AUC\": {\n",
- " \"cmap\": get_colormap(\"pinks\"),\n",
- " \"var_lims\": (0.5, 0.8),\n",
- " \"label\": \"Drought-related\\nmortality (%/year)\",\n",
- " \"panel\": [\"C\", \"D\"],\n",
- " \"cbar_ylocation\": 0.15,\n",
- " \"cbar_xlocation\": 0.46,\n",
- " },\n",
- " \"insects_AUC\": {\n",
- " \"cmap\": get_colormap(\"blues\"),\n",
- " \"var_lims\": (0.5, 0.8),\n",
- " \"label\": \"Insect-related\\nmortality (%/year)\",\n",
- " \"panel\": [\"E\", \"F\"],\n",
- " \"cbar_ylocation\": 0.64,\n",
- " \"cbar_xlocation\": 0.46,\n",
- " },\n",
- " \"drought_R2\": {\n",
- " \"cmap\": get_colormap(\"pinks\"),\n",
- " \"var_lims\": (0, 0.05),\n",
- " \"label\": \"Drought-related\\nmortality (%/year)\",\n",
- " \"panel\": [\"C\", \"D\"],\n",
- " \"cbar_ylocation\": 0.15,\n",
- " \"cbar_xlocation\": 1.01,\n",
- " },\n",
- " \"insects_R2\": {\n",
- " \"cmap\": get_colormap(\"blues\"),\n",
- " \"var_lims\": (0, 0.15),\n",
- " \"label\": \"Insect-related\\nmortality (%/year)\",\n",
- " \"panel\": [\"E\", \"F\"],\n",
- " \"cbar_ylocation\": 0.64,\n",
- " \"cbar_xlocation\": 1.01,\n",
- " },\n",
- "}"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "altered-norwegian",
- "metadata": {},
- "outputs": [],
- "source": [
- "matplotlib.rc(\"font\", family=\"sans-serif\")\n",
- "matplotlib.rc(\"font\", serif=\"Helvetica Neue\")\n",
- "matplotlib.rc(\"text\", usetex=\"false\")\n",
- "matplotlib.rcParams.update({\"font.size\": 14, \"svg.fonttype\": \"none\"})"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "biological-alexandria",
- "metadata": {},
- "outputs": [],
- "source": [
- "fig, axarr = plt.subplots(\n",
- " nrows=2,\n",
- " ncols=2,\n",
- " figsize=(12, 10),\n",
- " subplot_kw={\"projection\": plot.cartopy_proj_albers()},\n",
- ")\n",
- "for row, dataset in enumerate([\"insects\", \"drought\"]):\n",
- " for column, metric in enumerate([\"AUC\", \"R2\"]):\n",
- " vmin, vmax = (\n",
- " plot_params[\"{}_{}\".format(dataset, metric)][\"var_lims\"][0],\n",
- " plot_params[\"{}_{}\".format(dataset, metric)][\"var_lims\"][1],\n",
- " )\n",
- " map_plot = ds_dict[dataset][metric].plot.imshow(\n",
- " ax=axarr[row, column],\n",
- " cmap=plot_params[\"{}_{}\".format(dataset, metric)][\"cmap\"],\n",
- " vmin=vmin,\n",
- " vmax=vmax,\n",
- " add_colorbar=False,\n",
- " add_labels=False,\n",
- " )\n",
- " plot.map_pretty(axarr[row, column], title=metric)\n",
- " plot.add_colorbar(\n",
- " fig,\n",
- " to_plot=map_plot,\n",
- " y_location=plot_params[\"{}_{}\".format(dataset, metric)][\n",
- " \"cbar_ylocation\"\n",
- " ],\n",
- " x_location=plot_params[\"{}_{}\".format(dataset, metric)][\n",
- " \"cbar_xlocation\"\n",
- " ],\n",
- " vmin=plot_params[\"{}_{}\".format(dataset, metric)][\"var_lims\"][0],\n",
- " vmax=plot_params[\"{}_{}\".format(dataset, metric)][\"var_lims\"][1],\n",
- " cbar_label=plot_params[\"{}_{}\".format(dataset, metric)][\"label\"],\n",
- " )\n",
- "plt.tight_layout(pad=-6)\n",
- "fig.savefig(\"Supplementary-Figure-05.svg\", format=\"svg\", bbox_inches=\"tight\")"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "underlying-correlation",
- "metadata": {},
- "outputs": [],
- "source": [
- "df_drought = pd.read_csv(\n",
- " \"Drought_USwide_CrossValidationR2_4-21-21.csv\", header=None\n",
- ")\n",
- "df_insects = pd.read_csv(\n",
- " \"Insect_USwide_CrossValidationR2_4-21-21.csv\", header=None\n",
- ")"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "discrete-qatar",
- "metadata": {},
- "outputs": [],
- "source": [
- "print(\"drought: spatial cross validation R2 percentiles\")\n",
- "print(np.percentile(df_drought[0], [5, 50, 95]))"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "bulgarian-bracelet",
- "metadata": {},
- "outputs": [],
- "source": [
- "print(\"insects: spatial cross validation R2 percentiles\")\n",
- "print(np.percentile(df_insects[0], [5, 50, 95]))"
- ]
- }
- ],
- "metadata": {
- "kernelspec": {
- "display_name": "Python 3",
- "language": "python",
- "name": "python3"
- },
- "language_info": {
- "codemirror_mode": {
- "name": "ipython",
- "version": 3
- },
- "file_extension": ".py",
- "mimetype": "text/x-python",
- "name": "python",
- "nbconvert_exporter": "python",
- "pygments_lexer": "ipython3",
- "version": "3.8.8"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 5
+ "nbformat": 4,
+ "nbformat_minor": 5
}
diff --git a/notebooks/paper/Supplementary-Figure-06/Supplementary-Figure-06.ipynb b/notebooks/paper/Supplementary-Figure-06/Supplementary-Figure-06.ipynb
index c51fc4a..a64ff9b 100644
--- a/notebooks/paper/Supplementary-Figure-06/Supplementary-Figure-06.ipynb
+++ b/notebooks/paper/Supplementary-Figure-06/Supplementary-Figure-06.ipynb
@@ -1,89 +1,89 @@
{
- "cells": [
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "40c064a4",
- "metadata": {},
- "outputs": [],
- "source": [
- "import pandas as pd\n",
- "import numpy as np\n",
- "import matplotlib.pyplot as plt"
- ]
+ "cells": [
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "40c064a4",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import pandas as pd\n",
+ "import numpy as np\n",
+ "import matplotlib.pyplot as plt"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "f29d0150",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "plt.rcParams.update({\"font.size\": 14, \"svg.fonttype\": \"none\"})"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "2e47be5a",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "df = pd.read_csv(\"noanalog_ssp370_4-5-22.csv\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "fcbc3d1d",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "fields = [\"tempall\", \"pcpall\", \"pdsiall\", \"cwdall\", \"petall\", \"vpdall\"]\n",
+ "labels = {\n",
+ " \"tempall\": {\"x\": \"Percent novel climate (temperature)\"},\n",
+ " \"pcpall\": {\"x\": \"Percent novel climate (precipitation)\"},\n",
+ " \"pdsiall\": {\"x\": \"Percent novel climate (PDSI)\"},\n",
+ " \"cwdall\": {\"x\": \"Percent novel climate (CWD)\"},\n",
+ " \"petall\": {\"x\": \"Percent novel climate (PET)\"},\n",
+ " \"vpdall\": {\"x\": \"Percent novel climate (VPD)\"},\n",
+ "}\n",
+ "plt.figure(figsize=(16, 8))\n",
+ "\n",
+ "for i, f in enumerate(fields):\n",
+ " ax = plt.subplot(2, 3, i + 1)\n",
+ " plt.hist(df[f], rwidth=0.8, bins=np.arange(0, 100, 5), color=\"black\")\n",
+ " ax.spines[\"top\"].set_visible(False)\n",
+ " ax.spines[\"right\"].set_visible(False)\n",
+ " if i == 0 or i == 3:\n",
+ " ax.set_ylabel(\"Frequency\")\n",
+ " ax.set_xlabel(labels[f][\"x\"])\n",
+ " ax.set_xlim((-5, 105))\n",
+ " ax.set_ylim((0, 100))\n",
+ "\n",
+ "plt.savefig(\"Supplementary-Figure-06.svg\")"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3 (ipykernel)",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.8.6"
+ }
},
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "f29d0150",
- "metadata": {},
- "outputs": [],
- "source": [
- "plt.rcParams.update({\"font.size\": 14, \"svg.fonttype\": \"none\"})"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "2e47be5a",
- "metadata": {},
- "outputs": [],
- "source": [
- "df = pd.read_csv(\"noanalog_ssp370_4-5-22.csv\")"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "fcbc3d1d",
- "metadata": {},
- "outputs": [],
- "source": [
- "fields = [\"tempall\", \"pcpall\", \"pdsiall\", \"cwdall\", \"petall\", \"vpdall\"]\n",
- "labels = {\n",
- " \"tempall\": {\"x\": \"Percent novel climate (temperature)\"},\n",
- " \"pcpall\": {\"x\": \"Percent novel climate (precipitation)\"},\n",
- " \"pdsiall\": {\"x\": \"Percent novel climate (PDSI)\"},\n",
- " \"cwdall\": {\"x\": \"Percent novel climate (CWD)\"},\n",
- " \"petall\": {\"x\": \"Percent novel climate (PET)\"},\n",
- " \"vpdall\": {\"x\": \"Percent novel climate (VPD)\"},\n",
- "}\n",
- "plt.figure(figsize=(16, 8))\n",
- "\n",
- "for i, f in enumerate(fields):\n",
- " ax = plt.subplot(2, 3, i + 1)\n",
- " plt.hist(df[f], rwidth=0.8, bins=np.arange(0, 100, 5), color=\"black\")\n",
- " ax.spines[\"top\"].set_visible(False)\n",
- " ax.spines[\"right\"].set_visible(False)\n",
- " if i == 0 or i == 3:\n",
- " ax.set_ylabel(\"Frequency\")\n",
- " ax.set_xlabel(labels[f][\"x\"])\n",
- " ax.set_xlim((-5, 105))\n",
- " ax.set_ylim((0, 100))\n",
- "\n",
- "plt.savefig(\"Supplementary-Figure-06.svg\")"
- ]
- }
- ],
- "metadata": {
- "kernelspec": {
- "display_name": "Python 3 (ipykernel)",
- "language": "python",
- "name": "python3"
- },
- "language_info": {
- "codemirror_mode": {
- "name": "ipython",
- "version": 3
- },
- "file_extension": ".py",
- "mimetype": "text/x-python",
- "name": "python",
- "nbconvert_exporter": "python",
- "pygments_lexer": "ipython3",
- "version": "3.8.6"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 5
+ "nbformat": 4,
+ "nbformat_minor": 5
}
diff --git a/notebooks/paper/Supplementary-Figure-07/Supplementary-Figure-07.ipynb b/notebooks/paper/Supplementary-Figure-07/Supplementary-Figure-07.ipynb
index f8e6f80..f086376 100644
--- a/notebooks/paper/Supplementary-Figure-07/Supplementary-Figure-07.ipynb
+++ b/notebooks/paper/Supplementary-Figure-07/Supplementary-Figure-07.ipynb
@@ -1,109 +1,109 @@
{
- "cells": [
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "f4fb0c40",
- "metadata": {},
- "outputs": [],
- "source": [
- "import pandas as pd\n",
- "import numpy as np\n",
- "import matplotlib.pyplot as plt\n",
- "import statsmodels.api as sm\n",
- "from statsmodels.tools.tools import add_constant"
- ]
+ "cells": [
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "f4fb0c40",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import pandas as pd\n",
+ "import numpy as np\n",
+ "import matplotlib.pyplot as plt\n",
+ "import statsmodels.api as sm\n",
+ "from statsmodels.tools.tools import add_constant"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "7eea3a1a",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "plt.rcParams.update({\"font.size\": 14, \"svg.fonttype\": \"none\"})"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "65d2e5e3",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "df1 = pd.read_csv(\"BAcomparison_toCP.csv\")\n",
+ "df2 = pd.read_csv(\"cVegTreecomparison_toCP.csv\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "cd94fbae",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "model1 = sm.OLS(df1[\"Log_StatModelBA\"], add_constant(df1[\"Log_CMIPBA\"])).fit()\n",
+ "yhat1 = model1.predict(add_constant(df1[\"Log_CMIPBA\"]))\n",
+ "\n",
+ "x2 = np.asarray(\n",
+ " [\n",
+ " np.ones(df2[\"Log_DeltaBA\"].shape),\n",
+ " df2[\"Log_DeltaBA\"],\n",
+ " df2[\"Log_DeltaBA\"] ** 2,\n",
+ " ]\n",
+ ").T\n",
+ "model2 = sm.OLS(df2[\"CMIP_deltacVegTree\"], x2).fit()\n",
+ "yhat2 = model2.predict(x2)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "7aaf6de3",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "plt.figure(figsize=(13, 6))\n",
+ "ax1 = plt.subplot(1, 2, 1)\n",
+ "plt.plot(df1[\"Log_CMIPBA\"], df1[\"Log_StatModelBA\"], \"k.\")\n",
+ "plt.plot(df1[\"Log_CMIPBA\"], yhat1, \"red\", linewidth=2)\n",
+ "plt.xlabel(\"log(CMIP6 fire emissions)\")\n",
+ "plt.ylabel(\"log(Modeled burn area)\")\n",
+ "plt.xticks([-3.5, -3, -2.5])\n",
+ "ax1.spines[\"top\"].set_visible(False)\n",
+ "ax1.spines[\"right\"].set_visible(False)\n",
+ "\n",
+ "ax2 = plt.subplot(1, 2, 2)\n",
+ "plt.plot(df2[\"Log_DeltaBA\"], df2[\"CMIP_deltacVegTree\"], \"k.\")\n",
+ "plt.plot(df2[\"Log_DeltaBA\"], yhat2, \"red\", linewidth=2)\n",
+ "plt.xlabel(\"log(Future burn area - Historical burn area)\")\n",
+ "plt.ylabel(\"log(CMIP6 future cVegTree - Historical cVegTree)\")\n",
+ "ax2.spines[\"top\"].set_visible(False)\n",
+ "ax2.spines[\"right\"].set_visible(False)\n",
+ "\n",
+ "plt.savefig(\"Supplementary-Figure-07.svg\")"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3 (ipykernel)",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.8.6"
+ }
},
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "7eea3a1a",
- "metadata": {},
- "outputs": [],
- "source": [
- "plt.rcParams.update({\"font.size\": 14, \"svg.fonttype\": \"none\"})"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "65d2e5e3",
- "metadata": {},
- "outputs": [],
- "source": [
- "df1 = pd.read_csv(\"BAcomparison_toCP.csv\")\n",
- "df2 = pd.read_csv(\"cVegTreecomparison_toCP.csv\")"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "cd94fbae",
- "metadata": {},
- "outputs": [],
- "source": [
- "model1 = sm.OLS(df1[\"Log_StatModelBA\"], add_constant(df1[\"Log_CMIPBA\"])).fit()\n",
- "yhat1 = model1.predict(add_constant(df1[\"Log_CMIPBA\"]))\n",
- "\n",
- "x2 = np.asarray(\n",
- " [\n",
- " np.ones(df2[\"Log_DeltaBA\"].shape),\n",
- " df2[\"Log_DeltaBA\"],\n",
- " df2[\"Log_DeltaBA\"] ** 2,\n",
- " ]\n",
- ").T\n",
- "model2 = sm.OLS(df2[\"CMIP_deltacVegTree\"], x2).fit()\n",
- "yhat2 = model2.predict(x2)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "7aaf6de3",
- "metadata": {},
- "outputs": [],
- "source": [
- "plt.figure(figsize=(13, 6))\n",
- "ax1 = plt.subplot(1, 2, 1)\n",
- "plt.plot(df1[\"Log_CMIPBA\"], df1[\"Log_StatModelBA\"], \"k.\")\n",
- "plt.plot(df1[\"Log_CMIPBA\"], yhat1, \"red\", linewidth=2)\n",
- "plt.xlabel(\"log(CMIP6 fire emissions)\")\n",
- "plt.ylabel(\"log(Modeled burn area)\")\n",
- "plt.xticks([-3.5, -3, -2.5])\n",
- "ax1.spines[\"top\"].set_visible(False)\n",
- "ax1.spines[\"right\"].set_visible(False)\n",
- "\n",
- "ax2 = plt.subplot(1, 2, 2)\n",
- "plt.plot(df2[\"Log_DeltaBA\"], df2[\"CMIP_deltacVegTree\"], \"k.\")\n",
- "plt.plot(df2[\"Log_DeltaBA\"], yhat2, \"red\", linewidth=2)\n",
- "plt.xlabel(\"log(Future burn area - Historical burn area)\")\n",
- "plt.ylabel(\"log(CMIP6 future cVegTree - Historical cVegTree)\")\n",
- "ax2.spines[\"top\"].set_visible(False)\n",
- "ax2.spines[\"right\"].set_visible(False)\n",
- "\n",
- "plt.savefig(\"Supplementary-Figure-07.svg\")"
- ]
- }
- ],
- "metadata": {
- "kernelspec": {
- "display_name": "Python 3 (ipykernel)",
- "language": "python",
- "name": "python3"
- },
- "language_info": {
- "codemirror_mode": {
- "name": "ipython",
- "version": 3
- },
- "file_extension": ".py",
- "mimetype": "text/x-python",
- "name": "python",
- "nbconvert_exporter": "python",
- "pygments_lexer": "ipython3",
- "version": "3.8.6"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 5
+ "nbformat": 4,
+ "nbformat_minor": 5
}
diff --git a/notebooks/paper/Supplementary-Figure-08/Supplementary-Figure-08.ipynb b/notebooks/paper/Supplementary-Figure-08/Supplementary-Figure-08.ipynb
index d392fe6..3b19028 100644
--- a/notebooks/paper/Supplementary-Figure-08/Supplementary-Figure-08.ipynb
+++ b/notebooks/paper/Supplementary-Figure-08/Supplementary-Figure-08.ipynb
@@ -1,417 +1,417 @@
{
- "cells": [
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "sustained-barrier",
- "metadata": {},
- "outputs": [],
- "source": [
- "%load_ext autoreload\n",
- "%autoreload 2\n",
- "\n",
- "import numpy as np\n",
- "import pandas as pd\n",
- "import scipy as sp\n",
- "from carbonplan_forest_risks import load, setup, plot, fit, utils, prepare, collect\n",
- "import xarray as xr\n",
- "from carbonplan_forest_risks.utils import get_store\n",
- "import altair as alt\n",
- "from carbonplan.data import cat\n",
- "import rioxarray\n",
- "import cartopy.crs as ccrs\n",
- "import cartopy\n",
- "import cartopy.feature as cfeature\n",
- "import matplotlib.pyplot as plt\n",
- "import warnings\n",
- "warnings.filterwarnings('ignore')\n",
- "import matplotlib\n",
- "from carbonplan_data import utils\n",
- "alt.themes.enable(\"carbonplan_light\")"
- ]
+ "cells": [
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "sustained-barrier",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "%load_ext autoreload\n",
+ "%autoreload 2\n",
+ "\n",
+ "import numpy as np\n",
+ "import pandas as pd\n",
+ "import scipy as sp\n",
+ "from carbonplan_forest_risks import load, setup, plot, fit, utils, prepare, collect\n",
+ "import xarray as xr\n",
+ "from carbonplan_forest_risks.utils import get_store\n",
+ "import altair as alt\n",
+ "from carbonplan.data import cat\n",
+ "import rioxarray\n",
+ "import cartopy.crs as ccrs\n",
+ "import cartopy\n",
+ "import cartopy.feature as cfeature\n",
+ "import matplotlib.pyplot as plt\n",
+ "import warnings\n",
+ "warnings.filterwarnings('ignore')\n",
+ "import matplotlib\n",
+ "from carbonplan_data import utils\n",
+ "alt.themes.enable(\"carbonplan_light\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "bizarre-semester",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "alt.data_transformers.disable_max_rows()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "administrative-tours",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "coarsen = 4\n",
+ "mask = (\n",
+ " (\n",
+ " load.nlcd(store=\"az\", year=2001).sel(band=[41, 42, 43, 90]).sum(\"band\")\n",
+ " > 0.25\n",
+ " )\n",
+ " .astype(\"float\")\n",
+ " .coarsen(x=coarsen, y=coarsen, boundary=\"trim\")\n",
+ " .mean()\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "1d62ddf5-7993-4bde-ae05-eb6761b8472e",
+ "metadata": {},
+ "source": [
+ "### load in fire data\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "black-michigan",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "historical_fire = xr.open_zarr(\n",
+ " \"https://carbonplan.blob.core.windows.net/carbonplan-forests/risks/results/paper/fire_terraclimate.zarr\"\n",
+ ").load()\n",
+ "fire_mask = ~np.isnan(historical_fire.historical.isel(time=0).drop(\"time\"))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "legendary-module",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "ds = (\n",
+ " xr.open_zarr(\n",
+ " \"https://carbonplan.blob.core.windows.net/carbonplan-forests/risks/results/paper/fire_cmip.zarr\"\n",
+ " )\n",
+ " .assign_coords({\"x\": mask.x, \"y\": mask.y})\n",
+ " .where(fire_mask)\n",
+ " .groupby(\"time.year\")\n",
+ " .sum()\n",
+ " .where(fire_mask)\n",
+ " .compute()\n",
+ ") * 100 # scale to percent"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "invalid-navigator",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "maps = {}\n",
+ "maps[\"Fire\"] = (\n",
+ " ds.sel(scenario=\"ssp370\", year=slice(\"2080\", \"2099\"))\n",
+ " .mean(dim=\"year\")\n",
+ " .mean(dim=\"gcm\")\n",
+ " .drop(\"scenario\")\n",
+ " .compute()\n",
+ " .probability\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "focused-quest",
+ "metadata": {},
+ "source": [
+ "### load insects and drought\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "final-bailey",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "for variable in [\"drought\", \"insects\"]:\n",
+ " maps[variable.capitalize()] = (\n",
+ " xr.open_zarr(\n",
+ " \"https://carbonplan.blob.core.windows.net/carbonplan-forests/risks/results/paper/{}_cmip.zarr\".format(\n",
+ " variable\n",
+ " )\n",
+ " )\n",
+ " .assign_coords({\"year\": np.arange(1975, 2100, 10)})\n",
+ " .sel(year=slice(2080, 2099))\n",
+ " .mean(dim=\"year\")\n",
+ " .probability.sel(scenario=\"ssp370\")\n",
+ " .mean(dim=\"gcm\")\n",
+ " .drop(\"scenario\")\n",
+ " )"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "photographic-label",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "gcms = [\n",
+ " (\"MRI-ESM2-0\", (0, 0)),\n",
+ " (\"MIROC-ES2L\", (1, 0)),\n",
+ " (\"MPI-ESM1-2-LR\", (2, 0)),\n",
+ " (\"ACCESS-ESM1-5\", (3, 0)),\n",
+ " (\"ACCESS-CM2\", (4, 0)),\n",
+ " (\"CanESM5-CanOE\", (5, 0)),\n",
+ "]\n",
+ "titles = [\n",
+ " \"Burn area\\n[%/year]\",\n",
+ " \"Drought mortality\\n[]\",\n",
+ " \"Biotic agent mortality\\n[]\",\n",
+ "]"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "ca6db507-9958-460c-96c5-bf86d8ef4322",
+ "metadata": {},
+ "source": [
+ "### Load in biomass data from National biomass and carbon database\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "8e7baa3f-cca5-43f9-894f-2aba3939f6b7",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "biomass = xr.open_rasterio(\n",
+ " \"https://carbonplan.blob.core.windows.net/carbonplan-data/raw/nbcd/NBCD_countrywide_biomass_mosaic.tif\"\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "2a8a8263-dc0a-4d61-8a13-ef7ca000d58c",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "reprojected_biomass = biomass.rio.reproject(plot.cartopy_proj_albers())"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "edea4770-28af-49ef-a94c-4f46b7cc87c7",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# convert from tons per pixel to tons/hectare by dividing by 5.76 (the # hectares in a 240 m pixel) per the readme\n",
+ "maps[\"Biomass\"] = reprojected_biomass / 5.76\n",
+ "# aggregate 64x64 240m cells for plotting\n",
+ "maps[\"Biomass\"] = (\n",
+ " maps[\"Biomass\"]\n",
+ " .coarsen(y=64, x=64, boundary=\"trim\")\n",
+ " .mean()\n",
+ " .isel(band=0)\n",
+ " .drop([\"band\", \"spatial_ref\"])\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "9edc71f0-84d2-456a-8b50-086ab30d7459",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# for plotting purposes mask out anywhere that is less than 1 ton/ha\n",
+ "maps[\"Biomass\"] = maps[\"Biomass\"].where(maps[\"Biomass\"] > 1)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "absent-concern",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "plot_params = {\n",
+ " \"Fire\": {\n",
+ " \"cmap\": get_colormap(\"reds\"),\n",
+ " \"var_lims\": (0, 3),\n",
+ " \"label\": \"Burn area\\n(%/year)\",\n",
+ " \"panel\": \"A\",\n",
+ " \"cbar_ylocation\": 0.55,\n",
+ " \"cbar_xlocation\": 0.44,\n",
+ " \"panel_location\": (0, 0),\n",
+ " },\n",
+ " \"Insects\": {\n",
+ " \"cmap\": get_colormap(\"blues\"),\n",
+ " \"var_lims\": (0, 0.8),\n",
+ " \"label\": \"Insect-related\\nmortality (%/year)\",\n",
+ " \"panel\": \"B\",\n",
+ " \"cbar_ylocation\": 0.55,\n",
+ " \"cbar_xlocation\": 0.96,\n",
+ " \"panel_location\": (0, 1),\n",
+ " },\n",
+ " \"Drought\": {\n",
+ " \"cmap\": get_colormap(\"pinks\"),\n",
+ " \"var_lims\": (0, 4),\n",
+ " \"label\": \"Drought-related\\nmortality (%/year)\",\n",
+ " \"panel\": \"C\",\n",
+ " \"cbar_ylocation\": 0.05,\n",
+ " \"cbar_xlocation\": 0.44,\n",
+ " \"panel_location\": (1, 0),\n",
+ " },\n",
+ " \"Biomass\": {\n",
+ " \"cmap\": get_colormap(\"greens\"),\n",
+ " \"var_lims\": (0, 300),\n",
+ " \"label\": \"Biomass (tons/ha)\",\n",
+ " \"panel\": \"D\",\n",
+ " \"cbar_ylocation\": 0.05,\n",
+ " \"cbar_xlocation\": 0.96,\n",
+ " \"panel_location\": (1, 1),\n",
+ " },\n",
+ "}"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "e11da3f3-b015-4e1a-a825-6e6acab424e6",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def get_colormap(name):\n",
+ " if name == \"blues\":\n",
+ " return get_continuous_cmap([\"#CFE0F9\", \"#588EF9\", \"#0432A5\"])\n",
+ " elif name == \"pinks\":\n",
+ " return get_continuous_cmap([\"#F9C7ED\", \"#E563BA\", \"#770361\"])\n",
+ " elif name == \"reds\":\n",
+ " return get_continuous_cmap([\"#F9D3BD\", \"#E87A3D\", \"#752003\"])\n",
+ " elif name == \"greens\":\n",
+ " return get_continuous_cmap([\"#C9E4BF\", \"#76BA74\", \"#36763C\"])"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "sweet-arena",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "matplotlib.rc(\"font\", family=\"sans-serif\")\n",
+ "matplotlib.rc(\"font\", serif=\"Helvetica Neue\")\n",
+ "matplotlib.rc(\"text\", usetex=\"false\")\n",
+ "matplotlib.rcParams.update({\"font.size\": 14, \"svg.fonttype\": \"none\"})"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "headed-employee",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "state_borders, us_border = plot.cartopy_borders()\n",
+ "fig, axarr = plt.subplots(\n",
+ " nrows=2,\n",
+ " ncols=2,\n",
+ " figsize=(10, 6),\n",
+ " subplot_kw={\"projection\": plot.cartopy_proj_albers()},\n",
+ ")\n",
+ "from mpl_toolkits.axes_grid1 import make_axes_locatable\n",
+ "\n",
+ "for row, variable in enumerate([\"Fire\", \"Drought\", \"Insects\", \"Biomass\"]):\n",
+ " vmin, vmax = (\n",
+ " plot_params[variable][\"var_lims\"][0],\n",
+ " plot_params[variable][\"var_lims\"][1],\n",
+ " )\n",
+ " map_plot = maps[variable].plot.imshow(\n",
+ " ax=axarr[plot_params[variable][\"panel_location\"]],\n",
+ " cmap=plot_params[variable][\"cmap\"],\n",
+ " vmin=vmin,\n",
+ " vmax=vmax,\n",
+ " add_colorbar=False,\n",
+ " )\n",
+ " plot.map_pretty(axarr[plot_params[variable][\"panel_location\"]], title=\"\")\n",
+ "\n",
+ " axarr[plot_params[variable][\"panel_location\"]].text(\n",
+ " 0.12,\n",
+ " 1.05,\n",
+ " plot_params[variable][\"panel\"],\n",
+ " transform=axarr[plot_params[variable][\"panel_location\"]].transAxes,\n",
+ " fontsize=18,\n",
+ " )\n",
+ " cax = fig.add_axes(\n",
+ " [\n",
+ " plot_params[variable][\"cbar_xlocation\"],\n",
+ " plot_params[variable][\"cbar_ylocation\"],\n",
+ " 0.018,\n",
+ " 0.14,\n",
+ " ]\n",
+ " )\n",
+ " cbar = fig.colorbar(map_plot, cax=cax, orientation=\"vertical\")\n",
+ "\n",
+ " cax.text(\n",
+ " 0.5,\n",
+ " -0.22,\n",
+ " plot_params[variable][\"var_lims\"][0],\n",
+ " transform=cax.transAxes,\n",
+ " horizontalalignment=\"center\",\n",
+ " )\n",
+ " cax.text(\n",
+ " 0.5,\n",
+ " 1.05,\n",
+ " plot_params[variable][\"var_lims\"][1],\n",
+ " transform=cax.transAxes,\n",
+ " horizontalalignment=\"center\",\n",
+ " )\n",
+ " cax.text(\n",
+ " 1.8,\n",
+ " 0.5,\n",
+ " plot_params[variable][\"label\"],\n",
+ " transform=cax.transAxes,\n",
+ " verticalalignment=\"center\",\n",
+ " multialignment=\"center\",\n",
+ " rotation=-90,\n",
+ " )\n",
+ " print(variable)\n",
+ " cbar = fig.colorbar(map_plot, cax=cax, orientation=\"vertical\")\n",
+ " cbar.outline.set_visible(False)\n",
+ " cbar.set_ticks([])\n",
+ "plt.tight_layout(pad=-2)\n",
+ "for format_string in [\"svg\", \"png\"]:\n",
+ " fig.savefig(\n",
+ " \"Figure-Supp8.\" + format_string,\n",
+ " format=format_string,\n",
+ " bbox_inches=\"tight\",\n",
+ " )"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python [conda env:notebook] *",
+ "language": "python",
+ "name": "conda-env-notebook-py"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.9.12"
+ }
},
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "bizarre-semester",
- "metadata": {},
- "outputs": [],
- "source": [
- "alt.data_transformers.disable_max_rows()"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "administrative-tours",
- "metadata": {},
- "outputs": [],
- "source": [
- "coarsen = 4\n",
- "mask = (\n",
- " (\n",
- " load.nlcd(store=\"az\", year=2001).sel(band=[41, 42, 43, 90]).sum(\"band\")\n",
- " > 0.25\n",
- " )\n",
- " .astype(\"float\")\n",
- " .coarsen(x=coarsen, y=coarsen, boundary=\"trim\")\n",
- " .mean()\n",
- ")"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "1d62ddf5-7993-4bde-ae05-eb6761b8472e",
- "metadata": {},
- "source": [
- "### load in fire data\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "black-michigan",
- "metadata": {},
- "outputs": [],
- "source": [
- "historical_fire = xr.open_zarr(\n",
- " \"https://carbonplan.blob.core.windows.net/carbonplan-forests/risks/results/paper/fire_terraclimate.zarr\"\n",
- ").load()\n",
- "fire_mask = ~np.isnan(historical_fire.historical.isel(time=0).drop(\"time\"))"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "legendary-module",
- "metadata": {},
- "outputs": [],
- "source": [
- "ds = (\n",
- " xr.open_zarr(\n",
- " \"https://carbonplan.blob.core.windows.net/carbonplan-forests/risks/results/paper/fire_cmip.zarr\"\n",
- " )\n",
- " .assign_coords({\"x\": mask.x, \"y\": mask.y})\n",
- " .where(fire_mask)\n",
- " .groupby(\"time.year\")\n",
- " .sum()\n",
- " .where(fire_mask)\n",
- " .compute()\n",
- ") * 100 # scale to percent"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "invalid-navigator",
- "metadata": {},
- "outputs": [],
- "source": [
- "maps = {}\n",
- "maps[\"Fire\"] = (\n",
- " ds.sel(scenario=\"ssp370\", year=slice(\"2080\", \"2099\"))\n",
- " .mean(dim=\"year\")\n",
- " .mean(dim=\"gcm\")\n",
- " .drop(\"scenario\")\n",
- " .compute()\n",
- " .probability\n",
- ")"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "focused-quest",
- "metadata": {},
- "source": [
- "### load insects and drought\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "final-bailey",
- "metadata": {},
- "outputs": [],
- "source": [
- "for variable in [\"drought\", \"insects\"]:\n",
- " maps[variable.capitalize()] = (\n",
- " xr.open_zarr(\n",
- " \"https://carbonplan.blob.core.windows.net/carbonplan-forests/risks/results/paper/{}_cmip.zarr\".format(\n",
- " variable\n",
- " )\n",
- " )\n",
- " .assign_coords({\"year\": np.arange(1975, 2100, 10)})\n",
- " .sel(year=slice(2080, 2099))\n",
- " .mean(dim=\"year\")\n",
- " .probability.sel(scenario=\"ssp370\")\n",
- " .mean(dim=\"gcm\")\n",
- " .drop(\"scenario\")\n",
- " )"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "photographic-label",
- "metadata": {},
- "outputs": [],
- "source": [
- "gcms = [\n",
- " (\"MRI-ESM2-0\", (0, 0)),\n",
- " (\"MIROC-ES2L\", (1, 0)),\n",
- " (\"MPI-ESM1-2-LR\", (2, 0)),\n",
- " (\"ACCESS-ESM1-5\", (3, 0)),\n",
- " (\"ACCESS-CM2\", (4, 0)),\n",
- " (\"CanESM5-CanOE\", (5, 0)),\n",
- "]\n",
- "titles = [\n",
- " \"Burn area\\n[%/year]\",\n",
- " \"Drought mortality\\n[]\",\n",
- " \"Biotic agent mortality\\n[]\",\n",
- "]"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "ca6db507-9958-460c-96c5-bf86d8ef4322",
- "metadata": {},
- "source": [
- "### Load in biomass data from National biomass and carbon database\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "8e7baa3f-cca5-43f9-894f-2aba3939f6b7",
- "metadata": {},
- "outputs": [],
- "source": [
- "biomass = xr.open_rasterio(\n",
- " \"https://carbonplan.blob.core.windows.net/carbonplan-data/raw/nbcd/NBCD_countrywide_biomass_mosaic.tif\"\n",
- ")"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "2a8a8263-dc0a-4d61-8a13-ef7ca000d58c",
- "metadata": {},
- "outputs": [],
- "source": [
- "reprojected_biomass = biomass.rio.reproject(plot.cartopy_proj_albers())"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "edea4770-28af-49ef-a94c-4f46b7cc87c7",
- "metadata": {},
- "outputs": [],
- "source": [
- "# convert from tons per pixel to tons/hectare by dividing by 5.76 (the # hectares in a 240 m pixel) per the readme\n",
- "maps[\"Biomass\"] = reprojected_biomass / 5.76\n",
- "# aggregate 64x64 240m cells for plotting\n",
- "maps[\"Biomass\"] = (\n",
- " maps[\"Biomass\"]\n",
- " .coarsen(y=64, x=64, boundary=\"trim\")\n",
- " .mean()\n",
- " .isel(band=0)\n",
- " .drop([\"band\", \"spatial_ref\"])\n",
- ")"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "9edc71f0-84d2-456a-8b50-086ab30d7459",
- "metadata": {},
- "outputs": [],
- "source": [
- "# for plotting purposes mask out anywhere that is less than 1 ton/ha\n",
- "maps[\"Biomass\"] = maps[\"Biomass\"].where(maps[\"Biomass\"] > 1)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "absent-concern",
- "metadata": {},
- "outputs": [],
- "source": [
- "plot_params = {\n",
- " \"Fire\": {\n",
- " \"cmap\": get_colormap(\"reds\"),\n",
- " \"var_lims\": (0, 3),\n",
- " \"label\": \"Burn area\\n(%/year)\",\n",
- " \"panel\": \"A\",\n",
- " \"cbar_ylocation\": 0.55,\n",
- " \"cbar_xlocation\": 0.44,\n",
- " \"panel_location\": (0, 0),\n",
- " },\n",
- " \"Insects\": {\n",
- " \"cmap\": get_colormap(\"blues\"),\n",
- " \"var_lims\": (0, 0.8),\n",
- " \"label\": \"Insect-related\\nmortality (%/year)\",\n",
- " \"panel\": \"B\",\n",
- " \"cbar_ylocation\": 0.55,\n",
- " \"cbar_xlocation\": 0.96,\n",
- " \"panel_location\": (0, 1),\n",
- " },\n",
- " \"Drought\": {\n",
- " \"cmap\": get_colormap(\"pinks\"),\n",
- " \"var_lims\": (0, 4),\n",
- " \"label\": \"Drought-related\\nmortality (%/year)\",\n",
- " \"panel\": \"C\",\n",
- " \"cbar_ylocation\": 0.05,\n",
- " \"cbar_xlocation\": 0.44,\n",
- " \"panel_location\": (1, 0),\n",
- " },\n",
- " \"Biomass\": {\n",
- " \"cmap\": get_colormap(\"greens\"),\n",
- " \"var_lims\": (0, 300),\n",
- " \"label\": \"Biomass (tons/ha)\",\n",
- " \"panel\": \"D\",\n",
- " \"cbar_ylocation\": 0.05,\n",
- " \"cbar_xlocation\": 0.96,\n",
- " \"panel_location\": (1, 1),\n",
- " },\n",
- "}"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "e11da3f3-b015-4e1a-a825-6e6acab424e6",
- "metadata": {},
- "outputs": [],
- "source": [
- "def get_colormap(name):\n",
- " if name == \"blues\":\n",
- " return get_continuous_cmap([\"#CFE0F9\", \"#588EF9\", \"#0432A5\"])\n",
- " elif name == \"pinks\":\n",
- " return get_continuous_cmap([\"#F9C7ED\", \"#E563BA\", \"#770361\"])\n",
- " elif name == \"reds\":\n",
- " return get_continuous_cmap([\"#F9D3BD\", \"#E87A3D\", \"#752003\"])\n",
- " elif name == \"greens\":\n",
- " return get_continuous_cmap([\"#C9E4BF\", \"#76BA74\", \"#36763C\"])"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "sweet-arena",
- "metadata": {},
- "outputs": [],
- "source": [
- "matplotlib.rc(\"font\", family=\"sans-serif\")\n",
- "matplotlib.rc(\"font\", serif=\"Helvetica Neue\")\n",
- "matplotlib.rc(\"text\", usetex=\"false\")\n",
- "matplotlib.rcParams.update({\"font.size\": 14, \"svg.fonttype\": \"none\"})"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "headed-employee",
- "metadata": {},
- "outputs": [],
- "source": [
- "state_borders, us_border = plot.cartopy_borders()\n",
- "fig, axarr = plt.subplots(\n",
- " nrows=2,\n",
- " ncols=2,\n",
- " figsize=(10, 6),\n",
- " subplot_kw={\"projection\": plot.cartopy_proj_albers()},\n",
- ")\n",
- "from mpl_toolkits.axes_grid1 import make_axes_locatable\n",
- "\n",
- "for row, variable in enumerate([\"Fire\", \"Drought\", \"Insects\", \"Biomass\"]):\n",
- " vmin, vmax = (\n",
- " plot_params[variable][\"var_lims\"][0],\n",
- " plot_params[variable][\"var_lims\"][1],\n",
- " )\n",
- " map_plot = maps[variable].plot.imshow(\n",
- " ax=axarr[plot_params[variable][\"panel_location\"]],\n",
- " cmap=plot_params[variable][\"cmap\"],\n",
- " vmin=vmin,\n",
- " vmax=vmax,\n",
- " add_colorbar=False,\n",
- " )\n",
- " plot.map_pretty(axarr[plot_params[variable][\"panel_location\"]], title=\"\")\n",
- "\n",
- " axarr[plot_params[variable][\"panel_location\"]].text(\n",
- " 0.12,\n",
- " 1.05,\n",
- " plot_params[variable][\"panel\"],\n",
- " transform=axarr[plot_params[variable][\"panel_location\"]].transAxes,\n",
- " fontsize=18,\n",
- " )\n",
- " cax = fig.add_axes(\n",
- " [\n",
- " plot_params[variable][\"cbar_xlocation\"],\n",
- " plot_params[variable][\"cbar_ylocation\"],\n",
- " 0.018,\n",
- " 0.14,\n",
- " ]\n",
- " )\n",
- " cbar = fig.colorbar(map_plot, cax=cax, orientation=\"vertical\")\n",
- "\n",
- " cax.text(\n",
- " 0.5,\n",
- " -0.22,\n",
- " plot_params[variable][\"var_lims\"][0],\n",
- " transform=cax.transAxes,\n",
- " horizontalalignment=\"center\",\n",
- " )\n",
- " cax.text(\n",
- " 0.5,\n",
- " 1.05,\n",
- " plot_params[variable][\"var_lims\"][1],\n",
- " transform=cax.transAxes,\n",
- " horizontalalignment=\"center\",\n",
- " )\n",
- " cax.text(\n",
- " 1.8,\n",
- " 0.5,\n",
- " plot_params[variable][\"label\"],\n",
- " transform=cax.transAxes,\n",
- " verticalalignment=\"center\",\n",
- " multialignment=\"center\",\n",
- " rotation=-90,\n",
- " )\n",
- " print(variable)\n",
- " cbar = fig.colorbar(map_plot, cax=cax, orientation=\"vertical\")\n",
- " cbar.outline.set_visible(False)\n",
- " cbar.set_ticks([])\n",
- "plt.tight_layout(pad=-2)\n",
- "for format_string in [\"svg\", \"png\"]:\n",
- " fig.savefig(\n",
- " \"Figure-Supp8.\" + format_string,\n",
- " format=format_string,\n",
- " bbox_inches=\"tight\",\n",
- " )"
- ]
- }
- ],
- "metadata": {
- "kernelspec": {
- "display_name": "Python [conda env:notebook] *",
- "language": "python",
- "name": "conda-env-notebook-py"
- },
- "language_info": {
- "codemirror_mode": {
- "name": "ipython",
- "version": 3
- },
- "file_extension": ".py",
- "mimetype": "text/x-python",
- "name": "python",
- "nbconvert_exporter": "python",
- "pygments_lexer": "ipython3",
- "version": "3.9.12"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 5
+ "nbformat": 4,
+ "nbformat_minor": 5
}
diff --git a/notebooks/paper/Supplementary-Figure-09/Supplementary-Figure-09.ipynb b/notebooks/paper/Supplementary-Figure-09/Supplementary-Figure-09.ipynb
index b00383d..bcc40f1 100644
--- a/notebooks/paper/Supplementary-Figure-09/Supplementary-Figure-09.ipynb
+++ b/notebooks/paper/Supplementary-Figure-09/Supplementary-Figure-09.ipynb
@@ -1,136 +1,136 @@
{
- "cells": [
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "loaded-sullivan",
- "metadata": {},
- "outputs": [],
- "source": [
- "import pandas as pd\n",
- "import numpy as np\n",
- "import matplotlib.pyplot as plt"
- ]
+ "cells": [
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "loaded-sullivan",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import pandas as pd\n",
+ "import numpy as np\n",
+ "import matplotlib.pyplot as plt"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "comparable-revision",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "plt.rcParams.update({\"font.size\": 14, \"svg.fonttype\": \"none\"})"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "accessible-relations",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "df_drought_coef = pd.read_csv(\n",
+ " \"SuppFig_DroughtModelCoefficients-WeightedUnweighted_4-26-21.csv\"\n",
+ ")\n",
+ "df_drought_pred = pd.read_csv(\n",
+ " \"SuppFig_DroughtModelMortPredictions-WeightedUnweighted_4-26-21.csv\"\n",
+ ")\n",
+ "df_insects_coef = pd.read_csv(\n",
+ " \"SuppFig_InsectModelCoefficients-WeightedUnweighted_4-26-21.csv\"\n",
+ ")\n",
+ "df_insects_pred = pd.read_csv(\n",
+ " \"SuppFig_InsectModelMortPredictions-WeightedUnweighted_4-26-21.csv\"\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "complimentary-efficiency",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "fig, axs = plt.subplots(2, 2, figsize=(12, 12))\n",
+ "\n",
+ "\n",
+ "def style(ax):\n",
+ " ax.spines[\"right\"].set_visible(False)\n",
+ " ax.spines[\"top\"].set_visible(False)\n",
+ "\n",
+ "\n",
+ "axs[0][0].plot([-8, 8], [-8, 8], \"gray\")\n",
+ "axs[0][0].plot(df_drought_coef[\"V1\"], df_drought_coef[\"V2\"], \"k.\")\n",
+ "axs[0][0].set_ylim([-8, 8])\n",
+ "axs[0][0].set_xlim([-8, 8])\n",
+ "axs[0][0].set_xticks([-5, 0, 5])\n",
+ "axs[0][0].set_yticks([-5, 0, 5])\n",
+ "axs[0][0].set_ylabel(\"Weighted coefficient\")\n",
+ "style(axs[0][0])\n",
+ "\n",
+ "axs[0][1].plot([-0.005, 0.04], [-0.005, 0.04], \"gray\")\n",
+ "axs[0][1].plot(df_drought_pred[\"V1\"], df_drought_pred[\"V2\"], \"k.\")\n",
+ "axs[0][1].set_ylim([-0.005, 0.04])\n",
+ "axs[0][1].set_xlim([-0.005, 0.04])\n",
+ "axs[0][1].set_xticks([0, 0.01, 0.02, 0.03, 0.04])\n",
+ "axs[0][1].set_yticks([0, 0.01, 0.02, 0.03, 0.04])\n",
+ "axs[0][1].set_ylabel(\"Weighted mortality (%/year)\")\n",
+ "axs[0][1].plot([-8, -8], [8, 8], \"k\")\n",
+ "style(axs[0][1])\n",
+ "\n",
+ "axs[1][0].plot([-8, 8], [-8, 8], \"gray\")\n",
+ "axs[1][0].plot(df_insects_coef[\"V1\"], df_insects_coef[\"V2\"], \"k.\")\n",
+ "axs[1][0].set_ylim([-8, 8])\n",
+ "axs[1][0].set_xlim([-8, 8])\n",
+ "axs[1][0].set_xticks([-5, 0, 5])\n",
+ "axs[1][0].set_yticks([-5, 0, 5])\n",
+ "axs[1][0].set_ylabel(\"Weighted coefficient\")\n",
+ "axs[1][0].set_xlabel(\"Unweighted coefficient\")\n",
+ "style(axs[1][0])\n",
+ "\n",
+ "axs[1][1].plot([-0.005, 0.04], [-0.005, 0.04], \"gray\")\n",
+ "axs[1][1].plot(df_insects_pred[\"V1\"], df_insects_pred[\"V2\"], \"k.\")\n",
+ "axs[1][1].set_ylim([-0.005, 0.04])\n",
+ "axs[1][1].set_xlim([-0.005, 0.04])\n",
+ "axs[1][1].set_xticks([0, 0.01, 0.02, 0.03, 0.04])\n",
+ "axs[1][1].set_yticks([0, 0.01, 0.02, 0.03, 0.04])\n",
+ "axs[1][1].set_ylabel(\"Weighted mortality (%/year)\")\n",
+ "axs[1][1].set_xlabel(\"Unweighted mortality (%/year)\")\n",
+ "style(axs[1][1])\n",
+ "\n",
+ "plt.savefig(\"Supplementary-Figure-09.svg\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "whole-citation",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "inds = ~np.isnan(df_insects_pred[\"V1\"]) & ~np.isnan(df_insects_pred[\"V2\"])\n",
+ "np.corrcoef(df_insects_pred[\"V1\"][inds], df_insects_pred[\"V2\"][inds]) ** 2"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.8.6"
+ }
},
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "comparable-revision",
- "metadata": {},
- "outputs": [],
- "source": [
- "plt.rcParams.update({\"font.size\": 14, \"svg.fonttype\": \"none\"})"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "accessible-relations",
- "metadata": {},
- "outputs": [],
- "source": [
- "df_drought_coef = pd.read_csv(\n",
- " \"SuppFig_DroughtModelCoefficients-WeightedUnweighted_4-26-21.csv\"\n",
- ")\n",
- "df_drought_pred = pd.read_csv(\n",
- " \"SuppFig_DroughtModelMortPredictions-WeightedUnweighted_4-26-21.csv\"\n",
- ")\n",
- "df_insects_coef = pd.read_csv(\n",
- " \"SuppFig_InsectModelCoefficients-WeightedUnweighted_4-26-21.csv\"\n",
- ")\n",
- "df_insects_pred = pd.read_csv(\n",
- " \"SuppFig_InsectModelMortPredictions-WeightedUnweighted_4-26-21.csv\"\n",
- ")"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "complimentary-efficiency",
- "metadata": {},
- "outputs": [],
- "source": [
- "fig, axs = plt.subplots(2, 2, figsize=(12, 12))\n",
- "\n",
- "\n",
- "def style(ax):\n",
- " ax.spines[\"right\"].set_visible(False)\n",
- " ax.spines[\"top\"].set_visible(False)\n",
- "\n",
- "\n",
- "axs[0][0].plot([-8, 8], [-8, 8], \"gray\")\n",
- "axs[0][0].plot(df_drought_coef[\"V1\"], df_drought_coef[\"V2\"], \"k.\")\n",
- "axs[0][0].set_ylim([-8, 8])\n",
- "axs[0][0].set_xlim([-8, 8])\n",
- "axs[0][0].set_xticks([-5, 0, 5])\n",
- "axs[0][0].set_yticks([-5, 0, 5])\n",
- "axs[0][0].set_ylabel(\"Weighted coefficient\")\n",
- "style(axs[0][0])\n",
- "\n",
- "axs[0][1].plot([-0.005, 0.04], [-0.005, 0.04], \"gray\")\n",
- "axs[0][1].plot(df_drought_pred[\"V1\"], df_drought_pred[\"V2\"], \"k.\")\n",
- "axs[0][1].set_ylim([-0.005, 0.04])\n",
- "axs[0][1].set_xlim([-0.005, 0.04])\n",
- "axs[0][1].set_xticks([0, 0.01, 0.02, 0.03, 0.04])\n",
- "axs[0][1].set_yticks([0, 0.01, 0.02, 0.03, 0.04])\n",
- "axs[0][1].set_ylabel(\"Weighted mortality (%/year)\")\n",
- "axs[0][1].plot([-8, -8], [8, 8], \"k\")\n",
- "style(axs[0][1])\n",
- "\n",
- "axs[1][0].plot([-8, 8], [-8, 8], \"gray\")\n",
- "axs[1][0].plot(df_insects_coef[\"V1\"], df_insects_coef[\"V2\"], \"k.\")\n",
- "axs[1][0].set_ylim([-8, 8])\n",
- "axs[1][0].set_xlim([-8, 8])\n",
- "axs[1][0].set_xticks([-5, 0, 5])\n",
- "axs[1][0].set_yticks([-5, 0, 5])\n",
- "axs[1][0].set_ylabel(\"Weighted coefficient\")\n",
- "axs[1][0].set_xlabel(\"Unweighted coefficient\")\n",
- "style(axs[1][0])\n",
- "\n",
- "axs[1][1].plot([-0.005, 0.04], [-0.005, 0.04], \"gray\")\n",
- "axs[1][1].plot(df_insects_pred[\"V1\"], df_insects_pred[\"V2\"], \"k.\")\n",
- "axs[1][1].set_ylim([-0.005, 0.04])\n",
- "axs[1][1].set_xlim([-0.005, 0.04])\n",
- "axs[1][1].set_xticks([0, 0.01, 0.02, 0.03, 0.04])\n",
- "axs[1][1].set_yticks([0, 0.01, 0.02, 0.03, 0.04])\n",
- "axs[1][1].set_ylabel(\"Weighted mortality (%/year)\")\n",
- "axs[1][1].set_xlabel(\"Unweighted mortality (%/year)\")\n",
- "style(axs[1][1])\n",
- "\n",
- "plt.savefig(\"Supplementary-Figure-09.svg\")"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "whole-citation",
- "metadata": {},
- "outputs": [],
- "source": [
- "inds = ~np.isnan(df_insects_pred[\"V1\"]) & ~np.isnan(df_insects_pred[\"V2\"])\n",
- "np.corrcoef(df_insects_pred[\"V1\"][inds], df_insects_pred[\"V2\"][inds]) ** 2"
- ]
- }
- ],
- "metadata": {
- "kernelspec": {
- "display_name": "Python 3",
- "language": "python",
- "name": "python3"
- },
- "language_info": {
- "codemirror_mode": {
- "name": "ipython",
- "version": 3
- },
- "file_extension": ".py",
- "mimetype": "text/x-python",
- "name": "python",
- "nbconvert_exporter": "python",
- "pygments_lexer": "ipython3",
- "version": "3.8.6"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 5
+ "nbformat": 4,
+ "nbformat_minor": 5
}
diff --git a/notebooks/paper/Supplementary-Figure-10/Supplementary-Figure-10.ipynb b/notebooks/paper/Supplementary-Figure-10/Supplementary-Figure-10.ipynb
index d1c410e..ecc4631 100644
--- a/notebooks/paper/Supplementary-Figure-10/Supplementary-Figure-10.ipynb
+++ b/notebooks/paper/Supplementary-Figure-10/Supplementary-Figure-10.ipynb
@@ -1,173 +1,173 @@
{
- "cells": [
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "angry-journey",
- "metadata": {},
- "outputs": [],
- "source": [
- "%load_ext autoreload\n",
- "%autoreload 2\n",
- "\n",
- "import numpy as np\n",
- "import pandas as pd\n",
- "import scipy as sp\n",
- "from carbonplan_forest_risks import load, setup, plot, fit, utils, prepare, collect\n",
- "import xarray as xr\n",
- "from carbonplan_forest_risks.utils import get_store\n",
- "import altair as alt\n",
- "import rioxarray\n",
- "from carbonplan.data import cat\n",
- "from carbonplan_styles.mpl import get_colormap\n",
- "import cartopy.crs as ccrs\n",
- "import cartopy\n",
- "import cartopy.feature as cfeature\n",
- "import matplotlib.pyplot as plt\n",
- "import matplotlib\n",
- "from mpl_toolkits.axes_grid1 import make_axes_locatable\n",
- "\n",
- "from carbonplan_data import utils\n",
- "alt.data_transformers.disable_max_rows()"
- ]
+ "cells": [
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "angry-journey",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "%load_ext autoreload\n",
+ "%autoreload 2\n",
+ "\n",
+ "import numpy as np\n",
+ "import pandas as pd\n",
+ "import scipy as sp\n",
+ "from carbonplan_forest_risks import load, setup, plot, fit, utils, prepare, collect\n",
+ "import xarray as xr\n",
+ "from carbonplan_forest_risks.utils import get_store\n",
+ "import altair as alt\n",
+ "import rioxarray\n",
+ "from carbonplan.data import cat\n",
+ "from carbonplan_styles.mpl import get_colormap\n",
+ "import cartopy.crs as ccrs\n",
+ "import cartopy\n",
+ "import cartopy.feature as cfeature\n",
+ "import matplotlib.pyplot as plt\n",
+ "import matplotlib\n",
+ "from mpl_toolkits.axes_grid1 import make_axes_locatable\n",
+ "\n",
+ "from carbonplan_data import utils\n",
+ "alt.data_transformers.disable_max_rows()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "requested-jamaica",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "coarsen = 4\n",
+ "store = \"az\"\n",
+ "tlim = (\"1984\", \"2018\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "strong-freight",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "historical_fire = historical_fire = xr.open_zarr(\n",
+ " \"https://carbonplan.blob.core.windows.net/carbonplan-forests/risks/results/paper/fire_terraclimate.zarr\"\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "closed-jimmy",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "fire_mask = ~np.isnan(historical_fire.historical.isel(time=0).drop(\"time\"))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "broad-isolation",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "historical_fire = (\n",
+ " historical_fire.groupby(\"time.month\")\n",
+ " .mean()\n",
+ " .where(fire_mask)\n",
+ " .compute()[\"historical\"]\n",
+ ") * 100 # cast to percent"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "plain-benefit",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "plot_params = {\n",
+ " \"cmap\": get_colormap(\"reds\"),\n",
+ " \"var_lims\": (0, 0.03),\n",
+ " \"label\": \"Burn area\\n(%/year)\",\n",
+ " \"y_loc\": 0.2,\n",
+ " \"cbar_height\": 0.6,\n",
+ " \"x_loc\": 1.08,\n",
+ " \"width\": 0.03,\n",
+ "}\n",
+ "matplotlib.rc(\"font\", family=\"sans-serif\")\n",
+ "matplotlib.rc(\"font\", serif=\"Helvetica Neue\")\n",
+ "matplotlib.rc(\"text\", usetex=\"false\")\n",
+ "matplotlib.rcParams.update({\"font.size\": 14, \"svg.fonttype\": \"none\"})"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "contrary-employee",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "months = [\"Mar\", \"Apr\", \"May\", \"Jun\", \"Jul\", \"Aug\", \"Sep\", \"Oct\", \"Nov\"]"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "diverse-buddy",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "p = historical_fire.sel(month=slice(3, 11)).plot.imshow(\n",
+ " col=\"month\",\n",
+ " col_wrap=3,\n",
+ " vmin=0,\n",
+ " vmax=0.1,\n",
+ " subplot_kws={\"projection\": plot.cartopy_proj_albers()},\n",
+ " add_colorbar=False,\n",
+ " cmap=plot_params[\"cmap\"],\n",
+ " figsize=(8, 6),\n",
+ ")\n",
+ "for i, ax in enumerate(p.axes.flat):\n",
+ " plot.map_pretty(ax, title=months[i])\n",
+ " ax.set_title(\"\")\n",
+ "\n",
+ "plot.add_colorbar(\n",
+ " p.fig,\n",
+ " y_location=plot_params[\"y_loc\"],\n",
+ " vmin=plot_params[\"var_lims\"][0],\n",
+ " vmax=plot_params[\"var_lims\"][1],\n",
+ " cbar_label=plot_params[\"label\"],\n",
+ " cmap=plot_params[\"cmap\"],\n",
+ " height=plot_params[\"cbar_height\"],\n",
+ " x_location=plot_params[\"x_loc\"],\n",
+ " width=plot_params[\"width\"],\n",
+ ")\n",
+ "plt.tight_layout(pad=-4)\n",
+ "plt.savefig(\"fig_supp7.svg\", format=\"svg\", bbox_inches=\"tight\")"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python [conda env:notebook] *",
+ "language": "python",
+ "name": "conda-env-notebook-py"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.9.12"
+ }
},
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "requested-jamaica",
- "metadata": {},
- "outputs": [],
- "source": [
- "coarsen = 4\n",
- "store = \"az\"\n",
- "tlim = (\"1984\", \"2018\")"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "strong-freight",
- "metadata": {},
- "outputs": [],
- "source": [
- "historical_fire = historical_fire = xr.open_zarr(\n",
- " \"https://carbonplan.blob.core.windows.net/carbonplan-forests/risks/results/paper/fire_terraclimate.zarr\"\n",
- ")"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "closed-jimmy",
- "metadata": {},
- "outputs": [],
- "source": [
- "fire_mask = ~np.isnan(historical_fire.historical.isel(time=0).drop(\"time\"))"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "broad-isolation",
- "metadata": {},
- "outputs": [],
- "source": [
- "historical_fire = (\n",
- " historical_fire.groupby(\"time.month\")\n",
- " .mean()\n",
- " .where(fire_mask)\n",
- " .compute()[\"historical\"]\n",
- ") * 100 # cast to percent"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "plain-benefit",
- "metadata": {},
- "outputs": [],
- "source": [
- "plot_params = {\n",
- " \"cmap\": get_colormap(\"reds\"),\n",
- " \"var_lims\": (0, 0.03),\n",
- " \"label\": \"Burn area\\n(%/year)\",\n",
- " \"y_loc\": 0.2,\n",
- " \"cbar_height\": 0.6,\n",
- " \"x_loc\": 1.08,\n",
- " \"width\": 0.03,\n",
- "}\n",
- "matplotlib.rc(\"font\", family=\"sans-serif\")\n",
- "matplotlib.rc(\"font\", serif=\"Helvetica Neue\")\n",
- "matplotlib.rc(\"text\", usetex=\"false\")\n",
- "matplotlib.rcParams.update({\"font.size\": 14, \"svg.fonttype\": \"none\"})"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "contrary-employee",
- "metadata": {},
- "outputs": [],
- "source": [
- "months = [\"Mar\", \"Apr\", \"May\", \"Jun\", \"Jul\", \"Aug\", \"Sep\", \"Oct\", \"Nov\"]"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "diverse-buddy",
- "metadata": {},
- "outputs": [],
- "source": [
- "p = historical_fire.sel(month=slice(3, 11)).plot.imshow(\n",
- " col=\"month\",\n",
- " col_wrap=3,\n",
- " vmin=0,\n",
- " vmax=0.1,\n",
- " subplot_kws={\"projection\": plot.cartopy_proj_albers()},\n",
- " add_colorbar=False,\n",
- " cmap=plot_params[\"cmap\"],\n",
- " figsize=(8, 6),\n",
- ")\n",
- "for i, ax in enumerate(p.axes.flat):\n",
- " plot.map_pretty(ax, title=months[i])\n",
- " ax.set_title(\"\")\n",
- "\n",
- "plot.add_colorbar(\n",
- " p.fig,\n",
- " y_location=plot_params[\"y_loc\"],\n",
- " vmin=plot_params[\"var_lims\"][0],\n",
- " vmax=plot_params[\"var_lims\"][1],\n",
- " cbar_label=plot_params[\"label\"],\n",
- " cmap=plot_params[\"cmap\"],\n",
- " height=plot_params[\"cbar_height\"],\n",
- " x_location=plot_params[\"x_loc\"],\n",
- " width=plot_params[\"width\"],\n",
- ")\n",
- "plt.tight_layout(pad=-4)\n",
- "plt.savefig(\"fig_supp7.svg\", format=\"svg\", bbox_inches=\"tight\")"
- ]
- }
- ],
- "metadata": {
- "kernelspec": {
- "display_name": "Python [conda env:notebook] *",
- "language": "python",
- "name": "conda-env-notebook-py"
- },
- "language_info": {
- "codemirror_mode": {
- "name": "ipython",
- "version": 3
- },
- "file_extension": ".py",
- "mimetype": "text/x-python",
- "name": "python",
- "nbconvert_exporter": "python",
- "pygments_lexer": "ipython3",
- "version": "3.9.12"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 5
+ "nbformat": 4,
+ "nbformat_minor": 5
}
diff --git a/notebooks/paper/Supplementary-Figure-11/Supplementary-Figure-11.ipynb b/notebooks/paper/Supplementary-Figure-11/Supplementary-Figure-11.ipynb
index a03f701..cb7570e 100644
--- a/notebooks/paper/Supplementary-Figure-11/Supplementary-Figure-11.ipynb
+++ b/notebooks/paper/Supplementary-Figure-11/Supplementary-Figure-11.ipynb
@@ -1,230 +1,230 @@
{
- "cells": [
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "utility-appeal",
- "metadata": {},
- "outputs": [],
- "source": [
- "%load_ext autoreload\n",
- "%autoreload 2\n",
- "\n",
- "import numpy as np\n",
- "import pandas as pd\n",
- "import scipy as sp\n",
- "from carbonplan_forest_risks import load, setup, plot, fit, utils, prepare, collect\n",
- "import xarray as xr\n",
- "from carbonplan_forest_risks.utils import get_store\n",
- "import altair as alt\n",
- "import rioxarray\n",
- "from carbonplan.data import cat\n",
- "from carbonplan_styles.mpl import get_colormap\n",
- "import cartopy.crs as ccrs\n",
- "import cartopy\n",
- "import cartopy.feature as cfeature\n",
- "import matplotlib.pyplot as plt\n",
- "import matplotlib\n",
- "from mpl_toolkits.axes_grid1 import make_axes_locatable\n",
- "\n",
- "from carbonplan_data import utils\n",
- "alt.data_transformers.disable_max_rows()"
- ]
+ "cells": [
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "utility-appeal",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "%load_ext autoreload\n",
+ "%autoreload 2\n",
+ "\n",
+ "import numpy as np\n",
+ "import pandas as pd\n",
+ "import scipy as sp\n",
+ "from carbonplan_forest_risks import load, setup, plot, fit, utils, prepare, collect\n",
+ "import xarray as xr\n",
+ "from carbonplan_forest_risks.utils import get_store\n",
+ "import altair as alt\n",
+ "import rioxarray\n",
+ "from carbonplan.data import cat\n",
+ "from carbonplan_styles.mpl import get_colormap\n",
+ "import cartopy.crs as ccrs\n",
+ "import cartopy\n",
+ "import cartopy.feature as cfeature\n",
+ "import matplotlib.pyplot as plt\n",
+ "import matplotlib\n",
+ "from mpl_toolkits.axes_grid1 import make_axes_locatable\n",
+ "\n",
+ "from carbonplan_data import utils\n",
+ "alt.data_transformers.disable_max_rows()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "measured-switzerland",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "coarsen = 4\n",
+ "store = \"az\"\n",
+ "tlim = (\"1984\", \"2018\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "comparable-insertion",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "ds_dict = {\"Observed\": {}, \"Modeled\": {}}"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "foster-nature",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "ds_dict[\"Modeled\"][\"raw\"] = historical_fire = historical_fire = xr.open_zarr(\n",
+ " \"https://carbonplan.blob.core.windows.net/carbonplan-forests/risks/results/paper/fire_terraclimate.zarr\"\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "inner-kennedy",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "fire_mask = ~np.isnan(ds_dict[\"Modeled\"][\"raw\"].isel(time=0).drop(\"time\"))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "integral-fireplace",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "forest_mask = (\n",
+ " load.nlcd(store=store, year=2001).sel(band=[41, 42, 43, 90]).sum(\"band\")\n",
+ " > 0.25\n",
+ ").astype(\"float\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "nearby-paradise",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "ds_dict[\"Observed\"][\"raw\"] = load.mtbs(\n",
+ " store=store, coarsen=coarsen, tlim=tlim, mask=forest_mask\n",
+ ")\n",
+ "ds_dict[\"Observed\"][\"raw\"] = (\n",
+ " ds_dict[\"Observed\"][\"raw\"]\n",
+ " .assign_coords(\n",
+ " {\"x\": ds_dict[\"Modeled\"][\"raw\"].x, \"y\": ds_dict[\"Modeled\"][\"raw\"].y}\n",
+ " )\n",
+ " .assign_coords(\n",
+ " {\n",
+ " \"lat\": ds_dict[\"Modeled\"][\"raw\"].lat,\n",
+ " \"lon\": ds_dict[\"Modeled\"][\"raw\"].lon,\n",
+ " }\n",
+ " )[\"monthly\"]\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "constitutional-pursuit",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "for setup in [\"Observed\", \"Modeled\"]:\n",
+ " ds_dict[setup][\"annual\"] = (\n",
+ " ds_dict[setup][\"raw\"]\n",
+ " .groupby(\"time.year\")\n",
+ " .sum()\n",
+ " .where(fire_mask)\n",
+ " .mean(dim=[\"x\", \"y\"])\n",
+ " .compute()\n",
+ " ) * 100\n",
+ " ds_dict[setup][\"seasonal\"] = (\n",
+ " ds_dict[setup][\"raw\"]\n",
+ " .groupby(\"time.month\")\n",
+ " .mean()\n",
+ " .where(fire_mask)\n",
+ " .mean(dim=[\"x\", \"y\"])\n",
+ " .compute()\n",
+ " ) * 100"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "vocal-earthquake",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "plot_params = {\n",
+ " \"annual\": {\"y_label\": \"Annual burn area\\n(%/year)\"},\n",
+ " \"seasonal\": {\"y_label\": \"Monthly burn area\\n(%/month)\"},\n",
+ " \"colors\": {\"Modeled\": \"#E87A3D\", \"Observed\": \"grey\"},\n",
+ "}"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "challenging-progressive",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "matplotlib.rc(\"font\", family=\"sans-serif\")\n",
+ "matplotlib.rc(\"font\", serif=\"Helvetica Neue\")\n",
+ "matplotlib.rc(\"text\", usetex=\"false\")\n",
+ "matplotlib.rcParams.update({\"font.size\": 14, \"svg.fonttype\": \"none\"})"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "lucky-capability",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "fig, axarr = plt.subplots(nrows=2, figsize=(8, 8))\n",
+ "for setup in [\"Observed\", \"Modeled\"]:\n",
+ " ds_dict[setup][\"annual\"].historical.plot(\n",
+ " ax=axarr[0], color=plot_params[\"colors\"][setup], label=setup\n",
+ " )\n",
+ " axarr[0].set_ylabel(plot_params[\"annual\"][\"y_label\"])\n",
+ " ds_dict[setup][\"seasonal\"].historical.plot(\n",
+ " ax=axarr[1], color=plot_params[\"colors\"][setup], label=setup\n",
+ " )\n",
+ " axarr[1].set_ylabel(plot_params[\"seasonal\"][\"y_label\"])\n",
+ "axarr[0].set_xlabel(\"\")\n",
+ "axarr[1].set_xlabel(\"\")\n",
+ "axarr[0].legend()\n",
+ "axarr[1].set_xticks(np.arange(1, 13))\n",
+ "axarr[1].set_xticklabels(\n",
+ " [\n",
+ " \"Jan\",\n",
+ " \"Feb\",\n",
+ " \"Mar\",\n",
+ " \"Apr\",\n",
+ " \"May\",\n",
+ " \"Jun\",\n",
+ " \"Jul\",\n",
+ " \"Aug\",\n",
+ " \"Sep\",\n",
+ " \"Oct\",\n",
+ " \"Nov\",\n",
+ " \"Dec\",\n",
+ " ]\n",
+ ")\n",
+ "# plt.savefig(\"supp11.svg\", format=\"svg\", bbox_inches=\"tight\")"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python [conda env:notebook] *",
+ "language": "python",
+ "name": "conda-env-notebook-py"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.9.12"
+ }
},
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "measured-switzerland",
- "metadata": {},
- "outputs": [],
- "source": [
- "coarsen = 4\n",
- "store = \"az\"\n",
- "tlim = (\"1984\", \"2018\")"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "comparable-insertion",
- "metadata": {},
- "outputs": [],
- "source": [
- "ds_dict = {\"Observed\": {}, \"Modeled\": {}}"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "foster-nature",
- "metadata": {},
- "outputs": [],
- "source": [
- "ds_dict[\"Modeled\"][\"raw\"] = historical_fire = historical_fire = xr.open_zarr(\n",
- " \"https://carbonplan.blob.core.windows.net/carbonplan-forests/risks/results/paper/fire_terraclimate.zarr\"\n",
- ")"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "inner-kennedy",
- "metadata": {},
- "outputs": [],
- "source": [
- "fire_mask = ~np.isnan(ds_dict[\"Modeled\"][\"raw\"].isel(time=0).drop(\"time\"))"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "integral-fireplace",
- "metadata": {},
- "outputs": [],
- "source": [
- "forest_mask = (\n",
- " load.nlcd(store=store, year=2001).sel(band=[41, 42, 43, 90]).sum(\"band\")\n",
- " > 0.25\n",
- ").astype(\"float\")"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "nearby-paradise",
- "metadata": {},
- "outputs": [],
- "source": [
- "ds_dict[\"Observed\"][\"raw\"] = load.mtbs(\n",
- " store=store, coarsen=coarsen, tlim=tlim, mask=forest_mask\n",
- ")\n",
- "ds_dict[\"Observed\"][\"raw\"] = (\n",
- " ds_dict[\"Observed\"][\"raw\"]\n",
- " .assign_coords(\n",
- " {\"x\": ds_dict[\"Modeled\"][\"raw\"].x, \"y\": ds_dict[\"Modeled\"][\"raw\"].y}\n",
- " )\n",
- " .assign_coords(\n",
- " {\n",
- " \"lat\": ds_dict[\"Modeled\"][\"raw\"].lat,\n",
- " \"lon\": ds_dict[\"Modeled\"][\"raw\"].lon,\n",
- " }\n",
- " )[\"monthly\"]\n",
- ")"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "constitutional-pursuit",
- "metadata": {},
- "outputs": [],
- "source": [
- "for setup in [\"Observed\", \"Modeled\"]:\n",
- " ds_dict[setup][\"annual\"] = (\n",
- " ds_dict[setup][\"raw\"]\n",
- " .groupby(\"time.year\")\n",
- " .sum()\n",
- " .where(fire_mask)\n",
- " .mean(dim=[\"x\", \"y\"])\n",
- " .compute()\n",
- " ) * 100\n",
- " ds_dict[setup][\"seasonal\"] = (\n",
- " ds_dict[setup][\"raw\"]\n",
- " .groupby(\"time.month\")\n",
- " .mean()\n",
- " .where(fire_mask)\n",
- " .mean(dim=[\"x\", \"y\"])\n",
- " .compute()\n",
- " ) * 100"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "vocal-earthquake",
- "metadata": {},
- "outputs": [],
- "source": [
- "plot_params = {\n",
- " \"annual\": {\"y_label\": \"Annual burn area\\n(%/year)\"},\n",
- " \"seasonal\": {\"y_label\": \"Monthly burn area\\n(%/month)\"},\n",
- " \"colors\": {\"Modeled\": \"#E87A3D\", \"Observed\": \"grey\"},\n",
- "}"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "challenging-progressive",
- "metadata": {},
- "outputs": [],
- "source": [
- "matplotlib.rc(\"font\", family=\"sans-serif\")\n",
- "matplotlib.rc(\"font\", serif=\"Helvetica Neue\")\n",
- "matplotlib.rc(\"text\", usetex=\"false\")\n",
- "matplotlib.rcParams.update({\"font.size\": 14, \"svg.fonttype\": \"none\"})"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "lucky-capability",
- "metadata": {},
- "outputs": [],
- "source": [
- "fig, axarr = plt.subplots(nrows=2, figsize=(8, 8))\n",
- "for setup in [\"Observed\", \"Modeled\"]:\n",
- " ds_dict[setup][\"annual\"].historical.plot(\n",
- " ax=axarr[0], color=plot_params[\"colors\"][setup], label=setup\n",
- " )\n",
- " axarr[0].set_ylabel(plot_params[\"annual\"][\"y_label\"])\n",
- " ds_dict[setup][\"seasonal\"].historical.plot(\n",
- " ax=axarr[1], color=plot_params[\"colors\"][setup], label=setup\n",
- " )\n",
- " axarr[1].set_ylabel(plot_params[\"seasonal\"][\"y_label\"])\n",
- "axarr[0].set_xlabel(\"\")\n",
- "axarr[1].set_xlabel(\"\")\n",
- "axarr[0].legend()\n",
- "axarr[1].set_xticks(np.arange(1, 13))\n",
- "axarr[1].set_xticklabels(\n",
- " [\n",
- " \"Jan\",\n",
- " \"Feb\",\n",
- " \"Mar\",\n",
- " \"Apr\",\n",
- " \"May\",\n",
- " \"Jun\",\n",
- " \"Jul\",\n",
- " \"Aug\",\n",
- " \"Sep\",\n",
- " \"Oct\",\n",
- " \"Nov\",\n",
- " \"Dec\",\n",
- " ]\n",
- ")\n",
- "# plt.savefig(\"supp11.svg\", format=\"svg\", bbox_inches=\"tight\")"
- ]
- }
- ],
- "metadata": {
- "kernelspec": {
- "display_name": "Python [conda env:notebook] *",
- "language": "python",
- "name": "conda-env-notebook-py"
- },
- "language_info": {
- "codemirror_mode": {
- "name": "ipython",
- "version": 3
- },
- "file_extension": ".py",
- "mimetype": "text/x-python",
- "name": "python",
- "nbconvert_exporter": "python",
- "pygments_lexer": "ipython3",
- "version": "3.9.12"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 5
+ "nbformat": 4,
+ "nbformat_minor": 5
}
diff --git a/notebooks/share/fire_risks_counties.ipynb b/notebooks/share/fire_risks_counties.ipynb
index 88912f5..d581bc0 100644
--- a/notebooks/share/fire_risks_counties.ipynb
+++ b/notebooks/share/fire_risks_counties.ipynb
@@ -1,219 +1,219 @@
{
- "cells": [
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "947b0886",
- "metadata": {},
- "outputs": [],
- "source": [
- "import xarray as xr\n",
- "import numpy as np\n",
- "import pandas as pd\n",
- "from showit import image\n",
- "from scipy.stats import binom\n",
- "import matplotlib.pyplot as plt\n",
- "import geopandas\n",
- "import rasterio\n",
- "from rasterio import Affine\n",
- "from tqdm import tqdm"
- ]
+ "cells": [
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "947b0886",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import xarray as xr\n",
+ "import numpy as np\n",
+ "import pandas as pd\n",
+ "from showit import image\n",
+ "from scipy.stats import binom\n",
+ "import matplotlib.pyplot as plt\n",
+ "import geopandas\n",
+ "import rasterio\n",
+ "from rasterio import Affine\n",
+ "from tqdm import tqdm"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "efe27b80",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def integrated_risk(p):\n",
+ " return (1 - binom.cdf(0, 20, p)) * 100"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "6da00394",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "ds = xr.open_zarr(\n",
+ " \"https://carbonplan.blob.core.windows.net/carbonplan-forests/risks/results/web/fire.zarr\"\n",
+ ").load()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "0fa21c48",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "counties = geopandas.read_file(\n",
+ " \"cb_2021_us_county_500k/cb_2021_us_county_500k.shp\"\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "5bae54f7",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "exclude = list([\"02\", \"15\", \"60\", \"66\", \"69\", \"72\", \"78\"])\n",
+ "counties = counties[list(map(lambda x: x not in exclude, counties[\"STATEFP\"]))]"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "3e356a4d",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "counties = counties.to_crs(\"EPSG:5070\").reset_index()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "c3363b94",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "get_mask = lambda geometry: rasterio.features.geometry_mask(\n",
+ " [geometry],\n",
+ " out_shape=ds.lat.shape,\n",
+ " transform=Affine(4000, 0.0, -2493045.0, 0.0, -4000, 3310005.0),\n",
+ " all_touched=False,\n",
+ " invert=True,\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "cd56a44c",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "scenarios = [\"ssp245\", \"ssp370\", \"ssp585\"]\n",
+ "columns = [\"state_code\", \"state_name\", \"county_code\", \"county_name\"] + list(\n",
+ " ds.year.values\n",
+ ")\n",
+ "data = {key: [] for key in scenarios}\n",
+ "dfs = {key: [] for key in scenarios}\n",
+ "\n",
+ "for index, county in tqdm(counties.iterrows()):\n",
+ " mask = np.tile(get_mask(county[\"geometry\"]), [12, 1, 1])\n",
+ " means = ds.where(mask).mean([\"x\", \"y\"])\n",
+ " for scenario in scenarios:\n",
+ " values = integrated_risk(means[scenario].values)\n",
+ " data[scenario].append(\n",
+ " [\n",
+ " county[\"STATEFP\"],\n",
+ " county[\"STUSPS\"],\n",
+ " county[\"COUNTYFP\"],\n",
+ " county[\"NAME\"],\n",
+ " ]\n",
+ " + list(values)\n",
+ " )\n",
+ "\n",
+ "for scenario in scenarios:\n",
+ " dfs[scenario] = pd.DataFrame(data[scenario], columns=columns)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "44b0b5be",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "dfs[\"ssp245\"].dropna().reset_index(drop=True).to_csv(\n",
+ " \"CarbonPlan-Fire-Risk-SSP-4.5.csv\", index=False, header=True\n",
+ ")\n",
+ "dfs[\"ssp370\"].dropna().reset_index(drop=True).to_csv(\n",
+ " \"CarbonPlan-Fire-Risk-SSP-7.0.csv\", index=False, header=True\n",
+ ")\n",
+ "dfs[\"ssp585\"].dropna().reset_index(drop=True).to_csv(\n",
+ " \"CarbonPlan-Fire-Risk-SSP-8.5.csv\", index=False, header=True\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "f433c8a2",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "len(dfs[\"ssp585\"])"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "38573ebc",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "counties[\"fire\"] = dfs[\"ssp585\"][\"2050\"]"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "1e0701ae",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "counties.plot(\n",
+ " column=\"fire\", cmap=\"hot\", vmin=0, vmax=50, figsize=(15, 10), legend=True\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "7aa7c6a8",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "counties.plot(column=\"fire\", cmap=\"hot\", figsize=(15, 10))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "d3f9b311",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "counties.plot(column=\"fire\", vmin=0, vmax=25)"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python [conda env:notebook] *",
+ "language": "python",
+ "name": "conda-env-notebook-py"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.8.12"
+ }
},
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "efe27b80",
- "metadata": {},
- "outputs": [],
- "source": [
- "def integrated_risk(p):\n",
- " return (1 - binom.cdf(0, 20, p)) * 100"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "6da00394",
- "metadata": {},
- "outputs": [],
- "source": [
- "ds = xr.open_zarr(\n",
- " \"https://carbonplan.blob.core.windows.net/carbonplan-forests/risks/results/web/fire.zarr\"\n",
- ").load()"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "0fa21c48",
- "metadata": {},
- "outputs": [],
- "source": [
- "counties = geopandas.read_file(\n",
- " \"cb_2021_us_county_500k/cb_2021_us_county_500k.shp\"\n",
- ")"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "5bae54f7",
- "metadata": {},
- "outputs": [],
- "source": [
- "exclude = list([\"02\", \"15\", \"60\", \"66\", \"69\", \"72\", \"78\"])\n",
- "counties = counties[list(map(lambda x: x not in exclude, counties[\"STATEFP\"]))]"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "3e356a4d",
- "metadata": {},
- "outputs": [],
- "source": [
- "counties = counties.to_crs(\"EPSG:5070\").reset_index()"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "c3363b94",
- "metadata": {},
- "outputs": [],
- "source": [
- "get_mask = lambda geometry: rasterio.features.geometry_mask(\n",
- " [geometry],\n",
- " out_shape=ds.lat.shape,\n",
- " transform=Affine(4000, 0.0, -2493045.0, 0.0, -4000, 3310005.0),\n",
- " all_touched=False,\n",
- " invert=True,\n",
- ")"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "cd56a44c",
- "metadata": {},
- "outputs": [],
- "source": [
- "scenarios = [\"ssp245\", \"ssp370\", \"ssp585\"]\n",
- "columns = [\"state_code\", \"state_name\", \"county_code\", \"county_name\"] + list(\n",
- " ds.year.values\n",
- ")\n",
- "data = {key: [] for key in scenarios}\n",
- "dfs = {key: [] for key in scenarios}\n",
- "\n",
- "for index, county in tqdm(counties.iterrows()):\n",
- " mask = np.tile(get_mask(county[\"geometry\"]), [12, 1, 1])\n",
- " means = ds.where(mask).mean([\"x\", \"y\"])\n",
- " for scenario in scenarios:\n",
- " values = integrated_risk(means[scenario].values)\n",
- " data[scenario].append(\n",
- " [\n",
- " county[\"STATEFP\"],\n",
- " county[\"STUSPS\"],\n",
- " county[\"COUNTYFP\"],\n",
- " county[\"NAME\"],\n",
- " ]\n",
- " + list(values)\n",
- " )\n",
- "\n",
- "for scenario in scenarios:\n",
- " dfs[scenario] = pd.DataFrame(data[scenario], columns=columns)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "44b0b5be",
- "metadata": {},
- "outputs": [],
- "source": [
- "dfs[\"ssp245\"].dropna().reset_index(drop=True).to_csv(\n",
- " \"CarbonPlan-Fire-Risk-SSP-4.5.csv\", index=False, header=True\n",
- ")\n",
- "dfs[\"ssp370\"].dropna().reset_index(drop=True).to_csv(\n",
- " \"CarbonPlan-Fire-Risk-SSP-7.0.csv\", index=False, header=True\n",
- ")\n",
- "dfs[\"ssp585\"].dropna().reset_index(drop=True).to_csv(\n",
- " \"CarbonPlan-Fire-Risk-SSP-8.5.csv\", index=False, header=True\n",
- ")"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "f433c8a2",
- "metadata": {},
- "outputs": [],
- "source": [
- "len(dfs[\"ssp585\"])"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "38573ebc",
- "metadata": {},
- "outputs": [],
- "source": [
- "counties[\"fire\"] = dfs[\"ssp585\"][\"2050\"]"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "1e0701ae",
- "metadata": {},
- "outputs": [],
- "source": [
- "counties.plot(\n",
- " column=\"fire\", cmap=\"hot\", vmin=0, vmax=50, figsize=(15, 10), legend=True\n",
- ")"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "7aa7c6a8",
- "metadata": {},
- "outputs": [],
- "source": [
- "counties.plot(column=\"fire\", cmap=\"hot\", figsize=(15, 10))"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "d3f9b311",
- "metadata": {},
- "outputs": [],
- "source": [
- "counties.plot(column=\"fire\", vmin=0, vmax=25)"
- ]
- }
- ],
- "metadata": {
- "kernelspec": {
- "display_name": "Python [conda env:notebook] *",
- "language": "python",
- "name": "conda-env-notebook-py"
- },
- "language_info": {
- "codemirror_mode": {
- "name": "ipython",
- "version": 3
- },
- "file_extension": ".py",
- "mimetype": "text/x-python",
- "name": "python",
- "nbconvert_exporter": "python",
- "pygments_lexer": "ipython3",
- "version": "3.8.12"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 5
+ "nbformat": 4,
+ "nbformat_minor": 5
}
diff --git a/scripts/article_prep.py b/scripts/article_prep.py
index 98149b6..790e492 100644
--- a/scripts/article_prep.py
+++ b/scripts/article_prep.py
@@ -28,124 +28,126 @@ def default(self, obj):
return super(NpEncoder, self).default(obj)
-warnings.filterwarnings('ignore')
+warnings.filterwarnings("ignore")
-account_key = os.environ.get('BLOB_ACCOUNT_KEY')
+account_key = os.environ.get("BLOB_ACCOUNT_KEY")
gcms = [
- ('CanESM5-CanOE', 'r3i1p2f1'),
- ('MIROC-ES2L', 'r1i1p1f2'),
- ('ACCESS-CM2', 'r1i1p1f1'),
- ('ACCESS-ESM1-5', 'r10i1p1f1'),
- ('MRI-ESM2-0', 'r1i1p1f1'),
- ('MPI-ESM1-2-LR', 'r10i1p1f1'),
+ ("CanESM5-CanOE", "r3i1p2f1"),
+ ("MIROC-ES2L", "r1i1p1f2"),
+ ("ACCESS-CM2", "r1i1p1f1"),
+ ("ACCESS-ESM1-5", "r10i1p1f1"),
+ ("MRI-ESM2-0", "r1i1p1f1"),
+ ("MPI-ESM1-2-LR", "r10i1p1f1"),
]
-scenarios = ['ssp245', 'ssp370', 'ssp585']
+scenarios = ["ssp245", "ssp370", "ssp585"]
website_mask = (
load.nlcd(store="az", year=2016).sel(band=[41, 42, 43, 90]).sum("band") > 0.5
).astype("float")
region_bboxes = {
- 'CONUS': {'x': slice(-3e6, 3e6), 'y': slice(4e6, 0)},
- 'PNW': {'x': slice(-2.5e6, -1e6), 'y': slice(3.5e6, 2.4e6)},
- 'Southwest': {'x': slice(-1.8e6, -0.9e6), 'y': slice(1.8e6, 0.9e6)},
- 'California': {'x': slice(-2.3e6, -1.8e6), 'y': slice(2.5e6, 1.2e6)},
- 'Southeast': {
- 'x': slice(0.6e6, 1.8e6),
- 'y': slice(1.6e6, 0.3e6),
+ "CONUS": {"x": slice(-3e6, 3e6), "y": slice(4e6, 0)},
+ "PNW": {"x": slice(-2.5e6, -1e6), "y": slice(3.5e6, 2.4e6)},
+ "Southwest": {"x": slice(-1.8e6, -0.9e6), "y": slice(1.8e6, 0.9e6)},
+ "California": {"x": slice(-2.3e6, -1.8e6), "y": slice(2.5e6, 1.2e6)},
+ "Southeast": {
+ "x": slice(0.6e6, 1.8e6),
+ "y": slice(1.6e6, 0.3e6),
},
}
def build_climate_cube(
- tlim=(1970, 2099), variables=['tmean'], downscaling_method='quantile-mapping-v3'
+ tlim=(1970, 2099), variables=["tmean"], downscaling_method="quantile-mapping-v3"
):
""""""
gcms = [
- ('CanESM5-CanOE', 'r3i1p2f1'),
- ('MIROC-ES2L', 'r1i1p1f2'),
- ('ACCESS-CM2', 'r1i1p1f1'),
- ('ACCESS-ESM1-5', 'r10i1p1f1'),
- ('MRI-ESM2-0', 'r1i1p1f1'),
- ('MPI-ESM1-2-LR', 'r10i1p1f1'),
+ ("CanESM5-CanOE", "r3i1p2f1"),
+ ("MIROC-ES2L", "r1i1p1f2"),
+ ("ACCESS-CM2", "r1i1p1f1"),
+ ("ACCESS-ESM1-5", "r10i1p1f1"),
+ ("MRI-ESM2-0", "r1i1p1f1"),
+ ("MPI-ESM1-2-LR", "r10i1p1f1"),
]
- scenarios = ['ssp245', 'ssp370', 'ssp585']
+ scenarios = ["ssp245", "ssp370", "ssp585"]
all_scenarios = []
for scenario in scenarios:
all_gcms = []
- for (gcm, ensemble_member) in gcms:
+ for gcm, ensemble_member in gcms:
cmip = load.cmip(
- store='az',
+ store="az",
model=gcm,
tlim=tlim,
scenario=scenario,
historical=True,
member=ensemble_member,
method=downscaling_method,
- sampling='annual',
+ sampling="annual",
variables=variables,
)
all_gcms.append(cmip)
- concatted = xr.concat(all_gcms, dim='gcm')
- concatted = concatted.assign_coords({'gcm': [gcm[0] for gcm in gcms]})
+ concatted = xr.concat(all_gcms, dim="gcm")
+ concatted = concatted.assign_coords({"gcm": [gcm[0] for gcm in gcms]})
all_scenarios.append(concatted)
- ds = xr.concat(all_scenarios, dim='scenario')
- ds = ds.assign_coords({'scenario': scenarios})
+ ds = xr.concat(all_scenarios, dim="scenario")
+ ds = ds.assign_coords({"scenario": scenarios})
return ds
def repackage_drought_insects(ds):
gcms = [
- ('CanESM5-CanOE', 'r3i1p2f1'),
- ('MIROC-ES2L', 'r1i1p1f2'),
- ('ACCESS-CM2', 'r1i1p1f1'),
- ('ACCESS-ESM1-5', 'r10i1p1f1'),
- ('MRI-ESM2-0', 'r1i1p1f1'),
- ('MPI-ESM1-2-LR', 'r10i1p1f1'),
+ ("CanESM5-CanOE", "r3i1p2f1"),
+ ("MIROC-ES2L", "r1i1p1f2"),
+ ("ACCESS-CM2", "r1i1p1f1"),
+ ("ACCESS-ESM1-5", "r10i1p1f1"),
+ ("MRI-ESM2-0", "r1i1p1f1"),
+ ("MPI-ESM1-2-LR", "r10i1p1f1"),
]
- scenarios = ['ssp245', 'ssp370', 'ssp585']
+ scenarios = ["ssp245", "ssp370", "ssp585"]
all_gcms = []
- for (gcm, ensemble_member) in gcms:
+ for gcm, ensemble_member in gcms:
all_gcms.append(
- ds[['{}-{}'.format(gcm, scenario) for scenario in scenarios]]
- .to_array(dim='scenario', name='probability')
- .assign_coords({'scenario': scenarios})
+ ds[["{}-{}".format(gcm, scenario) for scenario in scenarios]]
+ .to_array(dim="scenario", name="probability")
+ .assign_coords({"scenario": scenarios})
)
- full_ds = xr.concat(all_gcms, dim='gcm').to_dataset()
- full_ds = full_ds.assign_coords({'gcm': [gcm for (gcm, ensemble_member) in gcms]})
+ full_ds = xr.concat(all_gcms, dim="gcm").to_dataset()
+ full_ds = full_ds.assign_coords({"gcm": [gcm for (gcm, ensemble_member) in gcms]})
return full_ds
-def timeseries_dict(ds, time_period='historical'):
+def timeseries_dict(ds, time_period="historical"):
gcms = [
- ('CanESM5-CanOE', 'r3i1p2f1'),
- ('MIROC-ES2L', 'r1i1p1f2'),
- ('ACCESS-CM2', 'r1i1p1f1'),
- ('ACCESS-ESM1-5', 'r10i1p1f1'),
- ('MRI-ESM2-0', 'r1i1p1f1'),
- ('MPI-ESM1-2-LR', 'r10i1p1f1'),
+ ("CanESM5-CanOE", "r3i1p2f1"),
+ ("MIROC-ES2L", "r1i1p1f2"),
+ ("ACCESS-CM2", "r1i1p1f1"),
+ ("ACCESS-ESM1-5", "r10i1p1f1"),
+ ("MRI-ESM2-0", "r1i1p1f1"),
+ ("MPI-ESM1-2-LR", "r10i1p1f1"),
]
mean = []
gcm_dict = {}
- for (gcm, ensemble_member) in gcms:
+ for gcm, ensemble_member in gcms:
gcm_dict[gcm] = []
- if time_period == 'historical':
+ if time_period == "historical":
years = np.arange(1980, 2020, 10)
- elif time_period == 'future':
+ elif time_period == "future":
years = np.arange(2020, 2100, 10)
for year in years:
# average across scenarios
mean.append(
{
- 'y': year,
- 'r': ds.mean(dim='gcm').sel(year=year).values.item(),
+ "y": year,
+ "r": ds.mean(dim="gcm").sel(year=year).values.item(),
}
)
# then populate all the gcms
- for (gcm, ensemble_member) in gcms:
- gcm_dict[gcm].append({'y': year, 'r': ds.sel(gcm=gcm, year=year).values.item()})
+ for gcm, ensemble_member in gcms:
+ gcm_dict[gcm].append(
+ {"y": year, "r": ds.sel(gcm=gcm, year=year).values.item()}
+ )
return mean, gcm_dict
@@ -155,13 +157,13 @@ def timeseries_dict(ds, time_period='historical'):
slice_to_list = lambda x: [x.start, x.stop]
for region in region_bboxes:
region_bboxes_lists[region] = {}
- for coord in ['x', 'y']:
+ for coord in ["x", "y"]:
region_bboxes_lists[region][coord] = slice_to_list(region_bboxes[region][coord])
with fsspec.open(
- 'az://carbonplan-forests/risks/results/web/time-series-bounding-boxes.json',
+ "az://carbonplan-forests/risks/results/web/time-series-bounding-boxes.json",
account_name="carbonplan",
account_key=account_key,
- mode='w',
+ mode="w",
) as f:
json.dump(region_bboxes_lists, f, indent=2, cls=NpEncoder)
@@ -171,25 +173,25 @@ def timeseries_dict(ds, time_period='historical'):
results_dict = {}
# select out bounding boxes
# select out bounding boxes
-for impact in ['insects', 'drought', 'fire', 'tmean']:
+for impact in ["insects", "drought", "fire", "tmean"]:
results_dict[impact] = {}
# read in the temperature data from its different sources and create a datacube
# of the same specs as the risks
- if impact == 'tmean':
+ if impact == "tmean":
ds = build_climate_cube()
# grab the risks data
else:
- store_path = 'risks/results/web/{}_full.zarr'.format(impact)
+ store_path = "risks/results/web/{}_full.zarr".format(impact)
ds = xr.open_zarr(
get_store(
- 'carbonplan-forests',
+ "carbonplan-forests",
store_path,
account_key=account_key,
)
)
- ds = ds.assign_coords({'year': np.arange(1980, 2100, 10)})
+ ds = ds.assign_coords({"year": np.arange(1980, 2100, 10)})
- if impact in ['insects', 'drought']:
+ if impact in ["insects", "drought"]:
# restructure the insects/drought ones to align with the temp/fire
ds = repackage_drought_insects(ds)
@@ -203,11 +205,11 @@ def timeseries_dict(ds, time_period='historical'):
}
)
# align to the annual timesteps for tmean and fire
- if impact == 'tmean':
+ if impact == "tmean":
# calculate decadal mean
ds = ds.coarsen(time=10).mean().compute()
- ds = ds.rename({'time': 'year'})
- ds = ds.assign_coords({'year': np.arange(1970, 2100, 10)})
+ ds = ds.rename({"time": "year"})
+ ds = ds.assign_coords({"year": np.arange(1970, 2100, 10)})
# mask according to the mask we use for the web
ds = ds.where(website_mask > 0).compute()
# then do rolling mean for two decades (and drop the first timestep which only
@@ -216,7 +218,7 @@ def timeseries_dict(ds, time_period='historical'):
# loop through each of the regions of interest
for region, bbox in region_bboxes.items():
- print('Calculating regional averages over the {} for {}'.format(region, impact))
+ print("Calculating regional averages over the {} for {}".format(region, impact))
# initialize the dictionary
results_dict[impact][region] = {}
# select out the box you want
@@ -224,26 +226,28 @@ def timeseries_dict(ds, time_period='historical'):
# aggregate the different risks according to either 20 year integrated risk for fire
# or just multiply by 100 to convert to percentage and then by 20 for the 20 year
# total mortality for insects/drought
- if impact == 'fire':
+ if impact == "fire":
selected = selected.apply(utils.integrated_risk)
- elif impact in ['drought', 'insects']:
+ elif impact in ["drought", "insects"]:
selected *= 100 * 20
# calculate regional averages (these have already been masked) and then select the
# appropriate variable
- if impact == 'tmean':
- selected = selected.mean(dim=['x', 'y']).compute().tmean
+ if impact == "tmean":
+ selected = selected.mean(dim=["x", "y"]).compute().tmean
# create anomalies
- selected -= selected.sel(year=[1980, 1990, 2000]).mean(dim='year')
+ selected -= selected.sel(year=[1980, 1990, 2000]).mean(dim="year")
else:
- selected = selected.mean(dim=['x', 'y']).compute().probability
+ selected = selected.mean(dim=["x", "y"]).compute().probability
# first populate the historical values
- results_dict[impact][region]['historical'] = {}
+ results_dict[impact][region]["historical"] = {}
# initialize your dictionary with the gcm keys
- mean, models = timeseries_dict(selected.mean(dim='scenario'), time_period='historical')
- results_dict[impact][region]['historical']['mean'] = mean
- results_dict[impact][region]['historical']['models'] = models
+ mean, models = timeseries_dict(
+ selected.mean(dim="scenario"), time_period="historical"
+ )
+ results_dict[impact][region]["historical"]["mean"] = mean
+ results_dict[impact][region]["historical"]["models"] = models
# then fill in each of the three different scenarios
@@ -251,15 +255,17 @@ def timeseries_dict(ds, time_period='historical'):
results_dict[impact][region][scenario] = {}
# initialize your dictionary with the gcm keys
- mean, models = timeseries_dict(selected.sel(scenario=scenario), time_period='future')
- results_dict[impact][region][scenario]['mean'] = mean
- results_dict[impact][region][scenario]['models'] = models
+ mean, models = timeseries_dict(
+ selected.sel(scenario=scenario), time_period="future"
+ )
+ results_dict[impact][region][scenario]["mean"] = mean
+ results_dict[impact][region][scenario]["models"] = models
# write out to dictionary to rendered within the explainer
with fsspec.open(
- 'az://carbonplan-forests/risks/results/web/time-series-hybrid.json',
+ "az://carbonplan-forests/risks/results/web/time-series-hybrid.json",
account_name="carbonplan",
account_key=account_key,
- mode='w',
+ mode="w",
) as f:
json.dump(results_dict, f, indent=2, cls=NpEncoder)
diff --git a/scripts/biomass.py b/scripts/biomass.py
index ff7fade..1b8e2d4 100644
--- a/scripts/biomass.py
+++ b/scripts/biomass.py
@@ -9,66 +9,66 @@
args = sys.argv
if len(args) < 2:
- store = 'local'
+ store = "local"
else:
store = args[1]
-variables = ['tmean', 'ppt']
+variables = ["tmean", "ppt"]
-print('[biomass] loading data')
-df = load.fia(store=store, states='conus')
+print("[biomass] loading data")
+df = load.fia(store=store, states="conus")
df = load.terraclim(
store=store,
tlim=(2000, 2020),
variables=variables,
remove_nans=True,
- sampling='annual',
+ sampling="annual",
df=df,
)
-type_codes = df['type_code'].unique()
+type_codes = df["type_code"].unique()
-print('[biomass] fitting models')
+print("[biomass] fitting models")
models = {}
for code in tqdm(type_codes):
- df_type = df[df['type_code'] == code].reset_index()
- x = df_type['age']
- y = df_type['biomass']
- f = [df_type['tmean_mean'], df_type['ppt_mean']]
- model = fit.growth(x=x, y=y, f=f, noise='gamma')
+ df_type = df[df["type_code"] == code].reset_index()
+ x = df_type["age"]
+ y = df_type["biomass"]
+ f = [df_type["tmean_mean"], df_type["ppt_mean"]]
+ model = fit.growth(x=x, y=y, f=f, noise="gamma")
models[code] = model
-print('[biomass] preparing for evaluations')
+print("[biomass] preparing for evaluations")
pf = pd.DataFrame()
-pf['lat'] = df['lat']
-pf['lon'] = df['lon']
-pf['type_code'] = df['type_code']
+pf["lat"] = df["lat"]
+pf["lon"] = df["lon"]
+pf["type_code"] = df["type_code"]
-print('[biomass] evaluating predictions on training data')
+print("[biomass] evaluating predictions on training data")
for code in type_codes:
if code in models.keys():
model = models[code]
- inds = df['type_code'] == code
- x = df[inds]['age']
- f = [df[inds]['tmean_mean'], df[inds]['ppt_mean']]
- pf.loc[inds, 'historical'] = model.predict(x, f)
+ inds = df["type_code"] == code
+ x = df[inds]["age"]
+ f = [df[inds]["tmean_mean"], df[inds]["ppt_mean"]]
+ pf.loc[inds, "historical"] = model.predict(x, f)
-print('[biomass] evaluating predictions on future climate models')
+print("[biomass] evaluating predictions on future climate models")
targets = list(map(lambda x: str(x), np.arange(2005, 2100, 10)))
cmip_models = [
- 'CanESM5-CanOE',
- 'MIROC-ES2L',
- 'ACCESS-CM2',
- 'ACCESS-ESM1-5',
- 'MRI-ESM2-0',
- 'MPI-ESM1-2-LR',
+ "CanESM5-CanOE",
+ "MIROC-ES2L",
+ "ACCESS-CM2",
+ "ACCESS-ESM1-5",
+ "MRI-ESM2-0",
+ "MPI-ESM1-2-LR",
]
-scenarios = ['ssp245', 'ssp370', 'ssp585']
+scenarios = ["ssp245", "ssp370", "ssp585"]
for it in tqdm(range(len(targets))):
target = targets[it]
tlim = (str(int(target) - 10), str(int(target) + 9))
for cmip_model in cmip_models:
for scenario in scenarios:
- key = cmip_model + '_' + scenario + '_' + target
+ key = cmip_model + "_" + scenario + "_" + target
df = load.cmip(
store=store,
tlim=(int(tlim[0]), int(tlim[1])),
@@ -76,30 +76,30 @@
historical=True if int(tlim[0]) < 2015 else False,
model=cmip_model,
scenario=scenario,
- sampling='annual',
+ sampling="annual",
df=df,
)
pf[key] = np.NaN
for code in type_codes:
if code in models.keys():
model = models[code]
- inds = df['type_code'] == code
- x = df[inds]['age']
- year = df[inds]['year']
- f = [df[inds]['tmean_mean'], df[inds]['ppt_mean']]
+ inds = df["type_code"] == code
+ x = df[inds]["age"]
+ year = df[inds]["year"]
+ f = [df[inds]["tmean_mean"], df[inds]["ppt_mean"]]
if it == 0:
pf.loc[inds, key] = model.predict(
np.maximum(x + (float(target) - year), 0), f
)
else:
prev_target = targets[it - 1]
- prev_key = cmip_model + '_' + scenario + '_' + prev_target
- diff = model.predict(x + (float(target) - year), f) - model.predict(
- x + (float(prev_target) - year), f
- )
+ prev_key = cmip_model + "_" + scenario + "_" + prev_target
+ diff = model.predict(
+ x + (float(target) - year), f
+ ) - model.predict(x + (float(prev_target) - year), f)
pf.loc[inds, key] = np.maximum(pf[prev_key][inds] + diff, 0)
-pf['r2'] = pf['type_code'].map(lambda k: models[k].train_r2)
-pf['scale'] = pf['type_code'].map(lambda k: models[k].scale)
+pf["r2"] = pf["type_code"].map(lambda k: models[k].train_r2)
+pf["scale"] = pf["type_code"].map(lambda k: models[k].scale)
-pf.to_parquet('data/biomass_v2.parquet', compression='gzip', engine='fastparquet')
+pf.to_parquet("data/biomass_v2.parquet", compression="gzip", engine="fastparquet")
diff --git a/scripts/convert.py b/scripts/convert.py
index 9a0c17f..ab1801c 100644
--- a/scripts/convert.py
+++ b/scripts/convert.py
@@ -16,27 +16,27 @@ def integrated_risk(p):
args = sys.argv
if len(args) < 2:
- raise ValueError('must specify dataset')
+ raise ValueError("must specify dataset")
dataset = args[1]
if len(args) > 2:
coarsen = int(args[2])
- savename = f'{dataset}_d{coarsen}'
+ savename = f"{dataset}_d{coarsen}"
res = 4000 * coarsen
else:
coarsen = 0
savename = dataset
res = 4000
-print(f'[{dataset}] converting to geojson')
+print(f"[{dataset}] converting to geojson")
precision = 2
-store = utils.get_store('carbonplan-forests', f'risks/results/web/{dataset}.zarr')
+store = utils.get_store("carbonplan-forests", f"risks/results/web/{dataset}.zarr")
ds = xr.open_zarr(store)
if coarsen > 0:
- ds = ds.coarsen(x=coarsen, y=coarsen, boundary='trim').mean().compute()
+ ds = ds.coarsen(x=coarsen, y=coarsen, boundary="trim").mean().compute()
# if dataset == 'fire':
# scenarios = ['ssp245', 'ssp370', 'ssp585']
@@ -46,16 +46,16 @@ def integrated_risk(p):
# )
# ds[scenario] = functools.reduce(lambda a, b: a + b, [ds[key] for key in keys]) / len(keys)
-if 'fire' in dataset or 'biomass' in dataset:
- scenarios = ['ssp245', 'ssp370', 'ssp585']
- ds = ds.sel(year=slice('2010', '2090'))
- targets = ds['year']
+if "fire" in dataset or "biomass" in dataset:
+ scenarios = ["ssp245", "ssp370", "ssp585"]
+ ds = ds.sel(year=slice("2010", "2090"))
+ targets = ds["year"]
a = np.concatenate([ds[scenario].values for scenario in scenarios], axis=0)
- if 'fire' in dataset:
+ if "fire" in dataset:
a = integrated_risk(a)
- if 'insects' in dataset or 'drought' in dataset:
+ if "insects" in dataset or "drought" in dataset:
a = a * 20
a[np.isnan(a)] = 0
@@ -66,32 +66,32 @@ def integrated_risk(p):
for s, scenario in enumerate(scenarios):
for y, year in enumerate(targets):
- key = str(s) + '_' + str(y)
+ key = str(s) + "_" + str(y)
a = ds[scenario].sel(year=year).values
- if 'fire' in dataset:
+ if "fire" in dataset:
a = integrated_risk(a)
- if 'insects' in dataset or 'drought' in dataset:
+ if "insects" in dataset or "drought" in dataset:
a = a * 20
a[np.isnan(a)] = 0
df[key] = np.round(a[r, c], precision)
-if 'insects' in dataset or 'drought' in dataset:
- a = ds['historical'].values
+if "insects" in dataset or "drought" in dataset:
+ a = ds["historical"].values
- if 'insects' in dataset or 'drought' in dataset:
+ if "insects" in dataset or "drought" in dataset:
a = a * 100 * 20
a[np.isnan(a)] = 0
r, c = np.nonzero(a)
lat, lon = utils.rowcol_to_latlon(r, c, res=res)
df = pd.DataFrame()
- key = '0_0'
+ key = "0_0"
a[np.isnan(a)] = 0
df = pd.DataFrame()
df[key] = np.round(a[r, c], precision)
gdf = gpd.GeoDataFrame(df, geometry=gpd.points_from_xy(lon, lat))
-gdf.to_file(f'data/{savename}.geojson', driver='GeoJSON')
+gdf.to_file(f"data/{savename}.geojson", driver="GeoJSON")
diff --git a/scripts/drought.py b/scripts/drought.py
index 272796b..0275747 100644
--- a/scripts/drought.py
+++ b/scripts/drought.py
@@ -8,41 +8,41 @@
args = sys.argv
if len(args) < 2:
- store = 'local'
+ store = "local"
else:
store = args[1]
-data_vars = ['ppt', 'tavg']
-data_aggs = ['sum', 'mean']
+data_vars = ["ppt", "tavg"]
+data_aggs = ["sum", "mean"]
-print('[drought] loading data')
-df = load.fia(store=store, states='conus', group_repeats=True)
+print("[drought] loading data")
+df = load.fia(store=store, states="conus", group_repeats=True)
df = load.terraclim(
store=store,
- tlim=(int(df['year_0'].min()), 2020),
+ tlim=(int(df["year_0"].min()), 2020),
data_vars=data_vars,
data_aggs=data_aggs,
df=df,
group_repeats=True,
)
-print('[drought] prepare for fitting')
+print("[drought] prepare for fitting")
x, y, pf = prepare.drought(df)
x_z, x_mean, x_std = utils.zscore_2d(x)
-codes = pf['type_code'].unique()
+codes = pf["type_code"].unique()
-print('[drought] fit models')
+print("[drought] fit models")
models = {}
for code in tqdm(codes):
- inds = pf['type_code'] == code
+ inds = pf["type_code"] == code
model = fit.hurdle(x=x_z[inds], y=y[inds])
models[code] = model
-print('[drought] preparing for evaluations')
-df = load.fia(store=store, states='conus')
-pf = df[['lat', 'lon', 'type_code']].copy().reset_index(drop=True)
+print("[drought] preparing for evaluations")
+df = load.fia(store=store, states="conus")
+pf = df[["lat", "lon", "type_code"]].copy().reset_index(drop=True)
-print('[drought] evaluating predictions on historical data')
+print("[drought] evaluating predictions on historical data")
df = load.terraclim(
store=store,
tlim=(2005, 2014),
@@ -55,19 +55,19 @@
for code in codes:
if code in models.keys():
model = models[code]
- inds = df['type_code'] == code
- pf.loc[inds, 'historical'] = model.predict(x=x_z[inds])
+ inds = df["type_code"] == code
+ pf.loc[inds, "historical"] = model.predict(x=x_z[inds])
-print('[drought] evaluating on future climate models')
+print("[drought] evaluating on future climate models")
targets = list(map(lambda x: str(x), np.arange(2020, 2120, 20)))
-cmip_models = ['BCC-CSM2-MR', 'ACCESS-ESM1-5', 'CanESM5', 'MIROC6', 'MPI-ESM1-2-LR']
-scenarios = ['ssp245', 'ssp370', 'ssp585']
+cmip_models = ["BCC-CSM2-MR", "ACCESS-ESM1-5", "CanESM5", "MIROC6", "MPI-ESM1-2-LR"]
+scenarios = ["ssp245", "ssp370", "ssp585"]
for it in tqdm(range(len(targets))):
target = targets[it]
tlim = (str(int(target) - 5), str(int(target) + 4))
for cmip_model in cmip_models:
for scenario in scenarios:
- key = cmip_model + '_' + scenario + '_' + target
+ key = cmip_model + "_" + scenario + "_" + target
df = load.cmip(
store=store,
tlim=(int(tlim[0]), int(tlim[1])),
@@ -84,9 +84,11 @@
for code in codes:
if code in models.keys():
model = models[code]
- inds = df['type_code'] == code
+ inds = df["type_code"] == code
pf.loc[inds, key] = model.predict(x=x_z[inds])
-pf['r2'] = pf['type_code'].map(lambda k: models[k].train_r2 if k in models.keys() else np.NaN)
+pf["r2"] = pf["type_code"].map(
+ lambda k: models[k].train_r2 if k in models.keys() else np.NaN
+)
-pf.to_parquet('data/drought.parquet', compression='gzip', engine='fastparquet')
+pf.to_parquet("data/drought.parquet", compression="gzip", engine="fastparquet")
diff --git a/scripts/export.py b/scripts/export.py
index d2c8cf7..689f0ab 100755
--- a/scripts/export.py
+++ b/scripts/export.py
@@ -10,86 +10,86 @@
from carbonplan_forest_risks import load
# parameters
-variables = ['ppt', 'tmean', 'pdsi', 'cwd', 'pet', 'vpd', 'rh']
+variables = ["ppt", "tmean", "pdsi", "cwd", "pet", "vpd", "rh"]
targets_future = list(map(lambda x: str(x), np.arange(2015, 2105, 10)))
targets_historical = list(map(lambda x: str(x), np.arange(1955, 2015, 10)))
targets_terraclimate = list(map(lambda x: str(x), np.arange(1965, 2020, 10)))
-prefix = 'az://carbonplan-scratch/forests'
-states = 'conus'
-version = 'v18'
-date = '05-03-2021'
+prefix = "az://carbonplan-scratch/forests"
+states = "conus"
+version = "v18"
+date = "05-03-2021"
def write_df(df, name):
- fname = f'{prefix}/{name}-{version}-{date}.csv'
- print('writing', fname)
+ fname = f"{prefix}/{name}-{version}-{date}.csv"
+ print("writing", fname)
with fsspec.open(
fname,
- 'w',
- account_name='carbonplan',
- account_key=os.environ['BLOB_ACCOUNT_KEY'],
+ "w",
+ account_name="carbonplan",
+ account_key=os.environ["BLOB_ACCOUNT_KEY"],
) as f:
df.to_csv(f, index=False)
def terraclimate_fia_wide():
# generate wide data w/ terraclim
- df_fia = load.fia(store='az', states=states, group_repeats=True)
+ df_fia = load.fia(store="az", states=states, group_repeats=True)
df = load.terraclim(
- store='az',
- tlim=(int(df_fia['year_0'].min()), 2020),
+ store="az",
+ tlim=(int(df_fia["year_0"].min()), 2020),
variables=variables,
df=df_fia,
group_repeats=True,
- sampling='annual',
+ sampling="annual",
)
- write_df(df, 'FIA-TerraClim-Wide')
+ write_df(df, "FIA-TerraClim-Wide")
def terraclimate_fia_long():
# generate long data w/ terraclim
- df_fia = load.fia(store='az', states=states, clean=False)
+ df_fia = load.fia(store="az", states=states, clean=False)
for target in targets_terraclimate:
tlim = (str(int(target) - 5), str(int(target) + 4))
print(tlim)
df = load.terraclim(
- store='az',
+ store="az",
tlim=(int(tlim[0]), int(tlim[1])),
variables=variables,
df=df_fia,
- sampling='annual',
+ sampling="annual",
)
- write_df(df, f'FIA-TerraClim-Long-{tlim[0]}.{tlim[1]}')
+ write_df(df, f"FIA-TerraClim-Long-{tlim[0]}.{tlim[1]}")
def cmip_fia_long(cmip_table, method):
# generate long data w/ cmip
- df_fia = load.fia(store='az', states=states, clean=False)
+ df_fia = load.fia(store="az", states=states, clean=False)
keep_vars = (
- ['lat', 'lon', 'plot_cn']
- + [var + '_min' for var in variables]
- + [var + '_mean' for var in variables]
- + [var + '_max' for var in variables]
+ ["lat", "lon", "plot_cn"]
+ + [var + "_min" for var in variables]
+ + [var + "_mean" for var in variables]
+ + [var + "_max" for var in variables]
)
for i, row in cmip_table.iterrows():
- if 'hist' in row.scenario:
+ if "hist" in row.scenario:
targets = targets_historical
else:
targets = targets_future
for target in targets:
- historical = target == '2015'
+ historical = target == "2015"
tlim = (str(int(target) - 5), str(int(target) + 4))
print(tlim, row)
df = load.cmip(
- store='az',
+ store="az",
tlim=(int(tlim[0]), int(tlim[1])),
variables=variables,
df=df_fia,
@@ -98,20 +98,20 @@ def cmip_fia_long(cmip_table, method):
member=row.member,
historical=historical,
method=method,
- sampling='annual',
+ sampling="annual",
)
df = df[keep_vars]
write_df(
df,
- f'{method}/FIA-CMIP6-Long-{row.model}.{row.scenario}.{row.member}-{tlim[0]}.{tlim[1]}',
+ f"{method}/FIA-CMIP6-Long-{row.model}.{row.scenario}.{row.member}-{tlim[0]}.{tlim[1]}",
)
-if __name__ == '__main__':
+if __name__ == "__main__":
df = get_cmip_runs(comp=True, unique=True).reset_index()
- with dask.config.set(scheduler='processes'):
+ with dask.config.set(scheduler="processes"):
with ProgressBar():
terraclimate_fia_long()
terraclimate_fia_wide()
- for method in ['quantile-mapping-v3']: # , 'bias-corrected']:
+ for method in ["quantile-mapping-v3"]: # , 'bias-corrected']:
cmip_fia_long(df, method=method)
diff --git a/scripts/fire.py b/scripts/fire.py
index 657bbb0..fd6190a 100644
--- a/scripts/fire.py
+++ b/scripts/fire.py
@@ -9,28 +9,30 @@
from carbonplan_forest_risks import collect, fit, load, prepare, utils
from carbonplan_forest_risks.utils import get_store
-warnings.simplefilter('ignore', category=RuntimeWarning)
-account_key = os.environ.get('BLOB_ACCOUNT_KEY')
+warnings.simplefilter("ignore", category=RuntimeWarning)
+account_key = os.environ.get("BLOB_ACCOUNT_KEY")
args = sys.argv
if len(args) < 2:
- store = 'local'
+ store = "local"
else:
store = args[1]
run_name = args[2]
- data_vars = args[3].strip('[]').split(',')
+ data_vars = args[3].strip("[]").split(",")
coarsen_fit = int(args[4])
coarsen_predict = int(args[5])
tlim = (1983, 2018)
-analysis_tlim = slice('1984', '2018')
+analysis_tlim = slice("1984", "2018")
-print('[fire] loading data')
-mask = (load.nlcd(store=store, year=2001).sel(band=[41, 42, 43, 90]).sum('band') > 0.25).astype(
- 'float'
+print("[fire] loading data")
+mask = (
+ load.nlcd(store=store, year=2001).sel(band=[41, 42, 43, 90]).sum("band") > 0.25
+).astype("float")
+nftd = load.nftd(
+ store=store, groups="all", coarsen=coarsen_fit, mask=mask, area_threshold=1500
)
-nftd = load.nftd(store=store, groups='all', coarsen=coarsen_fit, mask=mask, area_threshold=1500)
climate = load.terraclim(
store=store,
@@ -41,28 +43,30 @@
sampling="monthly",
)
mtbs = load.mtbs(store=store, coarsen=coarsen_fit, tlim=tlim, mask=mask)
-mtbs = mtbs.assign_coords({'x': nftd.x, 'y': nftd.y})
+mtbs = mtbs.assign_coords({"x": nftd.x, "y": nftd.y})
-print('[fire] fitting model')
-prepend = climate.sel(time=slice('1983', '1983'))
+print("[fire] fitting model")
+prepend = climate.sel(time=slice("1983", "1983"))
x, y = prepare.fire(
- climate.sel(time=slice('1984', '2018')),
+ climate.sel(time=slice("1984", "2018")),
nftd,
mtbs,
add_global_climate_trends={
- 'tmean': {'climate_prepend': prepend, 'rolling_period': 12},
- 'ppt': {'climate_prepend': prepend, 'rolling_period': 12},
+ "tmean": {"climate_prepend": prepend, "rolling_period": 12},
+ "ppt": {"climate_prepend": prepend, "rolling_period": 12},
},
add_local_climate_trends=None,
- analysis_tlim=slice('1984', '2018'),
+ analysis_tlim=slice("1984", "2018"),
)
x_z, x_mean, x_std = utils.zscore_2d(x)
model = fit.hurdle(x_z, y, log=False)
yhat = model.predict(x_z)
prediction = collect.fire(yhat, mtbs)
-print('[fire] evaluating on training data')
+print("[fire] evaluating on training data")
# reload everything at the appropriate coarsen level (in this case no coarsening)
-nftd = load.nftd(store=store, groups='all', mask=mask, coarsen=coarsen_predict, area_threshold=1500)
+nftd = load.nftd(
+ store=store, groups="all", mask=mask, coarsen=coarsen_predict, area_threshold=1500
+)
climate = load.terraclim(
store=store,
@@ -70,11 +74,11 @@
coarsen=coarsen_predict,
variables=data_vars,
mask=mask,
- sampling='monthly',
+ sampling="monthly",
)
for year in np.arange(1984, 2024, 10):
ds = xr.Dataset()
- print('[fire] evaluating on decade beginning in {}'.format(year))
+ print("[fire] evaluating on decade beginning in {}".format(year))
prepend_time_slice = slice(str(year - 1), str(year - 1))
analysis_time_slice = slice(str(year), str(year + 9))
prepend = climate.sel(time=prepend_time_slice)
@@ -83,8 +87,8 @@
nftd,
mtbs,
add_global_climate_trends={
- 'tmean': {'climate_prepend': prepend, 'rolling_period': 12},
- 'ppt': {'climate_prepend': prepend, 'rolling_period': 12},
+ "tmean": {"climate_prepend": prepend, "rolling_period": 12},
+ "ppt": {"climate_prepend": prepend, "rolling_period": 12},
},
add_local_climate_trends=None,
analysis_tlim=analysis_time_slice,
@@ -92,50 +96,50 @@
x_z = utils.zscore_2d(x, mean=x_mean, std=x_std)
yhat = model.predict(x_z)
prediction = collect.fire(yhat, climate.sel(time=analysis_time_slice))
- ds['historical'] = (['time', 'y', 'x'], prediction['prediction'])
+ ds["historical"] = (["time", "y", "x"], prediction["prediction"])
ds = ds.assign_coords(
{
- 'x': climate.x,
- 'y': climate.y,
- 'time': climate.sel(time=analysis_time_slice).time,
- 'lat': climate.lat,
- 'lon': climate.lon,
+ "x": climate.x,
+ "y": climate.y,
+ "time": climate.sel(time=analysis_time_slice).time,
+ "lat": climate.lat,
+ "lon": climate.lon,
}
)
- if store == 'local':
- ds.to_zarr('data/fire_historical.zarr', mode='w')
- elif store == 'az':
+ if store == "local":
+ ds.to_zarr("data/fire_historical.zarr", mode="w")
+ elif store == "az":
path = get_store(
- 'carbonplan-forests',
- 'risks/results/paper/fire_terraclimate_{}.zarr'.format(run_name),
+ "carbonplan-forests",
+ "risks/results/paper/fire_terraclimate_{}.zarr".format(run_name),
account_key=account_key,
)
if year == 1984:
- ds.to_zarr(path, consolidated=True, mode='w')
+ ds.to_zarr(path, consolidated=True, mode="w")
else:
- ds.to_zarr(path, consolidated=True, mode='a', append_dim='time')
-print('[fire] evaluating on future climate')
+ ds.to_zarr(path, consolidated=True, mode="a", append_dim="time")
+print("[fire] evaluating on future climate")
cmip_models = [
- ('CanESM5-CanOE', 'r3i1p2f1'),
- ('MIROC-ES2L', 'r1i1p1f2'),
- ('ACCESS-CM2', 'r1i1p1f1'),
- ('ACCESS-ESM1-5', 'r10i1p1f1'),
- ('MRI-ESM2-0', 'r1i1p1f1'),
- ('MPI-ESM1-2-LR', 'r10i1p1f1'),
+ ("CanESM5-CanOE", "r3i1p2f1"),
+ ("MIROC-ES2L", "r1i1p1f2"),
+ ("ACCESS-CM2", "r1i1p1f1"),
+ ("ACCESS-ESM1-5", "r10i1p1f1"),
+ ("MRI-ESM2-0", "r1i1p1f1"),
+ ("MPI-ESM1-2-LR", "r10i1p1f1"),
]
-scenarios = ['ssp245', 'ssp370', 'ssp585']
-for (cmip_model, member) in cmip_models:
+scenarios = ["ssp245", "ssp370", "ssp585"]
+for cmip_model, member in cmip_models:
for scenario in tqdm(scenarios):
results = []
climate = load.cmip(
store=store,
model=cmip_model,
coarsen=coarsen_predict,
- method='quantile-mapping-v3',
+ method="quantile-mapping-v3",
scenario=scenario,
- tlim=('1969', '2099'),
+ tlim=("1969", "2099"),
variables=data_vars,
- sampling='monthly',
+ sampling="monthly",
member=member,
historical=True,
mask=mask,
@@ -145,7 +149,9 @@
ds_future = xr.Dataset()
print(
- '[fire] conducting prediction for {} {} {}'.format(cmip_model, scenario, year)
+ "[fire] conducting prediction for {} {} {}".format(
+ cmip_model, scenario, year
+ )
)
prepend_time_slice = slice(str(year - 1), str(year - 1))
analysis_time_slice = slice(str(year), str(year + 9))
@@ -155,8 +161,8 @@
climate.sel(time=analysis_time_slice),
nftd,
add_global_climate_trends={
- 'tmean': {'climate_prepend': prepend, 'rolling_period': 12},
- 'ppt': {'climate_prepend': prepend, 'rolling_period': 12},
+ "tmean": {"climate_prepend": prepend, "rolling_period": 12},
+ "ppt": {"climate_prepend": prepend, "rolling_period": 12},
},
add_local_climate_trends=None,
eval_only=True,
@@ -165,34 +171,36 @@
x_z = utils.zscore_2d(x, mean=x_mean, std=x_std)
y_hat = model.predict(x_z)
prediction = collect.fire(y_hat, climate.sel(time=analysis_time_slice))
- ds_future[cmip_model + '_' + scenario] = (
- ['time', 'y', 'x'],
- prediction['prediction'],
+ ds_future[cmip_model + "_" + scenario] = (
+ ["time", "y", "x"],
+ prediction["prediction"],
)
ds_future = ds_future.assign_coords(
{
- 'x': climate.x,
- 'y': climate.y,
- 'time': climate.sel(time=analysis_time_slice).time,
- 'lat': climate.lat,
- 'lon': climate.lon,
+ "x": climate.x,
+ "y": climate.y,
+ "time": climate.sel(time=analysis_time_slice).time,
+ "lat": climate.lat,
+ "lon": climate.lon,
}
)
path = get_store(
- 'carbonplan-scratch',
- 'data/fire_future_{}_{}_{}.zarr'.format(run_name, cmip_model, scenario),
+ "carbonplan-scratch",
+ "data/fire_future_{}_{}_{}.zarr".format(
+ run_name, cmip_model, scenario
+ ),
account_key=account_key,
)
# if it's the first year then make a fresh store by overwriting; if it's later, append to existing file
if year == 1970:
- mode = 'w'
+ mode = "w"
append_dim = None
else:
- mode = 'a'
- append_dim = 'time'
+ mode = "a"
+ append_dim = "time"
ds_future.to_zarr(path, mode=mode, append_dim=append_dim)
print(
- '[fire] completed future run for {}-{} and year {}'.format(
+ "[fire] completed future run for {}-{} and year {}".format(
cmip_model, scenario, year
)
)
@@ -206,11 +214,18 @@
## combine all of the runs into a single zarr file for follow-on analysis
postprocess = True
-gcms = ['CanESM5-CanOE', 'MIROC-ES2L', 'ACCESS-CM2', 'ACCESS-ESM1-5', 'MRI-ESM2-0', 'MPI-ESM1-2-LR']
-scenarios = ['ssp245', 'ssp370', 'ssp585']
+gcms = [
+ "CanESM5-CanOE",
+ "MIROC-ES2L",
+ "ACCESS-CM2",
+ "ACCESS-ESM1-5",
+ "MRI-ESM2-0",
+ "MPI-ESM1-2-LR",
+]
+scenarios = ["ssp245", "ssp370", "ssp585"]
out_path = get_store(
- 'carbonplan-forests',
- 'risks/results/paper/fire_cmip_{}.zarr'.format(run_name),
+ "carbonplan-forests",
+ "risks/results/paper/fire_cmip_{}.zarr".format(run_name),
account_key=account_key,
)
@@ -220,17 +235,19 @@
scenario_list = []
for scenario in scenarios:
path = get_store(
- 'carbonplan-scratch',
- 'data/fire_future_{}_{}_{}.zarr'.format(run_name, gcm, scenario),
+ "carbonplan-scratch",
+ "data/fire_future_{}_{}_{}.zarr".format(run_name, gcm, scenario),
account_key=account_key,
)
scenario_list.append(
- xr.open_zarr(path).rename({'{}_{}'.format(gcm, scenario): 'probability'})
+ xr.open_zarr(path).rename(
+ {"{}_{}".format(gcm, scenario): "probability"}
+ )
)
- print('{} {} is done!'.format(scenario, gcm))
- ds = xr.concat(scenario_list, dim='scenario')
- ds = ds.assign_coords({'scenario': scenarios})
+ print("{} {} is done!".format(scenario, gcm))
+ ds = xr.concat(scenario_list, dim="scenario")
+ ds = ds.assign_coords({"scenario": scenarios})
gcm_list.append(ds)
- full_ds = xr.concat(gcm_list, dim='gcm')
- full_ds = full_ds.assign_coords({'gcm': gcms})
- full_ds.to_zarr(out_path, consolidated=True, mode='w')
+ full_ds = xr.concat(gcm_list, dim="gcm")
+ full_ds = full_ds.assign_coords({"gcm": gcms})
+ full_ds.to_zarr(out_path, consolidated=True, mode="w")
diff --git a/scripts/insects.py b/scripts/insects.py
index 5bf7fd1..0f765b8 100644
--- a/scripts/insects.py
+++ b/scripts/insects.py
@@ -8,42 +8,42 @@
args = sys.argv
if len(args) < 2:
- store = 'local'
+ store = "local"
else:
store = args[1]
-data_vars = ['ppt', 'tavg']
-data_aggs = ['sum', 'mean']
+data_vars = ["ppt", "tavg"]
+data_aggs = ["sum", "mean"]
-print('[insects] loading data')
-df = load.fia(store=store, states='conus', group_repeats=True)
+print("[insects] loading data")
+df = load.fia(store=store, states="conus", group_repeats=True)
df = load.terraclim(
store=store,
- tlim=(int(df['year_0'].min()), 2020),
+ tlim=(int(df["year_0"].min()), 2020),
data_vars=data_vars,
data_aggs=data_aggs,
df=df,
group_repeats=True,
)
-print('[insects] prepare for fitting')
+print("[insects] prepare for fitting")
x, y, pf = prepare.insects(df)
x_z, x_mean, x_std = utils.zscore_2d(x)
-codes = pf['type_code'].unique()
+codes = pf["type_code"].unique()
-print('[insects] fit models')
+print("[insects] fit models")
models = {}
for code in tqdm(codes):
- inds = pf['type_code'] == code
+ inds = pf["type_code"] == code
if (y[inds].sum() > 1) & (y[inds].sum() > 1):
model = fit.hurdle(x=x_z[inds], y=y[inds])
models[code] = model
-print('[insects] preparing for evaluations')
-df = load.fia(store=store, states='conus')
-pf = df[['lat', 'lon', 'type_code']].copy().reset_index(drop=True)
+print("[insects] preparing for evaluations")
+df = load.fia(store=store, states="conus")
+pf = df[["lat", "lon", "type_code"]].copy().reset_index(drop=True)
-print('[insects] evaluating predictions on historical data')
+print("[insects] evaluating predictions on historical data")
df = load.terraclim(
store=store,
tlim=(2005, 2014),
@@ -56,19 +56,19 @@
for code in codes:
if code in models.keys():
model = models[code]
- inds = df['type_code'] == code
- pf.loc[inds, 'historical'] = model.predict(x=x_z[inds])
+ inds = df["type_code"] == code
+ pf.loc[inds, "historical"] = model.predict(x=x_z[inds])
-print('[insects] evaluating on future climate models')
+print("[insects] evaluating on future climate models")
targets = list(map(lambda x: str(x), np.arange(2020, 2120, 20)))
-cmip_models = ['BCC-CSM2-MR', 'ACCESS-ESM1-5', 'CanESM5', 'MIROC6', 'MPI-ESM1-2-LR']
-scenarios = ['ssp245', 'ssp370', 'ssp585']
+cmip_models = ["BCC-CSM2-MR", "ACCESS-ESM1-5", "CanESM5", "MIROC6", "MPI-ESM1-2-LR"]
+scenarios = ["ssp245", "ssp370", "ssp585"]
for it in tqdm(range(len(targets))):
target = targets[it]
tlim = (str(int(target) - 5), str(int(target) + 4))
for cmip_model in cmip_models:
for scenario in scenarios:
- key = cmip_model + '_' + scenario + '_' + target
+ key = cmip_model + "_" + scenario + "_" + target
df = load.cmip(
store=store,
tlim=(int(tlim[0]), int(tlim[1])),
@@ -85,9 +85,11 @@
for code in codes:
if code in models.keys():
model = models[code]
- inds = df['type_code'] == code
+ inds = df["type_code"] == code
pf.loc[inds, key] = model.predict(x=x_z[inds])
-pf['r2'] = pf['type_code'].map(lambda k: models[k].train_r2 if k in models.keys() else np.NaN)
+pf["r2"] = pf["type_code"].map(
+ lambda k: models[k].train_r2 if k in models.keys() else np.NaN
+)
-pf.to_parquet('data/insects.parquet', compression='gzip', engine='fastparquet')
+pf.to_parquet("data/insects.parquet", compression="gzip", engine="fastparquet")
diff --git a/scripts/package_insects_drought.py b/scripts/package_insects_drought.py
index 34fa090..7162703 100644
--- a/scripts/package_insects_drought.py
+++ b/scripts/package_insects_drought.py
@@ -10,7 +10,7 @@
# flake8: noqa
-account_key = os.environ.get('BLOB_ACCOUNT_KEY')
+account_key = os.environ.get("BLOB_ACCOUNT_KEY")
# this is only used to provide the x/y template for the insects/drought tifs
grid_template = (
@@ -21,51 +21,55 @@
# # we'll pass a mask for when we do the webmap data prep
cmip_insect_url_template = "https://carbonplan.blob.core.windows.net/carbonplan-scratch/from-bill-05-03-2021/InsectProjections_Maps_5-5-21/InsectModelProjection_{}.{}.{}-{}.{}-v18climate_05-05-2021.tif"
da = load.impacts(cmip_insect_url_template, grid_template, mask=None) * 100
-out_path = get_store('carbonplan-forests', 'risks/results/paper/insects_cmip_v5.zarr')
+out_path = get_store("carbonplan-forests", "risks/results/paper/insects_cmip_v5.zarr")
ds = xr.Dataset()
-ds['probability'] = da.to_array(dim='vars').rename({'vars': 'gcm'})
-ds.to_zarr(out_path, mode='w', consolidated=True)
+ds["probability"] = da.to_array(dim="vars").rename({"vars": "gcm"})
+ds.to_zarr(out_path, mode="w", consolidated=True)
cmip_drought_url_template = "https://carbonplan.blob.core.windows.net/carbonplan-scratch/from-bill-05-03-2021/DroughtProjections_Maps_5-5-21/DroughtModelProjection_{}.{}.{}-{}.{}-v18climate_05-05-2021.tif"
da = load.impacts(cmip_drought_url_template, grid_template, mask=None) * 100
-out_path = get_store('carbonplan-forests', 'risks/results/paper/drought_cmip_v5.zarr')
+out_path = get_store("carbonplan-forests", "risks/results/paper/drought_cmip_v5.zarr")
ds = xr.Dataset()
-ds['probability'] = da.to_array(dim='vars').rename({'vars': 'gcm'})
-ds.to_zarr(out_path, mode='w', consolidated=True)
+ds["probability"] = da.to_array(dim="vars").rename({"vars": "gcm"})
+ds.to_zarr(out_path, mode="w", consolidated=True)
# load in historical runs to create drought_terraclimate and insects_terraclimate
terraclimate_insect_url_template = "https://carbonplan.blob.core.windows.net/carbonplan-scratch/from-bill-05-03-2021/Fig2_TerraClimateHistModels_4-22-21/InsectModel_ModeledTerraClimateFIAlong_{}-{}_04-22-2021.tif"
ds = xr.Dataset()
-ds['probability'] = (
+ds["probability"] = (
load.impacts(
terraclimate_insect_url_template,
grid_template,
mask=None,
period_start=1990,
period_end=2020,
- met_data='terraclimate',
+ met_data="terraclimate",
)
* 100
)
-out_path = get_store('carbonplan-forests', 'risks/results/paper/insects_terraclimate.zarr')
-ds.to_zarr(out_path, mode='w', consolidated=True)
+out_path = get_store(
+ "carbonplan-forests", "risks/results/paper/insects_terraclimate.zarr"
+)
+ds.to_zarr(out_path, mode="w", consolidated=True)
terraclimate_drought_url_template = "https://carbonplan.blob.core.windows.net/carbonplan-scratch/from-bill-05-03-2021/Fig2_TerraClimateHistModels_4-22-21/DroughtModel_ModeledTerraClimateFIAlong_{}-{}_04-22-2021.tif"
ds = xr.Dataset()
-ds['probability'] = (
+ds["probability"] = (
load.impacts(
terraclimate_drought_url_template,
grid_template,
mask=None,
period_start=1990,
period_end=2020,
- met_data='terraclimate',
+ met_data="terraclimate",
)
* 100
)
-out_path = get_store('carbonplan-forests', 'risks/results/paper/drought_terraclimate.zarr')
-ds.to_zarr(out_path, mode='w', consolidated=True)
+out_path = get_store(
+ "carbonplan-forests", "risks/results/paper/drought_terraclimate.zarr"
+)
+ds.to_zarr(out_path, mode="w", consolidated=True)
diff --git a/scripts/regrid.py b/scripts/regrid.py
index ace59ea..3e319cc 100644
--- a/scripts/regrid.py
+++ b/scripts/regrid.py
@@ -11,66 +11,69 @@
args = sys.argv
if len(args) < 2:
- raise ValueError('must specify dataset')
+ raise ValueError("must specify dataset")
dataset = args[1]
if len(args) == 2:
- store = 'local'
+ store = "local"
else:
store = args[2]
cmip_models = [
- 'CanESM5-CanOE',
- 'MIROC-ES2L',
- 'ACCESS-CM2',
- 'ACCESS-ESM1-5',
- 'MRI-ESM2-0',
- 'MPI-ESM1-2-LR',
+ "CanESM5-CanOE",
+ "MIROC-ES2L",
+ "ACCESS-CM2",
+ "ACCESS-ESM1-5",
+ "MRI-ESM2-0",
+ "MPI-ESM1-2-LR",
]
-scenarios = ['ssp245', 'ssp370', 'ssp585']
+scenarios = ["ssp245", "ssp370", "ssp585"]
targets = list(map(lambda x: str(x), np.arange(2010, 2100, 10)))
-pf = pd.read_parquet(f'data/{dataset}.parquet')
+pf = pd.read_parquet(f"data/{dataset}.parquet")
ds = xr.Dataset()
-print(f'[{dataset}] filtering values')
+print(f"[{dataset}] filtering values")
pf = pf.dropna().reset_index(drop=True)
-print(f'[{dataset}] computing multi model mean')
+print(f"[{dataset}] computing multi model mean")
for scenario in scenarios:
for target in targets:
keys = list(
filter(
lambda x: x is not None,
- [key if ((scenario in key) & (target in key)) else None for key in pf.columns],
+ [
+ key if ((scenario in key) & (target in key)) else None
+ for key in pf.columns
+ ],
)
)
- pf[scenario + '_' + target] = pf[keys].mean(axis=1)
+ pf[scenario + "_" + target] = pf[keys].mean(axis=1)
-print(f'[{dataset}] regridding predictions')
+print(f"[{dataset}] regridding predictions")
nlcd = load.nlcd(store=store, year=2016, classes=[41, 42, 43, 90])
-final_mask = nlcd.sum('band')
-final_mask.attrs['crs'] = nlcd.attrs['crs']
+final_mask = nlcd.sum("band")
+final_mask.attrs["crs"] = nlcd.attrs["crs"]
-if 'biomass' in dataset:
+if "biomass" in dataset:
final_mask.values = final_mask.values * (final_mask.values > 0.5)
else:
final_mask.values = final_mask.values > 0.5
-ds['historical'] = fit.interp(pf, final_mask, var='historical')
+ds["historical"] = fit.interp(pf, final_mask, var="historical")
for scenario in tqdm(scenarios):
results = []
for target in targets:
- key = scenario + '_' + target
+ key = scenario + "_" + target
gridded = fit.interp(pf, final_mask, var=key)
results.append(gridded)
- da = xr.concat(results, dim=xr.Variable('year', targets))
+ da = xr.concat(results, dim=xr.Variable("year", targets))
ds[scenario] = da
-account_key = os.environ.get('BLOB_ACCOUNT_KEY')
+account_key = os.environ.get("BLOB_ACCOUNT_KEY")
path = utils.get_store(
- 'carbonplan-forests', f'risks/results/web/{dataset}.zarr', account_key=account_key
+ "carbonplan-forests", f"risks/results/web/{dataset}.zarr", account_key=account_key
)
-ds.to_zarr(path, mode='w')
+ds.to_zarr(path, mode="w")
diff --git a/scripts/regrid_bill.py b/scripts/regrid_bill.py
index a217df8..de97d94 100644
--- a/scripts/regrid_bill.py
+++ b/scripts/regrid_bill.py
@@ -5,33 +5,33 @@
from carbonplan_forest_risks import fit, load, utils
-store = 'az'
+store = "az"
df = pd.read_csv(
- 'https://carbonplan.blob.core.windows.net/carbonplan-scratch/from-bill-04-14-2021/Fig1D_DroughtModel_ModeledFIAlongEnsembleHistMort_FIAlong_04-14-2021.csv'
+ "https://carbonplan.blob.core.windows.net/carbonplan-scratch/from-bill-04-14-2021/Fig1D_DroughtModel_ModeledFIAlongEnsembleHistMort_FIAlong_04-14-2021.csv"
)
pf = pd.DataFrame()
-pf['lat'] = df['V3']
-pf['lon'] = df['V2']
-pf['mortality'] = df['V6']
+pf["lat"] = df["V3"]
+pf["lon"] = df["V2"]
+pf["mortality"] = df["V6"]
pf = pf.dropna().reset_index(drop=True)
ds = xr.Dataset()
nlcd = load.nlcd(store=store, year=2016, classes=[41, 42, 43, 90])
-final_mask = nlcd.sum('band')
-final_mask.attrs['crs'] = nlcd.attrs['crs']
+final_mask = nlcd.sum("band")
+final_mask.attrs["crs"] = nlcd.attrs["crs"]
final_mask.values = final_mask.values > 0.5
-gridded = fit.interp(pf, final_mask, var='mortality')
+gridded = fit.interp(pf, final_mask, var="mortality")
-ds['historical'] = gridded
+ds["historical"] = gridded
-account_key = os.environ.get('BLOB_ACCOUNT_KEY')
+account_key = os.environ.get("BLOB_ACCOUNT_KEY")
path = utils.get_store(
- 'carbonplan-forests', 'risks/results/web/drought.zarr', account_key=account_key
+ "carbonplan-forests", "risks/results/web/drought.zarr", account_key=account_key
)
-ds.to_zarr(path, mode='w')
+ds.to_zarr(path, mode="w")
diff --git a/scripts/stats.py b/scripts/stats.py
index 06bada2..9acd165 100644
--- a/scripts/stats.py
+++ b/scripts/stats.py
@@ -31,16 +31,18 @@ def score(x, y, model, da, method):
b = b - b.mean()
spatial_r2 = 1 - np.sum((a - b) ** 2) / np.sum((a - np.mean(a)) ** 2)
- bias = (prediction['prediction'].mean().values - da.mean().values) / da.mean().values
+ bias = (
+ prediction["prediction"].mean().values - da.mean().values
+ ) / da.mean().values
return {
- 'method': method,
- 'roc': roc,
- 'r2': r2,
- 'annual_r2': annual_r2,
- 'seasonal_r2': seasonal_r2,
- 'spatial_r2': spatial_r2,
- 'bias': bias,
+ "method": method,
+ "roc": roc,
+ "r2": r2,
+ "annual_r2": annual_r2,
+ "seasonal_r2": seasonal_r2,
+ "spatial_r2": spatial_r2,
+ "bias": bias,
}
@@ -56,18 +58,18 @@ def crossval(x, y, selection, da, method):
return score(test_x, test_y, model, da[selection], method)
-def shuffle(x, y, da, method='months'):
- if 'months' in method:
- inds = np.arange(len(da['time'].values)).copy()
+def shuffle(x, y, da, method="months"):
+ if "months" in method:
+ inds = np.arange(len(da["time"].values)).copy()
np.random.shuffle(inds)
y = y.copy().reshape(da.shape)[inds].flatten()
- elif 'years' in method:
- years = pd.to_datetime(da['time'].values).year
+ elif "years" in method:
+ years = pd.to_datetime(da["time"].values).year
scrambled = years.unique().values.copy()
np.random.shuffle(scrambled)
inds = np.array([np.argwhere(years == y) for y in scrambled]).flatten()
y = y.copy().reshape(da.shape)[inds].flatten()
- elif 'all' in method:
+ elif "all" in method:
y = y.copy()
np.random.shuffle(y)
else:
@@ -86,10 +88,10 @@ def append(df, results):
variables = ["ppt", "tmean", "cwd"]
store = "az"
-print('[stats] loading data')
-mask = (load.nlcd(store=store, year=2001).sel(band=[41, 42, 43, 90]).sum('band') > 0.25).astype(
- 'float'
-)
+print("[stats] loading data")
+mask = (
+ load.nlcd(store=store, year=2001).sel(band=[41, 42, 43, 90]).sum("band") > 0.25
+).astype("float")
nftd = load.nftd(store=store, area_threshold=1500, coarsen=coarsen, mask=mask)
climate = load.terraclim(
store=store,
@@ -101,62 +103,64 @@ def append(df, results):
)
mtbs = load.mtbs(store=store, coarsen=coarsen, tlim=tlim, mask=mask)
-prepend = climate.sel(time=slice('1983', '1983'))
+prepend = climate.sel(time=slice("1983", "1983"))
x, y = prepare.fire(
- climate.sel(time=slice('1984', '2018')),
+ climate.sel(time=slice("1984", "2018")),
nftd,
mtbs,
add_global_climate_trends={
- 'tmean': {'climate_prepend': prepend, 'rolling_period': 12},
- 'ppt': {'climate_prepend': prepend, 'rolling_period': 12},
+ "tmean": {"climate_prepend": prepend, "rolling_period": 12},
+ "ppt": {"climate_prepend": prepend, "rolling_period": 12},
},
add_local_climate_trends=None,
- analysis_tlim=slice('1984', '2018'),
+ analysis_tlim=slice("1984", "2018"),
)
x_z, x_mean, x_std = utils.zscore_2d(x)
df = pd.DataFrame()
# same training and testing
-print('[stats] same training and testing')
+print("[stats] same training and testing")
model = fit.hurdle(x_z, y, log=False)
-results = score(x_z, y, model, mtbs['monthly'], 'training')
+results = score(x_z, y, model, mtbs["monthly"], "training")
df = append(df, results)
# cross validation
-years = pd.to_datetime(mtbs['time'].values).year
+years = pd.to_datetime(mtbs["time"].values).year
nruns = 10
-print('[stats] split halves cross validation')
+print("[stats] split halves cross validation")
for index in range(nruns):
scrambled = years.unique().values.copy()
np.random.shuffle(scrambled)
subset = scrambled[0 : round(len(scrambled) / 2)]
selection = [y in subset for y in years]
- results = crossval(x_z, y, selection, mtbs['monthly'], f'split_halves_{index}')
+ results = crossval(x_z, y, selection, mtbs["monthly"], f"split_halves_{index}")
df = append(df, results)
-print('[stats] extrapolation cross validation')
-for index, threshold in enumerate([2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014]):
+print("[stats] extrapolation cross validation")
+for index, threshold in enumerate(
+ [2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014]
+):
selection = years > threshold
- results = crossval(x_z, y, selection, mtbs['monthly'], f'extrapolate_{index}')
+ results = crossval(x_z, y, selection, mtbs["monthly"], f"extrapolate_{index}")
df = append(df, results)
-print('[stats] shuffling')
+print("[stats] shuffling")
for index in range(nruns):
- results = shuffle(x_z, y, mtbs['monthly'], f'shuffle_months_{index}')
+ results = shuffle(x_z, y, mtbs["monthly"], f"shuffle_months_{index}")
df = append(df, results)
for index in range(nruns):
- results = shuffle(x_z, y, mtbs['monthly'], f'shuffle_years_{index}')
+ results = shuffle(x_z, y, mtbs["monthly"], f"shuffle_years_{index}")
df = append(df, results)
for index in range(nruns):
- results = shuffle(x_z, y, mtbs['monthly'], f'shuffle_all_{index}')
+ results = shuffle(x_z, y, mtbs["monthly"], f"shuffle_all_{index}")
df = append(df, results)
-df = df[['method', 'roc', 'r2', 'annual_r2', 'seasonal_r2', 'spatial_r2', 'bias']]
+df = df[["method", "roc", "r2", "annual_r2", "seasonal_r2", "spatial_r2", "bias"]]
print(df)
-df.to_csv('fire_stats.csv')
+df.to_csv("fire_stats.csv")
diff --git a/scripts/website_prep.py b/scripts/website_prep.py
index 335097b..0d8416d 100644
--- a/scripts/website_prep.py
+++ b/scripts/website_prep.py
@@ -12,10 +12,10 @@
# flake8: noqa
-warnings.filterwarnings('ignore')
+warnings.filterwarnings("ignore")
-impacts_to_process = ['fire']
-account_key = os.environ.get('BLOB_ACCOUNT_KEY')
+impacts_to_process = ["fire"]
+account_key = os.environ.get("BLOB_ACCOUNT_KEY")
rolling = True
# specify the kind of mask you want to use
mask_for_website = True
@@ -34,8 +34,8 @@
for impact in impacts_to_process:
ds = xr.open_zarr(
get_store(
- 'carbonplan-forests',
- 'risks/results/web/{}_cmip_high_res.zarr'.format(impact),
+ "carbonplan-forests",
+ "risks/results/web/{}_cmip_high_res.zarr".format(impact),
account_key=account_key,
)
)
@@ -45,30 +45,34 @@
"y": website_mask.y,
}
)
- if impact == 'fire':
- ds = ds.groupby('time.year').sum().coarsen(year=10).mean().compute()
- ds = ds.assign_coords({'year': np.arange(1970, 2100, 10)})
+ if impact == "fire":
+ ds = ds.groupby("time.year").sum().coarsen(year=10).mean().compute()
+ ds = ds.assign_coords({"year": np.arange(1970, 2100, 10)})
ds = ds.rolling(year=2).mean().drop_sel(year=1970)
else:
- ds = ds.assign_coords({'year': np.arange(1970, 2100, 10)})
+ ds = ds.assign_coords({"year": np.arange(1970, 2100, 10)})
ds = ds.rolling(year=2).mean().drop_sel(year=1970)
- ds = ds.assign_coords({'year': list(map(lambda x: str(x), np.arange(1980, 2100, 10)))})
+ ds = ds.assign_coords(
+ {"year": list(map(lambda x: str(x), np.arange(1980, 2100, 10)))}
+ )
if mask_for_website:
ds = ds.where(website_mask)
# first write out the full ds which will be used for the article
out_path = get_store(
- 'carbonplan-forests',
- 'risks/results/web/{}_full.zarr'.format(impact),
+ "carbonplan-forests",
+ "risks/results/web/{}_full.zarr".format(impact),
account_key=account_key,
)
- ds.to_zarr(out_path, mode='w')
+ ds.to_zarr(out_path, mode="w")
# then write out the ensemble-mean (which will be used for the webmap)
- ds = ds.mean(dim='gcm').probability.to_dataset(dim='scenario')
+ ds = ds.mean(dim="gcm").probability.to_dataset(dim="scenario")
out_path = get_store(
- 'carbonplan-forests', 'risks/results/web/{}.zarr'.format(impact), account_key=account_key
+ "carbonplan-forests",
+ "risks/results/web/{}.zarr".format(impact),
+ account_key=account_key,
)
- ds.to_zarr(out_path, mode='w')
+ ds.to_zarr(out_path, mode="w")
diff --git a/tests/test_forests.py b/tests/test_forests.py
index 85b8916..74742a6 100644
--- a/tests/test_forests.py
+++ b/tests/test_forests.py
@@ -1,4 +1,4 @@
def test_version():
from carbonplan_forest_risks import version
- assert version != '0.0.0'
+ assert version != "0.0.0"