Skip to content

Commit

Permalink
Two or more races pop (#190)
Browse files Browse the repository at this point in the history
  • Loading branch information
raphaellaude authored Nov 19, 2024
1 parent 8fc81fb commit 46f3e47
Show file tree
Hide file tree
Showing 13 changed files with 139 additions and 137 deletions.
96 changes: 9 additions & 87 deletions app/src/app/components/sidebar/Evaluation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,48 +3,24 @@ import {useMapStore} from '@/app/store/mapStore';
import {useQuery} from '@tanstack/react-query';
import {
CleanedP1ZoneSummaryStats,
CleanedP1ZoneSummaryStatsKeys,
getP1SummaryStats,
P1ZoneSummaryStats,
P1ZoneSummaryStatsKeys,
} from '@/app/utils/api/apiHandlers';
import {Button, Checkbox, CheckboxGroup} from '@radix-ui/themes';
import {Heading, Flex, Spinner, Text} from '@radix-ui/themes';
import {Button, CheckboxGroup} from '@radix-ui/themes';
import {Flex, Spinner, Text} from '@radix-ui/themes';
import {queryClient} from '@utils/api/queryClient';
import {formatNumber, NumberFormats} from '@/app/utils/numbers';
import {colorScheme} from '@/app/constants/colors';
import {
getEntryTotal,
getStdDevColor,
stdDevArray,
stdDevColors,
sumArray,
} from '@utils/summaryStats';
import {interpolateBlues, interpolateGreys} from 'd3-scale-chromatic';
import {getEntryTotal} from '@utils/summaryStats';
import {interpolateGreys} from 'd3-scale-chromatic';

type EvalModes = 'share' | 'count' | 'totpop';
type ColumnConfiguration<T extends Record<string, any>> = Array<{label: string; column: keyof T}>;
type EvaluationProps = {
columnConfig?: ColumnConfiguration<P1ZoneSummaryStats>;
};

// const calculateColumn = (
// mode: EvalModes,
// entry: P1ZoneSummaryStats,
// totals: P1ZoneSummaryStats,
// column: keyof Omit<CleanedP1ZoneSummaryStats, 'zone'>
// ) => {
// const count = entry[column];
// switch (mode) {
// case 'count':
// return count;
// case 'pct':
// return count / entry['total'];
// case 'share':
// return count / totals[column];
// }
// };

const defaultColumnConfig: ColumnConfiguration<P1ZoneSummaryStats> = [
{
label: 'White',
Expand All @@ -66,6 +42,10 @@ const defaultColumnConfig: ColumnConfiguration<P1ZoneSummaryStats> = [
label: 'Pacific Isl.',
column: 'nhpi_pop',
},
{
label: 'Two or More Races',
column: 'two_or_more_races_pop',
},
{
label: 'Other',
column: 'other_pop',
Expand All @@ -81,10 +61,6 @@ const modeButtonConfig: Array<{label: string; value: EvalModes}> = [
label: 'Population by Count',
value: 'count',
},
// {
// label: "Population by Percent of Zone",
// value: 'totpop'
// }
];

const numberFormats: Record<EvalModes, NumberFormats> = {
Expand All @@ -104,8 +80,6 @@ const getColConfig = (evalMode: EvalModes) => {

const Evaluation: React.FC<EvaluationProps> = ({columnConfig = defaultColumnConfig}) => {
const [evalMode, setEvalMode] = useState<EvalModes>('share');
// const [showAverages, setShowAverages] = useState<boolean>(true);
// const [showStdDev, setShowStdDev] = useState<boolean>(false);
const [colorBg, setColorBg] = useState<boolean>(true);
const [showUnassigned, setShowUnassigned] = useState<boolean>(true);

Expand Down Expand Up @@ -152,18 +126,10 @@ const Evaluation: React.FC<EvaluationProps> = ({columnConfig = defaultColumnConf
unassigned[`${key}_pct`] = total / unassigned[key];
unassigned[key] = total;
});
// const averages: Record<string, number> = {};
// const stdDevs: Record<string, number> = {};
// CleanedP1ZoneSummaryStatsKeys.forEach(key => {
// const values = data.results.map(row => row[key]);
// averages[key] = sumArray(values) / data.results.length;
// stdDevs[key] = stdDevArray(values);
// });

return {
unassigned,
maxValues,
// averages,
// stdDevs
};
}, [data?.results, totPop]);

Expand Down Expand Up @@ -210,29 +176,9 @@ const Evaluation: React.FC<EvaluationProps> = ({columnConfig = defaultColumnConf
<CheckboxGroup.Item value="unassigned" onClick={() => setShowUnassigned(v => !v)}>
Show Unassigned Population
</CheckboxGroup.Item>
{/* <CheckboxGroup.Item value="averages" onClick={() => setShowAverages(v => !v)}>
Show Zone Averages
</CheckboxGroup.Item>
<CheckboxGroup.Item value="stddev" onClick={() => setShowStdDev(v => !v)}>
Show Zone Std. Dev.
</CheckboxGroup.Item> */}
<CheckboxGroup.Item value="colorBg" onClick={() => setColorBg(v => !v)}>
<Flex gap="3">
<p>Color Cells By Values</p>
{/* {colorByStdDev && (
<span>
{Object.entries(stdDevColors)
.sort((a, b) => +a[0] - +b[0])
.map(([stdev, backgroundColor], i) => (
<span
className="inline-flex items-center justify-center size-6"
style={{backgroundColor}}
>
{+stdev > 0 ? `+${stdev}`: stdev}
</span>
))}
</span>
)} */}
</Flex>
</CheckboxGroup.Item>
</CheckboxGroup.Root>
Expand All @@ -250,30 +196,6 @@ const Evaluation: React.FC<EvaluationProps> = ({columnConfig = defaultColumnConf
</tr>
</thead>
<tbody>
{/* {!!(averages && showAverages) && (
<tr className="border-b hover:bg-gray-50">
<td className="py-2 px-4 font-medium flex flex-row items-center gap-1">
Zone Averages
</td>
{columnConfig.map((f, i) => (
<td className="py-2 px-4 text-right">
{formatNumber(averages[columnGetter(f.column)], numberFormat)}
</td>
))}
</tr>
)}
{!!(stdDevs && showStdDev) && (
<tr className="border-b hover:bg-gray-50">
<td className="py-2 px-4 font-medium flex flex-row items-center gap-1">
Zone Std. Dev.
</td>
{columnConfig.map((f, i) => (
<td className="py-2 px-4 text-right">
{formatNumber(stdDevs[columnGetter(f.column)], numberFormat)}
</td>
))}
</tr>
)} */}
{rows
.sort((a, b) => a.zone - b.zone)
.map(row => {
Expand Down
4 changes: 4 additions & 0 deletions app/src/app/utils/api/apiHandlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,7 @@ export interface P1ZoneSummaryStats {
nhpi_pop: number;
black_pop: number;
white_pop: number;
two_or_more_races_pop: number;
}
export type P1TotPopSummaryStats = Omit<P1ZoneSummaryStats, 'zone'>;

Expand All @@ -181,6 +182,7 @@ export const P1ZoneSummaryStatsKeys = [
'nhpi_pop',
'black_pop',
'white_pop',
'two_or_more_races_pop',
] as const;

export const CleanedP1ZoneSummaryStatsKeys = [
Expand All @@ -192,6 +194,7 @@ export const CleanedP1ZoneSummaryStatsKeys = [
'nhpi_pop_pct',
'black_pop_pct',
'white_pop_pct',
'two_or_more_races_pop_pct',
] as const;

export interface CleanedP1ZoneSummaryStats extends P1ZoneSummaryStats {
Expand All @@ -202,6 +205,7 @@ export interface CleanedP1ZoneSummaryStats extends P1ZoneSummaryStats {
nhpi_pop_pct: number;
black_pop_pct: number;
white_pop_pct: number;
two_or_more_races_pop_pct: number;
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
"""missing two or more races
Revision ID: d90c9a1a246b
Revises: 2494caf34886
Create Date: 2024-11-18 23:56:24.881723
"""

from typing import Sequence, Union

from alembic import op
import sqlalchemy as sa
from app.constants import SQL_DIR
from pathlib import Path


# revision identifiers, used by Alembic.
revision: str = "d90c9a1a246b"
down_revision: Union[str, None] = "2494caf34886"
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None


def upgrade() -> None:
for udf in [
"available_summary_stat_udf.sql",
"summary_stats_p1.sql",
"summary_stats_p1_totals.sql",
"summary_stats_p4.sql",
"summary_stats_p4_totals.sql",
]:
with Path(SQL_DIR, udf).open() as f:
sql = f.read()
op.execute(sql)

op.execute(
sa.text(
"""
UPDATE districtrmap d
SET available_summary_stats = (
SELECT
CASE WHEN d.child_layer IS NOT NULL THEN
(
SELECT ARRAY_AGG(summary_stat) FROM get_available_summary_stats(d.child_layer)
INTERSECT
SELECT ARRAY_AGG(summary_stat) FROM get_available_summary_stats(d.parent_layer)
)
ELSE
(SELECT ARRAY_AGG(summary_stat) FROM get_available_summary_stats(d.parent_layer))
END
)
"""
)
)


def downgrade() -> None:
# Since the previous migraiton touching this logic was buggy, not going to
# to write a downgrade for it.
pass
9 changes: 2 additions & 7 deletions backend/app/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,9 +107,7 @@ async def create_document(
DistrictrMap.tiles_s3_path.label("tiles_s3_path"), # pyright: ignore
DistrictrMap.num_districts.label("num_districts"), # pyright: ignore
DistrictrMap.extent.label("extent"), # pyright: ignore
DistrictrMap.available_summary_stats.label(
"available_summary_stats"
), # pyright: ignore
DistrictrMap.available_summary_stats.label("available_summary_stats"), # pyright: ignore
)
.where(Document.document_id == document_id)
.join(
Expand Down Expand Up @@ -261,7 +259,6 @@ async def get_assignments(document_id: str, session: Session = Depends(get_sessi

@app.get("/api/document/{document_id}", response_model=DocumentPublic)
async def get_document(document_id: str, session: Session = Depends(get_session)):

stmt = (
select(
Document.document_id,
Expand All @@ -273,9 +270,7 @@ async def get_document(document_id: str, session: Session = Depends(get_session)
DistrictrMap.tiles_s3_path.label("tiles_s3_path"), # pyright: ignore
DistrictrMap.num_districts.label("num_districts"), # pyright: ignore
DistrictrMap.extent.label("extent"), # pyright: ignore
DistrictrMap.available_summary_stats.label(
"available_summary_stats"
), # pyright: ignore
DistrictrMap.available_summary_stats.label("available_summary_stats"), # pyright: ignore
) # pyright: ignore
.where(Document.document_id == document_id)
.join(
Expand Down
2 changes: 2 additions & 0 deletions backend/app/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,7 @@ class PopulationStatsP1(BaseModel):
nhpi_pop: int
black_pop: int
white_pop: int
two_or_more_races_pop: int


class SummaryStatsP1(PopulationStatsP1):
Expand All @@ -233,6 +234,7 @@ class PopulationStatsP4(BaseModel):
non_hispanic_black_vap: int
non_hispanic_white_vap: int
non_hispanic_other_vap: int
non_hispanic_two_or_more_races_vap: int


class SummaryStatsP4(PopulationStatsP4):
Expand Down
22 changes: 12 additions & 10 deletions backend/app/sql/available_summary_stat_udf.sql
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ DECLARE
p3 BOOLEAN;
p4 BOOLEAN;
BEGIN
SELECT count(column_name) = 6 INTO p1
SELECT count(column_name) = 7 INTO p1
FROM INFORMATION_SCHEMA.COLUMNS
WHERE table_name = gerrydb_table_name
AND table_schema = 'gerrydb'
Expand All @@ -15,10 +15,11 @@ BEGIN
'amin_pop',
'nhpi_pop',
'black_pop',
'white_pop')
'white_pop',
'two_or_more_races_pop')
;

SELECT count(column_name) = 6 INTO p3
SELECT count(column_name) = 7 INTO p3
FROM INFORMATION_SCHEMA.COLUMNS
WHERE table_name = gerrydb_table_name
AND table_schema = 'gerrydb'
Expand All @@ -27,10 +28,11 @@ BEGIN
'amin_vap',
'nhpi_vap',
'black_vap',
'white_vap')
'white_vap',
'two_or_more_races_vap')
;

SELECT count(column_name) = 7 INTO p2
SELECT count(column_name) = 8 INTO p2
FROM INFORMATION_SCHEMA.COLUMNS
WHERE table_name = gerrydb_table_name
AND table_schema = 'gerrydb'
Expand All @@ -40,11 +42,11 @@ BEGIN
'non_hispanic_nhpi_pop',
'non_hispanic_black_pop',
'non_hispanic_white_pop',
'non_hispanic_other_pop'
)
'non_hispanic_other_pop',
'non_hispanic_two_or_more_races_pop')
;

SELECT count(column_name) = 7 INTO p4
SELECT count(column_name) = 8 INTO p4
FROM INFORMATION_SCHEMA.COLUMNS
WHERE table_name = gerrydb_table_name
AND table_schema = 'gerrydb'
Expand All @@ -54,8 +56,8 @@ BEGIN
'non_hispanic_nhpi_vap',
'non_hispanic_black_vap',
'non_hispanic_white_vap',
'non_hispanic_other_vap'
)
'non_hispanic_other_vap',
'non_hispanic_two_or_more_races_vap')
;

RETURN QUERY
Expand Down
10 changes: 7 additions & 3 deletions backend/app/sql/summary_stats_p1.sql
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
CREATE OR REPLACE FUNCTION get_summary_stats_p1(document_id UUID)
DROP FUNCTION IF EXISTS get_summary_stats_p1(uuid);

CREATE FUNCTION get_summary_stats_p1(document_id UUID)
RETURNS TABLE (
zone TEXT,
other_pop BIGINT,
asian_pop BIGINT,
amin_pop BIGINT,
nhpi_pop BIGINT,
black_pop BIGINT,
white_pop BIGINT
white_pop BIGINT,
two_or_more_races_pop BIGINT
) AS $$
DECLARE
doc_districtrmap RECORD;
Expand All @@ -30,7 +33,8 @@ BEGIN
SUM(COALESCE(blocks.amin_pop, 0))::BIGINT AS amin_pop,
SUM(COALESCE(blocks.nhpi_pop, 0))::BIGINT AS nhpi_pop,
SUM(COALESCE(blocks.black_pop, 0))::BIGINT AS black_pop,
SUM(COALESCE(blocks.white_pop, 0))::BIGINT AS white_pop
SUM(COALESCE(blocks.white_pop, 0))::BIGINT AS white_pop,
SUM(COALESCE(blocks.two_or_more_races_pop, 0))::BIGINT AS two_or_more_races_pop
FROM document.assignments
LEFT JOIN gerrydb.%I blocks
ON blocks.path = assignments.geo_id
Expand Down
Loading

0 comments on commit 46f3e47

Please sign in to comment.