Merge branch 'usds:main' into main
|
@ -12,24 +12,26 @@ import * as constants from '../../data/constants';
|
|||
import * as EXPLORE_COPY from '../../data/copy/explore';
|
||||
import * as METHODOLOGY_COPY from '../../data/copy/methodology';
|
||||
|
||||
export const readablePercentile = (percentile: number) => {
|
||||
return Math.round(percentile * 100);
|
||||
export const readablePercentile = (percentile: number | null) => {
|
||||
return percentile ? Math.round(percentile * 100) : 'N/A';
|
||||
};
|
||||
|
||||
// Todo: Add internationalization to superscript ticket #582
|
||||
const getSuperscriptOrdinal = (percentile: number) => {
|
||||
const englishOrdinalRules = new Intl.PluralRules('en', {
|
||||
type: 'ordinal',
|
||||
});
|
||||
const suffixes = {
|
||||
zero: 'th',
|
||||
one: 'st',
|
||||
two: 'nd',
|
||||
few: 'rd',
|
||||
many: 'th',
|
||||
other: 'th',
|
||||
};
|
||||
return suffixes[englishOrdinalRules.select(percentile)];
|
||||
const getSuperscriptOrdinal = (percentile: number | string) => {
|
||||
if (typeof percentile === "number") {
|
||||
const englishOrdinalRules = new Intl.PluralRules('en', {
|
||||
type: 'ordinal',
|
||||
});
|
||||
const suffixes = {
|
||||
zero: 'th',
|
||||
one: 'st',
|
||||
two: 'nd',
|
||||
few: 'rd',
|
||||
many: 'th',
|
||||
other: 'th',
|
||||
};
|
||||
return suffixes[englishOrdinalRules.select(percentile)];
|
||||
}
|
||||
};
|
||||
|
||||
interface IAreaDetailProps {
|
||||
|
@ -40,11 +42,13 @@ const AreaDetail = ({properties}:IAreaDetailProps) => {
|
|||
const intl = useIntl();
|
||||
const [isCommunityFocus, setIsCommunityFocus] = React.useState<boolean>(true);
|
||||
|
||||
const score = properties[constants.SCORE_PROPERTY_HIGH] as number;
|
||||
const blockGroup = properties[constants.GEOID_PROPERTY];
|
||||
const population = properties[constants.TOTAL_POPULATION];
|
||||
const countyName = properties[constants.COUNTY_NAME];
|
||||
const stateName = properties[constants.STATE_NAME];
|
||||
console.log("Area Detail properies: ", properties);
|
||||
|
||||
const score = properties[constants.SCORE_PROPERTY_HIGH] ? properties[constants.SCORE_PROPERTY_HIGH] as number : 0;
|
||||
const blockGroup = properties[constants.GEOID_PROPERTY] ? properties[constants.GEOID_PROPERTY] : "N/A";
|
||||
const population = properties[constants.TOTAL_POPULATION] ? properties[constants.TOTAL_POPULATION] : "N/A";
|
||||
const countyName = properties[constants.COUNTY_NAME] ? properties[constants.COUNTY_NAME] : "N/A";
|
||||
const stateName = properties[constants.STATE_NAME] ? properties[constants.STATE_NAME] : "N/A";
|
||||
|
||||
useEffect(() => {
|
||||
if (score >= constants.SCORE_BOUNDARY_PRIORITIZED ) {
|
||||
|
@ -65,77 +69,92 @@ const AreaDetail = ({properties}:IAreaDetailProps) => {
|
|||
const areaMedianIncome:indicatorInfo = {
|
||||
label: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATORS.AREA_MEDIAN_INCOME),
|
||||
description: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATOR_DESCRIPTION.AREA_MEDIAN_INCOME),
|
||||
value: properties[constants.AREA_MEDIAN_INCOME_PERCENTILE],
|
||||
value: properties[constants.AREA_MEDIAN_INCOME_PERCENTILE] ?
|
||||
properties[constants.AREA_MEDIAN_INCOME_PERCENTILE] : null,
|
||||
};
|
||||
const eduInfo:indicatorInfo = {
|
||||
label: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATORS.EDUCATION),
|
||||
description: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATOR_DESCRIPTION.EDUCATION),
|
||||
value: properties[constants.EDUCATION_PROPERTY_PERCENTILE],
|
||||
value: properties[constants.EDUCATION_PROPERTY_PERCENTILE] ?
|
||||
properties[constants.EDUCATION_PROPERTY_PERCENTILE] : null,
|
||||
};
|
||||
const poverty:indicatorInfo = {
|
||||
label: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATORS.POVERTY),
|
||||
description: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATOR_DESCRIPTION.POVERTY),
|
||||
value: properties[constants.POVERTY_PROPERTY_PERCENTILE],
|
||||
value: properties[constants.POVERTY_PROPERTY_PERCENTILE] ?
|
||||
properties[constants.POVERTY_PROPERTY_PERCENTILE] : null,
|
||||
};
|
||||
const asthma:indicatorInfo = {
|
||||
label: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATORS.ASTHMA),
|
||||
description: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATOR_DESCRIPTION.ASTHMA),
|
||||
value: properties[constants.ASTHMA_PERCENTILE],
|
||||
value: properties[constants.ASTHMA_PERCENTILE] ?
|
||||
properties[constants.ASTHMA_PERCENTILE] : null,
|
||||
};
|
||||
const diabetes:indicatorInfo = {
|
||||
label: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATORS.DIABETES),
|
||||
description: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATOR_DESCRIPTION.DIABETES),
|
||||
value: properties[constants.DIABETES_PERCENTILE],
|
||||
value: properties[constants.DIABETES_PERCENTILE] ?
|
||||
properties[constants.DIABETES_PERCENTILE] : null,
|
||||
};
|
||||
const dieselPartMatter:indicatorInfo = {
|
||||
label: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATORS.DIESEL_PARTICULATE_MATTER),
|
||||
description: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATOR_DESCRIPTION.DIESEL_PARTICULATE_MATTER),
|
||||
value: properties[constants.DIESEL_MATTER_PERCENTILE],
|
||||
value: properties[constants.DIESEL_MATTER_PERCENTILE] ?
|
||||
properties[constants.DIESEL_MATTER_PERCENTILE] : null,
|
||||
};
|
||||
const lifeExpect:indicatorInfo = {
|
||||
label: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATORS.LIFE_EXPECT),
|
||||
description: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATOR_DESCRIPTION.LIFE_EXPECT),
|
||||
value: properties[constants.LIFE_PERCENTILE],
|
||||
value: properties[constants.LIFE_PERCENTILE] ?
|
||||
properties[constants.LIFE_PERCENTILE] : null,
|
||||
};
|
||||
const energyBurden:indicatorInfo = {
|
||||
label: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATORS.ENERGY_BURDEN),
|
||||
description: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATOR_DESCRIPTION.ENERGY_BURDEN),
|
||||
value: properties[constants.ENERGY_PERCENTILE],
|
||||
value: properties[constants.ENERGY_PERCENTILE] ?
|
||||
properties[constants.ENERGY_PERCENTILE] : null,
|
||||
};
|
||||
const pm25:indicatorInfo = {
|
||||
label: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATORS.PM_2_5),
|
||||
description: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATOR_DESCRIPTION.PM_2_5),
|
||||
value: properties[constants.PM25_PERCENTILE],
|
||||
value: properties[constants.PM25_PERCENTILE] ?
|
||||
properties[constants.PM25_PERCENTILE] : null,
|
||||
};
|
||||
const leadPaint:indicatorInfo = {
|
||||
label: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATORS.LEAD_PAINT),
|
||||
description: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATOR_DESCRIPTION.LEAD_PAINT),
|
||||
value: properties[constants.LEAD_PAINT_PERCENTILE],
|
||||
value: properties[constants.LEAD_PAINT_PERCENTILE] ?
|
||||
properties[constants.LEAD_PAINT_PERCENTILE] : null,
|
||||
};
|
||||
const trafficVolume:indicatorInfo = {
|
||||
label: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATORS.TRAFFIC_VOLUME),
|
||||
description: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATOR_DESCRIPTION.TRAFFIC_VOLUME),
|
||||
value: properties[constants.TRAFFIC_PERCENTILE],
|
||||
value: properties[constants.TRAFFIC_PERCENTILE] ?
|
||||
properties[constants.TRAFFIC_PERCENTILE] : null,
|
||||
};
|
||||
const wasteWater:indicatorInfo = {
|
||||
label: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATORS.WASTE_WATER),
|
||||
description: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATOR_DESCRIPTION.WASTE_WATER),
|
||||
value: properties[constants.WASTEWATER_PERCENTILE],
|
||||
value: properties[constants.WASTEWATER_PERCENTILE] ?
|
||||
properties[constants.WASTEWATER_PERCENTILE] : null,
|
||||
};
|
||||
const femaRisk:indicatorInfo = {
|
||||
label: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATORS.FEMA_RISK),
|
||||
description: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATOR_DESCRIPTION.FEMA_RISK),
|
||||
value: properties[constants.FEMA_PERCENTILE],
|
||||
value: properties[constants.FEMA_PERCENTILE] ?
|
||||
properties[constants.FEMA_PERCENTILE] : null,
|
||||
};
|
||||
const heartDisease:indicatorInfo = {
|
||||
label: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATORS.HEART_DISEASE),
|
||||
description: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATOR_DESCRIPTION.HEART_DISEASE),
|
||||
value: properties[constants.HEART_PERCENTILE],
|
||||
value: properties[constants.HEART_PERCENTILE] ?
|
||||
properties[constants.HEART_PERCENTILE] : null,
|
||||
};
|
||||
const houseBurden:indicatorInfo = {
|
||||
label: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATORS.HOUSE_BURDEN),
|
||||
description: intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_INDICATOR_DESCRIPTION.HOUSE_BURDEN),
|
||||
value: properties[constants.HOUSING_BURDEN_PROPERTY_PERCENTILE],
|
||||
value: properties[constants.HOUSING_BURDEN_PROPERTY_PERCENTILE] ?
|
||||
properties[constants.HOUSING_BURDEN_PROPERTY_PERCENTILE] : null,
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@ exports[`rendering of the AreaDetail checks if various text fields are visible 1
|
|||
County:
|
||||
</span>
|
||||
<span>
|
||||
undefined
|
||||
N/A
|
||||
</span>
|
||||
</li>
|
||||
<li>
|
||||
|
@ -27,7 +27,7 @@ exports[`rendering of the AreaDetail checks if various text fields are visible 1
|
|||
State:
|
||||
</span>
|
||||
<span>
|
||||
undefined
|
||||
N/A
|
||||
</span>
|
||||
</li>
|
||||
<li>
|
||||
|
@ -134,11 +134,9 @@ exports[`rendering of the AreaDetail checks if various text fields are visible 1
|
|||
Asthma
|
||||
</h4>
|
||||
<div>
|
||||
NaN
|
||||
N/A
|
||||
<sup>
|
||||
<span>
|
||||
th
|
||||
</span>
|
||||
<span />
|
||||
</sup>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -156,11 +154,9 @@ exports[`rendering of the AreaDetail checks if various text fields are visible 1
|
|||
Diabetes
|
||||
</h4>
|
||||
<div>
|
||||
NaN
|
||||
N/A
|
||||
<sup>
|
||||
<span>
|
||||
th
|
||||
</span>
|
||||
<span />
|
||||
</sup>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -178,11 +174,9 @@ exports[`rendering of the AreaDetail checks if various text fields are visible 1
|
|||
Diesel particulate matter
|
||||
</h4>
|
||||
<div>
|
||||
NaN
|
||||
N/A
|
||||
<sup>
|
||||
<span>
|
||||
th
|
||||
</span>
|
||||
<span />
|
||||
</sup>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -200,11 +194,9 @@ exports[`rendering of the AreaDetail checks if various text fields are visible 1
|
|||
Energy burden
|
||||
</h4>
|
||||
<div>
|
||||
NaN
|
||||
N/A
|
||||
<sup>
|
||||
<span>
|
||||
th
|
||||
</span>
|
||||
<span />
|
||||
</sup>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -222,11 +214,9 @@ exports[`rendering of the AreaDetail checks if various text fields are visible 1
|
|||
FEMA Risk Index
|
||||
</h4>
|
||||
<div>
|
||||
NaN
|
||||
N/A
|
||||
<sup>
|
||||
<span>
|
||||
th
|
||||
</span>
|
||||
<span />
|
||||
</sup>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -244,11 +234,9 @@ exports[`rendering of the AreaDetail checks if various text fields are visible 1
|
|||
Heart disease
|
||||
</h4>
|
||||
<div>
|
||||
NaN
|
||||
N/A
|
||||
<sup>
|
||||
<span>
|
||||
th
|
||||
</span>
|
||||
<span />
|
||||
</sup>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -288,11 +276,9 @@ exports[`rendering of the AreaDetail checks if various text fields are visible 1
|
|||
Lead paint
|
||||
</h4>
|
||||
<div>
|
||||
NaN
|
||||
N/A
|
||||
<sup>
|
||||
<span>
|
||||
th
|
||||
</span>
|
||||
<span />
|
||||
</sup>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -310,11 +296,9 @@ exports[`rendering of the AreaDetail checks if various text fields are visible 1
|
|||
Life expectancy
|
||||
</h4>
|
||||
<div>
|
||||
NaN
|
||||
N/A
|
||||
<sup>
|
||||
<span>
|
||||
th
|
||||
</span>
|
||||
<span />
|
||||
</sup>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -332,11 +316,9 @@ exports[`rendering of the AreaDetail checks if various text fields are visible 1
|
|||
PM2.5
|
||||
</h4>
|
||||
<div>
|
||||
NaN
|
||||
N/A
|
||||
<sup>
|
||||
<span>
|
||||
th
|
||||
</span>
|
||||
<span />
|
||||
</sup>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -354,11 +336,9 @@ exports[`rendering of the AreaDetail checks if various text fields are visible 1
|
|||
Traffic proximity and volume
|
||||
</h4>
|
||||
<div>
|
||||
NaN
|
||||
N/A
|
||||
<sup>
|
||||
<span>
|
||||
th
|
||||
</span>
|
||||
<span />
|
||||
</sup>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -376,11 +356,9 @@ exports[`rendering of the AreaDetail checks if various text fields are visible 1
|
|||
Wastewater discharge
|
||||
</h4>
|
||||
<div>
|
||||
NaN
|
||||
N/A
|
||||
<sup>
|
||||
<span>
|
||||
th
|
||||
</span>
|
||||
<span />
|
||||
</sup>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* eslint-disable no-unused-vars */
|
||||
// External Libs:
|
||||
import React, {MouseEvent, useRef, useState, useMemo} from 'react';
|
||||
import React, {useRef, useState, useMemo} from 'react';
|
||||
import {Map, MapboxGeoJSONFeature, LngLatBoundsLike} from 'maplibre-gl';
|
||||
import ReactMapGL, {
|
||||
MapEvent,
|
||||
|
@ -136,29 +136,6 @@ const J40Map = ({location}: IJ40Interface) => {
|
|||
});
|
||||
};
|
||||
|
||||
const onClickTerritoryFocusButton = (event: MouseEvent<HTMLButtonElement>) => {
|
||||
event.stopPropagation();
|
||||
const buttonID = event.target && (event.target as HTMLElement).id;
|
||||
|
||||
switch (buttonID) {
|
||||
case '48':
|
||||
goToPlace(constants.LOWER_48_BOUNDS);
|
||||
break;
|
||||
case 'AK':
|
||||
goToPlace(constants.ALASKA_BOUNDS);
|
||||
break;
|
||||
case 'HI':
|
||||
goToPlace(constants.HAWAII_BOUNDS);
|
||||
break;
|
||||
case 'PR':
|
||||
goToPlace(constants.PUERTO_RICO_BOUNDS);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
const onTransitionStart = () => {
|
||||
setTransitionInProgress(true);
|
||||
};
|
||||
|
@ -273,7 +250,7 @@ const J40Map = ({location}: IJ40Interface) => {
|
|||
onClick={onClickGeolocate}
|
||||
/> : ''}
|
||||
{geolocationInProgress ? <div>Geolocation in progress...</div> : ''}
|
||||
<TerritoryFocusControl onClickTerritoryFocusButton={onClickTerritoryFocusButton}/>
|
||||
<TerritoryFocusControl goToPlace={goToPlace}/>
|
||||
{'fs' in flags ? <FullscreenControl className={styles.fullscreenControl}/> :'' }
|
||||
|
||||
</ReactMapGL>
|
||||
|
|
|
@ -1,21 +1,53 @@
|
|||
import {useIntl} from 'gatsby-plugin-intl';
|
||||
import React, {MouseEventHandler} from 'react';
|
||||
import {_useMapControl as useMapControl} from 'react-map-gl';
|
||||
import React from 'react';
|
||||
import {LngLatBoundsLike} from 'mapbox-gl';
|
||||
|
||||
import * as styles from './territoryFocusControl.module.scss';
|
||||
import * as EXPLORE_COPY from '../data/copy/explore';
|
||||
import * as constants from '../data/constants';
|
||||
|
||||
interface ITerritoryFocusControl {
|
||||
onClickTerritoryFocusButton: MouseEventHandler<HTMLButtonElement>;
|
||||
goToPlace(bounds: LngLatBoundsLike): void;
|
||||
}
|
||||
|
||||
const TerritoryFocusControl = ({onClickTerritoryFocusButton}: ITerritoryFocusControl) => {
|
||||
|
||||
const TerritoryFocusControl = ({goToPlace}: ITerritoryFocusControl) => {
|
||||
const intl = useIntl();
|
||||
|
||||
const {containerRef} = useMapControl({
|
||||
// @ts-ignore // Types have not caught up yet, see https://github.com/visgl/react-map-gl/issues/1492
|
||||
onClick: onClickTerritoryFocusButton,
|
||||
});
|
||||
const onClickTerritoryFocusButton = (event: React.MouseEvent<HTMLButtonElement>) => {
|
||||
event.stopPropagation();
|
||||
const buttonID = event.target && (event.target as HTMLElement).id;
|
||||
|
||||
switch (buttonID) {
|
||||
case '48':
|
||||
goToPlace(constants.LOWER_48_BOUNDS);
|
||||
break;
|
||||
case 'AK':
|
||||
goToPlace(constants.ALASKA_BOUNDS);
|
||||
break;
|
||||
case 'HI':
|
||||
goToPlace(constants.HAWAII_BOUNDS);
|
||||
break;
|
||||
case 'PR':
|
||||
goToPlace(constants.PUERTO_RICO_BOUNDS);
|
||||
break;
|
||||
case 'GU':
|
||||
goToPlace(constants.GUAM_BOUNDS);
|
||||
break;
|
||||
case 'AS':
|
||||
goToPlace(constants.AMERICAN_SAMOA_BOUNDS);
|
||||
break;
|
||||
case 'MP':
|
||||
goToPlace(constants.MARIANA_ISLAND_BOUNDS);
|
||||
break;
|
||||
case 'VI':
|
||||
goToPlace(constants.US_VIRGIN_ISLANDS_BOUNDS);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
const territories = [
|
||||
{
|
||||
|
@ -34,6 +66,22 @@ const TerritoryFocusControl = ({onClickTerritoryFocusButton}: ITerritoryFocusCon
|
|||
short: intl.formatMessage(EXPLORE_COPY.MAP.PR_SHORT),
|
||||
long: intl.formatMessage(EXPLORE_COPY.MAP.PR_LONG),
|
||||
},
|
||||
{
|
||||
short: intl.formatMessage(EXPLORE_COPY.MAP.GU_SHORT),
|
||||
long: intl.formatMessage(EXPLORE_COPY.MAP.GU_LONG),
|
||||
},
|
||||
{
|
||||
short: intl.formatMessage(EXPLORE_COPY.MAP.AS_SHORT),
|
||||
long: intl.formatMessage(EXPLORE_COPY.MAP.AS_LONG),
|
||||
},
|
||||
{
|
||||
short: intl.formatMessage(EXPLORE_COPY.MAP.MP_SHORT),
|
||||
long: intl.formatMessage(EXPLORE_COPY.MAP.MP_LONG),
|
||||
},
|
||||
{
|
||||
short: intl.formatMessage(EXPLORE_COPY.MAP.VI_SHORT),
|
||||
long: intl.formatMessage(EXPLORE_COPY.MAP.VI_LONG),
|
||||
},
|
||||
];
|
||||
// the offset for this array should map the territories variable
|
||||
const territoriesIconClassName = [
|
||||
|
@ -41,16 +89,20 @@ const TerritoryFocusControl = ({onClickTerritoryFocusButton}: ITerritoryFocusCon
|
|||
'mapboxgl-ctrl-zoom-to-ak',
|
||||
'mapboxgl-ctrl-zoom-to-hi',
|
||||
'mapboxgl-ctrl-zoom-to-pr',
|
||||
'mapboxgl-ctrl-zoom-to-gu',
|
||||
'mapboxgl-ctrl-zoom-to-as',
|
||||
'mapboxgl-ctrl-zoom-to-mp',
|
||||
'mapboxgl-ctrl-zoom-to-vi',
|
||||
];
|
||||
|
||||
return (
|
||||
<div ref={containerRef} className={styles.territoryFocusContainer}>
|
||||
<div className={styles.territoryFocusContainer}>
|
||||
<div className={'mapboxgl-ctrl mapboxgl-ctrl-group'}>
|
||||
{territories.map((territory, index) =>
|
||||
<button
|
||||
id={territory.short}
|
||||
key={territory.short}
|
||||
onClick={onClickTerritoryFocusButton}
|
||||
onClick={(e) => onClickTerritoryFocusButton(e)}
|
||||
className={'mapboxgl-ctrl-icon ' + territoriesIconClassName[index]}
|
||||
aria-label={intl.formatMessage(
|
||||
{
|
||||
|
|
|
@ -121,6 +121,11 @@ export const AMERICAN_SAMOA_BOUNDS: LngLatBoundsLike = [
|
|||
[-168.1433, -11.046934],
|
||||
];
|
||||
|
||||
export const US_VIRGIN_ISLANDS_BOUNDS: LngLatBoundsLike = [
|
||||
[-65.5782239, 17.6739145],
|
||||
[-64.2704123, 18.7495796],
|
||||
];
|
||||
|
||||
export const DEFAULT_CENTER = [32.4687126, -86.502136];
|
||||
|
||||
// Opacity
|
||||
|
|
|
@ -57,6 +57,16 @@ export const MAP = defineMessages({
|
|||
defaultMessage: 'Zoom in to the state or regional level to see prioritized communities on the map.',
|
||||
description: 'zoom warning on map',
|
||||
},
|
||||
SEARCH_PLACEHOLDER: {
|
||||
id: 'map.search.placeholder.text',
|
||||
defaultMessage: 'Enter a city, state or ZIP',
|
||||
description: 'placeholder text for search',
|
||||
},
|
||||
SEARCH_RESULTS_EMPTY_MESSAGE: {
|
||||
id: 'map.search.results.empty.text',
|
||||
defaultMessage: 'No location found. Please try another location.',
|
||||
description: 'text displaying message for no search results found',
|
||||
},
|
||||
LOWER48_SHORT: {
|
||||
id: 'map.territoryFocus.lower48.short',
|
||||
defaultMessage: '48',
|
||||
|
@ -97,15 +107,45 @@ export const MAP = defineMessages({
|
|||
defaultMessage: 'Puerto Rico',
|
||||
description: 'The full name indicating the bounds of Puerto Rico',
|
||||
},
|
||||
SEARCH_PLACEHOLDER: {
|
||||
id: 'map.search.placeholder.text',
|
||||
defaultMessage: 'Enter a city, state or ZIP',
|
||||
description: 'placeholder text for search',
|
||||
GU_SHORT: {
|
||||
id: 'map.territoryFocus.guam.short',
|
||||
defaultMessage: 'GU',
|
||||
description: 'The abbreviated name indicating the bounds of Guam',
|
||||
},
|
||||
SEARCH_RESULTS_EMPTY_MESSAGE: {
|
||||
id: 'map.search.results.empty.text',
|
||||
defaultMessage: 'No location found. Please try another location.',
|
||||
description: 'text displaying message for no search results found',
|
||||
GU_LONG: {
|
||||
id: 'map.territoryFocus.guam.long',
|
||||
defaultMessage: 'Guam',
|
||||
description: 'The full name indicating the bounds of Guam',
|
||||
},
|
||||
AS_SHORT: {
|
||||
id: 'map.territoryFocus.american.samoa.short',
|
||||
defaultMessage: 'AS',
|
||||
description: 'The abbreviated name indicating the bounds of American Somoa',
|
||||
},
|
||||
AS_LONG: {
|
||||
id: 'map.territoryFocus.american.samoa.long',
|
||||
defaultMessage: 'American Somoa',
|
||||
description: 'The full name indicating the bounds of American Somoa',
|
||||
},
|
||||
MP_SHORT: {
|
||||
id: 'map.territoryFocus.commonwealth.nmp.short',
|
||||
defaultMessage: 'MP',
|
||||
description: 'The abbreviated name indicating the bounds of Commonwealth of Northern Mariana Islands',
|
||||
},
|
||||
MP_LONG: {
|
||||
id: 'map.territoryFocus.commonwealth.nmp.long',
|
||||
defaultMessage: 'Commonwealth of Northern Mariana Islands',
|
||||
description: 'The full name indicating the bounds of Commonwealth of Northern Mariana Islands',
|
||||
},
|
||||
VI_SHORT: {
|
||||
id: 'map.territoryFocus.us.virgin.islands.short',
|
||||
defaultMessage: 'VI',
|
||||
description: 'The abbreviated name indicating the bounds of US Virgin Islands',
|
||||
},
|
||||
VI_LONG: {
|
||||
id: 'map.territoryFocus.us.virgin.islands.long',
|
||||
defaultMessage: 'US Virgin Islands',
|
||||
description: 'The full name indicating the bounds of US Virgin Islands',
|
||||
},
|
||||
});
|
||||
|
||||
|
|
|
@ -1 +1,21 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M-.54.11h24v24h-24Z" transform="translate(0.54 -0.11)" style="fill:none"/><path d="M11.74,13.46H10.18V16H8.61V13.46H4.67V12.31L8.79,6.83h1.39v5.28h1.56ZM8.61,9.22,6.34,12.11H8.61Z" transform="translate(0.54 -0.11)"/><path d="M12.74,13.77a2.23,2.23,0,0,1,.15-.83,2.62,2.62,0,0,1,.39-.67,3.51,3.51,0,0,1,.55-.54,6.51,6.51,0,0,1,.64-.43,4,4,0,0,1-1.08-.89A2,2,0,0,1,13,9.12a2.21,2.21,0,0,1,.22-.95,2.54,2.54,0,0,1,.62-.77,3.13,3.13,0,0,1,.94-.5,3.8,3.8,0,0,1,1.19-.18,4,4,0,0,1,1.1.15,3.14,3.14,0,0,1,.9.44,2.15,2.15,0,0,1,.61.7,1.82,1.82,0,0,1,.22.9,2.26,2.26,0,0,1-.4,1.34,3.46,3.46,0,0,1-1.08,1,4,4,0,0,1,1.24.95,2.07,2.07,0,0,1,.46,1.4,2.21,2.21,0,0,1-.25,1.06,2.54,2.54,0,0,1-.68.81A3.14,3.14,0,0,1,17,16a3.86,3.86,0,0,1-1.23.19A3.93,3.93,0,0,1,14.6,16a3.14,3.14,0,0,1-1-.48,2.15,2.15,0,0,1-.65-.76A2,2,0,0,1,12.74,13.77Zm4.63-.22A1,1,0,0,0,17.2,13a1.82,1.82,0,0,0-.42-.41,4.34,4.34,0,0,0-.56-.33c-.2-.1-.4-.2-.59-.31a2.45,2.45,0,0,0-1,.74,1.37,1.37,0,0,0-.35.85,1.08,1.08,0,0,0,.41.9,1.9,1.9,0,0,0,1.16.32,1.78,1.78,0,0,0,1.09-.31A1,1,0,0,0,17.37,13.55ZM14.58,9.2a1,1,0,0,0,.13.53,1.53,1.53,0,0,0,.35.37,2.64,2.64,0,0,0,.49.29l.55.26a2.13,2.13,0,0,0,.41-.26,1.88,1.88,0,0,0,.35-.34,2.2,2.2,0,0,0,.26-.39,1,1,0,0,0,.09-.41,1,1,0,0,0-.11-.47,1.15,1.15,0,0,0-.31-.35,1.19,1.19,0,0,0-.42-.21,1.59,1.59,0,0,0-.48-.07,1.51,1.51,0,0,0-.53.09,1.46,1.46,0,0,0-.41.23,1.13,1.13,0,0,0-.28.34A.92.92,0,0,0,14.58,9.2Z" transform="translate(0.54 -0.11)"/></svg>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 26.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:none;}
|
||||
</style>
|
||||
<path class="st0" d="M0,0h24v24H0L0,0z"/>
|
||||
<g>
|
||||
<path d="M8.9,15.6v-2.3H5v-1.1l3.5-5.5h1.9V12h1.1v1.2h-1.1v2.3H8.9z M6.5,12h2.3v-2c0-0.3,0-0.6,0-0.9c0-0.4,0-0.7,0-0.9H8.9
|
||||
C8.8,8.4,8.7,8.6,8.5,8.9C8.4,9.1,8.3,9.3,8.2,9.6L6.5,12z"/>
|
||||
<path d="M15.5,15.8c-0.6,0-1.1-0.1-1.6-0.3c-0.5-0.2-0.8-0.5-1.1-0.9s-0.4-0.8-0.4-1.3c0-0.6,0.2-1,0.5-1.4
|
||||
c0.3-0.4,0.7-0.7,1.1-0.9V11c-0.3-0.2-0.6-0.5-0.9-0.9c-0.2-0.3-0.4-0.7-0.4-1.2c0-0.5,0.1-0.9,0.3-1.3s0.6-0.6,1-0.8
|
||||
c0.4-0.2,0.9-0.3,1.4-0.3c0.8,0,1.4,0.2,1.9,0.7c0.5,0.4,0.7,1,0.7,1.7c0,0.4-0.1,0.8-0.4,1.2c-0.3,0.4-0.5,0.6-0.8,0.9V11
|
||||
c0.4,0.2,0.8,0.5,1.1,0.9c0.3,0.4,0.5,0.8,0.5,1.4c0,0.5-0.1,0.9-0.4,1.2c-0.3,0.4-0.6,0.7-1.1,0.9C16.6,15.6,16.1,15.8,15.5,15.8z
|
||||
M15.5,14.6c0.4,0,0.8-0.1,1.1-0.4s0.4-0.6,0.4-1c0-0.3-0.1-0.6-0.3-0.8c-0.2-0.2-0.4-0.4-0.8-0.5s-0.7-0.3-1.1-0.5
|
||||
c-0.3,0.2-0.5,0.4-0.7,0.7c-0.2,0.3-0.3,0.6-0.3,0.9c0,0.4,0.2,0.8,0.5,1.1S15,14.6,15.5,14.6z M16.1,10.6c0.2-0.2,0.4-0.5,0.6-0.7
|
||||
s0.2-0.5,0.2-0.8c0-0.4-0.1-0.7-0.3-1c-0.2-0.3-0.6-0.4-1-0.4c-0.3,0-0.6,0.1-0.9,0.3c-0.2,0.2-0.4,0.5-0.4,0.9
|
||||
c0,0.3,0.1,0.5,0.2,0.7c0.2,0.2,0.4,0.4,0.7,0.5C15.4,10.3,15.7,10.4,16.1,10.6z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
|
@ -1 +1,14 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M-.54.11h24v24h-24Z" transform="translate(0.54 -0.11)" style="fill:none"/><path d="M9.34,14H6.62L6,16H4.22L7.16,6.9H8.94L11.86,16H10ZM7,12.55H9l-.92-3H8Z" transform="translate(0.54 -0.11)"/><path d="M15.39,12.2h-.93V16H12.68V6.9h1.78v3.72h.93L17.47,6.9h2l-2.57,4.39L19.82,16h-2.2Z" transform="translate(0.54 -0.11)"/></svg>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 26.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:none;}
|
||||
</style>
|
||||
<path class="st0" d="M0,0h24v24H0L0,0z"/>
|
||||
<g>
|
||||
<path d="M3.8,15.6l3-9.2h1.9l3,9.2H9.9l-0.7-2.5H6.1l-0.7,2.5H3.8z M6.8,10.7l-0.3,1.1h2.3l-0.3-1.1c-0.1-0.5-0.3-1-0.4-1.5
|
||||
C8,8.7,7.8,8.2,7.7,7.7H7.6c-0.1,0.5-0.2,1-0.4,1.5S7,10.2,6.8,10.7z"/>
|
||||
<path d="M12.8,15.6V6.4h1.6v4.2h0l3.3-4.2h1.8L16.7,10l3.3,5.6h-1.8l-2.5-4.3l-1.3,1.6v2.7H12.8z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
|
Before Width: | Height: | Size: 415 B After Width: | Height: | Size: 747 B |
19
client/src/images/mapbtn-AS.svg
Normal file
|
@ -0,0 +1,19 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 26.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:none;}
|
||||
</style>
|
||||
<path class="st0" d="M0,0h24v24H0L0,0z"/>
|
||||
<g>
|
||||
<path d="M4.2,15.6l3-9.2h1.9l3,9.2h-1.7l-0.7-2.5H6.6l-0.7,2.5H4.2z M7.3,10.7L7,11.8h2.3L9,10.7c-0.1-0.5-0.3-1-0.4-1.5
|
||||
c-0.1-0.5-0.3-1-0.4-1.5H8.1C8,8.2,7.8,8.7,7.7,9.2S7.4,10.2,7.3,10.7z"/>
|
||||
<path d="M15.9,15.8c-0.6,0-1.2-0.1-1.8-0.3c-0.6-0.2-1.1-0.6-1.5-1l1-1.1c0.3,0.3,0.7,0.6,1.1,0.7c0.4,0.2,0.8,0.3,1.3,0.3
|
||||
c0.5,0,0.9-0.1,1.2-0.3c0.3-0.2,0.4-0.5,0.4-0.9c0-0.4-0.1-0.7-0.4-0.8c-0.3-0.2-0.6-0.3-1-0.5l-1.3-0.5c-0.3-0.1-0.6-0.3-0.9-0.5
|
||||
c-0.3-0.2-0.5-0.5-0.7-0.8C13.1,9.7,13,9.3,13,8.8c0-0.5,0.1-0.9,0.4-1.3c0.3-0.4,0.6-0.7,1.1-0.9c0.5-0.2,1-0.3,1.6-0.3
|
||||
c0.5,0,1,0.1,1.5,0.3c0.5,0.2,0.9,0.5,1.3,0.8l-0.8,1c-0.3-0.2-0.6-0.4-0.9-0.6c-0.3-0.1-0.7-0.2-1.1-0.2c-0.4,0-0.8,0.1-1,0.3
|
||||
c-0.3,0.2-0.4,0.5-0.4,0.8c0,0.2,0.1,0.4,0.2,0.6c0.1,0.2,0.3,0.3,0.5,0.4c0.2,0.1,0.5,0.2,0.7,0.3l1.2,0.5c0.5,0.2,1,0.5,1.3,0.9
|
||||
c0.3,0.4,0.5,0.9,0.5,1.6c0,0.5-0.1,0.9-0.4,1.4c-0.3,0.4-0.6,0.7-1.1,1C17.2,15.6,16.6,15.8,15.9,15.8z"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.3 KiB |
18
client/src/images/mapbtn-GU.svg
Normal file
|
@ -0,0 +1,18 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 26.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:none;}
|
||||
</style>
|
||||
<path class="st0" d="M0,0h24v24H0L0,0z"/>
|
||||
<g>
|
||||
<path d="M7.9,15.8c-0.8,0-1.6-0.2-2.2-0.5c-0.7-0.4-1.2-0.9-1.5-1.6C3.8,12.9,3.6,12,3.6,11c0-1,0.2-1.9,0.6-2.6
|
||||
c0.4-0.7,0.9-1.3,1.6-1.6s1.4-0.6,2.2-0.6c0.7,0,1.2,0.1,1.7,0.4c0.5,0.2,0.8,0.5,1.1,0.8L9.8,8.5C9.6,8.3,9.3,8.1,9,7.9
|
||||
C8.8,7.8,8.4,7.7,8,7.7C7.2,7.7,6.5,8,6,8.6C5.5,9.2,5.2,10,5.2,11c0,1,0.2,1.9,0.7,2.5s1.2,0.9,2.1,0.9c0.3,0,0.5,0,0.7-0.1
|
||||
c0.2-0.1,0.4-0.2,0.6-0.3v-2H7.6v-1.3h3.2v4c-0.3,0.3-0.7,0.6-1.2,0.8C9.1,15.7,8.5,15.8,7.9,15.8z"/>
|
||||
<path d="M16.3,15.8c-0.7,0-1.3-0.1-1.8-0.4s-0.9-0.7-1.2-1.3c-0.3-0.6-0.4-1.4-0.4-2.4V6.4h1.6v5.3c0,0.7,0.1,1.2,0.2,1.6
|
||||
c0.2,0.4,0.4,0.7,0.7,0.8c0.3,0.2,0.6,0.2,1,0.2c0.4,0,0.7-0.1,1-0.2c0.3-0.2,0.5-0.4,0.7-0.8c0.2-0.4,0.2-0.9,0.2-1.6V6.4h1.6v5.1
|
||||
c0,1-0.1,1.8-0.4,2.4c-0.3,0.6-0.7,1.1-1.2,1.3C17.6,15.6,17,15.8,16.3,15.8z"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.2 KiB |
|
@ -1 +1,13 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M-.54.11h24v24h-24Z" transform="translate(0.54 -0.11)" style="fill:none"/><path d="M9.64,12.19H6.7V16H4.92V6.9H6.7v3.7H9.64V6.9h1.78V16H9.64Z" transform="translate(0.54 -0.11)"/><path d="M12.63,14.41h2.31V8.48H12.63V6.9H19V8.48H16.72v5.93H19V16h-6.4Z" transform="translate(0.54 -0.11)"/></svg>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 26.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:none;}
|
||||
</style>
|
||||
<path class="st0" d="M0,0h24v24H0L0,0z"/>
|
||||
<g>
|
||||
<path d="M6.4,15.6V6.4H8v3.7h3.7V6.4h1.6v9.2h-1.6v-4.1H8v4.1H6.4z"/>
|
||||
<path d="M15.7,15.6V6.4h1.6v9.2H15.7z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
|
Before Width: | Height: | Size: 385 B After Width: | Height: | Size: 566 B |
17
client/src/images/mapbtn-MP.svg
Normal file
|
@ -0,0 +1,17 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 26.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:none;}
|
||||
</style>
|
||||
<path class="st0" d="M0,0h24v24H0L0,0z"/>
|
||||
<g>
|
||||
<path d="M3.7,15.6V6.4h1.8l1.6,4.5c0.1,0.3,0.2,0.6,0.3,0.9c0.1,0.3,0.2,0.6,0.3,0.9h0.1c0.1-0.3,0.2-0.6,0.3-0.9
|
||||
c0.1-0.3,0.2-0.6,0.3-0.9L10,6.4h1.8v9.2h-1.5v-4.2c0-0.3,0-0.6,0-0.9c0-0.3,0.1-0.7,0.1-1c0-0.3,0.1-0.7,0.1-0.9h-0.1l-0.7,2.1
|
||||
l-1.5,4.1h-1l-1.5-4.1L5,8.5H5C5,8.8,5,9.1,5.1,9.4c0,0.3,0.1,0.7,0.1,1c0,0.3,0,0.7,0,0.9v4.2H3.7z"/>
|
||||
<path d="M14.1,15.6V6.4H17c0.7,0,1.3,0.1,1.8,0.3c0.5,0.2,1,0.5,1.3,0.9s0.5,1,0.5,1.7c0,0.7-0.2,1.2-0.5,1.7
|
||||
c-0.3,0.4-0.7,0.8-1.2,1c-0.5,0.2-1.1,0.3-1.8,0.3h-1.3v3.4H14.1z M15.8,10.9h1.2c1.3,0,2-0.6,2-1.7c0-0.6-0.2-1-0.5-1.2
|
||||
c-0.3-0.2-0.9-0.3-1.5-0.3h-1.1V10.9z"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1 KiB |
|
@ -1 +1,17 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M-.54.11h24v24h-24Z" transform="translate(0.54 -0.11)" style="fill:none"/><path d="M5.25,7a12.1,12.1,0,0,1,1.2-.16c.44,0,.87-.06,1.31-.06a7.88,7.88,0,0,1,1.36.11,3.3,3.3,0,0,1,1.22.44,2.54,2.54,0,0,1,.89.92,3.05,3.05,0,0,1,.35,1.54,3.15,3.15,0,0,1-.3,1.43,2.79,2.79,0,0,1-.79,1,3.24,3.24,0,0,1-1.13.56,4.69,4.69,0,0,1-1.3.18H7.55l-.31,0-.21,0V16H5.25ZM7.9,8.3l-.49,0a2.53,2.53,0,0,0-.38,0v3l.16,0,.22,0H7.8a3.23,3.23,0,0,0,.69-.07,1.61,1.61,0,0,0,.62-.24,1.18,1.18,0,0,0,.43-.48,1.75,1.75,0,0,0,.17-.82,1.38,1.38,0,0,0-.16-.71,1.19,1.19,0,0,0-.41-.45,1.57,1.57,0,0,0-.58-.23A2.84,2.84,0,0,0,7.9,8.3Z" transform="translate(0.54 -0.11)"/><path d="M12.71,7l.64-.1L14,6.82l.67,0h.6a6.54,6.54,0,0,1,1.25.12,3.37,3.37,0,0,1,1.11.42,2.33,2.33,0,0,1,.78.81,2.55,2.55,0,0,1,.29,1.26,3.93,3.93,0,0,1-.11,1,3,3,0,0,1-.31.72,2.23,2.23,0,0,1-.47.54,4.33,4.33,0,0,1-.61.41l2.2,4H17.39l-1.84-3.56H14.49V16H12.71Zm2.73,1.36-.54,0a1.81,1.81,0,0,0-.41.05v2.64h.7a2.06,2.06,0,0,0,1.21-.34,1.3,1.3,0,0,0,.47-1.12,1.14,1.14,0,0,0-.37-.91A1.49,1.49,0,0,0,15.44,8.35Z" transform="translate(0.54 -0.11)"/></svg>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 26.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:none;}
|
||||
</style>
|
||||
<path class="st0" d="M0,0h24v24H0L0,0z"/>
|
||||
<g>
|
||||
<path d="M4.7,15.6V6.4h2.9c0.7,0,1.3,0.1,1.8,0.3c0.5,0.2,1,0.5,1.3,0.9s0.5,1,0.5,1.7c0,0.7-0.2,1.2-0.5,1.7
|
||||
c-0.3,0.4-0.7,0.8-1.2,1c-0.5,0.2-1.1,0.3-1.8,0.3H6.4v3.4H4.7z M6.4,10.9h1.2c1.3,0,2-0.6,2-1.7c0-0.6-0.2-1-0.5-1.2
|
||||
C8.7,7.8,8.2,7.7,7.5,7.7H6.4V10.9z"/>
|
||||
<path d="M12.9,15.6V6.4H16c0.6,0,1.2,0.1,1.7,0.3s0.9,0.5,1.2,0.8c0.3,0.4,0.4,0.9,0.4,1.6c0,0.7-0.2,1.3-0.5,1.7
|
||||
c-0.3,0.4-0.8,0.7-1.3,0.9l2.2,3.8h-1.8l-2-3.6h-1.4v3.6H12.9z M14.5,10.7h1.3c0.6,0,1.1-0.1,1.4-0.4c0.3-0.3,0.5-0.7,0.5-1.2
|
||||
c0-0.5-0.2-0.9-0.5-1.1c-0.3-0.2-0.8-0.3-1.4-0.3h-1.3V10.7z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1,018 B |
14
client/src/images/mapbtn-VI.svg
Normal file
|
@ -0,0 +1,14 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 26.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:none;}
|
||||
</style>
|
||||
<path class="st0" d="M0,0h24v24H0L0,0z"/>
|
||||
<g>
|
||||
<path d="M9,15.6L6.1,6.4h1.7L9.1,11c0.1,0.5,0.3,1,0.4,1.5c0.1,0.5,0.3,1,0.4,1.5H10c0.2-0.5,0.3-1,0.4-1.5c0.1-0.5,0.2-1,0.4-1.5
|
||||
l1.3-4.6h1.7l-2.8,9.2H9z"/>
|
||||
<path d="M14.8,15.6V6.4h1.6v9.2H14.8z"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 654 B |
|
@ -262,6 +262,30 @@ This section will outline styles that are component specific
|
|||
background-image: url("../images/mapbtn-PR.svg");
|
||||
}
|
||||
}
|
||||
|
||||
button.mapboxgl-ctrl-zoom-to-gu {
|
||||
.mapboxgl-ctrl-icon {
|
||||
background-image: url("../images/mapbtn-GU.svg");
|
||||
}
|
||||
}
|
||||
|
||||
button.mapboxgl-ctrl-zoom-to-as {
|
||||
.mapboxgl-ctrl-icon {
|
||||
background-image: url("../images/mapbtn-AS.svg");
|
||||
}
|
||||
}
|
||||
|
||||
button.mapboxgl-ctrl-zoom-to-mp {
|
||||
.mapboxgl-ctrl-icon {
|
||||
background-image: url("../images/mapbtn-MP.svg");
|
||||
}
|
||||
}
|
||||
|
||||
button.mapboxgl-ctrl-zoom-to-vi {
|
||||
.mapboxgl-ctrl-icon {
|
||||
background-image: url("../images/mapbtn-VI.svg");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Area Detail Component
|
||||
|
|
|
@ -49,6 +49,11 @@ DATASET_LIST = [
|
|||
"module_dir": "geocorr",
|
||||
"class_name": "GeoCorrETL",
|
||||
},
|
||||
{
|
||||
"name": "child_opportunity_index",
|
||||
"module_dir": "child_opportunity_index",
|
||||
"class_name": "ChildOpportunityIndex",
|
||||
},
|
||||
{
|
||||
"name": "mapping_inequality",
|
||||
"module_dir": "mapping_inequality",
|
||||
|
|
|
@ -4,6 +4,8 @@ import datetime
|
|||
import pandas as pd
|
||||
from data_pipeline.config import settings
|
||||
|
||||
from data_pipeline.score import field_names
|
||||
|
||||
# Base Paths
|
||||
DATA_PATH = Path(settings.APP_ROOT) / "data"
|
||||
TMP_PATH = DATA_PATH / "tmp"
|
||||
|
@ -59,88 +61,92 @@ SCORE_DOWNLOADABLE_ZIP_FILE_PATH = (
|
|||
# Column subsets
|
||||
CENSUS_COUNTIES_COLUMNS = ["USPS", "GEOID", "NAME"]
|
||||
TILES_SCORE_COLUMNS = [
|
||||
"GEOID10_TRACT",
|
||||
"State Name",
|
||||
"County Name",
|
||||
"Total population",
|
||||
"Score D (percentile)",
|
||||
"Score D (top 25th percentile)",
|
||||
"Score E (percentile)",
|
||||
"Score E (top 25th percentile)",
|
||||
"Score G (communities)",
|
||||
"Score G",
|
||||
"Definition L (communities)",
|
||||
"Definition L (percentile)",
|
||||
"Poverty (Less than 200% of federal poverty line) (percentile)",
|
||||
"Percent individuals age 25 or over with less than high school degree (percentile)",
|
||||
"Linguistic isolation (percent) (percentile)",
|
||||
"Unemployed civilians (percent) (percentile)",
|
||||
"Housing burden (percent) (percentile)",
|
||||
"Diagnosed diabetes among adults aged >=18 years (percentile)",
|
||||
"Current asthma among adults aged >=18 years (percentile)",
|
||||
"Coronary heart disease among adults aged >=18 years (percentile)",
|
||||
"Life expectancy (years) (percentile)",
|
||||
"Traffic proximity and volume (percentile)",
|
||||
"FEMA Risk Index Expected Annual Loss Score (percentile)",
|
||||
"Energy burden (percentile)",
|
||||
"Wastewater discharge (percentile)",
|
||||
"Percent pre-1960s housing (lead paint indicator) (percentile)",
|
||||
"Diesel particulate matter (percentile)",
|
||||
"Particulate matter (PM2.5) (percentile)",
|
||||
"Median household income (% of AMI) (percentile)",
|
||||
"Percent of individuals < 200% Federal Poverty Line (percentile)",
|
||||
field_names.GEOID_TRACT_FIELD,
|
||||
field_names.STATE_FIELD,
|
||||
field_names.COUNTY_FIELD,
|
||||
field_names.TOTAL_POP_FIELD,
|
||||
field_names.SCORE_D + field_names.PERCENTILE_FIELD_SUFFIX,
|
||||
field_names.SCORE_D + field_names.TOP_25_PERCENTILE_SUFFIX,
|
||||
field_names.SCORE_E + field_names.PERCENTILE_FIELD_SUFFIX,
|
||||
field_names.SCORE_E + field_names.TOP_25_PERCENTILE_SUFFIX,
|
||||
field_names.SCORE_G_COMMUNITIES,
|
||||
field_names.SCORE_G,
|
||||
field_names.SCORE_L_COMMUNITIES,
|
||||
field_names.SCORE_L + field_names.PERCENTILE_FIELD_SUFFIX,
|
||||
field_names.POVERTY_FIELD + field_names.PERCENTILE_FIELD_SUFFIX,
|
||||
field_names.HIGH_SCHOOL_ED_FIELD + field_names.PERCENTILE_FIELD_SUFFIX,
|
||||
field_names.LINGUISTIC_ISO_FIELD + field_names.PERCENTILE_FIELD_SUFFIX,
|
||||
field_names.UNEMPLOYMENT_FIELD + field_names.PERCENTILE_FIELD_SUFFIX,
|
||||
field_names.HOUSING_BURDEN_FIELD + field_names.PERCENTILE_FIELD_SUFFIX,
|
||||
field_names.DIABETES_FIELD + field_names.PERCENTILE_FIELD_SUFFIX,
|
||||
field_names.ASTHMA_FIELD + field_names.PERCENTILE_FIELD_SUFFIX,
|
||||
field_names.HEART_DISEASE_FIELD + field_names.PERCENTILE_FIELD_SUFFIX,
|
||||
field_names.LIFE_EXPECTANCY_FIELD + field_names.PERCENTILE_FIELD_SUFFIX,
|
||||
field_names.TRAFFIC_FIELD + field_names.PERCENTILE_FIELD_SUFFIX,
|
||||
field_names.FEMA_RISK_FIELD + field_names.PERCENTILE_FIELD_SUFFIX,
|
||||
field_names.ENERGY_BURDEN_FIELD + field_names.PERCENTILE_FIELD_SUFFIX,
|
||||
field_names.WASTEWATER_FIELD + field_names.PERCENTILE_FIELD_SUFFIX,
|
||||
field_names.LEAD_PAINT_FIELD + field_names.PERCENTILE_FIELD_SUFFIX,
|
||||
field_names.DIESEL_FIELD + field_names.PERCENTILE_FIELD_SUFFIX,
|
||||
field_names.PM25_FIELD + field_names.PERCENTILE_FIELD_SUFFIX,
|
||||
field_names.MEDIAN_INCOME_AS_PERCENT_OF_AMI_FIELD
|
||||
+ field_names.PERCENTILE_FIELD_SUFFIX,
|
||||
field_names.POVERTY_LESS_THAN_200_FPL_FIELD
|
||||
+ field_names.PERCENTILE_FIELD_SUFFIX,
|
||||
]
|
||||
|
||||
# columns to round floats to 2 decimals
|
||||
TILES_SCORE_FLOAT_COLUMNS = [
|
||||
"Score D (percentile)",
|
||||
"Score D (top 25th percentile)",
|
||||
"Score E (percentile)",
|
||||
"Score E (top 25th percentile)",
|
||||
"Definition L (percentile)",
|
||||
"Poverty (Less than 200% of federal poverty line)",
|
||||
"Percent individuals age 25 or over with less than high school degree",
|
||||
"Linguistic isolation (percent)",
|
||||
"Unemployed civilians (percent)",
|
||||
"Housing burden (percent)",
|
||||
"Poverty (Less than 200% of federal poverty line) (percentile)",
|
||||
"Percent individuals age 25 or over with less than high school degree (percentile)",
|
||||
"Linguistic isolation (percent) (percentile)",
|
||||
"Unemployed civilians (percent) (percentile)",
|
||||
"Housing burden (percent) (percentile)",
|
||||
"Diagnosed diabetes among adults aged >=18 years (percentile)",
|
||||
"Current asthma among adults aged >=18 years (percentile)",
|
||||
"Coronary heart disease among adults aged >=18 years (percentile)",
|
||||
"Life expectancy (years) (percentile)",
|
||||
"Traffic proximity and volume (percentile)",
|
||||
"FEMA Risk Index Expected Annual Loss Score (percentile)",
|
||||
"Energy burden (percentile)",
|
||||
"Wastewater discharge (percentile)",
|
||||
"Percent pre-1960s housing (lead paint indicator) (percentile)",
|
||||
"Diesel particulate matter (percentile)",
|
||||
"Particulate matter (PM2.5) (percentile)",
|
||||
"Median household income (% of AMI) (percentile)",
|
||||
"Percent of individuals < 200% Federal Poverty Line (percentile)",
|
||||
field_names.SCORE_D + field_names.PERCENTILE_FIELD_SUFFIX,
|
||||
field_names.SCORE_D + field_names.TOP_25_PERCENTILE_SUFFIX,
|
||||
field_names.SCORE_E + field_names.PERCENTILE_FIELD_SUFFIX,
|
||||
field_names.SCORE_E + field_names.TOP_25_PERCENTILE_SUFFIX,
|
||||
field_names.SCORE_L + field_names.PERCENTILE_FIELD_SUFFIX,
|
||||
field_names.POVERTY_FIELD,
|
||||
field_names.HIGH_SCHOOL_ED_FIELD,
|
||||
field_names.LINGUISTIC_ISO_FIELD,
|
||||
field_names.UNEMPLOYMENT_FIELD,
|
||||
field_names.HOUSING_BURDEN_FIELD,
|
||||
field_names.POVERTY_FIELD + field_names.PERCENTILE_FIELD_SUFFIX,
|
||||
field_names.HIGH_SCHOOL_ED_FIELD + field_names.PERCENTILE_FIELD_SUFFIX,
|
||||
field_names.LINGUISTIC_ISO_FIELD + field_names.PERCENTILE_FIELD_SUFFIX,
|
||||
field_names.UNEMPLOYMENT_FIELD + field_names.PERCENTILE_FIELD_SUFFIX,
|
||||
field_names.HOUSING_BURDEN_FIELD + field_names.PERCENTILE_FIELD_SUFFIX,
|
||||
field_names.DIABETES_FIELD + field_names.PERCENTILE_FIELD_SUFFIX,
|
||||
field_names.ASTHMA_FIELD + field_names.PERCENTILE_FIELD_SUFFIX,
|
||||
field_names.HEART_DISEASE_FIELD + field_names.PERCENTILE_FIELD_SUFFIX,
|
||||
field_names.LIFE_EXPECTANCY_FIELD + field_names.PERCENTILE_FIELD_SUFFIX,
|
||||
field_names.TRAFFIC_FIELD + field_names.PERCENTILE_FIELD_SUFFIX,
|
||||
field_names.FEMA_RISK_FIELD + field_names.PERCENTILE_FIELD_SUFFIX,
|
||||
field_names.ENERGY_BURDEN_FIELD + field_names.PERCENTILE_FIELD_SUFFIX,
|
||||
field_names.WASTEWATER_FIELD + field_names.PERCENTILE_FIELD_SUFFIX,
|
||||
field_names.LEAD_PAINT_FIELD + field_names.PERCENTILE_FIELD_SUFFIX,
|
||||
field_names.DIESEL_FIELD + field_names.PERCENTILE_FIELD_SUFFIX,
|
||||
field_names.PM25_FIELD + field_names.PERCENTILE_FIELD_SUFFIX,
|
||||
field_names.MEDIAN_INCOME_AS_PERCENT_OF_AMI_FIELD
|
||||
+ field_names.PERCENTILE_FIELD_SUFFIX,
|
||||
field_names.POVERTY_LESS_THAN_200_FPL_FIELD
|
||||
+ field_names.PERCENTILE_FIELD_SUFFIX,
|
||||
]
|
||||
TILES_ROUND_NUM_DECIMALS = 2
|
||||
|
||||
DOWNLOADABLE_SCORE_INDICATOR_COLUMNS_BASIC = [
|
||||
"Area Median Income (State or metropolitan)",
|
||||
"Percent of individuals < 100% Federal Poverty Line",
|
||||
"Percent individuals age 25 or over with less than high school degree",
|
||||
"Diagnosed diabetes among adults aged >=18 years",
|
||||
"Current asthma among adults aged >=18 years",
|
||||
"Coronary heart disease among adults aged >=18 years",
|
||||
"Life expectancy (years)",
|
||||
"Traffic proximity and volume",
|
||||
"FEMA Risk Index Expected Annual Loss Score",
|
||||
"Energy burden",
|
||||
"Housing burden (percent)",
|
||||
"Wastewater discharge",
|
||||
"Percent pre-1960s housing (lead paint indicator)",
|
||||
"Diesel particulate matter",
|
||||
"Particulate matter (PM2.5)",
|
||||
"Total population",
|
||||
field_names.AMI_FIELD,
|
||||
field_names.POVERTY_LESS_THAN_100_FPL_FIELD,
|
||||
field_names.HIGH_SCHOOL_ED_FIELD,
|
||||
field_names.DIABETES_FIELD,
|
||||
field_names.ASTHMA_FIELD,
|
||||
field_names.HEART_DISEASE_FIELD,
|
||||
field_names.LIFE_EXPECTANCY_FIELD,
|
||||
field_names.TRAFFIC_FIELD,
|
||||
field_names.FEMA_RISK_FIELD,
|
||||
field_names.ENERGY_BURDEN_FIELD,
|
||||
field_names.HOUSING_BURDEN_FIELD,
|
||||
field_names.WASTEWATER_FIELD,
|
||||
field_names.LEAD_PAINT_FIELD,
|
||||
field_names.DIESEL_FIELD,
|
||||
field_names.PM25_FIELD,
|
||||
field_names.TOTAL_POP_FIELD,
|
||||
]
|
||||
|
||||
# For every indicator above, we want to include percentile and min-max normalized variants also
|
||||
|
@ -155,11 +161,12 @@ DOWNLOADABLE_SCORE_INDICATOR_COLUMNS_FULL = list(
|
|||
|
||||
# Finally we augment with the GEOID10, county, and state
|
||||
DOWNLOADABLE_SCORE_COLUMNS = [
|
||||
"GEOID10_TRACT",
|
||||
"County Name",
|
||||
"State Name",
|
||||
"Score G (communities)",
|
||||
"Median household income (% of AMI)",
|
||||
"Median household income (% of state median household income) (percentile)",
|
||||
field_names.GEOID_TRACT_FIELD,
|
||||
field_names.COUNTY_FIELD,
|
||||
field_names.STATE_FIELD,
|
||||
field_names.SCORE_G_COMMUNITIES,
|
||||
field_names.MEDIAN_INCOME_AS_PERCENT_OF_AMI_FIELD,
|
||||
field_names.MEDIAN_INCOME_AS_PERCENT_OF_STATE_FIELD
|
||||
+ field_names.PERCENTILE_FIELD_SUFFIX,
|
||||
*DOWNLOADABLE_SCORE_INDICATOR_COLUMNS_FULL,
|
||||
]
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
import functools
|
||||
from collections import namedtuple
|
||||
|
||||
import pandas as pd
|
||||
|
||||
from data_pipeline.etl.base import ExtractTransformLoad
|
||||
|
@ -29,6 +31,7 @@ class ScoreETL(ExtractTransformLoad):
|
|||
self.persistent_poverty_df: pd.DataFrame
|
||||
self.census_decennial_df: pd.DataFrame
|
||||
self.census_2010_df: pd.DataFrame
|
||||
self.child_opportunity_index_df: pd.DataFrame
|
||||
|
||||
def extract(self) -> None:
|
||||
logger.info("Loading data sets from disk.")
|
||||
|
@ -162,6 +165,19 @@ class ScoreETL(ExtractTransformLoad):
|
|||
low_memory=False,
|
||||
)
|
||||
|
||||
# Load COI data
|
||||
child_opportunity_index_csv = (
|
||||
constants.DATA_PATH
|
||||
/ "dataset"
|
||||
/ "child_opportunity_index"
|
||||
/ "usa.csv"
|
||||
)
|
||||
self.child_opportunity_index_df = pd.read_csv(
|
||||
child_opportunity_index_csv,
|
||||
dtype={self.GEOID_TRACT_FIELD_NAME: "string"},
|
||||
low_memory=False,
|
||||
)
|
||||
|
||||
def _join_tract_dfs(self, census_tract_dfs: list) -> pd.DataFrame:
|
||||
logger.info("Joining Census Tract dataframes")
|
||||
|
||||
|
@ -255,6 +271,7 @@ class ScoreETL(ExtractTransformLoad):
|
|||
self.census_acs_median_incomes_df,
|
||||
self.census_decennial_df,
|
||||
self.census_2010_df,
|
||||
self.child_opportunity_index_df,
|
||||
]
|
||||
|
||||
# Sanity check each data frame before merging.
|
||||
|
@ -305,7 +322,7 @@ class ScoreETL(ExtractTransformLoad):
|
|||
field_names.FEMA_RISK_FIELD,
|
||||
field_names.URBAN_HEURISTIC_FIELD,
|
||||
field_names.AIR_TOXICS_CANCER_RISK_FIELD,
|
||||
field_names.RESPITORY_HAZARD_FIELD,
|
||||
field_names.RESPIRATORY_HAZARD_FIELD,
|
||||
field_names.DIESEL_FIELD,
|
||||
field_names.PM25_FIELD,
|
||||
field_names.OZONE_FIELD,
|
||||
|
@ -323,6 +340,7 @@ class ScoreETL(ExtractTransformLoad):
|
|||
field_names.HIGH_SCHOOL_ED_FIELD,
|
||||
field_names.UNEMPLOYMENT_FIELD,
|
||||
field_names.MEDIAN_HOUSE_VALUE_FIELD,
|
||||
field_names.COLLEGE_ATTENDANCE_FIELD,
|
||||
field_names.EXPECTED_BUILDING_LOSS_RATE_FIELD,
|
||||
field_names.EXPECTED_AGRICULTURE_LOSS_RATE_FIELD,
|
||||
field_names.EXPECTED_POPULATION_LOSS_RATE_FIELD,
|
||||
|
@ -333,6 +351,9 @@ class ScoreETL(ExtractTransformLoad):
|
|||
field_names.CENSUS_POVERTY_LESS_THAN_100_FPL_FIELD_2010,
|
||||
field_names.CENSUS_DECENNIAL_TOTAL_POPULATION_FIELD_2009,
|
||||
field_names.CENSUS_DECENNIAL_AREA_MEDIAN_INCOME_PERCENT_FIELD_2009,
|
||||
field_names.EXTREME_HEAT_FIELD,
|
||||
field_names.HEALTHY_FOOD_FIELD,
|
||||
field_names.IMPENETRABLE_SURFACES_FIELD,
|
||||
]
|
||||
|
||||
non_numeric_columns = [
|
||||
|
@ -340,7 +361,32 @@ class ScoreETL(ExtractTransformLoad):
|
|||
field_names.PERSISTENT_POVERTY_FIELD,
|
||||
]
|
||||
|
||||
columns_to_keep = non_numeric_columns + numeric_columns
|
||||
# For some columns, high values are "good", so we want to reverse the percentile
|
||||
# so that high values are "bad" and any scoring logic can still check if it's
|
||||
# >= some threshold.
|
||||
# TODO: Add more fields here.
|
||||
# https://github.com/usds/justice40-tool/issues/970
|
||||
ReversePercentile = namedtuple(
|
||||
typename="ReversePercentile",
|
||||
field_names=["field_name", "low_field_name"],
|
||||
)
|
||||
reverse_percentiles = [
|
||||
# This dictionary follows the format:
|
||||
# <field name> : <field name for low values>
|
||||
# for instance, 3rd grade reading level : Low 3rd grade reading level.
|
||||
# This low field will not exist yet, it is only calculated for the
|
||||
# percentile.
|
||||
ReversePercentile(
|
||||
field_name=field_names.READING_FIELD,
|
||||
low_field_name=field_names.LOW_READING_FIELD,
|
||||
)
|
||||
]
|
||||
|
||||
columns_to_keep = (
|
||||
non_numeric_columns
|
||||
+ numeric_columns
|
||||
+ [rp.field_name for rp in reverse_percentiles]
|
||||
)
|
||||
|
||||
df_copy = df[columns_to_keep].copy()
|
||||
|
||||
|
@ -375,6 +421,19 @@ class ScoreETL(ExtractTransformLoad):
|
|||
df_copy[col] - min_value
|
||||
) / (max_value - min_value)
|
||||
|
||||
# Create reversed percentiles for these fields
|
||||
for reverse_percentile in reverse_percentiles:
|
||||
# Calculate reverse percentiles
|
||||
# For instance, for 3rd grade reading level (score from 0-500),
|
||||
# calculate reversed percentiles and give the result the name
|
||||
# `Low 3rd grade reading level (percentile)`.
|
||||
df_copy[
|
||||
f"{reverse_percentile.low_field_name}"
|
||||
f"{field_names.PERCENTILE_FIELD_SUFFIX}"
|
||||
] = df_copy[reverse_percentile.field_name].rank(
|
||||
pct=True, ascending=False
|
||||
)
|
||||
|
||||
# Special logic: create a combined population field.
|
||||
# We sometimes run analytics on "population", and this makes a single field
|
||||
# that is either the island area's population in 2009 or the state's
|
||||
|
|
|
@ -276,12 +276,15 @@ class PostScoreETL(ExtractTransformLoad):
|
|||
inplace=False,
|
||||
)
|
||||
|
||||
logger.info("Writing downloadable csv")
|
||||
downloadable_df_copy.to_csv(csv_path, index=False)
|
||||
|
||||
logger.info("Writing downloadable excel")
|
||||
downloadable_df_copy.to_excel(excel_path, index=False)
|
||||
|
||||
logger.info("Writing downloadable csv")
|
||||
downloadable_df_copy[self.GEOID_TRACT_FIELD_NAME] = (
|
||||
'"' + downloadable_df_copy[self.GEOID_TRACT_FIELD_NAME] + '"'
|
||||
)
|
||||
downloadable_df_copy.to_csv(csv_path, index=False)
|
||||
|
||||
logger.info("Compressing files")
|
||||
files_to_compress = [csv_path, excel_path, pdf_path]
|
||||
zip_files(zip_path, files_to_compress)
|
||||
|
|
|
@ -114,6 +114,27 @@ class CensusACSETL(ExtractTransformLoad):
|
|||
)
|
||||
self.HIGH_SCHOOL_ED_FIELD = "Percent individuals age 25 or over with less than high school degree"
|
||||
|
||||
# College attendance fields
|
||||
self.COLLEGE_ATTENDANCE_TOTAL_POPULATION_ASKED = (
|
||||
"B14004_001E" # Estimate!!Total
|
||||
)
|
||||
self.COLLEGE_ATTENDANCE_MALE_ENROLLED_PUBLIC = "B14004_003E" # Estimate!!Total!!Male!!Enrolled in public college or graduate school
|
||||
self.COLLEGE_ATTENDANCE_MALE_ENROLLED_PRIVATE = "B14004_008E" # Estimate!!Total!!Male!!Enrolled in private college or graduate school
|
||||
self.COLLEGE_ATTENDANCE_FEMALE_ENROLLED_PUBLIC = "B14004_019E" # Estimate!!Total!!Female!!Enrolled in public college or graduate school
|
||||
self.COLLEGE_ATTENDANCE_FEMALE_ENROLLED_PRIVATE = "B14004_024E" # Estimate!!Total!!Female!!Enrolled in private college or graduate school
|
||||
|
||||
self.COLLEGE_ATTENDANCE_FIELDS = [
|
||||
self.COLLEGE_ATTENDANCE_TOTAL_POPULATION_ASKED,
|
||||
self.COLLEGE_ATTENDANCE_MALE_ENROLLED_PUBLIC,
|
||||
self.COLLEGE_ATTENDANCE_MALE_ENROLLED_PRIVATE,
|
||||
self.COLLEGE_ATTENDANCE_FEMALE_ENROLLED_PUBLIC,
|
||||
self.COLLEGE_ATTENDANCE_FEMALE_ENROLLED_PRIVATE,
|
||||
]
|
||||
|
||||
self.COLLEGE_ATTENDANCE_FIELD = (
|
||||
"Percent enrollment in college or graduate school"
|
||||
)
|
||||
|
||||
self.RE_FIELDS = [
|
||||
"B02001_001E",
|
||||
"B02001_002E",
|
||||
|
@ -156,15 +177,30 @@ class CensusACSETL(ExtractTransformLoad):
|
|||
|
||||
self.STATE_GEOID_FIELD_NAME = "GEOID2"
|
||||
|
||||
self.COLUMNS_TO_KEEP = (
|
||||
[
|
||||
self.GEOID_TRACT_FIELD_NAME,
|
||||
self.UNEMPLOYED_FIELD_NAME,
|
||||
self.LINGUISTIC_ISOLATION_FIELD_NAME,
|
||||
self.MEDIAN_INCOME_FIELD_NAME,
|
||||
self.POVERTY_LESS_THAN_100_PERCENT_FPL_FIELD_NAME,
|
||||
self.POVERTY_LESS_THAN_150_PERCENT_FPL_FIELD_NAME,
|
||||
self.POVERTY_LESS_THAN_200_PERCENT_FPL_FIELD_NAME,
|
||||
self.MEDIAN_HOUSE_VALUE_FIELD_NAME,
|
||||
self.HIGH_SCHOOL_ED_FIELD,
|
||||
self.COLLEGE_ATTENDANCE_FIELD,
|
||||
]
|
||||
+ self.RE_OUTPUT_FIELDS
|
||||
+ [self.PERCENT_PREFIX + field for field in self.RE_OUTPUT_FIELDS]
|
||||
)
|
||||
|
||||
self.df: pd.DataFrame
|
||||
|
||||
def extract(self) -> None:
|
||||
# Define the variables to retrieve
|
||||
variables = (
|
||||
[
|
||||
# Income field
|
||||
self.MEDIAN_INCOME_FIELD,
|
||||
# House value
|
||||
self.MEDIAN_HOUSE_VALUE_FIELD,
|
||||
]
|
||||
+ self.EMPLOYMENT_FIELDS
|
||||
|
@ -172,6 +208,7 @@ class CensusACSETL(ExtractTransformLoad):
|
|||
+ self.POVERTY_FIELDS
|
||||
+ self.EDUCATIONAL_FIELDS
|
||||
+ self.RE_FIELDS
|
||||
+ self.COLLEGE_ATTENDANCE_FIELDS
|
||||
)
|
||||
|
||||
self.df = retrieve_census_acs_data(
|
||||
|
@ -308,6 +345,14 @@ class CensusACSETL(ExtractTransformLoad):
|
|||
df["B03003_003E"] / df["B03003_001E"]
|
||||
)
|
||||
|
||||
# Calculate college attendance:
|
||||
df[self.COLLEGE_ATTENDANCE_FIELD] = (
|
||||
df[self.COLLEGE_ATTENDANCE_MALE_ENROLLED_PUBLIC]
|
||||
+ df[self.COLLEGE_ATTENDANCE_MALE_ENROLLED_PRIVATE]
|
||||
+ df[self.COLLEGE_ATTENDANCE_FEMALE_ENROLLED_PUBLIC]
|
||||
+ df[self.COLLEGE_ATTENDANCE_FEMALE_ENROLLED_PRIVATE]
|
||||
) / df[self.COLLEGE_ATTENDANCE_TOTAL_POPULATION_ASKED]
|
||||
|
||||
# Save results to self.
|
||||
self.df = df
|
||||
|
||||
|
@ -317,23 +362,7 @@ class CensusACSETL(ExtractTransformLoad):
|
|||
# mkdir census
|
||||
self.OUTPUT_PATH.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
columns_to_include = (
|
||||
[
|
||||
self.GEOID_TRACT_FIELD_NAME,
|
||||
self.UNEMPLOYED_FIELD_NAME,
|
||||
self.LINGUISTIC_ISOLATION_FIELD_NAME,
|
||||
self.MEDIAN_INCOME_FIELD_NAME,
|
||||
self.POVERTY_LESS_THAN_100_PERCENT_FPL_FIELD_NAME,
|
||||
self.POVERTY_LESS_THAN_150_PERCENT_FPL_FIELD_NAME,
|
||||
self.POVERTY_LESS_THAN_200_PERCENT_FPL_FIELD_NAME,
|
||||
self.MEDIAN_HOUSE_VALUE_FIELD_NAME,
|
||||
self.HIGH_SCHOOL_ED_FIELD,
|
||||
]
|
||||
+ self.RE_OUTPUT_FIELDS
|
||||
+ [self.PERCENT_PREFIX + field for field in self.RE_OUTPUT_FIELDS]
|
||||
)
|
||||
|
||||
self.df[columns_to_include].to_csv(
|
||||
self.df[self.COLUMNS_TO_KEEP].to_csv(
|
||||
path_or_buf=self.OUTPUT_PATH / "usa.csv", index=False
|
||||
)
|
||||
|
||||
|
|
|
@ -0,0 +1,120 @@
|
|||
from pathlib import Path
|
||||
import pandas as pd
|
||||
|
||||
from data_pipeline.etl.base import ExtractTransformLoad
|
||||
from data_pipeline.score import field_names
|
||||
from data_pipeline.utils import get_module_logger, unzip_file_from_url
|
||||
|
||||
logger = get_module_logger(__name__)
|
||||
|
||||
|
||||
class ChildOpportunityIndex(ExtractTransformLoad):
|
||||
"""ETL Child Opportunity Index data.
|
||||
|
||||
COI compiles a number of useful data sets. In the future, we could pull these
|
||||
data sets in directly from their original creators.
|
||||
|
||||
Data dictionary available when you download zip from `self.COI_FILE_URL`.
|
||||
|
||||
Data source overview: https://data.diversitydatakids.org/dataset/coi20-child-opportunity-index-2-0-database.
|
||||
|
||||
Full technical documents: https://www.diversitydatakids.org/sites/default/files/2020-02/ddk_coi2.0_technical_documentation_20200212.pdf.
|
||||
|
||||
Github repo: https://github.com/diversitydatakids/COI/
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
self.COI_FILE_URL = (
|
||||
"https://data.diversitydatakids.org/datastore/zip/f16fff12-b1e5-4f60-85d3-"
|
||||
"3a0ededa30a0?format=csv"
|
||||
)
|
||||
|
||||
self.OUTPUT_PATH: Path = (
|
||||
self.DATA_PATH / "dataset" / "child_opportunity_index"
|
||||
)
|
||||
|
||||
self.TRACT_INPUT_COLUMN_NAME = "geoid"
|
||||
self.EXTREME_HEAT_INPUT_FIELD = "HE_HEAT"
|
||||
self.HEALTHY_FOOD_INPUT_FIELD = "HE_FOOD"
|
||||
self.IMPENETRABLE_SURFACES_INPUT_FIELD = "HE_GREEN"
|
||||
self.READING_INPUT_FIELD = "ED_READING"
|
||||
|
||||
# Constants for output
|
||||
self.COLUMNS_TO_KEEP = [
|
||||
self.GEOID_TRACT_FIELD_NAME,
|
||||
field_names.EXTREME_HEAT_FIELD,
|
||||
field_names.HEALTHY_FOOD_FIELD,
|
||||
field_names.IMPENETRABLE_SURFACES_FIELD,
|
||||
field_names.READING_FIELD,
|
||||
]
|
||||
|
||||
self.raw_df: pd.DataFrame
|
||||
self.output_df: pd.DataFrame
|
||||
|
||||
def extract(self) -> None:
|
||||
logger.info("Starting 51MB data download.")
|
||||
|
||||
unzip_file_from_url(
|
||||
file_url=self.COI_FILE_URL,
|
||||
download_path=self.TMP_PATH,
|
||||
unzipped_file_path=self.TMP_PATH / "child_opportunity_index",
|
||||
)
|
||||
|
||||
self.raw_df = pd.read_csv(
|
||||
filepath_or_buffer=self.TMP_PATH
|
||||
/ "child_opportunity_index"
|
||||
/ "raw.csv",
|
||||
# The following need to remain as strings for all of their digits, not get
|
||||
# converted to numbers.
|
||||
dtype={
|
||||
self.TRACT_INPUT_COLUMN_NAME: "string",
|
||||
},
|
||||
low_memory=False,
|
||||
)
|
||||
|
||||
def transform(self) -> None:
|
||||
logger.info("Starting transforms.")
|
||||
|
||||
output_df = self.raw_df.rename(
|
||||
columns={
|
||||
self.TRACT_INPUT_COLUMN_NAME: self.GEOID_TRACT_FIELD_NAME,
|
||||
self.EXTREME_HEAT_INPUT_FIELD: field_names.EXTREME_HEAT_FIELD,
|
||||
self.HEALTHY_FOOD_INPUT_FIELD: field_names.HEALTHY_FOOD_FIELD,
|
||||
self.IMPENETRABLE_SURFACES_INPUT_FIELD: field_names.IMPENETRABLE_SURFACES_FIELD,
|
||||
self.READING_INPUT_FIELD: field_names.READING_FIELD,
|
||||
}
|
||||
)
|
||||
|
||||
# Sanity check the tract field.
|
||||
if len(output_df[self.GEOID_TRACT_FIELD_NAME].str.len().unique()) != 1:
|
||||
raise ValueError("Wrong tract length.")
|
||||
|
||||
# COI has two rows per tract: one for 2010 and one for 2015.
|
||||
output_df = output_df[output_df["year"] == 2015]
|
||||
|
||||
# Convert percents from 0-100 to 0-1 to standardize with our other fields.
|
||||
percent_fields_to_convert = [
|
||||
field_names.HEALTHY_FOOD_FIELD,
|
||||
field_names.IMPENETRABLE_SURFACES_FIELD,
|
||||
]
|
||||
|
||||
for percent_field_to_convert in percent_fields_to_convert:
|
||||
output_df[percent_field_to_convert] = (
|
||||
output_df[percent_field_to_convert] / 100
|
||||
)
|
||||
|
||||
self.output_df = output_df
|
||||
|
||||
def validate(self) -> None:
|
||||
logger.info("Validating data.")
|
||||
|
||||
pass
|
||||
|
||||
def load(self) -> None:
|
||||
logger.info("Saving CSV")
|
||||
|
||||
self.OUTPUT_PATH.mkdir(parents=True, exist_ok=True)
|
||||
self.output_df[self.COLUMNS_TO_KEEP].to_csv(
|
||||
path_or_buf=self.OUTPUT_PATH / "usa.csv", index=False
|
||||
)
|
|
@ -8,6 +8,12 @@ logger = get_module_logger(__name__)
|
|||
|
||||
|
||||
class EJSCREENETL(ExtractTransformLoad):
|
||||
"""Load EJSCREEN data.
|
||||
|
||||
Data dictionary:
|
||||
https://gaftp.epa.gov/EJSCREEN/2019/2019_EJSCREEN_columns_explained.csv
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
self.EJSCREEN_FTP_URL = "https://edap-arcgiscloud-data-commons.s3.amazonaws.com/EJSCREEN2020/EJSCREEN_Tract_2020_USPR.csv.zip"
|
||||
self.EJSCREEN_CSV = self.TMP_PATH / "EJSCREEN_Tract_2020_USPR.csv"
|
||||
|
@ -19,7 +25,7 @@ class EJSCREENETL(ExtractTransformLoad):
|
|||
field_names.TOTAL_POP_FIELD,
|
||||
# pylint: disable=duplicate-code
|
||||
field_names.AIR_TOXICS_CANCER_RISK_FIELD,
|
||||
field_names.RESPITORY_HAZARD_FIELD,
|
||||
field_names.RESPIRATORY_HAZARD_FIELD,
|
||||
field_names.DIESEL_FIELD,
|
||||
field_names.PM25_FIELD,
|
||||
field_names.OZONE_FIELD,
|
||||
|
@ -61,7 +67,7 @@ class EJSCREENETL(ExtractTransformLoad):
|
|||
# but I think that's the direction we'd like to move all ETL classes. - LMB
|
||||
"ACSTOTPOP": field_names.TOTAL_POP_FIELD,
|
||||
"CANCER": field_names.AIR_TOXICS_CANCER_RISK_FIELD,
|
||||
"RESP": field_names.RESPITORY_HAZARD_FIELD,
|
||||
"RESP": field_names.RESPIRATORY_HAZARD_FIELD,
|
||||
"DSLPM": field_names.DIESEL_FIELD,
|
||||
"PM25": field_names.PM25_FIELD,
|
||||
"OZONE": field_names.OZONE_FIELD,
|
||||
|
|
|
@ -479,7 +479,7 @@
|
|||
"comparison_fields = [\n",
|
||||
" field_names.POVERTY_LESS_THAN_100_FPL_FIELD,\n",
|
||||
" field_names.POVERTY_LESS_THAN_200_FPL_FIELD,\n",
|
||||
" field_names.MEDIAN_INCOME_PERCENT_AMI_FIELD,\n",
|
||||
" field_names.MEDIAN_INCOME_AS_PERCENT_OF_AMI_FIELD,\n",
|
||||
" field_names.LINGUISTIC_ISO_FIELD,\n",
|
||||
" field_names.UNEMPLOYMENT_FIELD,\n",
|
||||
" field_names.HIGH_SCHOOL_ED_FIELD,\n",
|
||||
|
|
|
@ -1,6 +1,12 @@
|
|||
# Suffixes
|
||||
PERCENTILE_FIELD_SUFFIX = " (percentile)"
|
||||
MIN_MAX_FIELD_SUFFIX = " (min-max normalized)"
|
||||
TOP_25_PERCENTILE_SUFFIX = " (top 25th percentile)"
|
||||
|
||||
# Geographic field names
|
||||
GEOID_TRACT_FIELD = "GEOID10_TRACT"
|
||||
STATE_FIELD = "State Name"
|
||||
COUNTY_FIELD = "County Name"
|
||||
|
||||
# Score file field names
|
||||
SCORE_A = "Score A"
|
||||
|
@ -21,6 +27,7 @@ SCORE_I = "Score I"
|
|||
SCORE_I_COMMUNITIES = "Score I (communities)"
|
||||
SCORE_K = "NMTC (communities)"
|
||||
SCORE_K_COMMUNITIES = "Score K (communities)"
|
||||
SCORE_L = "Definition L"
|
||||
SCORE_L_COMMUNITIES = "Definition L (communities)"
|
||||
L_CLIMATE = "Climate Factor (Definition L)"
|
||||
L_ENERGY = "Energy Factor (Definition L)"
|
||||
|
@ -45,7 +52,6 @@ POVERTY_LESS_THAN_150_FPL_FIELD = (
|
|||
POVERTY_LESS_THAN_100_FPL_FIELD = (
|
||||
"Percent of individuals < 100% Federal Poverty Line"
|
||||
)
|
||||
MEDIAN_INCOME_PERCENT_AMI_FIELD = "Median household income (% of AMI)"
|
||||
STATE_MEDIAN_INCOME_FIELD = (
|
||||
"Median household income (State; 2019 inflation-adjusted dollars)"
|
||||
)
|
||||
|
@ -57,6 +63,8 @@ MEDIAN_INCOME_AS_PERCENT_OF_AMI_FIELD = "Median household income (% of AMI)"
|
|||
PERSISTENT_POVERTY_FIELD = "Persistent Poverty Census Tract"
|
||||
AMI_FIELD = "Area Median Income (State or metropolitan)"
|
||||
|
||||
COLLEGE_ATTENDANCE_FIELD = "Percent enrollment in college or graduate school"
|
||||
|
||||
# Climate
|
||||
FEMA_RISK_FIELD = "FEMA Risk Index Expected Annual Loss Score"
|
||||
EXPECTED_BUILDING_LOSS_RATE_FIELD = (
|
||||
|
@ -81,6 +89,7 @@ RMP_FIELD = "Proximity to Risk Management Plan (RMP) facilities"
|
|||
TSDF_FIELD = "Proximity to TSDF sites"
|
||||
NPL_FIELD = "Proximity to NPL sites"
|
||||
AIR_TOXICS_CANCER_RISK_FIELD = "Air toxics cancer risk"
|
||||
RESPIRATORY_HAZARD_FIELD = "Respiratory hazard index"
|
||||
|
||||
# Housing
|
||||
HOUSING_BURDEN_FIELD = "Housing burden (percent)"
|
||||
|
@ -96,7 +105,6 @@ DIABETES_FIELD = "Diagnosed diabetes among adults aged >=18 years"
|
|||
ASTHMA_FIELD = "Current asthma among adults aged >=18 years"
|
||||
HEART_DISEASE_FIELD = "Coronary heart disease among adults aged >=18 years"
|
||||
LIFE_EXPECTANCY_FIELD = "Life expectancy (years)"
|
||||
RESPITORY_HAZARD_FIELD = "Respiratory hazard index"
|
||||
CANCER_FIELD = "Cancer (excluding skin cancer) among adults aged >=18 years"
|
||||
HEALTH_INSURANCE_FIELD = (
|
||||
"Current lack of health insurance among adults aged 18-64 years"
|
||||
|
@ -200,30 +208,65 @@ HOLC_GRADE_D_TRACT_50_PERCENT_FIELD: str = "Tract is >50% HOLC Grade D"
|
|||
HOLC_GRADE_D_TRACT_75_PERCENT_FIELD: str = "Tract is >75% HOLC Grade D"
|
||||
|
||||
|
||||
# Child Opportunity Index data
|
||||
# Summer days with maximum temperature above 90F.
|
||||
EXTREME_HEAT_FIELD = "Summer days above 90F"
|
||||
|
||||
# Percentage households without a car located further than a half-mile from the
|
||||
# nearest supermarket.
|
||||
HEALTHY_FOOD_FIELD = "Percent low access to healthy food"
|
||||
|
||||
# Percentage impenetrable surface areas such as rooftops, roads or parking lots.
|
||||
IMPENETRABLE_SURFACES_FIELD = "Percent impenetrable surface areas"
|
||||
|
||||
# Percentage third graders scoring proficient on standardized reading tests,
|
||||
# converted to NAEP scale score points.
|
||||
READING_FIELD = "Third grade reading proficiency"
|
||||
LOW_READING_FIELD = "Low third grade reading proficiency"
|
||||
|
||||
# Names for individual factors being exceeded
|
||||
# Climate Change
|
||||
EXPECTED_POPULATION_LOSS_RATE_LOW_INCOME_FIELD = f"At or above the {PERCENTILE}th percentile for expected population loss rate and is low income"
|
||||
EXPECTED_AGRICULTURE_LOSS_RATE_LOW_INCOME_FIELD = f"At or above the {PERCENTILE}th percentile for expected agriculture loss rate and is low income"
|
||||
EXPECTED_BUILDING_LOSS_RATE_LOW_INCOME_FIELD = f"At or above the {PERCENTILE}th percentile for expected building loss rate and is low income"
|
||||
EXTREME_HEAT_MEDIAN_HOUSE_VALUE_LOW_INCOME_FIELD = (
|
||||
f"At or above the {PERCENTILE}th percentile for summer days above 90F and "
|
||||
f"the median house value is less than {MEDIAN_HOUSE_VALUE_PERCENTILE}th "
|
||||
f"percentile and is low income"
|
||||
)
|
||||
|
||||
# Clean energy and efficiency
|
||||
PM25_EXPOSURE_LOW_INCOME_FIELD = f"At or above the {PERCENTILE}th percentile for PM2.5 exposure and is low income"
|
||||
ENERGY_BURDEN_LOW_INCOME_FIELD = f"At or above the {PERCENTILE}th percentile for energy burden and is low income"
|
||||
|
||||
# Clean transportation
|
||||
DIESEL_PARTICULATE_MATTER_LOW_INCOME_FIELD = f"At or above the {PERCENTILE}th percentile for diesel particulate matter and is low income"
|
||||
TRAFFIC_PROXIMITY_LOW_INCOME_FIELD = f"At or above the {PERCENTILE}th percentile for traffic proximity and is low income"
|
||||
|
||||
# Affordable and Sustainable Housing
|
||||
LEAD_PAINT_MEDIAN_HOME_VALUE_LOW_INCOME_FIELD = (
|
||||
LEAD_PAINT_MEDIAN_HOUSE_VALUE_LOW_INCOME_FIELD = (
|
||||
f"At or above the {PERCENTILE}th percentile for lead paint and"
|
||||
" the median house value is less than {MEDIAN_HOUSE_VALUE_PERCENTILE}th percentile and is low income"
|
||||
f" the median house value is less than {MEDIAN_HOUSE_VALUE_PERCENTILE}th "
|
||||
f"percentile and is low income"
|
||||
)
|
||||
HOUSING_BURDEN_LOW_INCOME_FIELD = f"At or above the {PERCENTILE}th percentile for housing burden and is low income"
|
||||
|
||||
IMPENETRABLE_SURFACES_LOW_INCOME_FIELD = (
|
||||
f"At or above the {PERCENTILE}th percentile for impenetrable surfaces and is low "
|
||||
f"income"
|
||||
)
|
||||
|
||||
# Remediation and Reduction of Legacy Pollution
|
||||
RMP_LOW_INCOME_FIELD = f"At or above the {PERCENTILE}th percentile for proximity to RMP sites and is low income"
|
||||
SUPERFUND_LOW_INCOME_FIELD = f"At or above the {PERCENTILE}th percentile for proximity to superfund sites and is low income"
|
||||
HAZARDOUS_WASTE_LOW_INCOME_FIELD = f"At or above the {PERCENTILE}th percentile for proximity to hazardous waste facilities and is low income"
|
||||
AIR_TOXICS_CANCER_RISK_LOW_INCOME_FIELD = f"At or above the {PERCENTILE}th percentile for air toxics cancer risk and is low income"
|
||||
RESPIRATORY_HAZARD_LOW_INCOME_FIELD = f"At or above the {PERCENTILE}th percentile for respiratory hazard index and is low income"
|
||||
|
||||
# Critical Clean Water and Waste Infrastructure
|
||||
WASTEWATER_DISCHARGE_LOW_INCOME_FIELD = f"At or above the {PERCENTILE}th percentile for wastewater discharge and is low income"
|
||||
# Health Burden
|
||||
|
||||
# Health Burdens
|
||||
DIABETES_LOW_INCOME_FIELD = (
|
||||
f"At or above the {PERCENTILE}th percentile for diabetes and is low income"
|
||||
)
|
||||
|
@ -234,25 +277,35 @@ HEART_DISEASE_LOW_INCOME_FIELD = f"At or above the {PERCENTILE}th percentile for
|
|||
|
||||
LIFE_EXPECTANCY_LOW_INCOME_FIELD = f"At or above the {PERCENTILE}th percentile for life expectancy and is low income"
|
||||
|
||||
HEALTHY_FOOD_LOW_INCOME_FIELD = (
|
||||
f"At or above the {PERCENTILE}th percentile for low "
|
||||
f"access to healthy food and is low income"
|
||||
)
|
||||
|
||||
# Workforce
|
||||
UNEMPLOYMENT_LOW_HS_EDUCATION_FIELD = (
|
||||
f"At or above the {PERCENTILE}th percentile for unemployment"
|
||||
" and low HS education"
|
||||
" and has low HS education"
|
||||
)
|
||||
|
||||
LINGUISTIC_ISOLATION_LOW_HS_EDUCATION_FIELD = (
|
||||
f"At or above the {PERCENTILE}th percentile for households in linguistic isolation"
|
||||
" and low HS education"
|
||||
" and has low HS education"
|
||||
)
|
||||
|
||||
POVERTY_LOW_HS_EDUCATION_FIELD = (
|
||||
f"At or above the {PERCENTILE}th percentile for households at or below 100% federal poverty level"
|
||||
" and low HS education"
|
||||
" and has low HS education"
|
||||
)
|
||||
|
||||
LOW_READING_LOW_HS_EDUCATION_FIELD = (
|
||||
f"At or above the {PERCENTILE}th percentile for low 3rd grade reading proficiency"
|
||||
" and has low HS education"
|
||||
)
|
||||
|
||||
MEDIAN_INCOME_LOW_HS_EDUCATION_FIELD = (
|
||||
f"At or below the {PERCENTILE}th percentile for median income"
|
||||
" and low HS education"
|
||||
" and has low HS education"
|
||||
)
|
||||
|
||||
THRESHOLD_COUNT = "Total threshold criteria exceeded"
|
||||
|
|
|
@ -54,7 +54,7 @@ class ScoreC(Score):
|
|||
[
|
||||
field_names.AIR_TOXICS_CANCER_RISK_FIELD
|
||||
+ field_names.PERCENTILE_FIELD_SUFFIX,
|
||||
field_names.RESPITORY_HAZARD_FIELD
|
||||
field_names.RESPIRATORY_HAZARD_FIELD
|
||||
+ field_names.PERCENTILE_FIELD_SUFFIX,
|
||||
field_names.DIESEL_FIELD + field_names.PERCENTILE_FIELD_SUFFIX,
|
||||
field_names.PM25_FIELD + field_names.PERCENTILE_FIELD_SUFFIX,
|
||||
|
|
|
@ -36,7 +36,7 @@ class ScoreF(Score):
|
|||
)
|
||||
| (
|
||||
self.df[
|
||||
field_names.RESPITORY_HAZARD_FIELD
|
||||
field_names.RESPIRATORY_HAZARD_FIELD
|
||||
+ field_names.PERCENTILE_FIELD_SUFFIX
|
||||
]
|
||||
> 0.9
|
||||
|
|
|
@ -177,6 +177,8 @@ class ScoreL(Score):
|
|||
field_names.EXPECTED_POPULATION_LOSS_RATE_LOW_INCOME_FIELD,
|
||||
field_names.EXPECTED_AGRICULTURE_LOSS_RATE_LOW_INCOME_FIELD,
|
||||
field_names.EXPECTED_BUILDING_LOSS_RATE_LOW_INCOME_FIELD,
|
||||
field_names.EXTREME_HEAT_MEDIAN_HOUSE_VALUE_LOW_INCOME_FIELD,
|
||||
field_names.IMPENETRABLE_SURFACES_LOW_INCOME_FIELD,
|
||||
]
|
||||
|
||||
expected_population_loss_threshold = (
|
||||
|
@ -203,6 +205,28 @@ class ScoreL(Score):
|
|||
>= self.ENVIRONMENTAL_BURDEN_THRESHOLD
|
||||
)
|
||||
|
||||
extreme_heat_median_home_value_threshold = (
|
||||
self.df[
|
||||
field_names.EXTREME_HEAT_FIELD
|
||||
+ field_names.PERCENTILE_FIELD_SUFFIX
|
||||
]
|
||||
>= self.ENVIRONMENTAL_BURDEN_THRESHOLD
|
||||
) & (
|
||||
self.df[
|
||||
field_names.MEDIAN_HOUSE_VALUE_FIELD
|
||||
+ field_names.PERCENTILE_FIELD_SUFFIX
|
||||
]
|
||||
<= self.MEDIAN_HOUSE_VALUE_THRESHOLD
|
||||
)
|
||||
|
||||
impenetrable_surfaces_threshold = (
|
||||
self.df[
|
||||
field_names.IMPENETRABLE_SURFACES_FIELD
|
||||
+ field_names.PERCENTILE_FIELD_SUFFIX
|
||||
]
|
||||
>= self.ENVIRONMENTAL_BURDEN_THRESHOLD
|
||||
)
|
||||
|
||||
self.df[field_names.EXPECTED_POPULATION_LOSS_RATE_LOW_INCOME_FIELD] = (
|
||||
expected_population_loss_threshold
|
||||
& self.df[field_names.FPL_200_SERIES]
|
||||
|
@ -218,6 +242,18 @@ class ScoreL(Score):
|
|||
& self.df[field_names.FPL_200_SERIES]
|
||||
)
|
||||
|
||||
self.df[
|
||||
field_names.EXTREME_HEAT_MEDIAN_HOUSE_VALUE_LOW_INCOME_FIELD
|
||||
] = (
|
||||
extreme_heat_median_home_value_threshold
|
||||
& self.df[field_names.FPL_200_SERIES]
|
||||
)
|
||||
|
||||
self.df[field_names.IMPENETRABLE_SURFACES_LOW_INCOME_FIELD] = (
|
||||
impenetrable_surfaces_threshold
|
||||
& self.df[field_names.FPL_200_SERIES]
|
||||
)
|
||||
|
||||
self._increment_total_eligibility_exceeded(climate_eligibility_columns)
|
||||
|
||||
return self.df[climate_eligibility_columns].any(axis="columns")
|
||||
|
@ -320,11 +356,11 @@ class ScoreL(Score):
|
|||
# poverty level. Source: Census's American Community Survey]
|
||||
|
||||
housing_eligibility_columns = [
|
||||
field_names.LEAD_PAINT_MEDIAN_HOME_VALUE_LOW_INCOME_FIELD,
|
||||
field_names.LEAD_PAINT_MEDIAN_HOUSE_VALUE_LOW_INCOME_FIELD,
|
||||
field_names.HOUSING_BURDEN_LOW_INCOME_FIELD,
|
||||
]
|
||||
|
||||
lead_paint_median_house_hold_threshold = (
|
||||
lead_paint_median_home_value_threshold = (
|
||||
self.df[
|
||||
field_names.LEAD_PAINT_FIELD
|
||||
+ field_names.PERCENTILE_FIELD_SUFFIX
|
||||
|
@ -347,8 +383,8 @@ class ScoreL(Score):
|
|||
)
|
||||
|
||||
# series by series indicators
|
||||
self.df[field_names.LEAD_PAINT_MEDIAN_HOME_VALUE_LOW_INCOME_FIELD] = (
|
||||
lead_paint_median_house_hold_threshold
|
||||
self.df[field_names.LEAD_PAINT_MEDIAN_HOUSE_VALUE_LOW_INCOME_FIELD] = (
|
||||
lead_paint_median_home_value_threshold
|
||||
& self.df[field_names.FPL_200_SERIES]
|
||||
)
|
||||
|
||||
|
@ -371,6 +407,8 @@ class ScoreL(Score):
|
|||
field_names.RMP_LOW_INCOME_FIELD,
|
||||
field_names.SUPERFUND_LOW_INCOME_FIELD,
|
||||
field_names.HAZARDOUS_WASTE_LOW_INCOME_FIELD,
|
||||
field_names.AIR_TOXICS_CANCER_RISK_LOW_INCOME_FIELD,
|
||||
field_names.RESPIRATORY_HAZARD_LOW_INCOME_FIELD,
|
||||
]
|
||||
|
||||
rmp_sites_threshold = (
|
||||
|
@ -390,6 +428,22 @@ class ScoreL(Score):
|
|||
>= self.ENVIRONMENTAL_BURDEN_THRESHOLD
|
||||
)
|
||||
|
||||
air_toxics_cancer_risk_threshold = (
|
||||
self.df[
|
||||
field_names.AIR_TOXICS_CANCER_RISK_FIELD
|
||||
+ field_names.PERCENTILE_FIELD_SUFFIX
|
||||
]
|
||||
>= self.ENVIRONMENTAL_BURDEN_THRESHOLD
|
||||
)
|
||||
|
||||
respiratory_hazard_risk_threshold = (
|
||||
self.df[
|
||||
field_names.RESPIRATORY_HAZARD_FIELD
|
||||
+ field_names.PERCENTILE_FIELD_SUFFIX
|
||||
]
|
||||
>= self.ENVIRONMENTAL_BURDEN_THRESHOLD
|
||||
)
|
||||
|
||||
# individual series-by-series
|
||||
self.df[field_names.RMP_LOW_INCOME_FIELD] = (
|
||||
rmp_sites_threshold & self.df[field_names.FPL_200_SERIES]
|
||||
|
@ -400,6 +454,14 @@ class ScoreL(Score):
|
|||
self.df[field_names.HAZARDOUS_WASTE_LOW_INCOME_FIELD] = (
|
||||
tsdf_sites_threshold & self.df[field_names.FPL_200_SERIES]
|
||||
)
|
||||
self.df[field_names.AIR_TOXICS_CANCER_RISK_LOW_INCOME_FIELD] = (
|
||||
air_toxics_cancer_risk_threshold
|
||||
& self.df[field_names.FPL_200_SERIES]
|
||||
)
|
||||
self.df[field_names.RESPIRATORY_HAZARD_LOW_INCOME_FIELD] = (
|
||||
respiratory_hazard_risk_threshold
|
||||
& self.df[field_names.FPL_200_SERIES]
|
||||
)
|
||||
|
||||
self._increment_total_eligibility_exceeded(
|
||||
pollution_eligibility_columns
|
||||
|
@ -449,6 +511,7 @@ class ScoreL(Score):
|
|||
field_names.DIABETES_LOW_INCOME_FIELD,
|
||||
field_names.ASTHMA_LOW_INCOME_FIELD,
|
||||
field_names.HEART_DISEASE_LOW_INCOME_FIELD,
|
||||
field_names.HEALTHY_FOOD_LOW_INCOME_FIELD,
|
||||
field_names.LIFE_EXPECTANCY_LOW_INCOME_FIELD,
|
||||
]
|
||||
|
||||
|
@ -474,6 +537,14 @@ class ScoreL(Score):
|
|||
>= self.ENVIRONMENTAL_BURDEN_THRESHOLD
|
||||
)
|
||||
|
||||
healthy_food_threshold = (
|
||||
self.df[
|
||||
field_names.HEALTHY_FOOD_FIELD
|
||||
+ field_names.PERCENTILE_FIELD_SUFFIX
|
||||
]
|
||||
>= self.ENVIRONMENTAL_BURDEN_THRESHOLD
|
||||
)
|
||||
|
||||
life_expectancy_threshold = (
|
||||
self.df[
|
||||
field_names.LIFE_EXPECTANCY_FIELD
|
||||
|
@ -496,6 +567,9 @@ class ScoreL(Score):
|
|||
self.df[field_names.LIFE_EXPECTANCY_LOW_INCOME_FIELD] = (
|
||||
life_expectancy_threshold & self.df[field_names.FPL_200_SERIES]
|
||||
)
|
||||
self.df[field_names.HEALTHY_FOOD_LOW_INCOME_FIELD] = (
|
||||
healthy_food_threshold & self.df[field_names.FPL_200_SERIES]
|
||||
)
|
||||
|
||||
self._increment_total_eligibility_exceeded(health_eligibility_columns)
|
||||
|
||||
|
@ -513,6 +587,15 @@ class ScoreL(Score):
|
|||
# Where the high school degree achievement rates for adults 25 years and older is less than 95%
|
||||
# (necessary to screen out university block groups)
|
||||
|
||||
# Workforce criteria for states fields.
|
||||
workforce_eligibility_columns = [
|
||||
field_names.UNEMPLOYMENT_LOW_HS_EDUCATION_FIELD,
|
||||
field_names.POVERTY_LOW_HS_EDUCATION_FIELD,
|
||||
field_names.LINGUISTIC_ISOLATION_LOW_HS_EDUCATION_FIELD,
|
||||
field_names.MEDIAN_INCOME_LOW_HS_EDUCATION_FIELD,
|
||||
field_names.LOW_READING_LOW_HS_EDUCATION_FIELD,
|
||||
]
|
||||
|
||||
high_scool_achievement_rate_threshold = (
|
||||
self.df[field_names.HIGH_SCHOOL_ED_FIELD]
|
||||
>= self.LACK_OF_HIGH_SCHOOL_MINIMUM_THRESHOLD
|
||||
|
@ -528,7 +611,7 @@ class ScoreL(Score):
|
|||
|
||||
median_income_threshold = (
|
||||
self.df[
|
||||
field_names.MEDIAN_INCOME_PERCENT_AMI_FIELD
|
||||
field_names.MEDIAN_INCOME_AS_PERCENT_OF_AMI_FIELD
|
||||
+ field_names.PERCENTILE_FIELD_SUFFIX
|
||||
]
|
||||
# Note: a high median income as a % of AMI is good, so take 1 minus the threshold to invert it.
|
||||
|
@ -552,6 +635,14 @@ class ScoreL(Score):
|
|||
>= self.ENVIRONMENTAL_BURDEN_THRESHOLD
|
||||
)
|
||||
|
||||
low_reading_threshold = (
|
||||
self.df[
|
||||
field_names.LOW_READING_FIELD
|
||||
+ field_names.PERCENTILE_FIELD_SUFFIX
|
||||
]
|
||||
>= self.ENVIRONMENTAL_BURDEN_THRESHOLD
|
||||
)
|
||||
|
||||
self.df[field_names.LINGUISTIC_ISOLATION_LOW_HS_EDUCATION_FIELD] = (
|
||||
linguistic_isolation_threshold
|
||||
& high_scool_achievement_rate_threshold
|
||||
|
@ -569,15 +660,9 @@ class ScoreL(Score):
|
|||
unemployment_threshold & high_scool_achievement_rate_threshold
|
||||
)
|
||||
|
||||
# Workforce criteria for states fields that create indicator columns
|
||||
# for each tract in order to indicate whether they met any of the four
|
||||
# criteria. We will used this create individual indicator columns.
|
||||
workforce_eligibility_columns = [
|
||||
field_names.UNEMPLOYMENT_LOW_HS_EDUCATION_FIELD,
|
||||
field_names.POVERTY_LOW_HS_EDUCATION_FIELD,
|
||||
field_names.LINGUISTIC_ISOLATION_LOW_HS_EDUCATION_FIELD,
|
||||
field_names.MEDIAN_INCOME_LOW_HS_EDUCATION_FIELD,
|
||||
]
|
||||
self.df[field_names.LOW_READING_LOW_HS_EDUCATION_FIELD] = (
|
||||
low_reading_threshold & high_scool_achievement_rate_threshold
|
||||
)
|
||||
|
||||
workforce_combined_criteria_for_states = self.df[
|
||||
workforce_eligibility_columns
|
||||
|
|