Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions public/api/ecoregion_harvest_summary.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"meta": {"source": "conus_render ph_*.tif harvest probability (TreeMap-based, ~3.1km Albers) zonal mean by EPA L3 ecoregion", "n_ecoregions": 74, "fields": ["p_harvest_any", "p_harvest_clearcut", "p_harvest_partial"], "note": "Per-EPA-Level-III-ecoregion mean harvest probability. P(any), P(stand-replacement), P(partial)."}, "ecoregions": {"7.1.8": {"name": "Coast Range", "l1": "MARINE WEST COAST FOREST", "npix": 88, "p_harvest_any": 0.6855, "p_harvest_clearcut": 0.6664, "p_harvest_partial": 0.4093}, "10.1.2": {"name": "Columbia Plateau", "l1": "NORTH AMERICAN DESERTS", "npix": 237, "p_harvest_any": 0.7404, "p_harvest_clearcut": 0.6895, "p_harvest_partial": 0.6791}, "6.2.9": {"name": "Blue Mountains", "l1": "NORTHWESTERN FORESTED MOUNTAINS", "npix": 1995, "p_harvest_any": 0.8558, "p_harvest_clearcut": 0.7079, "p_harvest_partial": 0.5734}, "10.1.8": {"name": "Snake River Plain", "l1": "NORTH AMERICAN DESERTS", "npix": 52, "p_harvest_any": 0.8771, "p_harvest_clearcut": 0.6755, "p_harvest_partial": 0.6054}, "10.1.5": {"name": "Central Basin and Range", "l1": "NORTH AMERICAN DESERTS", "npix": 376, "p_harvest_any": 0.8527, "p_harvest_clearcut": 0.6661, "p_harvest_partial": 0.649}, "6.2.3": {"name": "Columbia Mountains/Northern Rockies", "l1": "NORTHWESTERN FORESTED MOUNTAINS", "npix": 5482, "p_harvest_any": 0.891, "p_harvest_clearcut": 0.7376, "p_harvest_partial": 0.6727}, "6.2.15": {"name": "Idaho Batholith", "l1": "NORTHWESTERN FORESTED MOUNTAINS", "npix": 3474, "p_harvest_any": 0.8972, "p_harvest_clearcut": 0.8046, "p_harvest_partial": 0.3389}, "6.2.10": {"name": "Middle Rockies", "l1": "NORTHWESTERN FORESTED MOUNTAINS", "npix": 3376, "p_harvest_any": 0.8746, "p_harvest_clearcut": 0.6936, "p_harvest_partial": 0.5571}, "10.1.4": {"name": "Wyoming Basin", "l1": "NORTH AMERICAN DESERTS", "npix": 83, "p_harvest_any": 0.8839, "p_harvest_clearcut": 0.6822, "p_harvest_partial": 0.6237}, "6.2.13": {"name": "Wasatch and Uinta Mountains", "l1": "NORTHWESTERN FORESTED MOUNTAINS", "npix": 766, "p_harvest_any": 0.8777, "p_harvest_clearcut": 0.7222, "p_harvest_partial": 0.5169}, "7.1.7": {"name": "Strait of Georgia/Puget Lowland", "l1": "MARINE WEST COAST FOREST", "npix": 29, "p_harvest_any": 0.9203, "p_harvest_clearcut": 0.7488, "p_harvest_partial": 0.6828}, "10.1.6": {"name": "Colorado Plateaus", "l1": "NORTH AMERICAN DESERTS", "npix": 68, "p_harvest_any": 0.8909, "p_harvest_clearcut": 0.7392, "p_harvest_partial": 0.563}, "6.2.14": {"name": "Southern Rockies", "l1": "NORTHWESTERN FORESTED MOUNTAINS", "npix": 375, "p_harvest_any": 0.8932, "p_harvest_clearcut": 0.7705, "p_harvest_partial": 0.4755}, "9.4.2": {"name": "Central Great Plains", "l1": "GREAT PLAINS", "npix": 4589, "p_harvest_any": 0.7917, "p_harvest_clearcut": 0.7176, "p_harvest_partial": 0.4446}, "9.4.4": {"name": "Flint Hills", "l1": "GREAT PLAINS", "npix": 1677, "p_harvest_any": 0.7666, "p_harvest_clearcut": 0.7038, "p_harvest_partial": 0.4813}, "9.4.5": {"name": "Cross Timbers", "l1": "GREAT PLAINS", "npix": 5828, "p_harvest_any": 0.8277, "p_harvest_clearcut": 0.7258, "p_harvest_partial": 0.443}, "9.4.6": {"name": "Edwards Plateau", "l1": "GREAT PLAINS", "npix": 102, "p_harvest_any": 0.815, "p_harvest_clearcut": 0.7086, "p_harvest_partial": 0.3777}, "9.6.1": {"name": "Southern Texas Plains/Interior Plains and Hills with Xerophytic Shrub and Oak Forest", "l1": "GREAT PLAINS", "npix": 54, "p_harvest_any": 0.8578, "p_harvest_clearcut": 0.7951, "p_harvest_partial": 0.3}, "9.4.7": {"name": "Texas Blackland Prairies", "l1": "GREAT PLAINS", "npix": 2774, "p_harvest_any": 0.8338, "p_harvest_clearcut": 0.7447, "p_harvest_partial": 0.4065}, "8.3.8": {"name": "East Central Texas Plains", "l1": "EASTERN TEMPERATE FORESTS", "npix": 2789, "p_harvest_any": 0.834, "p_harvest_clearcut": 0.7589, "p_harvest_partial": 0.4062}, "9.5.1": {"name": "Western Gulf Coastal Plain", "l1": "GREAT PLAINS", "npix": 3788, "p_harvest_any": 0.8427, "p_harvest_clearcut": 0.7639, "p_harvest_partial": 0.3785}, "8.3.7": {"name": "South Central Plains", "l1": "EASTERN TEMPERATE FORESTS", "npix": 15297, "p_harvest_any": 0.8493, "p_harvest_clearcut": 0.769, "p_harvest_partial": 0.4243}, "8.4.8": {"name": "Ouachita Mountains", "l1": "EASTERN TEMPERATE FORESTS", "npix": 2702, "p_harvest_any": 0.841, "p_harvest_clearcut": 0.7618, "p_harvest_partial": 0.4422}, "8.4.7": {"name": "Arkansas Valley", "l1": "EASTERN TEMPERATE FORESTS", "npix": 2850, "p_harvest_any": 0.8362, "p_harvest_clearcut": 0.7444, "p_harvest_partial": 0.4451}, "8.4.6": {"name": "Boston Mountains", "l1": "EASTERN TEMPERATE FORESTS", "npix": 1433, "p_harvest_any": 0.8057, "p_harvest_clearcut": 0.742, "p_harvest_partial": 0.4419}, "8.4.5": {"name": "Ozark Highlands", "l1": "EASTERN TEMPERATE FORESTS", "npix": 9059, "p_harvest_any": 0.7961, "p_harvest_clearcut": 0.7167, "p_harvest_partial": 0.4513}, "6.2.7": {"name": "Cascades", "l1": "NORTHWESTERN FORESTED MOUNTAINS", "npix": 1161, "p_harvest_any": 0.8422, "p_harvest_clearcut": 0.7169, "p_harvest_partial": 0.5839}, "9.2.4": {"name": "Central Irregular Plains", "l1": "GREAT PLAINS", "npix": 8270, "p_harvest_any": 0.8148, "p_harvest_clearcut": 0.7092, "p_harvest_partial": 0.503}, "6.2.4": {"name": "Canadian Rockies", "l1": "NORTHWESTERN FORESTED MOUNTAINS", "npix": 1038, "p_harvest_any": 0.8973, "p_harvest_clearcut": 0.7032, "p_harvest_partial": 0.66}, "9.3.1": {"name": "Northwestern Glaciated Plains", "l1": "GREAT PLAINS", "npix": 298, "p_harvest_any": 0.8563, "p_harvest_clearcut": 0.6851, "p_harvest_partial": 0.5549}, "9.3.3": {"name": "Northwestern Great Plains", "l1": "GREAT PLAINS", "npix": 239, "p_harvest_any": 0.8825, "p_harvest_clearcut": 0.6672, "p_harvest_partial": 0.6462}, "8.3.4": {"name": "Piedmont", "l1": "EASTERN TEMPERATE FORESTS", "npix": 16733, "p_harvest_any": 0.8306, "p_harvest_clearcut": 0.7636, "p_harvest_partial": 0.4697}, "9.2.1": {"name": "Aspen Parkland/Northern Glaciated Plains", "l1": "GREAT PLAINS", "npix": 4548, "p_harvest_any": 0.8847, "p_harvest_clearcut": 0.6826, "p_harvest_partial": 0.6471}, "9.2.3": {"name": "Western Corn Belt Plains", "l1": "GREAT PLAINS", "npix": 20716, "p_harvest_any": 0.8587, "p_harvest_clearcut": 0.7203, "p_harvest_partial": 0.6268}, "9.2.2": {"name": "Lake Manitoba and Lake Agassiz Plain", "l1": "GREAT PLAINS", "npix": 1407, "p_harvest_any": 0.8934, "p_harvest_clearcut": 0.6899, "p_harvest_partial": 0.6577}, "5.2.2": {"name": "Northern Minnesota Wetlands", "l1": "NORTHERN FORESTS", "npix": 35, "p_harvest_any": 0.8999, "p_harvest_clearcut": 0.7103, "p_harvest_partial": 0.6537}, "6.2.12": {"name": "Sierra Nevada", "l1": "NORTHWESTERN FORESTED MOUNTAINS", "npix": 1589, "p_harvest_any": 0.8563, "p_harvest_clearcut": 0.7299, "p_harvest_partial": 0.4779}, "5.2.1": {"name": "Northern Lakes and Forests", "l1": "NORTHERN FORESTS", "npix": 14416, "p_harvest_any": 0.8949, "p_harvest_clearcut": 0.7292, "p_harvest_partial": 0.653}, "8.1.4": {"name": "North Central Hardwood Forests", "l1": "EASTERN TEMPERATE FORESTS", "npix": 8798, "p_harvest_any": 0.8987, "p_harvest_clearcut": 0.7313, "p_harvest_partial": 0.6516}, "8.1.5": {"name": "Driftless Area", "l1": "EASTERN TEMPERATE FORESTS", "npix": 4774, "p_harvest_any": 0.8901, "p_harvest_clearcut": 0.7237, "p_harvest_partial": 0.6192}, "8.2.1": {"name": "Southeastern Wisconsin Till Plains", "l1": "EASTERN TEMPERATE FORESTS", "npix": 3153, "p_harvest_any": 0.8965, "p_harvest_clearcut": 0.7276, "p_harvest_partial": 0.6377}, "8.2.3": {"name": "Central Corn Belt Plains", "l1": "EASTERN TEMPERATE FORESTS", "npix": 5177, "p_harvest_any": 0.8476, "p_harvest_clearcut": 0.7049, "p_harvest_partial": 0.6213}, "8.2.4": {"name": "Eastern Corn Belt Plains", "l1": "EASTERN TEMPERATE FORESTS", "npix": 6581, "p_harvest_any": 0.8161, "p_harvest_clearcut": 0.7128, "p_harvest_partial": 0.5754}, "8.1.6": {"name": "Southern Michigan/Northern Indiana Drift Plains", "l1": "EASTERN TEMPERATE FORESTS", "npix": 5367, "p_harvest_any": 0.8784, "p_harvest_clearcut": 0.7273, "p_harvest_partial": 0.631}, "8.2.2": {"name": "Huron/Erie Lake Plains", "l1": "EASTERN TEMPERATE FORESTS", "npix": 3141, "p_harvest_any": 0.8925, "p_harvest_clearcut": 0.7286, "p_harvest_partial": 0.6327}, "5.3.1": {"name": "Northern Appalachian and Atlantic Maritime Highlands", "l1": "NORTHERN FORESTS", "npix": 8678, "p_harvest_any": 0.8751, "p_harvest_clearcut": 0.7145, "p_harvest_partial": 0.636}, "8.1.7": {"name": "Northeastern Coastal Zone", "l1": "EASTERN TEMPERATE FORESTS", "npix": 4088, "p_harvest_any": 0.8314, "p_harvest_clearcut": 0.6941, "p_harvest_partial": 0.6348}, "11.1.1": {"name": "California Coastal Sage, Chaparral, and Oak Woodlands", "l1": "MEDITERRANEAN CALIFORNIA", "npix": 1254, "p_harvest_any": 0.8298, "p_harvest_clearcut": 0.7104, "p_harvest_partial": 0.415}, "8.1.3": {"name": "Northern Allegheny Plateau", "l1": "EASTERN TEMPERATE FORESTS", "npix": 4686, "p_harvest_any": 0.8555, "p_harvest_clearcut": 0.7255, "p_harvest_partial": 0.6347}, "8.1.10": {"name": "Erie Drift Plain", "l1": "EASTERN TEMPERATE FORESTS", "npix": 3090, "p_harvest_any": 0.792, "p_harvest_clearcut": 0.6875, "p_harvest_partial": 0.6268}, "5.3.3": {"name": "North Central Appalachians", "l1": "NORTHERN FORESTS", "npix": 2652, "p_harvest_any": 0.8505, "p_harvest_clearcut": 0.71, "p_harvest_partial": 0.6362}, "8.5.1": {"name": "Middle Atlantic Coastal Plain", "l1": "EASTERN TEMPERATE FORESTS", "npix": 7539, "p_harvest_any": 0.8651, "p_harvest_clearcut": 0.7681, "p_harvest_partial": 0.4681}, "8.3.1": {"name": "Northern Piedmont", "l1": "EASTERN TEMPERATE FORESTS", "npix": 2904, "p_harvest_any": 0.807, "p_harvest_clearcut": 0.6964, "p_harvest_partial": 0.4704}, "8.3.5": {"name": "Southeastern Plains", "l1": "EASTERN TEMPERATE FORESTS", "npix": 33192, "p_harvest_any": 0.8554, "p_harvest_clearcut": 0.7682, "p_harvest_partial": 0.4411}, "8.4.4": {"name": "Blue Ridge", "l1": "EASTERN TEMPERATE FORESTS", "npix": 4678, "p_harvest_any": 0.8474, "p_harvest_clearcut": 0.7787, "p_harvest_partial": 0.4121}, "8.4.1": {"name": "Ridge and Valley", "l1": "EASTERN TEMPERATE FORESTS", "npix": 11353, "p_harvest_any": 0.8237, "p_harvest_clearcut": 0.7367, "p_harvest_partial": 0.4904}, "8.4.9": {"name": "Southwestern Appalachians", "l1": "EASTERN TEMPERATE FORESTS", "npix": 3825, "p_harvest_any": 0.8398, "p_harvest_clearcut": 0.7628, "p_harvest_partial": 0.4007}, "8.4.2": {"name": "Central Appalachians", "l1": "EASTERN TEMPERATE FORESTS", "npix": 6150, "p_harvest_any": 0.8249, "p_harvest_clearcut": 0.7352, "p_harvest_partial": 0.4817}, "11.1.2": {"name": "Central California Valley", "l1": "MEDITERRANEAN CALIFORNIA", "npix": 13, "p_harvest_any": 0.8438, "p_harvest_clearcut": 0.7218, "p_harvest_partial": 0.4405}, "8.4.3": {"name": "Western Allegheny Plateau", "l1": "EASTERN TEMPERATE FORESTS", "npix": 7825, "p_harvest_any": 0.8212, "p_harvest_clearcut": 0.7226, "p_harvest_partial": 0.5033}, "8.3.3": {"name": "Interior Plateau", "l1": "EASTERN TEMPERATE FORESTS", "npix": 12006, "p_harvest_any": 0.8399, "p_harvest_clearcut": 0.7461, "p_harvest_partial": 0.4433}, "8.3.2": {"name": "Interior River Valleys and Hills", "l1": "EASTERN TEMPERATE FORESTS", "npix": 7524, "p_harvest_any": 0.7914, "p_harvest_clearcut": 0.7141, "p_harvest_partial": 0.5064}, "8.5.2": {"name": "Mississippi Alluvial Plain", "l1": "EASTERN TEMPERATE FORESTS", "npix": 10875, "p_harvest_any": 0.8505, "p_harvest_clearcut": 0.7645, "p_harvest_partial": 0.4141}, "8.3.6": {"name": "Mississippi Valley Loess Plains", "l1": "EASTERN TEMPERATE FORESTS", "npix": 5232, "p_harvest_any": 0.8519, "p_harvest_clearcut": 0.7706, "p_harvest_partial": 0.4112}, "8.5.3": {"name": "Southern Coastal Plain", "l1": "EASTERN TEMPERATE FORESTS", "npix": 14281, "p_harvest_any": 0.8407, "p_harvest_clearcut": 0.778, "p_harvest_partial": 0.3827}, "15.4.1": {"name": "Southern Florida Coastal Plain", "l1": "TROPICAL WET FORESTS", "npix": 2127, "p_harvest_any": 0.8369, "p_harvest_clearcut": 0.7807, "p_harvest_partial": 0.3188}, "6.2.5": {"name": "North Cascades", "l1": "NORTHWESTERN FORESTED MOUNTAINS", "npix": 1072, "p_harvest_any": 0.8669, "p_harvest_clearcut": 0.6875, "p_harvest_partial": 0.649}, "6.2.11": {"name": "Klamath Mountains", "l1": "NORTHWESTERN FORESTED MOUNTAINS", "npix": 125, "p_harvest_any": 0.9018, "p_harvest_clearcut": 0.8752, "p_harvest_partial": 0.1314}, "11.1.3": {"name": "Southern and Baja California Pine-Oak Mountains", "l1": "MEDITERRANEAN CALIFORNIA", "npix": 6, "p_harvest_any": 0.7345, "p_harvest_clearcut": 0.6701, "p_harvest_partial": 0.1953}, "10.1.3": {"name": "Northern Basin and Range", "l1": "NORTH AMERICAN DESERTS", "npix": 672, "p_harvest_any": 0.8724, "p_harvest_clearcut": 0.664, "p_harvest_partial": 0.6511}, "8.1.8": {"name": "Acadian Plains and Hills", "l1": "EASTERN TEMPERATE FORESTS", "npix": 3578, "p_harvest_any": 0.8829, "p_harvest_clearcut": 0.7008, "p_harvest_partial": 0.6514}, "8.1.1": {"name": "Eastern Great Lakes Lowlands", "l1": "EASTERN TEMPERATE FORESTS", "npix": 4094, "p_harvest_any": 0.8857, "p_harvest_clearcut": 0.7243, "p_harvest_partial": 0.6443}, "8.5.4": {"name": "Atlantic Coastal Pine Barrens", "l1": "EASTERN TEMPERATE FORESTS", "npix": 1139, "p_harvest_any": 0.8296, "p_harvest_clearcut": 0.7213, "p_harvest_partial": 0.5137}, "6.2.8": {"name": "Eastern Cascades Slopes and Foothills", "l1": "NORTHWESTERN FORESTED MOUNTAINS", "npix": 1100, "p_harvest_any": 0.8505, "p_harvest_clearcut": 0.7409, "p_harvest_partial": 0.5059}}}
45 changes: 45 additions & 0 deletions scripts/build_ecoregion_harvest_summary.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
#!/usr/bin/env python3
"""Zonal-mean the CONUS harvest-probability rasters by EPA Level III ecoregion.

Inputs (on Cardinal, ~/conus_render/): ph_any.tif, ph_clearcut.tif,
ph_partial.tif — single-band float32 P(harvest) at ~3.1 km Albers, plus the
EPA L3 polygons (public/geo/us_eco_l3_features.geojson, WGS84).
Output: public/api/ecoregion_harvest_summary.json (mean P by L3 code).

Run: python3 scripts/build_ecoregion_harvest_summary.py (needs rasterio, pyproj)
The .tif inputs are not committed (each ~6.8 MB); pull from Cardinal first.
"""
import json, numpy as np, rasterio, sys
from rasterio.features import rasterize
from pyproj import Transformer
ALBERS="+proj=aea +lat_1=29.5 +lat_2=45.5 +lat_0=37.5 +lon_0=-96 +x_0=0 +y_0=0 +datum=NAD83 +units=m +no_defs"
GEO=sys.argv[1] if len(sys.argv)>1 else "public/geo/us_eco_l3_features.geojson"
tr=Transformer.from_crs("EPSG:4326",ALBERS,always_xy=True)
def reproj(g):
def rc(c): return [rc(x) if isinstance(x[0],(list,tuple)) else list(tr.transform(x[0],x[1])) for x in c]
return {"type":g["type"],"coordinates":rc(g["coordinates"])}
gj=json.load(open(GEO)); feats=gj["features"]; codes={}; meta={}
for f in feats:
p=f["properties"]; code=p.get("NA_L3CODE")
if code is None: continue
if code not in codes: codes[code]=len(codes)+1; meta[code]={"name":p.get("NA_L3NAME"),"l1":p.get("NA_L1NAME")}
shapes=[(reproj(f["geometry"]),codes[f["properties"]["NA_L3CODE"]]) for f in feats
if f["properties"].get("NA_L3CODE") and f.get("geometry")]
with rasterio.open("ph_any.tif") as r: transform=r.transform; H,W=r.height,r.width
zone=rasterize(shapes,out_shape=(H,W),transform=transform,fill=0,dtype="int32"); K=len(codes)+1
fields={"p_harvest_any":"ph_any.tif","p_harvest_clearcut":"ph_clearcut.tif","p_harvest_partial":"ph_partial.tif"}
band={}
for key,fn in fields.items():
with rasterio.open(fn) as r: a=r.read(1).astype("float64"); nod=r.nodata
valid=np.isfinite(a)&(zone>0)
if nod is not None: valid&=(a!=nod)
band[key]=(np.bincount(zone[valid],weights=a[valid],minlength=K),np.bincount(zone[valid],minlength=K))
inv={v:k for k,v in codes.items()}; out={}
for i in range(1,K):
if band["p_harvest_any"][1][i]<5: continue
code=inv[i]; rec={"name":meta[code]["name"],"l1":meta[code]["l1"],"npix":int(band["p_harvest_any"][1][i])}
for key in fields:
s,cc=band[key]; rec[key]=round(float(s[i]/cc[i]),4) if cc[i]>0 else None
out[code]=rec
json.dump({"meta":{"source":"conus_render ph_*.tif harvest probability (TreeMap-based, ~3.1km Albers) zonal mean by EPA L3 ecoregion","n_ecoregions":len(out),"fields":list(fields.keys()),"note":"Per-EPA-Level-III-ecoregion mean harvest probability. P(any), P(stand-replacement), P(partial)."},"ecoregions":out},open("public/api/ecoregion_harvest_summary.json","w"))
print("wrote", len(out), "ecoregions")
7 changes: 6 additions & 1 deletion src/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import StumpagePanel from "./StumpagePanel.jsx";
import LandisStratified from "./LandisStratified.jsx";
import LandownerYields from "./LandownerYields.jsx";
import FaustmannRotation from "./FaustmannRotation.jsx";
import EcoregionHarvest from "./EcoregionHarvest.jsx";
import AOIReport from "./AOIReport.jsx";
import { findFeature, agbAtAge, polygonCentroid, polygonAreaM2, pointInGeometry } from "./geo.js";
import { ownershipComposition, riskSummary, forestFraction, forestTypeDiversity, rampRelative, rampValues, median, percentile } from "./rasterSample.js";
Expand Down Expand Up @@ -471,6 +472,7 @@ export default function App(){
const [landis,setLandis] = useState(null);
const [landowner,setLandowner] = useState(null);
const [faustmann,setFaustmann] = useState(null);
const [ecoHarvest,setEcoHarvest] = useState(null);
// v1.3 map/AOI tools
const [ecoOn,setEcoOn] = useState(false);
const [ecoGeo,setEcoGeo] = useState(null);
Expand Down Expand Up @@ -499,6 +501,7 @@ export default function App(){
j("api/landis_stratified.json").then(setLandis).catch(()=>{});
j("api/landowner_yields.json").then(setLandowner).catch(()=>{});
j("api/faustmann_rotation.json").then(setFaustmann).catch(()=>{});
j("api/ecoregion_harvest_summary.json").then(setEcoHarvest).catch(()=>{});
geo.features.forEach(ft=>{ const st=ft.properties.state; const c=s[st];
ft.properties.engines = c ? c.engines : 0;
ft.properties.hasSeries = (c && c.has_series) ? 1 : 0;
Expand Down Expand Up @@ -1403,12 +1406,13 @@ export default function App(){
{(!aoi || researchOpen) && <div className="tabs">
{[["engines","Engine compare"],["rd","RD trend"],["divergence","Engine spread"],
["stumpage","Stumpage"],["landis","LANDIS stratified"],
["landowner","Landowner yields"],["faustmann","Faustmann rotation"]].map(([k,lbl])=>{
["landowner","Landowner yields"],["faustmann","Faustmann rotation"],["ecoharvest","Ecoregion harvest"]].map(([k,lbl])=>{
const disabled = (k==="divergence" && !divergence)
|| (k==="stumpage" && !(stumpage && stumpage.series && stumpage.series[sel]))
|| (k==="landis" && !(landis && landis[sel]))
|| (k==="landowner" && !(landowner && landowner[sel]))
|| (k==="faustmann" && !(faustmann && faustmann[sel]))
|| (k==="ecoharvest" && !ecoHarvest)
|| ((k==="engines"||k==="rd") && !series);
return <button key={k} className={"tab"+(tab===k?" on":"")} disabled={disabled}
onClick={()=>setTab(k)} title={disabled?"no data for this state":lbl}>{lbl}</button>;
Expand All @@ -1426,6 +1430,7 @@ export default function App(){
{(!aoi || researchOpen) && tab==="landis" && <LandisStratified data={landis} state={sel}/>}
{(!aoi || researchOpen) && tab==="landowner" && <LandownerYields data={landowner} state={sel}/>}
{(!aoi || researchOpen) && tab==="faustmann" && <FaustmannRotation data={faustmann} state={sel}/>}
{(!aoi || researchOpen) && tab==="ecoharvest" && <EcoregionHarvest data={ecoHarvest}/>}
{(!aoi || researchOpen) && (tab==="engines"||tab==="rd") && (<>
{LANDIS_STATES.includes(sel) && (
<div className="controls" style={{margin:"0 4px 8px"}}>
Expand Down
Loading