Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
59 commits
Select commit Hold shift + click to select a range
24fadc5
Merge branch 'feature/jir' into dev/jab
jacob-a-brown Sep 20, 2024
ed7a74a
Added note to README.md for new sources to make tests
jacob-a-brown Sep 20, 2024
2d8530f
Convert MultiPolygon to Polygon for ST connector
jacob-a-brown Sep 20, 2024
eb9f923
Convert MultiPolygon to Polygon for ST2
jacob-a-brown Sep 23, 2024
3f0dd87
Merge branch 'feature/jir' into dev/jab
jacob-a-brown Sep 23, 2024
bf1b4c3
Merge branch 'dev/jir' into dev/jab
jacob-a-brown Sep 23, 2024
ec7a288
Added comment about contains in the transformer
jacob-a-brown Sep 24, 2024
5d7f451
Only change poly from MultiPolygon to Polygon by checking type
jacob-a-brown Sep 24, 2024
fb602c9
User site.id instead of site.name in reporting to be consistent
jacob-a-brown Sep 24, 2024
f9b771b
Start enumeration at 1 to get the correct number of sites for limits
jacob-a-brown Sep 24, 2024
3383a22
Only count sites toward site_limit if they have associated records
jacob-a-brown Sep 24, 2024
4ffa71e
Pass waterlevels tests
jacob-a-brown Sep 24, 2024
202b99a
Docstring for BaseTransformer._transform
jacob-a-brown Sep 25, 2024
7efceae
Changed config for BoR tests as it is in Otero County
jacob-a-brown Sep 25, 2024
20473bd
Added log and warn to transformer to communicate information to user
jacob-a-brown Sep 25, 2024
afda0b4
Updated docstring and type hints for BaseSiteSource._transform_sites
jacob-a-brown Sep 25, 2024
2d02e4a
Renamed parent_record site_record for clarity
jacob-a-brown Sep 25, 2024
b05098e
Disallow None values - including them breaks statistics/summaries
jacob-a-brown Nov 1, 2024
d9c1a13
Revert to old NMBGMR API until /v1 is live
jacob-a-brown Nov 1, 2024
7aa2d80
Ignore output files
jacob-a-brown Nov 1, 2024
b6d01b4
Enable user to specify single timeseries option for a single file
jacob-a-brown Nov 1, 2024
1807cd6
Add source, id, and parameter unit to timeseries files
jacob-a-brown Nov 1, 2024
084462b
Only add headers for first line of timeseries file
jacob-a-brown Nov 1, 2024
4d101df
Skip check() and discover() until implemented
jacob-a-brown Nov 1, 2024
8a8aa10
Enable user to choose separate timeseries files, or single timeseries…
jacob-a-brown Nov 1, 2024
9f4dbb5
Enable parameter record id to be same as site id | mg/L CaCO3 unit co…
jacob-a-brown Nov 4, 2024
cf09bee
Persist logs & warnings | Log site indices for user to track | Skip s…
jacob-a-brown Nov 4, 2024
5f6cc3b
Clean ST2 waterlevel records - only return if not None
jacob-a-brown Nov 5, 2024
02d045f
Keep non-numeric results if not summarize, keep for timeseries data
jacob-a-brown Nov 5, 2024
8e7ab1c
Add horizontal_datum to summary records
jacob-a-brown Nov 5, 2024
f422d78
Add horizontal_datum to summary records
jacob-a-brown Nov 5, 2024
bb5e4ee
Log if no sites are found
jacob-a-brown Nov 5, 2024
2d84c61
Catch value errors when converting units
jacob-a-brown Nov 5, 2024
5c093ff
Log/warn failed to convert units message
jacob-a-brown Nov 5, 2024
25cf6fa
Restrict WQP data to Water samples only
jacob-a-brown Nov 5, 2024
d65765c
Restrict WQP sites to New Mexico only
jacob-a-brown Nov 5, 2024
c277aab
Fixed statecode typo
jacob-a-brown Nov 5, 2024
dedc224
catch CaCO3 units edgecase for WQP data
jacob-a-brown Nov 5, 2024
16c6473
Provide site id for skipped converted unit items
jacob-a-brown Nov 5, 2024
05f16cb
Fixed error where records were added to time series that shouldve bee…
jacob-a-brown Nov 5, 2024
7c4ce17
Write configuration to output.logs.txt
jacob-a-brown Nov 5, 2024
8d9036c
Added missing string from config logs for export
jacob-a-brown Nov 5, 2024
777cfd0
Format/CICD for push to GitHub for branch dev/jab
jacob-a-brown Nov 5, 2024
4cd7154
Formatting changes
jacob-a-brown Nov 5, 2024
b7d4a0c
Removed redundant print message
jacob-a-brown Nov 5, 2024
bbc06bf
Clarify warning that no records were found for a site
jacob-a-brown Nov 6, 2024
b0b9e20
Add Silica analyte
jacob-a-brown Nov 6, 2024
01990ff
Silica mapping for all but dwb
jacob-a-brown Nov 6, 2024
064aa3c
Merge branch 'dev/jab' of https://github.com/DataIntegrationGroup/Dat…
jacob-a-brown Nov 6, 2024
a250b91
Conversion factor=1 for CaCO3 if unit is mg/L as CaCO3, else warn user
jacob-a-brown Nov 7, 2024
7933b35
DWB analyte mappings
jacob-a-brown Nov 7, 2024
7015139
Formatting changes
jacob-a-brown Nov 7, 2024
3c00090
Update conversion factor for HCO3- when unit are mg/L as CaCO3
jacob-a-brown Nov 11, 2024
8e3cfd8
Clarified docstrings | Simplified gathering log
jacob-a-brown Nov 11, 2024
4fe499c
Make log message more informative
jacob-a-brown Nov 11, 2024
fbe2595
Update NMBGMR URLs for new API
jacob-a-brown Nov 11, 2024
41e7dc0
Handle DWB non-detects
jacob-a-brown Nov 11, 2024
082e583
Formatting changes
jacob-a-brown Nov 11, 2024
0dc1bde
Added silica to list of available analytes
jacob-a-brown Nov 14, 2024
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
2 changes: 1 addition & 1 deletion .github/workflows/cicd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ name: CI/CD

