Screen for Recommended Replacement Technologies
- Input: MPAT (
data/03_processed/mpat/20260428_mpat_32604.gpkg) and YAML configuration inconfig/baseline/ - Output: Screening GeoPackage and CSV in
data/03_processed/tech_screening/ - Helper:
src/screen_techs.py; config exportersrc/export_config.py
Goal
The notebook applies HAR 11-62 site suitability criteria to the MPAT and assigns each parcel a set of recommended cesspool replacement technologies. Criteria, exclusion rules, display rules, and numeric thresholds come from a v6.1 Excel matrix that is exported to YAML configuration files. Each parcel ends up with a list of passing endpoints, a category label, planning flags, and recommendation flags for downstream visualization.
Inputs
The screening uses two kinds of inputs: the MPAT from the previous step, and the technology screening configuration. The configuration is authored in an Excel spreadsheet by Robert Litt and exported to three YAML files for runtime use.
- MPAT:
HiOSDS-TechSuitabilityAnalysis/data/03_processed/mpat/20260428_mpat_32604.gpkg(see Build MPAT — Outputs) - Configuration source:
- Excel matrix:
HiOSDS-TechSuitabilityAnalysis/data/01_inputs/prepared/tech_screening_matrix/HCPT_Matrix_v6.1.xlsx
- Excel matrix:
- Configuration runtime files (derived from the Excel via
src/export_config.py):- Criteria:
config/baseline/criteria.yaml - Endpoint rules:
config/baseline/endpoint_rules.yaml - Thresholds:
config/baseline/thresholds.yaml
- Criteria:
The Excel spreadsheet is the editable source of truth. The YAML files are the runtime configuration that the screening notebook consumes. To change a threshold or rule, edit the spreadsheet and re-run src/export_config.py.
Outputs
- Screening result GeoPackage:
HiOSDS-TechSuitabilityAnalysis/data/03_processed/tech_screening/20260428_tech_screening_32604.gpkg - CSV:
HiOSDS-TechSuitabilityAnalysis/data/03_processed/tech_screening/20260428_tech_screening.csv - README:
HiOSDS-TechSuitabilityAnalysis/data/03_processed/tech_screening/README.md(currently stale; documents an older “logic” output schema and needs to be regenerated against the v6.1 screening output)
The output is one row per parcel, joined back to parcel geometry. Each row carries the lists of passing, excluded, and hidden endpoints, an output category label, planning flags, and recommendation flags used in the web map.
Output schema
| Column | Type | Description |
|---|---|---|
tmk |
int | Parcel identifier (join key to MPAT) |
output_category |
category | One of CAT_1, CAT_2, CAT_3, CAT_LAST_RESORT, CAT_SUPPLEMENT_ONLY (see Processing step 7) |
passing_endpoints |
string | Comma-separated list of all PASS endpoints after Pass 2 |
primary_passing_endpoints |
string | PASS endpoints among E01–E12 |
supplement_passing_endpoints |
string | PASS endpoints among ES1, ES2 |
last_resort_passing_endpoints |
string | PASS endpoint E13 if applicable |
n_primary_passing |
int | Count of primary passing endpoints |
n_supplement_passing |
int | Count of supplement passing endpoints |
has_primary_endpoint |
bool | True if any of E01–E12 passes |
has_only_supplement |
bool | True if no primary passes but ES1 or ES2 does |
has_last_resort_only |
bool | True if E13 is the only passing endpoint |
flag_lot_size |
int (0/1) | 1 if net_parcel_area_sqft < lot_flag_sqft (planning flag) |
flag_soil_drainage |
int (0/1) | 1 if perc_est <= perc_slow_flag (planning flag) |
flag_flood |
int (0/1) | 1 if parcel is in an SFHA |
flag_negative_net_area |
int (0/1) | 1 if calculated building footprint area exceeded parcel area; net area clipped to zero |
flag_missing_gw |
int (0/1) | 1 if depth_to_wt_ft is missing |
flag_missing_slope |
int (0/1) | 1 if slope_pct is missing |
flag_missing_ksat |
int (0/1) | 1 if ksat_r is missing |
flag_missing_perc |
int (0/1) | 1 if perc_est is missing |
flag_soil_data_gap |
int (0/1) | 1 if any soil data is missing |
flag_missing_any_screening_input |
int (0/1) | 1 if any screening input is missing |
prefer_nsf245 |
bool | True if SMA_NSF245_PREFER or STREAM_NSF245_PREFER triggered |
rf_within_sma |
“Yes” / “No” | Whether the parcel is inside an SMA (display string for the web map) |
rf_within_50_ft_of_coast |
“Yes” / “No” | Web map display flag |
rf_within_50_ft_of_stream |
“Yes” / “No” | Web map display flag |
rf_within_1000_ft_of_well |
“Yes” / “No” | Web map display flag |
geometry |
geometry | EPSG:32604, parcel polygon (GeoPackage only; CSV drops geometry) |
Configuration Reference
The current baseline configuration is HAR 11-62 Subchapter 3 (distances in feet, areas in square feet), exported on 2026-04-14 from HCPT_Matrix_v6.1.xlsx. The three tabs below show the runtime contents of thresholds.yaml, criteria.yaml, and endpoint_rules.yaml. HAR section references and longer notes for each entry are in the YAML files themselves.
Numeric (or VERIFY) values that the criteria reference. The MPAT field column shows which column in the MPAT each threshold compares against. Verify shows the current confirmation status: CONFIRMED is final, VERIFY is pending DOH or further sourcing, PLANNING ESTIMATE is a WRRC working value, FLAG ONLY means the value drives a planning flag rather than a hard exclusion.
| Threshold | Value | MPAT field | Description | Verify |
|---|---|---|---|---|
gw_min_ft |
3 ft | depth_to_wt_ft |
Minimum depth to groundwater (standard LF and seepage pit) | CONFIRMED |
slope_max_lf_pct |
12 % | slope_pct |
Maximum slope (standard absorption trenches and LF) | VERIFY |
slope_max_cw_pct |
8 % | slope_pct |
Maximum slope (constructed wetland eco supplement) | VERIFY with DOH |
slope_seepage_trigger_pct |
12 % | slope_pct |
Slope threshold triggering seepage pit as alternative to trenches | CONFIRMED |
well_public_lf_ft |
1000 ft | dist_to_nearest_well_ft |
Setback from public water system (soil absorption system: LF, drip, beds) | CONFIRMED |
well_public_trt_ft |
500 ft | dist_to_nearest_well_ft |
Setback from public water system (treatment unit: septic tank or ATU) | CONFIRMED – 500 ft |
well_domestic_ft |
VERIFY | dist_to_nearest_well_ft |
Setback from domestic / private well (all system components) | VERIFY with DOH |
well_seepage_ft |
VERIFY | dist_to_nearest_well_ft |
Setback from public water system (seepage pit) | VERIFY |
well_bioreactor_ft |
300 ft | dist_to_nearest_well_ft |
Setback from well (bioreactor garden eco supplement) | VERIFY with DOH |
coast_min_ft |
50 ft | dist_to_coast_ft |
Minimum distance to coastline (all soil-dispersal systems) | CONFIRMED |
stream_min_ft |
50 ft | dist_to_streams_ft |
Minimum distance to stream (all soil-dispersal systems) | CONFIRMED |
stream_nsf245_ft |
300 ft | dist_to_streams_ft |
Stream proximity threshold for NSF 245 preference (not exclusion) | CONFIRMED |
lot_flag_sqft |
10000 sqft | net_parcel_area_sqft |
Net lot area flag threshold (planning proxy for standard LF feasibility) | PLANNING ESTIMATE |
lot_cw_min_sqft |
20000 sqft | net_parcel_area_sqft |
Minimum lot area (constructed wetland eco supplement) | VERIFY with DOH |
perc_slow_flag |
60 min/in | perc_est |
Perc rate upper flag limit (standard absorption trenches; FLAG, not hard exclusion) | FLAG ONLY |
perc_fast_pathway |
1 min/in | perc_est |
Perc rate lower threshold (triggers Soil Replacement System pathway) | CONFIRMED pathway |
perc_seepage_max |
10 min/in | perc_est |
Perc rate hard limit (seepage pit; weighted average must be at most this value) | CONFIRMED |
design_flow_gpd_bed |
200 gpd/bedroom | bedroom_qty |
Design wastewater flow per bedroom (used for drain field sizing) | CONFIRMED |
sma_inside |
0 | dist_to_sma_ft |
Inside Special Management Area (dist_to_sma_ft == 0) |
CONFIRMED |
sfha_flag |
T | sfha_tf |
Special Flood Hazard Area (advisory flag) | ACTIVE |
Each criterion compares one MPAT field against one threshold using a single operator and a default action. The action determines what role the criterion plays during screening: excludes_when is a hard Pass 1 exclusion; flags_when raises a planning flag without excluding; triggers_when and prefers_when are Pass 2 display rules; pathway and sizing are reserved for future engine extensions.
| Criterion | Rule | Action | Description |
|---|---|---|---|
SLOPE_MAX_LF |
slope_pct <= slope_max_lf_pct |
excludes_when | Maximum slope (standard absorption trenches and leach fields) |
SLOPE_SEEPAGE_TRIGGER |
slope_pct > slope_seepage_trigger_pct |
triggers_when | Steep slope (seepage pit shown only when met) |
SLOPE_MAX_CW |
slope_pct <= slope_max_cw_pct |
excludes_when | Maximum slope (constructed wetland eco supplement, ES2) |
WELL_STD |
dist_to_nearest_well_ft >= well_public_lf_ft |
excludes_when | Setback from public water system (soil absorption system: LF, drip) |
WELL_PUBLIC_TRT |
dist_to_nearest_well_ft >= well_public_trt_ft |
excludes_when | Setback from public water system (treatment unit: septic tank or ATU) |
WELL_SEEPAGE |
dist_to_nearest_well_ft >= well_seepage_ft |
excludes_when | Setback from water system (seepage pit) |
WELL_BIOREACTOR |
dist_to_nearest_well_ft >= well_bioreactor_ft |
excludes_when | Setback from well (bioreactor garden, ES1) |
COAST_MIN |
dist_to_coast_ft >= coast_min_ft |
excludes_when | Minimum distance to coastline (all soil-dispersal systems) |
STREAM_MIN |
dist_to_streams_ft >= stream_min_ft |
excludes_when | Minimum distance to stream (all soil-dispersal systems) |
STREAM_NSF245_PREFER |
dist_to_streams_ft < stream_nsf245_ft |
prefers_when | Near stream (NSF 245 endpoints ranked above NSF 40) |
SMA_NSF245_PREFER |
dist_to_sma_ft == sma_inside |
prefers_when | Inside SMA (NSF 245 ATU endpoints ranked above NSF 40) |
SMA_STD_CONDITIONAL |
dist_to_sma_ft == sma_inside |
excludes_when | Inside SMA (standard septic conditional, within 50 ft of shoreline excluded) |
LOT_STD_LF |
net_parcel_area_sqft >= lot_flag_sqft |
flags_when | Lot size planning flag (may be too small for standard LF) |
LOT_COMPACT_TRIGGER |
net_parcel_area_sqft < lot_flag_sqft |
triggers_when | Small lot (triggers compact LF and ATU endpoints E02, E05, E09) |
LOT_CW_MIN |
net_parcel_area_sqft >= lot_cw_min_sqft |
excludes_when | Minimum lot size (constructed wetland eco supplement, ES2) |
PERC_FLAG_SLOW |
perc_est <= perc_slow_flag |
flags_when | Soil perc upper flag limit (standard LF; FLAG, not hard exclusion) |
PERC_FLAG_FAST |
perc_est < perc_fast_pathway |
pathway | Perc less than 1 min/in (Soil Replacement System pathway applies) |
PERC_SEEPAGE_MAX |
perc_est <= perc_seepage_max |
excludes_when | Soil perc hard limit (seepage pit; weighted average must be at most threshold) |
FLOOD_SFHA |
sfha_tf == sfha_flag |
flags_when | In SFHA flood zone (advisory; no hard HAR exclusion) |
DESIGN_FLOW |
bedroom_qty × design_flow_gpd_bed |
sizing | Design flow per bedroom (used in drain field sizing; not a screening criterion) |
GW_MIN |
depth_to_wt_ft >= gw_min_ft |
excludes_when | Minimum depth to groundwater (standard leach field) |
GW_MIN_SEEPAGE |
depth_to_wt_ft >= gw_min_ft |
excludes_when | Minimum depth to groundwater (seepage pit; same 3 ft threshold) |
GW_MOUND_TRIGGER |
depth_to_wt_ft < gw_min_ft |
triggers_when | Shallow groundwater (mounded systems shown only when this is true) |
WELL_ATU_DRIP |
dist_to_nearest_well_ft >= well_public_trt_ft |
excludes_when | ATU and drip irrigation (100 ft minimum; VERIFY may differ from LF setback) |
Each endpoint declares which criteria gate it. Excludes lists hard Pass 1 exclusions: any failure removes the endpoint for that parcel. Triggers lists Pass 2 conditions that must be true for the endpoint to be displayed (otherwise the endpoint is marked HIDDEN). Prefers lists Pass 2 ranking conditions (not exclusions). Flags lists planning flags raised when the criterion is true. Inherits lists criteria inherited from another endpoint’s rules and is reserved for future engine use.
| ID | Display name | Approval | Excludes when | Triggers / Prefers when | Flags when |
|---|---|---|---|---|---|
| E01 | Standard Septic Tank + Standard Leach Field | Standard Approval | GW_MIN, SLOPE_MAX_LF, WELL_STD, COAST_MIN, STREAM_MIN | inherits GW_MOUND_TRIGGER | LOT_STD_LF, PERC_FLAG_SLOW, PERC_FLAG_FAST, FLOOD_SFHA |
| E02 | Standard Septic Tank + Compact (Traffic-Rated) LF | Conditional | GW_MIN, SLOPE_MAX_LF, WELL_STD, COAST_MIN, STREAM_MIN | triggers LOT_STD_LF | PERC_FLAG_SLOW |
| E03 | Standard Septic Tank + Mounded Leach Field | Case-by-Case | WELL_STD, COAST_MIN, STREAM_MIN | triggers GW_MOUND_TRIGGER | PERC_FLAG_SLOW |
| E04 | NSF 40 ATU + Standard Leach Field | Conditional | GW_MIN, SLOPE_MAX_LF, WELL_STD, COAST_MIN, STREAM_MIN, LOT_STD_LF | prefers SMA_NSF245_PREFER, STREAM_NSF245_PREFER | PERC_FLAG_SLOW |
| E05 | NSF 40 ATU + Compact (Traffic-Rated) LF | Conditional | GW_MIN, WELL_STD, COAST_MIN, STREAM_MIN | triggers LOT_STD_LF | PERC_FLAG_SLOW |
| E06 | NSF 40 ATU + Mounded Leach Field | Case-by-Case | WELL_STD, COAST_MIN, STREAM_MIN | triggers GW_MOUND_TRIGGER | PERC_FLAG_SLOW |
| E07 | NSF 40 ATU + Seepage Pit | Conditional (restricted) | GW_MIN_SEEPAGE, PERC_SEEPAGE_MAX, WELL_SEEPAGE, COAST_MIN, STREAM_MIN | triggers SLOPE_SEEPAGE_TRIGGER; prefers SMA_NSF245_PREFER | — |
| E08 | NSF 245 ATU + Standard Leach Field | Conditional | GW_MIN, SLOPE_MAX_LF, WELL_STD, LOT_STD_LF, COAST_MIN, STREAM_MIN | prefers SMA_NSF245_PREFER, STREAM_NSF245_PREFER | PERC_FLAG_SLOW |
| E09 | NSF 245 ATU + Compact (Traffic-Rated) LF | Conditional | GW_MIN, WELL_STD, COAST_MIN, STREAM_MIN | triggers LOT_STD_LF; prefers SMA_NSF245_PREFER, STREAM_NSF245_PREFER | PERC_FLAG_SLOW |
| E10 | NSF 245 ATU + Mounded Leach Field | Case-by-Case | WELL_STD, COAST_MIN, STREAM_MIN | triggers GW_MOUND_TRIGGER; prefers SMA_NSF245_PREFER | PERC_FLAG_SLOW |
| E11 | NSF 245 ATU + Subsurface Drip Irrigation | Conditional | WELL_ATU_DRIP, COAST_MIN, STREAM_MIN | prefers SMA_NSF245_PREFER, STREAM_NSF245_PREFER | PERC_FLAG_SLOW |
| E12 | NSF 245 ATU + Seepage Pit | Conditional (restricted) | GW_MIN_SEEPAGE, PERC_SEEPAGE_MAX, WELL_SEEPAGE, COAST_MIN, STREAM_MIN | triggers SLOPE_SEEPAGE_TRIGGER; prefers SMA_NSF245_PREFER, STREAM_NSF245_PREFER | — |
| E13 | Composting or Incinerating Toilet (last resort) | — | — | last_resort (Pass 2); inherits GW_MIN, WELL_STD, COAST_MIN, STREAM_MIN, LOT_STD_LF, PERC_FLAG_SLOW | — |
| ES1 | Bioreactor Garden (eco supplement) | Experimental / Limited | WELL_BIOREACTOR, COAST_MIN, STREAM_MIN | — | — |
| ES2 | Constructed Wetland (eco supplement) | Experimental / Limited | LOT_CW_MIN, SLOPE_MAX_CW, COAST_MIN, STREAM_MIN | — | — |
Processing Steps
The screening notebook (notebooks/03_screen_techs.ipynb) follows eight steps.
- Setup. Import modules, set the run date, resolve project paths, and define the input MPAT version and the output GeoPackage and CSV paths.
- Load MPAT and configuration. Load the MPAT GeoPackage. Load
criteria.yaml,endpoint_rules.yaml, andthresholds.yamlfromconfig/baseline/. Build the threshold lookup and surface any thresholds still markedVERIFY(currentlywell_domestic_ft,well_seepage_ft, andsfha_flag) so unconfirmed cutoffs do not silently apply. - Feature engineering. Derive the percolation rate estimate
perc_est = 423.33 / ksat_randdist_to_nearest_well_ftas the minimum of domestic and municipal well distances. Recomputenet_parcel_area_sqftand flag the small number of parcels (46 in the current run) where calculated building footprint area exceeded parcel area. - Pass 1: criteria evaluation. Evaluate each criterion in
criteria.yaml(for example,SLOPE_MAX_LF: slope_pct <= 12,WELL_STD: dist_to_nearest_well_ft >= 1000) against every parcel and produce a per-parcel pass/fail matrix. - Pass 1: endpoint screening. For each endpoint, check the criteria listed under
excludes_wheninendpoint_rules.yaml. If any hard criterion fails, the endpoint is marked EXCLUDE for that parcel; otherwise PASS. The result is one PASS/EXCLUDE row per parcel × endpoint. - Pass 2: display filters. Apply
triggers_whenandprefers_whenrules to mark some PASS endpoints as HIDDEN. HIDDEN means technically feasible but not the recommended display option for the parcel’s conditions (for example, mounded leach fields are hidden when groundwater depth is adequate). - Planning and data flags + output category. Assign per-parcel planning flags (lot size, soil drainage, flood, missing-data flags) and an output category. The five categories are:
CAT_1: E01 passes, no flagsCAT_2: E01 excluded, another primary endpoint passesCAT_3: E01 passes, has planning and/or data flagsCAT_LAST_RESORT: (no primary endpoint passes; E13 dry-system fallback)CAT_SUPPLEMENT_ONLY: no primary endpoint passes; only ES1 / ES2 supplements pass
- Build per-parcel summary and export. Build the final per-parcel result with comma-separated lists of passing, primary-passing, supplement-passing, and last-resort endpoints, plus the recommendation flags used in the web map (
prefer_nsf245,rf_within_sma,rf_within_50_ft_of_coast,rf_within_50_ft_of_stream,rf_within_1000_ft_of_well). Write the result to a GeoPackage (with geometry) and a CSV (geometry dropped).
Notes and Decisions
- Excel and YAML configuration. The Excel matrix is the editable source of truth. The YAML files in
config/baseline/are the version-controlled runtime inputs used by the screening notebook. - Percolation estimate. The screening uses
perc_est = 423.33 / ksat_r. Because SSURGO values are regional estimates, standard leach-field perc limits are treated as planning flags. The seepage pit perc limit remains a hard exclusion. - Negative net parcel area. Parcels where building footprint area exceeds parcel area are kept in the output. The screening clips net area to zero and raises
flag_negative_net_area. - Date prefix. Outputs from notebooks 02 and 03 carry a
YYYYMMDDprefix. The screening notebook reads a specific MPAT date throughmpat_v_date, which allows re-screening against an older MPAT if needed.
Resources
- Notebook:
notebooks/03_screen_techs.ipynb - Screening helpers:
src/screen_techs.py - Config exporter:
src/export_config.py(Excel matrix to YAML) - Configuration folder:
config/baseline/ - Output folder:
HiOSDS-TechSuitabilityAnalysis/data/03_processed/tech_screening/