Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Social Vulnerability Index (SVI) subpackage #169

Merged
merged 50 commits into from
May 24, 2022
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
ede9170
setup svi subpackage directory structure
aaraney Jan 27, 2022
ec51b56
fix dependency typo
aaraney Jan 28, 2022
d877b49
initial foundation for svi_client. todos: add exception handling and …
aaraney Jan 28, 2022
c96e498
strip down readme. sections will be filled in, in the future
aaraney Jan 28, 2022
6be7ae3
add urls to ESRI svi feature servers hosted by the cdc
aaraney Apr 11, 2022
79d0919
add field name map wrapper type
aaraney Apr 11, 2022
c14c215
change LOCATIONS AliasGroup to alias location abbreviations. in the f…
aaraney Apr 11, 2022
47dcbe0
method for building urls for cdc esri features servers
aaraney Apr 11, 2022
3294efd
update svi_client get method to use cdc esri feature server. this wil…
aaraney Apr 11, 2022
34be2e8
remove debug print statement
aaraney Apr 11, 2022
85d08d9
add comment to clarify why LIKE is used over equivalence test
aaraney Apr 11, 2022
1952504
remove unnecessary comment
aaraney Apr 11, 2022
67bbd5f
tract should have been census_tract in factory map
aaraney Apr 12, 2022
8fad687
change field names from theme_# to their literal names for clarity
aaraney Apr 12, 2022
d40aa26
return long dataframe format
aaraney Apr 12, 2022
317cfdc
static method overridden by subclasses to create missing fields
aaraney Apr 12, 2022
c2454ed
create missin county_fips field from some cdc data sources
aaraney Apr 12, 2022
d2f9ffe
create missing fields in get
aaraney Apr 12, 2022
ea75dae
reorder columns in get
aaraney Apr 12, 2022
d86f635
cdc esri sources with county fips present are only 3 digits long. ref…
aaraney Apr 12, 2022
9b537e3
forgot to exclude svi_edition when building urls.
aaraney Apr 12, 2022
0f29d08
add geographic context type to distinguish between SVI calc'd at the …
aaraney Apr 12, 2022
8ceb293
add get docstring summary and update example
aaraney Apr 12, 2022
1e80e03
update setup.cfg classifiers per @jarq6c's suggestions
aaraney Apr 12, 2022
b99d93a
raise value error for years without county geographic scale
aaraney Apr 12, 2022
9e2bb36
raise value errors when validating utility types
aaraney Apr 12, 2022
4978820
comment explaining why it is unnecessary to guard for response code i…
aaraney Apr 12, 2022
d3a6b90
remove unnecessary import
aaraney Apr 12, 2022
e590d85
use relative local imports in url_builder mod
aaraney Apr 12, 2022
05b81d8
add deps geopandas and pydanticc
aaraney Apr 12, 2022
ff13676
add cache_filename parameter to SVIClient constructor
aaraney Apr 22, 2022
cd37769
preform dataframe quality control before returning
aaraney Apr 22, 2022
7f990b2
update svi_client.get example now that string fields are lowered
aaraney Apr 22, 2022
4e021cd
use 1=1 where clause in US case.
aaraney Apr 22, 2022
b686baa
add SVIClient.get integration tests
aaraney Apr 22, 2022
f039bd6
add svi_client to github actions
aaraney Apr 25, 2022
6687c7d
import __future__.annotations to allow using MappingProxyType as type…
aaraney Apr 26, 2022
3f4cb4f
svi_client requires >= python 3.8 for typing.Literal support.
aaraney Apr 26, 2022
8532242
use typing_extension.Literal to provide python 3.7 support. add typin…
aaraney Apr 27, 2022
f1e430c
change min version back to python 3.7 for svi_client
aaraney Apr 27, 2022
bb95330
add results offset, results record count, and count only parameters t…
aaraney May 3, 2022
4563ad4
make concurrent requests in svi_client.get
aaraney May 3, 2022
bd0b7e2
fix typo
aaraney May 3, 2022
ef90e8e
fix bug when melting dataframes. also cast str cols to categories
aaraney May 20, 2022
f8dab85
dont sort collection of str and ints
aaraney May 20, 2022
e3b2866
add unit tests for utility fns
aaraney May 20, 2022
f916660
remove --use-feature=in-tree-build pip flag when installting package …
aaraney May 20, 2022
000bfec
rename test_utilities.py in svi client to make pytest's resolver happy
aaraney May 20, 2022
229548d
guard typing.get_args import. import typing_extensions.get_args to su…
aaraney May 20, 2022
b633153
fill out svi readme
aaraney May 24, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions python/svi_client/CONTRIBUTING.md
1 change: 1 addition & 0 deletions python/svi_client/LICENSE
2 changes: 2 additions & 0 deletions python/svi_client/MANIFEST.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
include LICENSE
include src/hydrotools/nwm_client/data/*
33 changes: 33 additions & 0 deletions python/svi_client/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# OWPHydroTools :: SVI Client

## Installation


## Usage


### Code
```python
```
### Example output
```console
```
### System Requirements

## Development

```bash
$ python3 -m venv env
$ source env/bin/activate
$ python3 -m pip install -U pip
$ python3 -m pip install -U setuptools
$ python3 -m pip install -e ".[develop]"
```

To generate a source distribution:
```bash
$ python3 -m pip install -U wheel build
$ python3 -m build
```

The packages generated in `dist/` can be installed directly with `pip` or uploaded to PyPI using `twine`.
1 change: 1 addition & 0 deletions python/svi_client/SECURITY.md
1 change: 1 addition & 0 deletions python/svi_client/TERMS.md
6 changes: 6 additions & 0 deletions python/svi_client/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[build-system]
build-backend = "setuptools.build_meta"
requires = [
"setuptools>=42",
"wheel",
]
4 changes: 4 additions & 0 deletions python/svi_client/pytest.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
[pytest]
markers =
slow: marks tests as slow (deselect with '-m "not slow"')

44 changes: 44 additions & 0 deletions python/svi_client/setup.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
[metadata]
name = hydrotools.svi_client
version = attr: hydrotools.svi_client._version.__version__
author = Austin Raney
author_email = [email protected]
description = Retrieve Social Vulnerability Index data from The Center for Disease Control / The Agency for Toxic Substances and Disease Registry.
long_description = file: README.md
long_description_content_type = text/markdown
charset = UTF-8
license = USDOC
license_files =
LICENSE
url = https://github.com/NOAA-OWP/hydrotools
project_urls =
Documentation = https://noaa-owp.github.io/hydrotools/hydrotools.svi_client.html
Source = https://github.com/NOAA-OWP/hydrotools/tree/main/python/svi_client
Tracker = https://github.com/NOAA-OWP/hydrotools/issues
classifiers =
Development Status :: 3 - Alpha
Intended Audience :: Education
Intended Audience :: Science/Research
License :: Free To Use But Restricted
Programming Language :: Python :: 3.7
Programming Language :: Python :: 3.8
Programming Language :: Python :: 3.9
Topic :: Scientific/Engineering :: Hydrology
aaraney marked this conversation as resolved.
Show resolved Hide resolved
Operating System :: OS Independent

[options]
packages = find_namespace:
package_dir =
=src
install_requires =
hydrotools._restclient
numpy >=1.20.0
pandas
python_requires = >=3.7

[options.packages.find]
where = src

[options.extras_require]
develop =
pytest
4 changes: 4 additions & 0 deletions python/svi_client/src/hydrotools/svi_client/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# removing __version__ import will cause build to fail. see: https://github.com/pypa/setuptools/issues/1724#issuecomment-627241822
from ._version import __version__

from .clients import SVIClient
1 change: 1 addition & 0 deletions python/svi_client/src/hydrotools/svi_client/_version.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
__version__ = "0.0.1"
87 changes: 87 additions & 0 deletions python/svi_client/src/hydrotools/svi_client/clients.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import io
from http import HTTPStatus
from hydrotools._restclient import RestClient
import pandas as pd

# local imports
from . import url_builders
from .types import GeographicScale, Year, utilities


class SVIClient:
_base_url = "https://svi.cdc.gov/"

def __init__(self) -> None:
self._rest_client = RestClient(
base_url=self._base_url, cache_filename="svi_client_cache"
)

def get(
self, location: str, geographic_scale: GeographicScale, year: Year
) -> pd.DataFrame:
"""[summary]

Parameters
----------
location : str
state / national name or abbreviation (e.g. "AL", "US", "Wyoming", "new york")
geographic_scale : GeographicScale "census_tract" or "county"
"county" scale data *not* available in 2000 or 2010
year : Year
2000, 2010, 2014, 2016, or 2018

Returns
-------
pd.DataFrame
Dataframe of Social Vulnerability Index values at the census tract or county scale

Examples
--------
>>> client = SVIClient()
... df = client.get("AL", "census_tract", "2018")
ST STATE ST_ABBR STCNTY ... M_UNINSUR EP_UNINSUR MP_UNINSUR E_DAYPOP
0 1 ALABAMA AL 1015 ... 12 -999.0 -999.0 656
1 1 ALABAMA AL 1015 ... 12 -999.0 -999.0 146
... .. ... ... ... ... ... ... ... ...
1178 1 ALABAMA AL 1015 ... 129 10.0 4.0 1832
1179 1 ALABAMA AL 1069 ... 98 17.7 4.4 2566

"""

url_path = url_builders.build_csv_url(
location=location, geographic_scale=geographic_scale, year=year
)

request = self._rest_client.get(url_path)

if request.status != HTTPStatus.OK: # 200
...

serialized_text = io.StringIO(request.text())

return pd.read_csv(serialized_text)

@staticmethod
def svi_documentation_url(year: Year) -> str:
year = utilities.validate_year(year)

urls = {
"2000": "https://www.atsdr.cdc.gov/placeandhealth/svi/documentation/pdf/SVI2000Documentation-H.pdf",
"2010": "https://www.atsdr.cdc.gov/placeandhealth/svi/documentation/pdf/SVI-2010-Documentation-H.pdf",
"2014": "https://www.atsdr.cdc.gov/placeandhealth/svi/documentation/pdf/SVI2014Documentation_01192022.pdf",
"2016": "https://www.atsdr.cdc.gov/placeandhealth/svi/documentation/pdf/SVI2016Documentation_01192022.pdf",
"2018": "https://www.atsdr.cdc.gov/placeandhealth/svi/documentation/pdf/SVI2018Documentation_01192022_1.pdf",
}

url = urls.get(year, None)

# raise error if valid year not in urls.
# when new svi releases are added, this will purposefully break.
if url is None:
# raise error
error_message = (
f"documentation for year: {year} has not been added to SVIClient."
)
raise ValueError(error_message)

return url
2 changes: 2 additions & 0 deletions python/svi_client/src/hydrotools/svi_client/types/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
from .type_definitions import LOCATIONS, GeographicScale, DataFormat, Year
from . import utilities
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
from hydrotools._restclient import Alias, AliasGroup

# typing imports
from typing import Literal

GeographicScale = Literal["census_tract", "county"]
DataFormat = Literal["csv", "shp"]
Year = Literal["2000", "2010", "2014", "2016", "2018", 2000, 2010, 2014, 2016, 2018]

# Geography options:
# source https://svi.cdc.gov/xmldata/SVI_StatesForDownload.xml
# used by form on https://svi.cdc.gov/data-download-wcms.html

# TODO: add "PuertoRico" and "States". will need to consider what datasets are available for these locations
LOCATIONS = AliasGroup(
[
Alias("US", ["us", "united states"]),
Alias("Alabama", ["al", "alabama"]),
Alias("Alaska", ["ak", "alaska"]),
Alias("Arizona", ["az", "arizona"]),
Alias("Arkansas", ["ar", "arkansas"]),
Alias("California", ["ca", "california"]),
Alias("Colorado", ["co", "colorado"]),
Alias("Connecticut", ["ct", "connecticut"]),
Alias("Delaware", ["de", "delaware"]),
Alias("DistrictofColumbia", ["dc", "district of columbia"]),
Alias("Florida", ["fl", "florida"]),
Alias("Georgia", ["ga", "georgia"]),
Alias("Hawaii", ["hi", "hawaii"]),
Alias("Idaho", ["id", "idaho"]),
Alias("Illinois", ["il", "illinois"]),
Alias("Indiana", ["in", "indiana"]),
Alias("Iowa", ["ia", "iowa"]),
Alias("Kansas", ["ks", "kansas"]),
Alias("Kentucky", ["ky", "kentucky"]),
Alias("Louisiana", ["la", "louisiana"]),
Alias("Maine", ["me", "maine"]),
Alias("Maryland", ["md", "maryland"]),
Alias("Massachusetts", ["ma", "massachusetts"]),
Alias("Michigan", ["mi", "michigan"]),
Alias("Minnesota", ["mn", "minnesota"]),
Alias("Mississippi", ["ms", "mississippi"]),
Alias("Missouri", ["mo", "missouri"]),
Alias("Montana", ["mt", "montana"]),
Alias("Nebraska", ["ne", "nebraska"]),
Alias("Nevada", ["nv", "nevada"]),
Alias("NewHampshire", ["nh", "new hampshire"]),
Alias("NewJersey", ["nj", "new jersey"]),
Alias("NewMexico", ["nm", "new mexico"]),
Alias("NewYork", ["ny", "new york"]),
Alias("NorthCarolina", ["nc", "north carolina"]),
Alias("NorthDakota", ["nd", "north dakota"]),
Alias("Ohio", ["oh", "ohio"]),
Alias("Oklahoma", ["ok", "oklahoma"]),
Alias("Oregon", ["or", "oregon"]),
Alias("Pennsylvania", ["pa", "pennsylvania"]),
Alias("RhodeIsland", ["ri", "rhode island"]),
Alias("SouthCarolina", ["sc", "south carolina"]),
Alias("SouthDakota", ["sd", "south dakota"]),
Alias("Tennessee", ["tn", "tennessee"]),
Alias("Texas", ["tx", "texas"]),
Alias("Utah", ["ut", "utah"]),
Alias("Vermont", ["vt", "vermont"]),
Alias("Virginia", ["va", "virginia"]),
Alias("Washington", ["wa", "washington"]),
Alias("WestVirginia", ["wv", "west virginia"]),
Alias("Wisconsin", ["wi", "wisconsin"]),
Alias("Wyoming", ["wy", "wyoming"]),
]
)
30 changes: 30 additions & 0 deletions python/svi_client/src/hydrotools/svi_client/types/utilities.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import typing


# local imports
from .type_definitions import LOCATIONS, GeographicScale, Year


def validate_location(location: str) -> str:
location_key = LOCATIONS.get(location.lower()) # noqa

if location_key is None:
...

return location_key


def validate_geographic_scale(geographic_scale: GeographicScale) -> str:
if geographic_scale not in typing.get_args(GeographicScale):
...

return geographic_scale


def validate_year(year: Year) -> str:
year_str = str(year)

if year_str not in typing.get_args(Year):
...

return year_str
Loading