on:
push:
branches: [ "main", "feature/jir"]
branches: [ "main", "feature/jir", "dev/jab"]
pull_request:
branches: [ "main"]

Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/format_code.yml
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
name: Format code
on:
pull_request:
branches: [feature/jir, ]
branches: [feature/jir]
push:
branches: [feature/jir,]
branches: [feature/jir, dev/jab]
jobs:
format:
runs-on: ubuntu-latest
Expand Down
9 changes: 9 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -169,3 +169,12 @@ cython_debug/
# and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/

# outputs
output_timeseries
output.combined.csv
output.csv
output.sites.csv
output.timeseries.csv
output.logs.txt
output.warnings.txt
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,14 @@ pip install nmuwd
```

## Usage

### Timeseries & Summary
The flag `--separate_timeseries_files` exports timeseries for every location in their own file in the directory output_series (e.g. AB-0002.csv, AB-0003.csv). Locations with only one observation are gathered and exported to the file `output.combined.csv.

The flag `--single_timeseries_file` exports all timeseries for all locations in one file titled output.timeseries.csv. It also exports a file titled output.sites.csv that contains site information, such as latitude, longitude, and elevation.

If neither of the above flags are specified, a summary table called output.csv is exported.

### Water Levels

Get water levels for a county. Return a summary csv
Expand Down Expand Up @@ -92,6 +100,7 @@ Available analytes:
- Nitrate
- pH
- Potassium
- Silica
- Sodium
- Sulfate
- TDS
Expand Down
45 changes: 31 additions & 14 deletions backend/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,9 @@ class Config(object):
use_csv: bool = True
use_geojson: bool = False

logs: list = []
warnings: list = []

def __init__(self, model=None, payload=None):
self.bbox = {}
if model:
Expand Down Expand Up @@ -313,21 +316,33 @@ def now_ms(self, days=0):
# return current time in milliseconds
return int((datetime.now() - td).timestamp() * 1000)

def report(self):
def report(self, log_report: bool = False):
def _report_attributes(title, attrs):
click.secho(
f"---- {title} --------------------------------------------------",
fg="yellow",
)
s = f"---- {title} --------------------------------------------------"
click.secho(s, fg="yellow")
if log_report:
self.logs.append(s)

for k in attrs:
v = getattr(self, k)
click.secho(f"{k}: {v}", fg="yellow")
click.secho("", fg="yellow")
s = f"{k}: {v}"
click.secho(s, fg="yellow")

if log_report:
self.logs.append(s)

s = ""
click.secho(s, fg="yellow")

if log_report:
self.logs.append(s)

s = "---- Begin configuration -------------------------------------\n"
click.secho(s, fg="yellow")

if log_report:
self.logs.append(s)

click.secho(
"---- Begin configuration -------------------------------------\n",
fg="yellow",
)
sources = [f"use_source_{s}" for s in SOURCE_KEYS]
attrs = [
"start_date",
Expand Down Expand Up @@ -356,9 +371,11 @@ def _report_attributes(title, attrs):
),
)

click.secho(
"---- End configuration -------------------------------------", fg="yellow"
)
s = "---- End configuration -------------------------------------\n"
click.secho(s, fg="yellow")

