From d8d8ea186f3e2db0e74f3fa3a8d6e116d7cbc8c3 Mon Sep 17 00:00:00 2001 From: davemfish Date: Fri, 10 Nov 2023 16:36:24 -0500 Subject: [PATCH] read LULC names & colors from frontend data data. --- frontend/src/edit/edit.jsx | 14 +++++++++- frontend/src/edit/scenarioTable.jsx | 39 ++++++++++++++++++---------- frontend/src/edit/studyAreaTable.jsx | 12 ++++++++- frontend/src/map/legendControl.jsx | 13 ++++++++-- frontend/src/map/lulcLayer.js | 11 +++++--- scripts/lulc_crosswalk.py | 34 +++--------------------- server/sql_app/crud.py | 21 +++------------ server/sql_app/models.py | 6 +---- 8 files changed, 74 insertions(+), 76 deletions(-) diff --git a/frontend/src/edit/edit.jsx b/frontend/src/edit/edit.jsx index d25ddb0..907ceb6 100644 --- a/frontend/src/edit/edit.jsx +++ b/frontend/src/edit/edit.jsx @@ -15,6 +15,16 @@ import InvestRunner from './investRunner'; import Results from './results'; import { getInvestResults } from '../requests'; +import nlcdLookup from '../../../appdata/nlcd_colormap.json'; +import nludLookup from '../../../appdata/nlud_colormap.json'; +import treeLookup from '../../../appdata/tree_colormap.json'; + +const LULC_LOOKUP = { + nlcd: nlcdLookup, + nlud: nludLookup, + tree: treeLookup, +}; + FocusStyleManager.onlyShowFocusOnTabs(); export default function EditMenu(props) { @@ -84,7 +94,9 @@ export default function EditMenu(props) { i++; } const topClasses = sortedClasses.slice(0, i); - descriptions[scenario.name][lulcType] = topClasses; + descriptions[scenario.name][lulcType] = topClasses.map( + (code) => LULC_LOOKUP[lulcType][code].name + ); }); }); setScenarioDescriptions(descriptions); diff --git a/frontend/src/edit/scenarioTable.jsx b/frontend/src/edit/scenarioTable.jsx index b530d6c..18c8f15 100644 --- a/frontend/src/edit/scenarioTable.jsx +++ b/frontend/src/edit/scenarioTable.jsx @@ -7,7 +7,15 @@ import { } from '@blueprintjs/core'; import { toAcres } from '../utils'; -import landuseCodes from '../../../appdata/lulc_crosswalk.json'; +import nlcdLookup from '../../../appdata/nlcd_colormap.json'; +import nludLookup from '../../../appdata/nlud_colormap.json'; +import treeLookup from '../../../appdata/tree_colormap.json'; + +const LULC_LOOKUP = { + nlcd: nlcdLookup, + nlud: nludLookup, + tree: treeLookup, +}; const LULC_TYPES = { 'nlcd': 'landcover', @@ -68,34 +76,37 @@ export default function ScenarioTable(props) { const rows = []; rows.push(scenarioHeader); - let categories; + let codes; switch (lulcType) { case 'nlcd': - categories = landcoverTypes; + codes = landcoverTypes; break; case 'nlud': - categories = landuseTypes; + codes = landuseTypes; break; case 'tree': - categories = treeTypes; + codes = treeTypes; break; default: - categories = []; + codes = []; } - categories.forEach((category) => { + codes.forEach((code) => { const counts = []; - Object.entries(scenarioTable).forEach(([name, table]) => { - const count = table[lulcType][category] || ''; + Object.entries(scenarioTable).forEach(([x, table]) => { + const count = table[lulcType][code] || ''; counts.push(count); }); if (counts.reduce((x, y) => (x || 0) + (y || 0), 0)) { // skip rows of all 0s const cells = []; cells.push( - - {category} + {LULC_LOOKUP[lulcType][code].name} ); cells.push(...counts.map((c, idx) => { @@ -105,7 +116,7 @@ export default function ScenarioTable(props) { } return {content}; })); - rows.push({cells}); + rows.push({cells}); } }); diff --git a/frontend/src/edit/studyAreaTable.jsx b/frontend/src/edit/studyAreaTable.jsx index e2ad985..2fbad1f 100644 --- a/frontend/src/edit/studyAreaTable.jsx +++ b/frontend/src/edit/studyAreaTable.jsx @@ -8,6 +8,15 @@ import { import { removeParcel } from '../requests'; import { toAcres } from '../utils'; +import nlcdLookup from '../../../appdata/nlcd_colormap.json'; +import nludLookup from '../../../appdata/nlud_colormap.json'; +import treeLookup from '../../../appdata/tree_colormap.json'; + +const LULC_LOOKUP = { + nlcd: nlcdLookup, + nlud: nludLookup, + tree: treeLookup, +}; const LULC_TYPES = { 'nlcd': 'landcover', @@ -73,7 +82,8 @@ export default function StudyAreaTable(props) { const data = JSON.parse(parcel.parcel_stats.lulc_stats); if (!data) { return; } const sorted = sortCounts(data[lulcType]); - rows.push(sorted.map(([label, count], i) => { + rows.push(sorted.map(([code, count], i) => { + const label = LULC_LOOKUP[lulcType][code].name; let header = ; let address = ; let rowClass = ''; diff --git a/frontend/src/map/legendControl.jsx b/frontend/src/map/legendControl.jsx index 312e1d8..b0ece9f 100644 --- a/frontend/src/map/legendControl.jsx +++ b/frontend/src/map/legendControl.jsx @@ -3,6 +3,15 @@ import React, { useState } from 'react'; import { HTMLSelect } from '@blueprintjs/core'; import landuseCodes from '../../../appdata/lulc_crosswalk.json'; +import nlcdLookup from '../../../appdata/nlcd_colormap.json'; +import nludLookup from '../../../appdata/nlud_colormap.json'; +import treeLookup from '../../../appdata/tree_colormap.json'; + +const LULC_LOOKUP = { + nlcd: nlcdLookup, + nlud: nludLookup, + tree: treeLookup, +}; const LULC_TYPES = { 'nlcd': 'landcover', @@ -44,14 +53,14 @@ export default function LegendControl(props) { <>
- {landuseCodes[lulcCode][lulcType].name} + {LULC_LOOKUP[lulcType][landuseCodes[lulcCode][lulcType]].name} ) :
diff --git a/frontend/src/map/lulcLayer.js b/frontend/src/map/lulcLayer.js index 3663a0d..a908c32 100644 --- a/frontend/src/map/lulcLayer.js +++ b/frontend/src/map/lulcLayer.js @@ -1,20 +1,23 @@ import GeoTIFF from 'ol/source/GeoTIFF'; import TileLayer from 'ol/layer/WebGLTile'; -import landuseCodes from '../../../appdata/lulc_crosswalk.json'; import { publicUrl } from '../utils'; +import landuseCodes from '../../../appdata/lulc_crosswalk.json'; +import nlcdLookup from '../../../appdata/nlcd_colormap.json'; +import nludLookup from '../../../appdata/nlud_colormap.json'; +import treeLookup from '../../../appdata/tree_colormap.json'; const nlcdColors = Array(3000).fill('#000000'); const nludColors = Array(3000).fill('#000000'); const treeColors = Array(3000).fill('#000000'); Object.entries(landuseCodes).forEach(([code, data]) => { - nlcdColors[code] = data.nlcd.color; + nlcdColors[code] = nlcdLookup[data.nlcd].color; }); Object.entries(landuseCodes).forEach(([code, data]) => { - nludColors[code] = data.nlud.color; + nludColors[code] = nludLookup[data.nlud].color; }); Object.entries(landuseCodes).forEach(([code, data]) => { - treeColors[code] = data.tree.color; + treeColors[code] = treeLookup[data.tree].color; }); // keys here match 'title' passed to lulcTileLayer diff --git a/scripts/lulc_crosswalk.py b/scripts/lulc_crosswalk.py index ad2346b..120657d 100644 --- a/scripts/lulc_crosswalk.py +++ b/scripts/lulc_crosswalk.py @@ -2,42 +2,14 @@ import pandas df = pandas.read_csv('../appdata/lulc_crosswalk.csv') - - -def construct_nlud_names(row): - name = '' - if row.nlud_simple_class: - name += row.nlud_simple_class - if row.nlud_simple_subclass: - name += f' ({row.nlud_simple_subclass})' - return name - - df = df.fillna('') -df['nlud_name'] = df.apply(construct_nlud_names, axis=1) - -with open('../appdata/nlcd_colormap.json') as file: - nlcd_map = json.load(file) -with open('../appdata/nlud_colormap.json') as file: - nlud_map = json.load(file) -with open('../appdata/tree_colormap.json') as file: - tree_map = json.load(file) data = {} for idx, row in df.iterrows(): data[row.lucode] = { - 'nlcd': { - 'name': row.nlcd_lulc, - 'color': nlcd_map[str(row.nlcd)] - }, - 'nlud': { - 'name': row.nlud_name, - 'color': nlud_map[str(row.nlud_simple)] - }, - 'tree': { - 'name': row.tree_canopy_cover, - 'color': tree_map[str(row.tree)] - } + 'nlcd': str(row.nlcd), + 'nlud': str(row.nlud_simple), + 'tree': str(row.tree) } diff --git a/server/sql_app/crud.py b/server/sql_app/crud.py index 236c398..8efc456 100644 --- a/server/sql_app/crud.py +++ b/server/sql_app/crud.py @@ -354,18 +354,6 @@ def get_lucode(db: Session, nlud_tier_2: str, nlud_tier_3: str, nlcd: str, tree: models.LulcCrosswalk.tree_canopy_cover == tree).first() -def get_lulc_string(db: Session, lucode: int): - row = db.query(models.LulcCrosswalk).filter( - models.LulcCrosswalk.lucode == lucode).first() - # LOGGER.debug(row) - # return f'{row.nlud_tier_3} | {row.nlcd_lulc} | {row.tree_canopy_cover}' - return json.dumps({ - 'nlud2': row.nlud_simple_class, - 'nlud3': row.nlud_simple_subclass, - 'nlcd': row.nlcd_lulc, - 'tree': row.tree_canopy_cover}) - - def explode_lulc_counts(db: Session, stats_dict): data = { 'nlcd': Counter(), @@ -375,10 +363,7 @@ def explode_lulc_counts(db: Session, stats_dict): for lucode, count in stats_dict.items(): row = db.query(models.LulcCrosswalk).filter( models.LulcCrosswalk.lucode == lucode).first() - nlud_label_2 = f' | {row.nlud_simple_subclass}' \ - if row.nlud_simple_subclass else '' - nlud_label = f'{row.nlud_simple_class}{nlud_label_2}' - data['nlud'][nlud_label] += count - data['nlcd'][row.nlcd_lulc] += count - data['tree'][row.tree_canopy_cover] += count + data['nlud'][row.nlud_simple] += count + data['nlcd'][row.nlcd] += count + data['tree'][row.tree] += count return data diff --git a/server/sql_app/models.py b/server/sql_app/models.py index 6cd00cb..479ead0 100644 --- a/server/sql_app/models.py +++ b/server/sql_app/models.py @@ -140,16 +140,12 @@ class LulcCrosswalk(Base): """Lookup table for landuse-landcover codes and labels.""" __tablename__ = "lulc_crosswalk" - frequency = Column(Integer) lucode = Column(Integer, primary_key=True) - code = Column(Integer) nlud_simple_class = Column(String) nlud_simple_subclass = Column(String) - simple_nlud = Column(Integer) + nlud_simple = Column(Integer) nlcd = Column(Integer) nlcd_lulc = Column(String) - nlcd_colors = Column(String) tree = Column(Integer) tree_canopy_cover = Column(String) - tree_colors = Column(String)