if log_report:
self.logs.append(s)

def validate(self):
if not self._validate_bbox():
Expand Down
6 changes: 4 additions & 2 deletions backend/connectors/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ The following are necessary for adding a source:
- the `use_source_<source>` flag needs to be added to the `analyte_sources` method in the `Config` class in **/backend/config.py** if analytes are available for that source
- the `use_source_<source>` flag needs to be added to the `water_level_sources` method in the `Config` class in **/backend/config.py** if water levels are available for that source

**IMPORTANT: add tests for the source**

For the sake of discription, the example source is called Faux.

# /backend/connectors/faux
Expand All @@ -30,7 +32,7 @@ The following methods need to be defined for Faux. See `BaseSiteSource` for doc
The following methods need to be defined for Faux. See `BaseAnalyteSource` for doc strings for each of the methods:

- `get_records`
- `_extract_parent_records`
- `_extract_site_records`
- `_extract_parameter_units`
- `_extract_most_recent`
- `_extract_parameter_result`
Expand All @@ -45,7 +47,7 @@ The following method is optional:
The following methods need to be defined for Faux. See `BaseWaterLevelSource` for doc strings for each of the methods:

- `get_records`
- `_extract_parent_records`
- `_extract_site_records`
- `_extract_parameter_units`
- `_extract_most_recent`
- `_extract_parameter_result`
Expand Down
10 changes: 4 additions & 6 deletions backend/connectors/bor/source.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,9 +87,9 @@ def _extract_most_recent(self, rs):
"units": record["attributes"]["resultAttributes"]["units"],
}

def _extract_parent_records(self, records, parent_record):
def _extract_site_records(self, records, site_record):
return [
ri for ri in records if ri["attributes"]["locationId"] == parent_record.id
ri for ri in records if ri["attributes"]["locationId"] == site_record.id
]

def _reorder_catalog_items(self, items):
Expand All @@ -98,12 +98,10 @@ def _reorder_catalog_items(self, items):
items = items[self._catalog_item_idx :] + items[: self._catalog_item_idx]
return items

def get_records(self, parent_record):
def get_records(self, site_record):
code = get_analyte_search_param(self.config.analyte, BOR_ANALYTE_MAPPING)

for i, item in enumerate(
self._reorder_catalog_items(parent_record.catalogItems)
):
for i, item in enumerate(self._reorder_catalog_items(site_record.catalogItems)):

data = self._execute_json_request(f'https://data.usbr.gov{item["id"]}')
if not data:
Expand Down
8 changes: 4 additions & 4 deletions backend/connectors/ckan/source.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,12 +112,12 @@ def _parse_response(self, resp):
class OSERoswellWaterLevelSource(OSERoswellSource, BaseWaterLevelSource):
transformer_klass = OSERoswellWaterLevelTransformer

def get_records(self, parent_record):
return self._parse_response(parent_record, self.get_response())
def get_records(self, site_record):
return self._parse_response(site_record, self.get_response())

def _parse_response(self, parent_record, resp):
def _parse_response(self, site_record, resp):
records = resp.json()["result"]["records"]
return [record for record in records if record["Site_ID"] == parent_record.id]
return [record for record in records if record["Site_ID"] == site_record.id]

def _extract_parameter_results(self, records):
return [float(r["DTWGS"]) for r in records]
Expand Down
16 changes: 8 additions & 8 deletions backend/connectors/ckan/transformer.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,17 +48,17 @@ def _transform(self, record):
class OSERoswellWaterLevelTransformer(WaterLevelTransformer):
source_tag = "CKAN/OSERoswell"

# def _transform_hook(self, record, config, parent_record):
# def _transform_hook(self, record, config, site_record):
# rec = {
# "id": parent_record.id,
# "id": site_record.id,
# "source": "CKAN/OSERoswell",
# "location": parent_record.name,
# "usgs_site_id": parent_record.id,
# "latitude": parent_record.latitude,
# "longitude": parent_record.longitude,
# "elevation": parent_record.elevation,
# "location": site_record.name,
# "usgs_site_id": site_record.id,
# "latitude": site_record.latitude,
# "longitude": site_record.longitude,
# "elevation": site_record.elevation,
# "elevation_units": "ft",
# "well_depth": parent_record.well_depth,
# "well_depth": site_record.well_depth,
# "well_depth_units": "ft",
# }
# if config.output_summary_waterlevel_stats:
Expand Down
8 changes: 4 additions & 4 deletions backend/connectors/isc_seven_rivers/source.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,12 +109,12 @@ def _extract_parameter_results(self, records):
def _extract_parameter_units(self, records):
return [r["units"] for r in records]

def get_records(self, parent_record):
def get_records(self, site_record):
config = self.config
analyte_id = self._get_analyte_id(config.analyte)
if analyte_id:
params = {
"monitoringPointId": parent_record.id,
"monitoringPointId": site_record.id,
"analyteId": analyte_id,
"start": 0,
"end": config.now_ms(days=1),
Expand Down Expand Up @@ -146,9 +146,9 @@ def get_datetime(record):
class ISCSevenRiversWaterLevelSource(BaseWaterLevelSource):
transformer_klass = ISCSevenRiversWaterLevelTransformer

def get_records(self, parent_record):
def get_records(self, site_record):
params = {
"id": parent_record.id,
"id": site_record.id,
"start": 0,
"end": self.config.now_ms(days=1),
}
Expand Down
12 changes: 6 additions & 6 deletions backend/connectors/isc_seven_rivers/transformer.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,14 +53,14 @@ class ISCSevenRiversAnalyteTransformer(AnalyteTransformer):
class ISCSevenRiversWaterLevelTransformer(WaterLevelTransformer):
source_tag = "ISCSevenRivers"

# def _transform_hook(self, record, config, parent_record):
# def _transform_hook(self, record, config, site_record):
# rec = {
# "source": "ISCSevenRivers",
# "id": parent_record.id,
# "location": parent_record.name,
# "latitude": parent_record.latitude,
# "longitude": parent_record.longitude,
# "elevation": parent_record.elevation,
# "id": site_record.id,
# "location": site_record.name,
# "latitude": site_record.latitude,
# "longitude": site_record.longitude,
# "elevation": site_record.elevation,
# "elevation_units": "ft",
# }
# if config.output_summary_waterlevel_stats:
Expand Down
27 changes: 17 additions & 10 deletions backend/connectors/mappings.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
ARSENIC,
NITRATE,
CALCIUM,
SILICA,
SODIUM,
POTASSIUM,
MAGNESIUM,
Expand All @@ -31,22 +32,24 @@
)

# DWB ===============================================================================
# the mapping below is the corresponding "@iot.id" for the ObservedProperties
DWB_ANALYTE_MAPPING: dict = {
ARSENIC: 3,
BICARBONATE: None,
CALCIUM: None,
BICARBONATE: 22, # BICARBONATE AS HCO3
CALCIUM: 11,
CARBONATE: None,
CHLORIDE: 15,
FLUORIDE: 19,
MAGNESIUM: None,
MAGNESIUM: 23,
NITRATE: 35,
POTASSIUM: None,
SODIUM: None,
POTASSIUM: 33,
SILICA: 37,
SODIUM: 38,
SULFATE: 41,
TDS: 90,
# "Uranium-238": 386,
URANIUM: 385, # "Combined Uranium"
PH: None,
PH: 81,
}
# ISC Seven Rivers ===============================================================================
"""
Expand Down Expand Up @@ -95,6 +98,7 @@
MAGNESIUM: "Magnesium",
NITRATE: "Nitrate",
POTASSIUM: "Potassium",
SILICA: "SiO2",
SODIUM: "Sodium",
SULFATE: "Sulfate",
TDS: "TDS calc",
Expand Down Expand Up @@ -137,6 +141,7 @@
MAGNESIUM: "Magnesium",
NITRATE: "Nitrate (as N)",
POTASSIUM: "Potassium",
SILICA: "Silica",
SODIUM: "Sodium",
SULFATE: "Sulfate",
TDS: "Total Dissolved Solids",
Expand All @@ -155,6 +160,7 @@
MAGNESIUM: ["Magnesium"],
NITRATE: ["Nitrate", "Nitrate-N", "Nitrate as N"],
POTASSIUM: ["Potassium"],
SILICA: ["Silica"],
SODIUM: ["Sodium"],
SULFATE: [
"Sulfate",
Expand All @@ -171,8 +177,8 @@
"""
Temp
DO
ALK HCO3
ALK CO3
ALK HCO3 <-- this is a measure of alkalinity, and not necessarily the same as Bicarbonate
ALK CO3 <-- this is a measure of alkalinity, and not necessarily the same as Carbonate
ALK OH
ALK
P ALK
Expand Down Expand Up @@ -224,14 +230,15 @@
"""
BOR_ANALYTE_MAPPING: dict = {
ARSENIC: "As",
BICARBONATE: "ALK HCO3",
BICARBONATE: None,
CALCIUM: "Ca",
CARBONATE: "ALK CO3",
CARBONATE: None,
CHLORIDE: "Cl",
FLUORIDE: "F",
MAGNESIUM: "Mg",
NITRATE: "NO3",
POTASSIUM: "K",
SILICA: "SiO2",
SODIUM: "Na",
SULFATE: "SO4",
TDS: "TDS",
Expand Down
Loading