├── .gitignore
├── .pre-commit-config.yaml
├── Dockerfile
├── LICENSE
├── Makefile
├── README.md
├── bitbucket-pipelines.yml
├── cfo
├── __init__.py
├── __version__.py
├── data
│ └── paths.json
├── tests
│ └── test_utils.py
└── utils.py
├── demos
├── api-introduction.ipynb
├── cloud-forest-demo.ipynb
└── czu-perimeter.geojson
├── environment.yml
├── img
├── cfo-fire.jpg
├── cfo-height.png
├── cfo-logo.png
├── cfo-terrain.jpg
├── cfo-understory.png
└── ipyleaflet-example.jpg
├── requirements.txt
└── setup.py
/.gitignore:
--------------------------------------------------------------------------------
1 | .zedstate
2 | *.pyc
3 | *__pycache__/*
4 | build/*
5 | dist/*
6 | cfo.egg-info/*
7 | .make/*
8 | .gcloudignore
9 | .dockerignore
10 | .coverage
11 | *.tif
12 | demos/.ipynb_checkpoints/*
13 |
--------------------------------------------------------------------------------
/.pre-commit-config.yaml:
--------------------------------------------------------------------------------
1 | # See https://pre-commit.com for more information
2 | # See https://pre-commit.com/hooks.html for more hooks
3 |
4 | default_language_version:
5 | python: python3.7
6 | repos:
7 | - repo: https://github.com/ambv/black
8 | rev: stable
9 | hooks:
10 | - id: black
11 | args: ["cfo", "--line-length=120", "--target-version=py37"]
12 | - repo: https://github.com/pycqa/flake8
13 | rev: master
14 | hooks:
15 | - id: flake8
16 | args: ["--select=C,E,F,W,B,B950", "--max-line-length=88", "--ignore=E203,E501,W503,F401"]
17 | - repo: https://github.com/pre-commit/pre-commit-hooks
18 | rev: v2.4.0
19 | hooks:
20 | - id: check-yaml
21 | - id: check-added-large-files
22 | - id: end-of-file-fixer
23 | - id: requirements-txt-fixer
24 |
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM continuumio/miniconda:latest
2 |
3 | # create working directory
4 | ENV APP_HOME /app
5 | WORKDIR $APP_HOME
6 |
7 | # install the conda environment
8 | COPY requirements.txt .
9 | COPY environment.yml .
10 | RUN conda env create --file environment.yml
11 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020+ Salo Sciences
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | # SETUP
2 |
3 | # help documentation
4 | .DEFAULT: help
5 | help:
6 | @echo "make init"
7 | @echo " initialize tools for development -- conda, pip, etc"
8 | @echo "make update"
9 | @echo " update tools for development -- conda, pip, etc"
10 | @echo "make docker-build"
11 | @echo " build docker image for salo-data-acquisition service"
12 | @echo "make docker-deploy"
13 | @echo " build and deploy docker image for cfo-api"
14 | @echo "make docker-clean"
15 | @echo " clean all docker containers, images, and data"
16 | @echo "make test"
17 | @echo " run tests"
18 |
19 | # environment variables
20 | CONDA_ENV=cfo
21 | CONDA_RUN=conda run --name ${CONDA_ENV}
22 | DOCKER_IMAGE=us.gcr.io/california-fores-1547767414612/cfo-api
23 | DOCKER_TAG_GIT:=$(shell git rev-parse --short=12 HEAD)
24 |
25 | # create directory for dummy files to indicate when targets need to be rerun
26 | DIR_MAKE=.make
27 | CONDA_UPDATED=${DIR_MAKE}/conda_updated
28 | PIP_UPDATED=${DIR_MAKE}/pip_updated
29 | DOCKER_INITIALIZED=${DIR_MAKE}/docker_initialized
30 |
31 |
32 | # ENTRY POINTS
33 |
34 | # initialize tools
35 | init: conda-init pip-init misc-update
36 | @:
37 |
38 | # update tools
39 | update: conda-update pip-update misc-update
40 | @:
41 |
42 | # run tests
43 | test:
44 | ${CONDA_RUN} pip install . && pytest --cov --no-cov-on-fail --cov-report=term-missing:skip-covered
45 |
46 |
47 | # DETAILED ENTRIES
48 |
49 | # conda
50 | conda-init:
51 | @conda env list | grep -q -w ${CONDA_ENV} || conda env create --file environment.yml
52 | @test -d ${DIR_MAKE} || mkdir ${DIR_MAKE}
53 | @touch ${CONDA_UPDATED}
54 |
55 | conda-update: conda-init ${CONDA_UPDATED}
56 | @:
57 | ${CONDA_UPDATED}: environment.yml
58 | ${CONDA_RUN} conda env update --file environment.yml --prune
59 | @test -d ${DIR_MAKE} || mkdir ${DIR_MAKE}
60 | @touch ${CONDA_UPDATED}
61 |
62 | # pip -- only needed because some packages are not available via conda, need to use the conda version of pip to work correctly
63 | pip-init: ${PIP_UPDATED}
64 | @:
65 | pip-update: ${PIP_UPDATED}
66 | @:
67 | ${PIP_UPDATED}: requirements.txt
68 | ${CONDA_RUN} pip install -r requirements.txt
69 | ${CONDA_RUN} pip install --editable .
70 | @test -d ${DIR_MAKE} || mkdir ${DIR_MAKE}
71 | @touch ${PIP_UPDATED}
72 |
73 | # misc
74 | misc-update:
75 | @${CONDA_RUN} pre-commit install
76 | @test ! -f .gcloudignore || rm .gcloudignore
77 | @cp .gitignore .gcloudignore
78 |
79 |
80 | # docker
81 | docker-init: ${DOCKER_INITIALIZED}
82 | @:
83 | ${DOCKER_INITIALIZED}:
84 | gcloud auth configure-docker
85 | @test -d ${DIR_MAKE} || mkdir ${DIR_MAKE}
86 | @touch ${DOCKER_INITIALIZED}
87 |
88 | docker-build: docker-init docker-clean
89 | @test ! -f .dockerignore || rm .dockerignore
90 | @cp .gitignore .dockerignore
91 | docker build --tag ${DOCKER_IMAGE}:${DOCKER_TAG_GIT} .
92 | docker tag ${DOCKER_IMAGE}:${DOCKER_TAG_GIT} ${DOCKER_IMAGE}:testing
93 | docker tag ${DOCKER_IMAGE}:${DOCKER_TAG_GIT} ${DOCKER_IMAGE}:latest
94 | @docker system prune -f
95 |
96 | docker-clean:
97 | @docker system prune -f
98 |
99 | docker-deploy: docker-build
100 | docker push ${DOCKER_IMAGE}:${DOCKER_TAG_GIT}
101 | gcloud container images add-tag ${DOCKER_IMAGE}:${DOCKER_TAG_GIT} ${DOCKER_IMAGE}:testing -q
102 | gcloud container images add-tag ${DOCKER_IMAGE}:${DOCKER_TAG_GIT} ${DOCKER_IMAGE}:latest -q
103 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | # Introduction
4 |
5 | The [California Forest Observatory][cfo-web] (CFO) is a data-driven forest monitoring system that maps the drivers of wildfire behavior across the state—including vegetation fuels, weather, topography & infrastructure—from space.
6 |
7 | The `cfo` library was designed to provide easy access to CFO datasets. Each dataset has a unique `asset_id`, and the `search` and `fetch` workflows were designed to query and download these assets.
8 |
9 | - You can search for asset IDs by geography, data type, and time of year
10 | - `forest.search(geography="SantaCruzCounty", metric="CanopyHeight", year=2020)`
11 | - You can download the data to your loacal machine
12 | - `forest.download(asset_id, output_file)`
13 | - If you don't want the file, you can just fetch the download URL
14 | - `forest.fetch(asset_id, dl=True)`
15 | - Or a WMS URL for web mapping
16 | - `forest.fetch(asset_id, wms=True)`
17 |
18 | You can find support for the CFO API at the [community forum][cfo-forum].
19 |
20 | ## License
21 |
22 | CFO data are available for free for non-commercial use per the [API terms][api-terms]. You must have a CFO account, which you can create by visiting [the web map][cfo-web], clicking the menu in the top right corner and selecting "Create an account." Please keep track of the e-mail address and password you used to create your Forest Observatory account, as you'll need them to authenticate API access.
23 |
24 | The software provided here, the `cfo` python API wrapper, is provided with an MIT license. Please do not confuse the license terms for the wrapper with the [terms of use][api-terms] for the API.
25 |
26 | ## Table of contents
27 |
28 | - [Installation](#installation)
29 | - [Authentication](#authentication)
30 | - [Searching for data](#searching)
31 | - [Downloading data](#downloads)
32 | - [Serving map tiles](#map-tiles)
33 | - [Contact](#contact)
34 |
35 | # Installation
36 |
37 | This library can be installed via `pip` directly from Github.
38 |
39 | ```bash
40 | pip install cfo
41 | ```
42 |
43 | If you don't have `pip` you could also clone the repository locally and install using python's `setuptools`
44 |
45 | ```bash
46 | git clone https://github.com/forestobservatory/cfo-api.git
47 | cd cfo-api
48 | python setup.py install
49 | ```
50 |
51 | Once installed, you should be able to load the `cfo` module in python. Instatiate the `api` class to begin working with the Forest Observatory API.
52 |
53 | ```python
54 | import cfo
55 | forest = cfo.api()
56 | ```
57 |
58 |
59 |
60 | # Authentication
61 |
62 | A Forest Observatory account is required to use the API (sign up free at [forestobservatory.com][cfo-web]).
63 |
64 | There are two authentication methods: entering your CFO account's email/password at runtime or setting environment variables.
65 |
66 | ### Passing your credentials at runtime
67 |
68 | Using any API call (`forest.search()`, `forest.fetch()`, `forest.download()`) will prompt you to enter the following authentication information:
69 |
70 | ```python
71 | >>> CFO E-mail: slug@forest.net
72 | >>> CFO Password: **********
73 | ```
74 |
75 | You can also authenticate directly with `forest.authenticate()`.
76 |
77 | This retrieves an authentication token from the API, which is stored as a temp file for future access (this does not store your e-mail/password). The API reads this stored token, which means you won't have to pass your email/password during each session.
78 |
79 | ### Setting environment variables
80 |
81 | You can forego runtime credential entry by setting environment variables. This is the lowest friction, least secure approach. You'll set the following variables in your `.bashrc` profile or elsewhere.
82 |
83 | ```bash
84 | export CFO_EMAIL=slug@forest.net
85 | export CFO_PASS=ari0limax
86 | ```
87 |
88 | ### Restoring a botched authentication
89 |
90 | The temp file that stores your authentication credentials can sometimes get donked up. To re-authenticate, use the following command to pass your credentials and overwrite the temporary token data.
91 |
92 | ```python
93 | forest.authenticate(ignore_temp=True)
94 | ```
95 |
96 |
97 |
98 | # Searching
99 |
100 | CFO data are organized by `asset_id`. These IDs contain information on the spatial extent of the data, the category and name of the data, the time of collection, and the spatial resolution. Asset IDs follow this naming format:
101 |
102 | ```python
103 | asset_id = {geography}-{category}-{metric}-{year}-{timeOfYear}-{resolution}
104 | ```
105 |
106 | Some examples:
107 |
108 | - A statewide vegetation fuels dateset that's rendered in the Layers tab: `California-Vegetation-CanopyHeight-2020-Summer-00010m`.
109 | - A statewide weather dataset queried in the Trends tab: `California-Weather-WindSpeed-2020-0601-03000m`.
110 | - A county-level dataset accessed in the Download tab: `Marin-Vegetation-SurfaceFuels-2020-Spring-00010m`.
111 |
112 | The `forest.search()` function queries the API and returns the assets that match the search terms.
113 |
114 | ```python
115 | >>> import cfo
116 | >>> forest = cfo.api()
117 | >>> forest.search(geography="MendocinoCounty", metric="CanopyCover")
118 | 2020-09-07 13:53:47,028 INFO cfo.utils [authenticate] Loaded cfo token
119 | ['MendocinoCounty-Vegetation-CanopyCover-2020-Fall-00010m']
120 | ```
121 |
122 | The default behavior of this function is to return the asset IDs as a list.
123 |
124 | You could instead return the API JSON data, including asset ID, the spatial extent (`bbox`) of the data, the catalog its stored in, etc. by setting `just_assets=False`.
125 |
126 | ```python
127 | >>> forest.search(geography="MendocinoCounty", metric="CanopyCover", just_assets=False)
128 | [{'asset_id': 'MendocinoCounty-Vegetation-CanopyCover-2020-Fall-00010m',
129 | 'attribute_dict': {},
130 | 'bbox': [-124.022978699284, -122.814767867036, 38.7548320538975, 40.0060478879686],
131 | 'catalog': 'cfo',
132 | 'description': 'CanopyCover',
133 | 'expiration_utc_datetime': '',
134 | 'utc_datetime': '2020-07-09 09:52:42.292286+00:00'}]
135 | ```
136 |
137 | And to examine the full response from the `requests` library, use `forest.search(raw=True)`.
138 |
139 | But with over 17,000 published assets it's not easy to know just what to search by. So we wrote some functions to simplify your searches.
140 |
141 | ### Convenience functions
142 |
143 | Based on the asset ID naming convention above, we've provided some `list` functions as a guide to what's available.
144 |
145 | - Geography - CFO datasets have been clipped to different spatial extents: statewide, by county, by municipality, by watershed.
146 | - `forest.list_geographies()` - returns the different geographic extents. Use `forest.list_geographies(by="County")` to narrow return just the unique counties.
147 | - `forest.list_geography_types()` - returns the categories of geographical clipping available.
148 | - Category - we currently provide three categories of data.
149 | - `forest.list_categories()` - returns [`Vegetation`, `Weather`, `Wildfire`]
150 | - Metric - each category of data contains a list of different available data types
151 | - `forest.list_metrics()` - returns the unique metrics for each category.
152 | - Run `forest.list_metrics(category="Weather")` to return only weather-specific metrics.
153 |
154 | Use these as keywords when searching for data (e.g. `id_list = forest.search(geography="FresnoCounty", category="Vegetation")`).
155 |
156 | You can also use wildcards:
157 |
158 | ```python
159 | >>> forest.search(geography='Plumas*', metric='CanopyHeight')
160 | ['PlumasCounty-Vegetation-CanopyHeight-2020-Fall-00010m',
161 | 'PlumasEurekaMunicipality-Vegetation-CanopyHeight-2020-Fall-00010m',
162 | 'PlumasLakeMunicipality-Vegetation-CanopyHeight-2020-Fall-00010m']
163 | ```
164 |
165 | ### A note on availabile datasets
166 |
167 | Even though we have a range of geographic extents, resolutions, and metrics, it is **not** the case that we provide all permutations of extent/resolution/metric. For example, we clip all `Vegetation` data to the county level, but we do not clip any `Weather` data that fine. All weather data are only available at the state level.
168 |
169 | This means you don't really need to specify the geographic extent if you search for weather data. You'll get pretty far with `wind_ids = forest.search(metric="WindSpeed")`.
170 |
171 |
172 |
173 | # Downloads
174 |
175 | Once you've generated a list of asset IDs, you can then download the files to your local machine. The `forest.download()` function requires an asset_id string so you'll have to iterate over search results, which are often returned as lists.
176 |
177 | Here's how to search for and download all data from Mendocino County.
178 |
179 | ```python
180 | import cfo
181 | forest = cfo.api()
182 | asset_ids = forest.search(geography="MendocinoCounty")
183 | for asset in asset_ids:
184 | forest.download(asset)
185 | ```
186 |
187 | Which generates the following output as it downloads each file.
188 |
189 | ```
190 | 2020-09-07 16:19:24,542 INFO cfo.utils [download] Beginning download for: MendocinoCounty-Vegetation-CanopyHeight-2020-Fall-00010m
191 | 2020-09-07 16:19:28,853 INFO cfo.utils [download] Successfully downloaded MendocinoCounty-Vegetation-CanopyHeight-2020-Fall-00010m to file: /home/slug/MendocinoCounty-Vegetation-CanopyHeight-2020-Fall-00010m.tif
192 | 2020-09-07 16:19:29,359 INFO cfo.utils [download] Beginning download for: MendocinoCounty-Vegetation-CanopyBaseHeight-2020-Fall-00010m
193 | 2020-09-07 16:19:32,321 INFO cfo.utils [download] Successfully downloaded MendocinoCounty-Vegetation-CanopyBaseHeight-2020-Fall-00010m to file: /home/slug/MendocinoCounty-Vegetation-CanopyBaseHeight-2020-Fall-00010m.tif
194 | ...
195 | ```
196 |
197 | This function uses the `fetch()` command under the hood to retrieve a URL for where the file is hosted on google cloud storage. It then performs a `GET` call to download the file locally.
198 |
199 | The function will download the file to your current working directory if you don't specify an output file path. You can set a custom output path with `forest.download(asset_id, path)`. This may be tricky if you're downloading multiple datasets, but you could parse the asset_id to generate useful names for output files.
200 |
201 | ```python
202 | asset_ids = forest.search(geography="MendocinoCounty")
203 | for asset in asset_ids:
204 | geo, category, metric, year, timeOfYear, res = asset.split("-")
205 | output_path = f"/external/downloads/CFO-{metric}-{year}.tif"
206 | forest.download(asset, output_path)
207 | ```
208 |
209 | Which generates the following output:
210 |
211 | ```
212 | 2020-09-07 23:10:02,312 INFO cfo.utils [download] Beginning download for: MendocinoCounty-Vegetation-CanopyHeight-2020-Fall-00010m
213 | 2020-09-07 23:10:25,163 INFO cfo.utils [download] Successfully downloaded MendocinoCounty-Vegetation-CanopyHeight-2020-Fall-00010m to file: /external/downloads/CFO-CanopyHeight-2020.tif
214 | 2020-09-07 23:10:25,596 INFO cfo.utils [download] Beginning download for: MendocinoCounty-Vegetation-CanopyBaseHeight-2020-Fall-00010m
215 | 2020-09-07 23:10:47,965 INFO cfo.utils [download] Successfully downloaded MendocinoCounty-Vegetation-CanopyBaseHeight-2020-Fall-00010m to file: /external/downloads/CFO-CanopyBaseHeight-2020.tif
216 | ...
217 | ```
218 |
219 |
220 | # Map tiles
221 |
222 | The `fetch` function also returns URLs for displaying CFO data in web mapping applications as WMS tile layers.
223 |
224 | ```python
225 | forest.fetch("MendocinoCounty-Vegetation-CanopyHeight-2020-Fall-00010m", wms=True)
226 | 'https://maps.salo.ai/geoserver/cfo/wms?layers=cfo:MendocinoCounty-Vegetation-CanopyHeight-2020-Fall-00010m&format="image/png"&styles=vegetation&p0=0.0&p2=1.44&p25=18.0&p30=21.599999999999998&p50=36.0&p60=43.199999999999996&p75=54.0&p90=64.8&p98=70.56&p100=72.0'
227 |
228 | ```
229 |
230 | WMS URLs don't always easily plug and play with different rendering services, but they should work with a little nudging. Here's how to use the above URL to visualize these data in a jupyter notebook with `ipyleaflet`.
231 |
232 | ```python
233 | from ipyleaflet import Map, WMSLayer, LayersControl, basemaps
234 | wms = WMSLayer(
235 | url='https://maps.salo.ai/geoserver/cfo/wms?p0=0.0&p2=1.44&p25=18.0&p30=21.599999999999998&p50=36.0&p60=43.199999999999996&p75=54.0&p90=64.8&p98=70.56&p100=72.0',
236 | layers="cfo:MendocinoCounty-Vegetation-CanopyHeight-2020-Fall-00010m",
237 | name="Mendocino Canopy Height",
238 | styles="vegetation",
239 | format="image/png8",
240 | transparent=True,
241 | attribution="Forest Observatory © Salo Sciences",
242 | )
243 | m = Map(basemap=basemaps.Stamen.Terrain, center=(39.39,-123.33), zoom=10)
244 | m.add_layer(wms)
245 | control = LayersControl(position='topright')
246 | m.add_control(control)
247 | m
248 | ```
249 |
250 | This code, executed in `jupyter-lab`, should look something like this.
251 |
252 |
253 |
254 | The URL has a lot of useful information. Here's a quick breakdown of what's encoded in the string returned from `fetch`.
255 |
256 | - The base URL (`https://maps.salo.ai/geoserver/cfo/wms`) is our map server address.
257 | - Each component following the `?` is a parameter passed to the map server.
258 | - `layers` specifies which asset to show (and is defined based on `{catalog}:{asset_id}` naming).
259 | - `format` defines the image format the data are rendered in (use `image/png8` for best performance).
260 | - `styles` defines the color palette (which you can retrieve with `forest.list_styles()`).
261 | - the long list of `p0, p2, p25, ..., p100` are parameters we use to render custom raster styles on the fly. These numbers are based on the min/max raster values of a dataset and can be altered on the fly to dynamically scale the data.
262 |
263 | # Contact
264 |
265 | Issue tracking isn't set up for this repository yet. Please visit the [Forest Observatory Community Forum][cfo-forum] for technical support. To get in touch directly or to inquire about commercial API access, contact [tech@forestobservatory.com](mailto:tech@forestobservatory.com).
266 |
267 | The California Forest Observatory API is developed and maintained by [Salo Sciences][salo-web].
268 |
269 |
270 | [api-terms]: https://forestobservatory.com/api.html
271 | [cfo-web]: https://forestobservatory.com
272 | [cfo-forum]: https://groups.google.com/a/forestobservatory.com/g/community
273 | [salo-web]: https://salo.ai
274 |
--------------------------------------------------------------------------------
/bitbucket-pipelines.yml:
--------------------------------------------------------------------------------
1 | definitions:
2 | steps:
3 | - step: &unit-tests
4 | name: Run unit tests
5 | script:
6 | - export PYTHONPATH=$PYTHONPATH:/opt/atlassian/pipelines/agent/build
7 | - conda run --name cfo pytest --cov --cov-report=xml:test-results/results.xml --cov-report=term-missing:skip-covered
8 | images:
9 | - image: &testing
10 | name: us.gcr.io/california-fores-1547767414612/cfo-api:testing
11 | username: _json_key
12 | password: '$GCR_JSON_KEY'
13 |
14 | pipelines:
15 | pull-requests:
16 | '**':
17 | - step:
18 | <<: *unit-tests
19 | image: *testing
20 | branches:
21 | master:
22 | - step:
23 | <<: *unit-tests
24 | image: *testing
25 |
--------------------------------------------------------------------------------
/cfo/__init__.py:
--------------------------------------------------------------------------------
1 | from .utils import API as api
2 |
--------------------------------------------------------------------------------
/cfo/__version__.py:
--------------------------------------------------------------------------------
1 | "1.0.1"
2 |
--------------------------------------------------------------------------------
/cfo/data/paths.json:
--------------------------------------------------------------------------------
1 | {"category":["Vegetation","Wildfire","Weather"],"metric":{"Vegetation":["CanopyHeight","CanopyCover","CanopyBaseHeight","CanopyBulkDensity","CanopyLayerCount","LadderFuelDensity","SurfaceFuels"],"Wildfire":["Hazard","Exposure"],"Weather":["Temperature","Humidity","WindDirection","WindSpeed"]},"geography":{"State":["California"],"County":["AlamedaCounty","AlpineCounty","AmadorCounty","ButteCounty","CalaverasCounty","ColusaCounty","ContraCostaCounty","DelNorteCounty","ElDoradoCounty","FresnoCounty","GlennCounty","HumboldtCounty","ImperialCounty","InyoCounty","KernCounty","KingsCounty","LakeCounty","LassenCounty","LosAngelesCounty","MaderaCounty","MarinCounty","MariposaCounty","MendocinoCounty","MercedCounty","ModocCounty","MonoCounty","MontereyCounty","NapaCounty","NevadaCounty","OrangeCounty","PlacerCounty","PlumasCounty","RiversideCounty","SacramentoCounty","SanBenitoCounty","SanBernardinoCounty","SanDiegoCounty","SanFranciscoCounty","SanJoaquinCounty","SanLuisObispoCounty","SanMateoCounty","SantaBarbaraCounty","SantaClaraCounty","SantaCruzCounty","ShastaCounty","SierraCounty","SiskiyouCounty","SolanoCounty","SonomaCounty","StanislausCounty","SutterCounty","TehamaCounty","TrinityCounty","TulareCounty","TuolumneCounty","VenturaCounty","YoloCounty","YubaCounty"],"Municipality":["AcalanesRidgeMunicipality","AcampoMunicipality","ActonMunicipality","AdelantoMunicipality","AdinMunicipality","AgouraHillsMunicipality","AguaDulceMunicipality","AguangaMunicipality","AhwahneeMunicipality","AirportMunicipality","AlamedaMunicipality","AlamoMunicipality","AlbanyMunicipality","AlbionMunicipality","AlderpointMunicipality","AlhambraMunicipality","AlhambraValleyMunicipality","AlisoViejoMunicipality","AlleghanyMunicipality","AllendaleMunicipality","AllensworthMunicipality","AlmanorMunicipality","AlondraParkMunicipality","AlpaughMunicipality","AlpineMunicipality","AlpineVillageMunicipality","AltaMunicipality","AltaSierraMunicipality","AltadenaMunicipality","AltoMunicipality","AlturasMunicipality","AlumRockMunicipality","AmadorCityMunicipality","AmericanCanyonMunicipality","AmestiMunicipality","AnaheimMunicipality","AnchorBayMunicipality","AndersonMunicipality","AngelsMunicipality","AngwinMunicipality","AntelopeMunicipality","AntiochMunicipality","AnzaMunicipality","AppleValleyMunicipality","AptosMunicipality","AptosHillsLarkinValleyMunicipality","ArbuckleMunicipality","ArcadiaMunicipality","ArcataMunicipality","ArdenArcadeMunicipality","ArmonaMunicipality","ArnoldMunicipality","AromasMunicipality","ArroyoGrandeMunicipality","ArtesiaMunicipality","ArtoisMunicipality","ArvinMunicipality","AshlandMunicipality","AspenSpringsMunicipality","AtascaderoMunicipality","AthertonMunicipality","AtwaterMunicipality","AuberryMunicipality","AuburnMunicipality","AuburnLakeTrailsMunicipality","AugustMunicipality","AvalonMunicipality","AvenalMunicipality","AveryMunicipality","AvilaBeachMunicipality","AvocadoHeightsMunicipality","AzusaMunicipality","BakerMunicipality","BakersfieldMunicipality","BaldwinParkMunicipality","BallardMunicipality","BallicoMunicipality","BangorMunicipality","BanningMunicipality","BarstowMunicipality","BassLakeMunicipality","BayPointMunicipality","BayviewMunicipality","BealeAFBMunicipality","BearCreekMunicipality","BearValleyMunicipality","BearValleySpringsMunicipality","BeaumontMunicipality","BeckwourthMunicipality","BeldenMunicipality","BellMunicipality","BellCanyonMunicipality","BellGardensMunicipality","BellaVistaMunicipality","BellflowerMunicipality","BelmontMunicipality","BelvedereMunicipality","BenLomondMunicipality","BenbowMunicipality","BendMunicipality","BeniciaMunicipality","BentonMunicipality","BerkeleyMunicipality","BermudaDunesMunicipality","BerryCreekMunicipality","BertschOceanviewMunicipality","BethelIslandMunicipality","BeverlyHillsMunicipality","BieberMunicipality","BigBearCityMunicipality","BigBearLakeMunicipality","BigBendMunicipality","BigCreekMunicipality","BigLagoonMunicipality","BigPineMunicipality","BigRiverMunicipality","BiggsMunicipality","BiolaMunicipality","BishopMunicipality","BlackPointGreenPointMunicipality","BlackhawkMunicipality","BlacklakeMunicipality","BlairsdenMunicipality","BloomfieldMunicipality","BloomingtonMunicipality","BlueLakeMunicipality","BluewaterMunicipality","BlytheMunicipality","BodegaMunicipality","BodegaBayMunicipality","BodfishMunicipality","BolinasMunicipality","BombayBeachMunicipality","BonadelleRanchosMaderaRanchosMunicipality","BonitaMunicipality","BonnyDoonMunicipality","BonsallMunicipality","BoonvilleMunicipality","BootjackMunicipality","BoronMunicipality","BorondaMunicipality","BorregoSpringsMunicipality","BostoniaMunicipality","BoulderCreekMunicipality","BoulevardMunicipality","BowlesMunicipality","BoyesHotSpringsMunicipality","BradburyMunicipality","BradleyMunicipality","BrawleyMunicipality","BreaMunicipality","BrentwoodMunicipality","BretHarteMunicipality","BridgeportMunicipality","BrisbaneMunicipality","BroadmoorMunicipality","BrookdaleMunicipality","BrooktrailsMunicipality","BuckMeadowsMunicipality","BuckhornMunicipality","BucksLakeMunicipality","BuelltonMunicipality","BuenaParkMunicipality","BuenaVistaMunicipality","BurbankMunicipality","BurlingameMunicipality","BurneyMunicipality","BurntRanchMunicipality","ButteCreekCanyonMunicipality","ButteMeadowsMunicipality","ButteValleyMunicipality","ButtonwillowMunicipality","ByronMunicipality","BystromMunicipality","CRoadMunicipality","CabazonMunicipality","CalabasasMunicipality","CalexicoMunicipality","CaliforniaCityMunicipality","CaliforniaHotSpringsMunicipality","CaliforniaPinesMunicipality","CalimesaMunicipality","CalipatriaMunicipality","CalistogaMunicipality","CallenderMunicipality","CalpellaMunicipality","CalpineMunicipality","CalwaMunicipality","CamancheNorthShoreMunicipality","CamancheVillageMunicipality","CamarilloMunicipality","CambriaMunicipality","CambrianParkMunicipality","CameronParkMunicipality","CaminoMunicipality","CaminoTassajaraMunicipality","CampNelsonMunicipality","CampPendletonNorthMunicipality","CampPendletonSouthMunicipality","CampbellMunicipality","CampoMunicipality","CamptonvilleMunicipality","CanbyMunicipality","CantuaCreekMunicipality","CanyonLakeMunicipality","CanyondamMunicipality","CapitolaMunicipality","CaribouMunicipality","CarlsbadMunicipality","CarmelValleyVillageMunicipality","CarmelbytheSeaMunicipality","CarmetMunicipality","CarmichaelMunicipality","CarnelianBayMunicipality","CarpinteriaMunicipality","CarrickMunicipality","CarsonMunicipality","CartagoMunicipality","CaruthersMunicipality","CasaConejoMunicipality","CasadeOroMountHelixMunicipality","CasmaliaMunicipality","CasparMunicipality","CasselMunicipality","CastaicMunicipality","CastleHillMunicipality","CastroValleyMunicipality","CastrovilleMunicipality","CathedralCityMunicipality","CatheysValleyMunicipality","CayucosMunicipality","CazaderoMunicipality","CedarRidgeMunicipality","CedarSlopeMunicipality","CedarvilleMunicipality","CentervilleMunicipality","CeresMunicipality","CerritosMunicipality","ChalfantMunicipality","ChallengeBrownsvilleMunicipality","ChannelIslandsBeachMunicipality","CharterOakMunicipality","CherokeeMunicipality","CherokeeStripMunicipality","CherryValleyMunicipality","CherrylandMunicipality","ChesterMunicipality","ChicoMunicipality","ChilcootVintonMunicipality","ChinaLakeAcresMunicipality","ChineseCampMunicipality","ChinoMunicipality","ChinoHillsMunicipality","ChowchillaMunicipality","ChualarMunicipality","ChulaVistaMunicipality","CitrusMunicipality","CitrusHeightsMunicipality","ClaremontMunicipality","ClarksburgMunicipality","ClayMunicipality","ClaytonMunicipality","ClearCreekMunicipality","ClearlakeMunicipality","ClearlakeOaksMunicipality","ClearlakeRivieraMunicipality","CleoneMunicipality","ClioMunicipality","ClipperMillsMunicipality","CloverdaleMunicipality","ClovisMunicipality","ClydeMunicipality","CoachellaMunicipality","CoalingaMunicipality","CoarsegoldMunicipality","CobbMunicipality","CoffeeCreekMunicipality","CohassetMunicipality","ColdSpringsMunicipality","ColevilleMunicipality","ColfaxMunicipality","CollegeCityMunicipality","ColliervilleMunicipality","ColmaMunicipality","ColomaMunicipality","ColtonMunicipality","ColumbiaMunicipality","ColusaMunicipality","CommerceMunicipality","ComptcheMunicipality","ComptonMunicipality","ConcordMunicipality","ConcowMunicipality","ContraCostaCentreMunicipality","CopperopolisMunicipality","CorcoranMunicipality","CorningMunicipality","CoronaMunicipality","CoronadoMunicipality","CoronitaMunicipality","CorralitosMunicipality","CorteMaderaMunicipality","CostaMesaMunicipality","CotatiMunicipality","CotodeCazaMunicipality","CottonwoodMunicipality","CoultervilleMunicipality","CountryClubMunicipality","CourtlandMunicipality","CoveloMunicipality","CovinaMunicipality","CowanMunicipality","CrescentCityMunicipality","CrescentMillsMunicipality","CresseyMunicipality","CrestMunicipality","CrestlineMunicipality","CrestonMunicipality","CrockettMunicipality","CrombergMunicipality","CrowleyLakeMunicipality","CrowsLandingMunicipality","CudahyMunicipality","CulverCityMunicipality","CupertinoMunicipality","CutlerMunicipality","CuttenMunicipality","CuyamaMunicipality","CypressMunicipality","DalyCityMunicipality","DanaPointMunicipality","DanvilleMunicipality","DaphnedaleParkMunicipality","DarwinMunicipality","DavenportMunicipality","DavisMunicipality","DayValleyMunicipality","DeerParkMunicipality","DelAireMunicipality","DelMarMunicipality","DelMonteForestMunicipality","DelReyMunicipality","DelReyOaksMunicipality","DelRioMunicipality","DelanoMunicipality","DelftColonyMunicipality","DelhiMunicipality","DellekerMunicipality","DenairMunicipality","DerbyAcresMunicipality","DescansoMunicipality","DesertCenterMunicipality","DesertEdgeMunicipality","DesertHotSpringsMunicipality","DesertPalmsMunicipality","DesertShoresMunicipality","DesertViewHighlandsMunicipality","DiabloMunicipality","DiabloGrandeMunicipality","DiamondBarMunicipality","DiamondSpringsMunicipality","DillonBeachMunicipality","DinubaMunicipality","DiscoveryBayMunicipality","DixonMunicipality","DixonLaneMeadowCreekMunicipality","DobbinsMunicipality","DogtownMunicipality","DollarPointMunicipality","DorringtonMunicipality","DorrisMunicipality","DosPalosMunicipality","DosPalosYMunicipality","DouglasCityMunicipality","DowneyMunicipality","DownievilleMunicipality","DoyleMunicipality","DrytownMunicipality","DuarteMunicipality","DublinMunicipality","DucorMunicipality","DunniganMunicipality","DunsmuirMunicipality","DurhamMunicipality","DustinAcresMunicipality","DutchFlatMunicipality","EaglevilleMunicipality","EarlimartMunicipality","EastFoothillsMunicipality","EastHemetMunicipality","EastLosAngelesMunicipality","EastNicolausMunicipality","EastOakdaleMunicipality","EastOrosiMunicipality","EastPaloAltoMunicipality","EastPasadenaMunicipality","EastPortervilleMunicipality","EastQuincyMunicipality","EastRanchoDominguezMunicipality","EastRichmondHeightsMunicipality","EastSanGabrielMunicipality","EastShoreMunicipality","EastSonoraMunicipality","EastTulareVillaMunicipality","EastWhittierMunicipality","EastonMunicipality","EastvaleMunicipality","EdgewoodMunicipality","EdmundsonAcresMunicipality","EdnaMunicipality","EdwardsAFBMunicipality","ElCajonMunicipality","ElCentroMunicipality","ElCerritoMunicipality","ElDoradoHillsMunicipality","ElGranadaMunicipality","ElMonteMunicipality","ElNidoMunicipality","ElPasodeRoblesMunicipality","ElPortalMunicipality","ElRanchoMunicipality","ElRioMunicipality","ElSegundoMunicipality","ElSobranteMunicipality","ElVeranoMunicipality","EldridgeMunicipality","ElizabethLakeMunicipality","ElkCreekMunicipality","ElkGroveMunicipality","ElkhornMunicipality","ElmiraMunicipality","ElvertaMunicipality","EmeraldLakeHillsMunicipality","EmeryvilleMunicipality","EmpireMunicipality","EncinitasMunicipality","EscalonMunicipality","EscondidoMunicipality","EspartoMunicipality","EtnaMunicipality","EucalyptusHillsMunicipality","EurekaMunicipality","ExeterMunicipality","FairOaksMunicipality","FairbanksRanchMunicipality","FairfaxMunicipality","FairfieldMunicipality","FairhavenMunicipality","FairmeadMunicipality","FairviewMunicipality","FallRiverMillsMunicipality","FallbrookMunicipality","FarmersvilleMunicipality","FarmingtonMunicipality","FellowsMunicipality","FeltonMunicipality","FerndaleMunicipality","FettersHotSpringsAguaCalienteMunicipality","FiddletownMunicipality","FieldbrookMunicipality","FieldsLandingMunicipality","FillmoreMunicipality","FirebaughMunicipality","FishCampMunicipality","FlorenceGrahamMunicipality","FlorinMunicipality","FloristonMunicipality","FlournoyMunicipality","FolsomMunicipality","FontanaMunicipality","FoothillFarmsMunicipality","ForbestownMunicipality","FordCityMunicipality","ForestMeadowsMunicipality","ForestRanchMunicipality","ForesthillMunicipality","ForestvilleMunicipality","FortBidwellMunicipality","FortBraggMunicipality","FortDickMunicipality","FortIrwinMunicipality","FortJonesMunicipality","FortWashingtonMunicipality","FortunaMunicipality","FosterCityMunicipality","FountainValleyMunicipality","FowlerMunicipality","FranklinMunicipality","FrazierParkMunicipality","FreedomMunicipality","FreeportMunicipality","FremontMunicipality","FrenchCampMunicipality","FrenchGulchMunicipality","FrenchValleyMunicipality","FresnoMunicipality","FriantMunicipality","FruitdaleMunicipality","FruitridgePocketMunicipality","FullerAcresMunicipality","FullertonMunicipality","FultonMunicipality","FurnaceCreekMunicipality","GaltMunicipality","GarbervilleMunicipality","GardenAcresMunicipality","GardenFarmsMunicipality","GardenGroveMunicipality","GardenaMunicipality","GareyMunicipality","GarnetMunicipality","GasquetMunicipality","GazelleMunicipality","GeorgetownMunicipality","GerberMunicipality","GeyservilleMunicipality","GilroyMunicipality","GlenEllenMunicipality","GlendaleMunicipality","GlendoraMunicipality","GoldMountainMunicipality","GoldRiverMunicipality","GoldenHillsMunicipality","GoletaMunicipality","GonzalesMunicipality","GoodHopeMunicipality","GoodyearsBarMunicipality","GoshenMunicipality","GraeagleMunicipality","GrandTerraceMunicipality","GrangevilleMunicipality","GraniteBayMunicipality","GraniteHillsMunicipality","GranitevilleMunicipality","GrassValleyMunicipality","GratonMunicipality","GraysonMunicipality","GreeleyHillMunicipality","GreenAcresMunicipality","GreenValleyMunicipality","GreenacresMunicipality","GreenfieldMunicipality","GreenhornMunicipality","GreenviewMunicipality","GreenvilleMunicipality","GrenadaMunicipality","GridleyMunicipality","GrimesMunicipality","GrizzlyFlatsMunicipality","GrovelandMunicipality","GroverBeachMunicipality","GuadalupeMunicipality","GuernevilleMunicipality","GuindaMunicipality","GustineMunicipality","HaciendaHeightsMunicipality","HalfMoonBayMunicipality","HamiltonBranchMunicipality","HamiltonCityMunicipality","HanfordMunicipality","HappyCampMunicipality","HarbisonCanyonMunicipality","HardwickMunicipality","HartlandMunicipality","HartleyMunicipality","HasleyCanyonMunicipality","HatCreekMunicipality","HawaiianGardensMunicipality","HawthorneMunicipality","HayforkMunicipality","HaywardMunicipality","HealdsburgMunicipality","HeberMunicipality","HemetMunicipality","HeraldMunicipality","HerculesMunicipality","HerlongMunicipality","HermosaBeachMunicipality","HesperiaMunicipality","HickmanMunicipality","HiddenHillsMunicipality","HiddenMeadowsMunicipality","HiddenValleyLakeMunicipality","HighgroveMunicipality","HighlandMunicipality","HighlandsBaywoodParkMunicipality","HillsboroughMunicipality","HilmarIrwinMunicipality","HiouchiMunicipality","HollisterMunicipality","HoltvilleMunicipality","HomeGardenMunicipality","HomeGardensMunicipality","HomelandMunicipality","HomesteadValleyMunicipality","HomewoodCanyonMunicipality","HoncutMunicipality","HoodMunicipality","HoopaMunicipality","HoplandMunicipality","HornbrookMunicipality","HornitosMunicipality","HughsonMunicipality","HumboldtHillMunicipality","HuntingtonBeachMunicipality","HuntingtonParkMunicipality","HuronMunicipality","HyampomMunicipality","HydesvilleMunicipality","IdlewildMunicipality","IdyllwildPineCoveMunicipality","ImperialMunicipality","ImperialBeachMunicipality","IndependenceMunicipality","IndianFallsMunicipality","IndianWellsMunicipality","IndianolaMunicipality","IndioMunicipality","IndioHillsMunicipality","IndustryMunicipality","InglewoodMunicipality","InterlakenMunicipality","InvernessMunicipality","InyokernMunicipality","IoneMunicipality","IronHorseMunicipality","IrvineMunicipality","IrwindaleMunicipality","IslaVistaMunicipality","IsletonMunicipality","IvanhoeMunicipality","JacksonMunicipality","JacumbaMunicipality","JamestownMunicipality","JamulMunicipality","JanesvilleMunicipality","JennerMunicipality","JohannesburgMunicipality","JohnstonvilleMunicipality","JohnsvilleMunicipality","JoshuaTreeMunicipality","JulianMunicipality","JunctionCityMunicipality","JuneLakeMunicipality","JurupaValleyMunicipality","KeddieMunicipality","KeelerMunicipality","KeeneMunicipality","KellyRidgeMunicipality","KelseyvilleMunicipality","KennedyMunicipality","KennedyMeadowsMunicipality","KensingtonMunicipality","KentfieldMunicipality","KenwoodMunicipality","KermanMunicipality","KernvilleMunicipality","KeswickMunicipality","KettlemanCityMunicipality","KeyesMunicipality","KingCityMunicipality","KingsBeachMunicipality","KingsburgMunicipality","KingvaleMunicipality","KirkwoodMunicipality","KlamathMunicipality","KnightsLandingMunicipality","KnightsenMunicipality","LaCanadaFlintridgeMunicipality","LaCrescentaMontroseMunicipality","LaHabraMunicipality","LaHabraHeightsMunicipality","LaHondaMunicipality","LaMesaMunicipality","LaMiradaMunicipality","LaPalmaMunicipality","LaPorteMunicipality","LaPresaMunicipality","LaPuenteMunicipality","LaQuintaMunicipality","LaRivieraMunicipality","LaSelvaBeachMunicipality","LaVerneMunicipality","LaVinaMunicipality","LaderaMunicipality","LaderaHeightsMunicipality","LaderaRanchMunicipality","LafayetteMunicipality","LagunaBeachMunicipality","LagunaHillsMunicipality","LagunaNiguelMunicipality","LagunaWoodsMunicipality","LagunitasForestKnollsMunicipality","LakeAlmanorCountryClubMunicipality","LakeAlmanorPeninsulaMunicipality","LakeAlmanorWestMunicipality","LakeArrowheadMunicipality","LakeCaliforniaMunicipality","LakeCityMunicipality","LakeDavisMunicipality","LakeDonPedroMunicipality","LakeElsinoreMunicipality","LakeForestMunicipality","LakeHughesMunicipality","LakeIsabellaMunicipality","LakeLosAngelesMunicipality","LakeMathewsMunicipality","LakeNacimientoMunicipality","LakeRiversideMunicipality","LakeSanMarcosMunicipality","LakeSherwoodMunicipality","LakeWildwoodMunicipality","LakeheadMunicipality","LakelandVillageMunicipality","LakeofthePinesMunicipality","LakeoftheWoodsMunicipality","LakeportMunicipality","LakesideMunicipality","LakeviewMunicipality","LakewoodMunicipality","LamontMunicipality","LanareMunicipality","LancasterMunicipality","LarkfieldWikiupMunicipality","LarkspurMunicipality","LasFloresMunicipality","LasLomasMunicipality","LathropMunicipality","LatonMunicipality","LawndaleMunicipality","LaytonvilleMunicipality","LeGrandMunicipality","LebecMunicipality","LeeViningMunicipality","LeggettMunicipality","LemonCoveMunicipality","LemonGroveMunicipality","LemonHillMunicipality","LemooreMunicipality","LemooreStationMunicipality","LennoxMunicipality","LenwoodMunicipality","LeonaValleyMunicipality","LewistonMunicipality","LexingtonHillsMunicipality","LikelyMunicipality","LincolnMunicipality","LincolnVillageMunicipality","LindaMunicipality","LindcoveMunicipality","LindenMunicipality","LindsayMunicipality","LinnellCampMunicipality","LitchfieldMunicipality","LittleGrassValleyMunicipality","LittleRiverMunicipality","LittleValleyMunicipality","LittlerockMunicipality","LiveOakMunicipality","LivermoreMunicipality","LivingstonMunicipality","LockefordMunicipality","LockwoodMunicipality","LodiMunicipality","LodogaMunicipality","LoletaMunicipality","LomaLindaMunicipality","LomaMarMunicipality","LomaRicaMunicipality","LomitaMunicipality","LompicoMunicipality","LompocMunicipality","LondonMunicipality","LonePineMunicipality","LongBarnMunicipality","LongBeachMunicipality","LookoutMunicipality","LoomisMunicipality","LosAlamitosMunicipality","LosAlamosMunicipality","LosAltosMunicipality","LosAltosHillsMunicipality","LosAngelesMunicipality","LosBanosMunicipality","LosBerrosMunicipality","LosGatosMunicipality","LosMolinosMunicipality","LosOlivosMunicipality","LosOsosMunicipality","LosRanchosMunicipality","LostHillsMunicipality","LowerLakeMunicipality","LoyaltonMunicipality","LoyolaMunicipality","LucasValleyMarinwoodMunicipality","LucerneMunicipality","LucerneValleyMunicipality","LynwoodMunicipality","LytleCreekMunicipality","MabieMunicipality","MacdoelMunicipality","MadRiverMunicipality","MaderaMunicipality","MaderaAcresMunicipality","MadisonMunicipality","MagaliaMunicipality","MalagaMunicipality","MalibuMunicipality","MammothLakesMunicipality","ManchesterMunicipality","ManhattanBeachMunicipality","ManilaMunicipality","MantecaMunicipality","MantonMunicipality","MarchARBMunicipality","MaricopaMunicipality","MarinCityMunicipality","MarinaMunicipality","MarinadelReyMunicipality","MariposaMunicipality","MarkleevilleMunicipality","MartellMunicipality","MartinezMunicipality","MarysvilleMunicipality","MathenyMunicipality","MatherMunicipality","MaxwellMunicipality","MayfairMunicipality","MayflowerVillageMunicipality","MaywoodMunicipality","McArthurMunicipality","McClellanParkMunicipality","McClenneyTractMunicipality","McCloudMunicipality","McFarlandMunicipality","McGeeCreekMunicipality","McKinleyvilleMunicipality","McKittrickMunicipality","McSwainMunicipality","MeadValleyMunicipality","MeadowValleyMunicipality","MeadowVistaMunicipality","MeadowbrookMunicipality","MeccaMunicipality","MeinersOaksMunicipality","MendocinoMunicipality","MendotaMunicipality","MenifeeMunicipality","MenloParkMunicipality","MentoneMunicipality","MercedMunicipality","MeridianMunicipality","MesaMunicipality","MesaVerdeMunicipality","MesaVistaMunicipality","MettlerMunicipality","MexicanColonyMunicipality","MiWukVillageMunicipality","MiddletownMunicipality","MidpinesMunicipality","MidwayCityMunicipality","MilfordMunicipality","MillValleyMunicipality","MillbraeMunicipality","MillvilleMunicipality","MilpitasMunicipality","MineralMunicipality","MinklerMunicipality","MiraMonteMunicipality","MirandaMunicipality","MissionCanyonMunicipality","MissionHillsMunicipality","MissionViejoMunicipality","ModestoMunicipality","MohawkVistaMunicipality","MojaveMunicipality","MokelumneHillMunicipality","MonmouthMunicipality","MonoCityMunicipality","MonoVistaMunicipality","MonroviaMunicipality","MonsonMunicipality","MontagueMunicipality","MontalvinManorMunicipality","MontaraMunicipality","MontclairMunicipality","MonteRioMunicipality","MonteSerenoMunicipality","MontebelloMunicipality","MontecitoMunicipality","MontereyMunicipality","MontereyParkMunicipality","MontereyParkTractMunicipality","MontgomeryCreekMunicipality","MonumentHillsMunicipality","MoorparkMunicipality","MoradaMunicipality","MoragaMunicipality","MorenoValleyMunicipality","MorganHillMunicipality","MorongoValleyMunicipality","MorroBayMunicipality","MoskowiteCornerMunicipality","MossBeachMunicipality","MossLandingMunicipality","MountHebronMunicipality","MountHermonMunicipality","MountLagunaMunicipality","MountShastaMunicipality","MountainCenterMunicipality","MountainGateMunicipality","MountainHouseMunicipality","MountainMesaMunicipality","MountainRanchMunicipality","MountainViewMunicipality","MountainViewAcresMunicipality","MuirBeachMunicipality","MurphysMunicipality","MurrietaMunicipality","MuscoyMunicipality","MyersFlatMunicipality","MyrtletownMunicipality","NapaMunicipality","NationalCityMunicipality","NeedlesMunicipality","NevadaCityMunicipality","NewCuyamaMunicipality","NewPineCreekMunicipality","NewarkMunicipality","NewcastleMunicipality","NewellMunicipality","NewmanMunicipality","NewportBeachMunicipality","NicasioMunicipality","NiceMunicipality","NicolausMunicipality","NilandMunicipality","NipinnawaseeMunicipality","NipomoMunicipality","NorcoMunicipality","NordMunicipality","NorrisCanyonMunicipality","NorthAuburnMunicipality","NorthEdwardsMunicipality","NorthElMonteMunicipality","NorthFairOaksMunicipality","NorthGateMunicipality","NorthHighlandsMunicipality","NorthLakeportMunicipality","NorthRichmondMunicipality","NorthSanJuanMunicipality","NorthShoreMunicipality","NorthTustinMunicipality","NorwalkMunicipality","NovatoMunicipality","NubieberMunicipality","NuevoMunicipality","OakGlenMunicipality","OakHillsMunicipality","OakParkMunicipality","OakShoresMunicipality","OakViewMunicipality","OakdaleMunicipality","OakhurstMunicipality","OaklandMunicipality","OakleyMunicipality","OakvilleMunicipality","OasisMunicipality","OccidentalMunicipality","OceanoMunicipality","OceansideMunicipality","OcotilloMunicipality","OildaleMunicipality","OjaiMunicipality","OlanchaMunicipality","OldFigGardenMunicipality","OldStationMunicipality","OlivehurstMunicipality","OntarioMunicipality","OnyxMunicipality","OrangeMunicipality","OrangeCoveMunicipality","OrangevaleMunicipality","OrcuttMunicipality","OrickMunicipality","OrindaMunicipality","OrlandMunicipality","OrosiMunicipality","OrovilleMunicipality","OrovilleEastMunicipality","OxnardMunicipality","PachecoMunicipality","PacificGroveMunicipality","PacificaMunicipality","PajaroMunicipality","PajaroDunesMunicipality","PalaMunicipality","PalermoMunicipality","PalmDesertMunicipality","PalmSpringsMunicipality","PalmdaleMunicipality","PaloAltoMunicipality","PaloCedroMunicipality","PaloVerdeMunicipality","PalosVerdesEstatesMunicipality","PanoramaHeightsMunicipality","ParadiseMunicipality","ParadiseParkMunicipality","ParamountMunicipality","ParklawnMunicipality","ParksdaleMunicipality","ParkwayMunicipality","ParkwoodMunicipality","ParlierMunicipality","PasadenaMunicipality","PasatiempoMunicipality","PaskentaMunicipality","PattersonMunicipality","PattersonTractMunicipality","PattonVillageMunicipality","PaxtonMunicipality","PaynesCreekMunicipality","PearsonvilleMunicipality","PennValleyMunicipality","PenngroveMunicipality","PenrynMunicipality","PerrisMunicipality","PescaderoMunicipality","PetalumaMunicipality","PetersMunicipality","PhelanMunicipality","PhillipsvilleMunicipality","PhiloMunicipality","PhoenixLakeMunicipality","PicoRiveraMunicipality","PiedmontMunicipality","PierpointMunicipality","PikeMunicipality","PineCanyonMunicipality","PineFlatMunicipality","PineGroveMunicipality","PineHillsMunicipality","PineMountainClubMunicipality","PineMountainLakeMunicipality","PineValleyMunicipality","PinoleMunicipality","PinonHillsMunicipality","PioneerMunicipality","PiruMunicipality","PismoBeachMunicipality","PittsburgMunicipality","PixleyMunicipality","PlacentiaMunicipality","PlacervilleMunicipality","PlainviewMunicipality","PlanadaMunicipality","PleasantHillMunicipality","PleasantonMunicipality","PleasurePointMunicipality","PlumasEurekaMunicipality","PlumasLakeMunicipality","PlymouthMunicipality","PointArenaMunicipality","PointReyesStationMunicipality","PollockPinesMunicipality","PomonaMunicipality","PonderosaMunicipality","PoplarCottonCenterMunicipality","PortCostaMunicipality","PortHuenemeMunicipality","PortervilleMunicipality","PortolaMunicipality","PortolaValleyMunicipality","PoseyMunicipality","PosoParkMunicipality","PotreroMunicipality","PotterValleyMunicipality","PowayMunicipality","PrattvilleMunicipality","PrincetonMunicipality","ProbertaMunicipality","PrunedaleMunicipality","QuartzHillMunicipality","QuincyMunicipality","RackerbyMunicipality","RailRoadFlatMunicipality","RainbowMunicipality","RaisinCityMunicipality","RamonaMunicipality","RanchoCalaverasMunicipality","RanchoCordovaMunicipality","RanchoCucamongaMunicipality","RanchoMirageMunicipality","RanchoMurietaMunicipality","RanchoPalosVerdesMunicipality","RanchoSanDiegoMunicipality","RanchoSantaFeMunicipality","RanchoSantaMargaritaMunicipality","RanchoTehamaReserveMunicipality","RandsburgMunicipality","RedBluffMunicipality","RedCorralMunicipality","RedcrestMunicipality","ReddingMunicipality","RedlandsMunicipality","RedondoBeachMunicipality","RedwayMunicipality","RedwoodCityMunicipality","RedwoodValleyMunicipality","ReedleyMunicipality","ReliezValleyMunicipality","RialtoMunicipality","RichfieldMunicipality","RichgroveMunicipality","RichmondMunicipality","RichvaleMunicipality","RidgecrestMunicipality","RidgemarkMunicipality","RioDellMunicipality","RioLindaMunicipality","RioOsoMunicipality","RioVistaMunicipality","RiodelMarMunicipality","RipleyMunicipality","RiponMunicipality","RiverPinesMunicipality","RiverbankMunicipality","RiverdaleMunicipality","RiverdaleParkMunicipality","RiversideMunicipality","RobbinsMunicipality","RobinsonMillMunicipality","RocklinMunicipality","RodeoMunicipality","RodriguezCampMunicipality","RohnertParkMunicipality","RollingHillsMunicipality","RollingHillsEstatesMunicipality","RollingwoodMunicipality","RomolandMunicipality","RosamondMunicipality","RoseHillsMunicipality","RosedaleMunicipality","RoselandMunicipality","RosemeadMunicipality","RosemontMunicipality","RosevilleMunicipality","RossMunicipality","RossmoorMunicipality","RoughandReadyMunicipality","RoundMountainMunicipality","RoundValleyMunicipality","RouseMunicipality","RowlandHeightsMunicipality","RunningSpringsMunicipality","RuthMunicipality","RutherfordMunicipality","SacramentoMunicipality","SalidaMunicipality","SalinasMunicipality","SalmonCreekMunicipality","SaltonCityMunicipality","SaltonSeaBeachMunicipality","SamoaMunicipality","SanAndreasMunicipality","SanAnselmoMunicipality","SanAntonioHeightsMunicipality","SanArdoMunicipality","SanBernardinoMunicipality","SanBrunoMunicipality","SanBuenaventuraMunicipality","SanCarlosMunicipality","SanClementeMunicipality","SanDiegoMunicipality","SanDiegoCountryEstatesMunicipality","SanDimasMunicipality","SanFernandoMunicipality","SanFranciscoMunicipality","SanGabrielMunicipality","SanGeronimoMunicipality","SanJacintoMunicipality","SanJoaquinMunicipality","SanJoseMunicipality","SanJuanBautistaMunicipality","SanJuanCapistranoMunicipality","SanLeandroMunicipality","SanLorenzoMunicipality","SanLucasMunicipality","SanLuisObispoMunicipality","SanMarcosMunicipality","SanMarinoMunicipality","SanMartinMunicipality","SanMateoMunicipality","SanMiguelMunicipality","SanPabloMunicipality","SanPasqualMunicipality","SanRafaelMunicipality","SanRamonMunicipality","SanSimeonMunicipality","SandCityMunicipality","SangerMunicipality","SantaAnaMunicipality","SantaBarbaraMunicipality","SantaClaraMunicipality","SantaClaritaMunicipality","SantaCruzMunicipality","SantaFeSpringsMunicipality","SantaMargaritaMunicipality","SantaMariaMunicipality","SantaMonicaMunicipality","SantaNellaMunicipality","SantaPaulaMunicipality","SantaRosaMunicipality","SantaRosaValleyMunicipality","SantaSusanaMunicipality","SantaVenetiaMunicipality","SantaYnezMunicipality","SanteeMunicipality","SaranapMunicipality","SaratogaMunicipality","SaticoyMunicipality","SattleyMunicipality","SausalitoMunicipality","ScotiaMunicipality","ScottsValleyMunicipality","SeaRanchMunicipality","SeacliffMunicipality","SealBeachMunicipality","SearlesValleyMunicipality","SeasideMunicipality","SebastopolMunicipality","SeeleyMunicipality","SelmaMunicipality","SequoiaCrestMunicipality","SerenodelMarMunicipality","SevilleMunicipality","ShafterMunicipality","ShandonMunicipality","ShastaMunicipality","ShastaLakeMunicipality","ShaverLakeMunicipality","ShellRidgeMunicipality","ShelterCoveMunicipality","SheridanMunicipality","ShingleSpringsMunicipality","ShingletownMunicipality","ShoshoneMunicipality","SierraBrooksMunicipality","SierraCityMunicipality","SierraMadreMunicipality","SierraVillageMunicipality","SierravilleMunicipality","SignalHillMunicipality","SilverCityMunicipality","SilverLakesMunicipality","SilveradoResortMunicipality","SimiValleyMunicipality","SisquocMunicipality","SkyValleyMunicipality","SleepyHollowMunicipality","SmartsvilleMunicipality","SmithCornerMunicipality","SmithRiverMunicipality","SnellingMunicipality","SodaBayMunicipality","SodaSpringsMunicipality","SolanaBeachMunicipality","SoledadMunicipality","SolvangMunicipality","SonomaMunicipality","SonoraMunicipality","SoquelMunicipality","SoulsbyvilleMunicipality","SouthDosPalosMunicipality","SouthElMonteMunicipality","SouthGateMunicipality","SouthLakeTahoeMunicipality","SouthMonroviaIslandMunicipality","SouthOrovilleMunicipality","SouthPasadenaMunicipality","SouthSanFranciscoMunicipality","SouthSanGabrielMunicipality","SouthSanJoseHillsMunicipality","SouthTaftMunicipality","SouthWhittierMunicipality","SpauldingMunicipality","SpreckelsMunicipality","SpringGardenMunicipality","SpringValleyMunicipality","SpringValleyLakeMunicipality","SpringvilleMunicipality","SquawValleyMunicipality","SquirrelMountainValleyMunicipality","St.HelenaMunicipality","StallionSpringsMunicipality","StanfordMunicipality","StantonMunicipality","StevensonRanchMunicipality","StevinsonMunicipality","StinsonBeachMunicipality","StirlingCityMunicipality","StocktonMunicipality","StonyfordMunicipality","StorrieMunicipality","StratfordMunicipality","StrathmoreMunicipality","StrawberryMunicipality","SugarloafMountainParkMunicipality","SugarloafSawMillMunicipality","SugarloafVillageMunicipality","SuisunCityMunicipality","SultanaMunicipality","SummerlandMunicipality","SunVillageMunicipality","SunnySlopesMunicipality","SunnysideMunicipality","SunnysideTahoeCityMunicipality","SunnyvaleMunicipality","SunolMunicipality","SusanvilleMunicipality","SutterMunicipality","SutterCreekMunicipality","SwallMeadowsMunicipality","TaftMunicipality","TaftHeightsMunicipality","TaftMosswoodMunicipality","TahoeVistaMunicipality","TahomaMunicipality","TalmageMunicipality","TamalpaisHomesteadValleyMunicipality","TaraHillsMunicipality","TarpeyVillageMunicipality","TaylorsvilleMunicipality","TecopaMunicipality","TehachapiMunicipality","TehamaMunicipality","TemeculaMunicipality","TemelecMunicipality","TemescalValleyMunicipality","TempleCityMunicipality","TempletonMunicipality","TennantMunicipality","TerminousMunicipality","TerraBellaMunicipality","TevistonMunicipality","ThermalMunicipality","ThermalitoMunicipality","ThorntonMunicipality","ThousandOaksMunicipality","ThousandPalmsMunicipality","ThreeRiversMunicipality","ThreeRocksMunicipality","TiburonMunicipality","TimberCoveMunicipality","TiptonMunicipality","TobinMunicipality","TomalesMunicipality","TonyvilleMunicipality","ToolevilleMunicipality","TopangaMunicipality","TopazMunicipality","ToroCanyonMunicipality","TorranceMunicipality","TracyMunicipality","TranquillityMunicipality","TraverMunicipality","TresPinosMunicipality","TrinidadMunicipality","TrinityCenterMunicipality","TrinityVillageMunicipality","TronaMunicipality","TrowbridgeMunicipality","TruckeeMunicipality","TulareMunicipality","TulelakeMunicipality","TuolumneCityMunicipality","TupmanMunicipality","TurlockMunicipality","TustinMunicipality","TuttleMunicipality","TuttletownMunicipality","TwainMunicipality","TwainHarteMunicipality","TwentyninePalmsMunicipality","TwinLakesMunicipality","UkiahMunicipality","UnionCityMunicipality","UniversityofCaliforniaDavisMunicipality","UniversityofCaliforniaMercedMunicipality","UplandMunicipality","UpperLakeMunicipality","VacavilleMunicipality","ValVerdeMunicipality","ValindaMunicipality","ValleVistaMunicipality","VallecitoMunicipality","VallejoMunicipality","ValleyAcresMunicipality","ValleyCenterMunicipality","ValleyFordMunicipality","ValleyHomeMunicipality","ValleyRanchMunicipality","ValleySpringsMunicipality","ValleyWellsMunicipality","VandenbergAFBMunicipality","VandenbergVillageMunicipality","VerdiMunicipality","VernonMunicipality","VictorMunicipality","VictorvilleMunicipality","ViewParkWindsorHillsMunicipality","VillaParkMunicipality","VinaMunicipality","VincentMunicipality","VineHillMunicipality","VineyardMunicipality","VisaliaMunicipality","VistaMunicipality","VistaSantaRosaMunicipality","VolcanoMunicipality","VoltaMunicipality","WalkerMunicipality","WallaceMunicipality","WalnutMunicipality","WalnutCreekMunicipality","WalnutGroveMunicipality","WalnutParkMunicipality","WarmSpringsMunicipality","WarnerValleyMunicipality","WascoMunicipality","WashingtonMunicipality","WaterfordMunicipality","WaterlooMunicipality","WatsonvilleMunicipality","WaukenaMunicipality","WawonaMunicipality","WeavervilleMunicipality","WeedMunicipality","WeedpatchMunicipality","WeldonMunicipality","WeottMunicipality","WestAthensMunicipality","WestBishopMunicipality","WestCarsonMunicipality","WestCovinaMunicipality","WestGoshenMunicipality","WestHollywoodMunicipality","WestMenloParkMunicipality","WestModestoMunicipality","WestParkMunicipality","WestPointMunicipality","WestPuenteValleyMunicipality","WestRanchoDominguezMunicipality","WestSacramentoMunicipality","WestWhittierLosNietosMunicipality","WesthavenMoonstoneMunicipality","WestlakeVillageMunicipality","WestleyMunicipality","WestminsterMunicipality","WestmontMunicipality","WestmorlandMunicipality","WestsideMunicipality","WestwoodMunicipality","WheatlandMunicipality","WhitehawkMunicipality","WhitewaterMunicipality","WhitleyGardensMunicipality","WhittierMunicipality","WildomarMunicipality","WilkersonMunicipality","WilliamsMunicipality","WillitsMunicipality","WillowCreekMunicipality","WillowbrookMunicipality","WillowsMunicipality","WilsoniaMunicipality","WiltonMunicipality","WinchesterMunicipality","WindsorMunicipality","WinterGardensMunicipality","WinterhavenMunicipality","WintersMunicipality","WintonMunicipality","WoffordHeightsMunicipality","WoodacreMunicipality","WoodbridgeMunicipality","WoodcrestMunicipality","WoodlakeMunicipality","WoodlandMunicipality","WoodlandsMunicipality","WoodsideMunicipality","WoodvilleMunicipality","WrightwoodMunicipality","YankeeHillMunicipality","YettemMunicipality","YoloMunicipality","YorbaLindaMunicipality","YosemiteLakesMunicipality","YosemiteValleyMunicipality","YountvilleMunicipality","YrekaMunicipality","YubaCityMunicipality","YucaipaMunicipality","YuccaValleyMunicipality","ZayanteMunicipality"],"Watershed":["AbbottsLagoonFrontalPacificOceanWatershed","AdobeValleyWatershed","AguaCalienteCreekFrontalSanFranciscoBayEstuariesWatershed","AirportLakeWatershed","AlamedaCreekWatershed","AlamitosBaySanPedroBayWatershed","AlamoCreekWatershed","AlamoPintadoCreekSantaYnezRiverWatershed","AlamoRiverWatershed","AlbionRiverFrontalPacificOceanWatershed","AlderCreekFrontalPacificOceanWatershed","AlgodonesDunesWatershed","AlgodonesDunesChocolateMountainWatershed","AlisoCreekFrontalGulfofSantaCatalinaWatershed","AlkaliValleyFrontalMonoLakeWatershed","AmargosaCreekWatershed","AmboyCraterWatershed","AmericanRiverWatershed","AngelSloughWatershed","AntelopeCreekWatershed","AntelopePlainWatershed","AntelopeValleyAntelopePlainWatershed","AnvilSpringCanyonWatershed","AppleValleyDryLakeWatershed","ArrastreCreekMellvilleLakeWatershed","ArroyoDoblegadoFrontalTulareLakeBedWatershed","ArroyoGrandeCreekWatershed","ArroyoHondoWatershed","ArroyoHondoFresnoSloughWatershed","ArroyoLasPositasWatershed","ArroyoMochoWatershed","ArroyoRamosoElRinconWatershed","ArroyoSaladaFrontalSaltonSeaWatershed","ArroyoSecoWatershed","ArroyoSecoUpperMilpitasWashWatershed","ArroyoTorcidoFrontalTulareLakeBedWatershed","ArroyoTozoHaciendaSpillwayWatershed","ArroyoValleWatershed","ArroyodelaLagunaWatershed","AshCreekWatershed","AshCreekSacramentoRiverWatershed","AuburnRavineWatershed","AustinCreekWatershed","AvenalCreekAlamoSoloSpringWatershed","BadWaterBasinAmargosaRiverWatershed","BadgerBasinWillowCreekWatershed","BallonaCreekWatershed","BasinCreekEelRiverWatershed","BattleCreekWatershed","BaxterCreekFrontalHoneyLakeWatershed","BaxterWashMojaveRiverWatershed","BearCreekWatershed","BearCreekMercedRiverWatershed","BearRiverWatershed","BeaverCreekWatershed","BeegumCreekWatershed","BellMountainWashMojaveRiverWatershed","BigChicoCreekWatershed","BigCreekWatershed","BigCreekFrontalPacificOceanWatershed","BigCreekTuolumneRiverWatershed","BigFrenchCreekTrinityRiverWatershed","BigLagoonFrontalPacificOceanWatershed","BigPineCreekOwensRiverWatershed","BigRiverWatershed","BigRockCreekBigRockWashWatershed","BigSageReservoirRattlesnakeCreekWatershed","BigSandyCreekWatershed","BigSandyCreekSanJoaquinRiverWatershed","BigSulphurCreekWatershed","BigSycamoreCanyonFrontalSantaMonicaBayWatershed","BigTujungaCreekWatershed","BigWashWatershed","BishopCreekWatershed","BissellHillsWatershed","BitterwaterCreekWatershed","BlackButteRiverWatershed","BlackCanyonWatershed","BlackHillsWatershed","BlackRascalCreekWatershed","BlackRockSpringCoyoteWellWatershed","BlackSulphurSpringCarrizoPlainWatershed","BlackhawkCanyonCougarButtesWatershed","BlacksCanyonPitRiverWatershed","BlueCreekWatershed","BluffCreekKlamathRiverWatershed","BogusCreekKlamathRiverWatershed","BolsaChicaChannelFrontalHuningtonHarbourWatershed","BorregoValleyBorregoSinkWashWatershed","BouquetCanyonWatershed","BristolLakeWatershed","BroadwellLakeWatershed","BrownsCanyonWatershed","BrownsCreekWatershed","BrownsWashCadizLakeWatershed","BrushCreekKernRiverWatershed","BucknellCreekEelRiverWatershed","BuckthornWashMojaveRiverWatershed","BuckwheatWashAmargosaRiverWatershed","BuenaVistaCreekWatershed","BuenaVistaLakeBedWatershed","BullRunCreekKernRiverWatershed","BurchCreekWatershed","BurneyCreekWatershed","BurnsCreekWatershed","BurroCanyonDryLakesWatershed","ButtCreekWatershed","ButteCreekWatershed","ButteCreekAshCreekWatershed","ButteCreekLostCreekWatershed","ButteValleyWatershed","CacheSloughWatershed","CadizValleyWatershed","CalaverasRiverWatershed","CalienteCreekWatershed","CaliforniaValleyWatershed","CalleguasCreekWatershed","CampCreekWatershed","CanebrakeCreekWatershed","CantuaCreekFresnoSloughWatershed","CanyonCreekWatershed","CanyonCreekScottRiverWatershed","CaparellCreekFrontalKernLakeBedWatershed","CapeMendicinoFrontalPacificOceanWatershed","CarmelBayFrontalPacificOceanWatershed","CarmelRiverWatershed","CarnerosCreekFrontalSanPabloBayEstuariesWatershed","CarrizoPlainSodaLakeWatershed","CastaicCreekWatershed","CastleCreekSacramentoRiverWatershed","CedarCreekWatershed","CentennialFlatWatershed","ChaloneCreekWatershed","ChamiseCreekEelRiverWatershed","CherryCreekWatershed","ChicagoValleyWatershed","ChimneyCreekWatershed","ChinaLakeWatershed","ChinoCreekWatershed","ChiquitoCreekWatershed","CholameCreekWatershed","ChurnCreekSacramentoRiverWatershed","ClaiborneCreekMcCloudRiverWatershed","ClarkForkWatershed","ClarkValleyWatershed","ClaveyRiverWatershed","ClearCreekWatershed","CleghornLakesWatershed","CleghornPassWatershed","ClipperValleyWashWatershed","ClipperWashWatershed","CloverSwaleCreekWatershed","CoarseGoldCreekWatershed","CoffeeCreekWatershed","ColdForkWatershed","ColdSpringCreekMadelinePlainsWatershed","ColeSloughKingsRiverWatershed","ColusaBasinDrainageCanalWatershed","ColusaDrainWatershed","ColusaTroughWatershed","ConnCreekWatershed","CooksieCreekFrontalPacificOceanWatershed","CoonCreekWatershed","CopicBayWatershed","CorbinCreekEelRiverWatershed","CorralHollowCreekWatershed","CorteMaderaCreekFrontalSanFransiscoBayEstuariesWatershed","CosoWashWatershed","CottonwoodCreekWatershed","CottonwoodCreekAshCreekWatershed","CottonwoodCreekKernRiverWatershed","CottonwoodCreekSanJoaquinRiverWatershed","CottonwoodCreekTylerhorseCanyonWatershed","CowCreekWatershed","CoyoteCreekWatershed","CoyoteLakeWatershed","CoyoteWashWatershed","CroniseValleyWatershed","CrowCreekSanJoaquinRiverWatershed","CruceroHillWatershed","CrystalCreekLucerneLakeWatershed","CuddebackLakeWatershed","CurryCreekSacramentoRiverWatershed","DaggettWashMojaveRiverWatershed","DaleLakeWatershed","DarwinWashWatershed","DeadmanCreekWatershed","DeepCanyonWatershed","DeepCreekWatershed","DeepCreekSecretCreekWatershed","DeepSpringsLakeWatershed","DeerCreekWatershed","DeerPeakWatershed","DelPuertoCreekWatershed","DevilCanyonFrontalIvanpahLakeWatershed","DevilsPlaygroundWashWatershed","DibbleCreekSacramentoRiverWatershed","DillonCreekWatershed","DinkeyCreekWatershed","DobbynCreekWatershed","DogCreekFishSloughWatershed","DominguezChannelWatershed","DoveSpringCanyonRedRockCanyonWatershed","DownieRiverWatershed","DrakesBayFrontalPacificOceanWatershed","DryCreekWatershed","DryCreekFrontalGooseLakeWatershed","DryCreekFrontalMonoLakeWatershed","DryCreekSouthForkPitRiverWatershed","DryValleyCreekWatershed","DryValleyGrasshopperValleyWatershed","DuckSloughWatershed","DutchmanCreekWatershed","DyerCreekLakeWoollomesWatershed","EastBranchNorthForkFeatherRiverWatershed","EastBranchSouthForkEelRiverWatershed","EastForkKaweahRiverWatershed","EastForkRussianRiverWatershed","EastForkScottRiverWatershed","EastForkTrinityRiverWatershed","ElPasoCreekWatershed","ElToroCreekSalinasRiverWatershed","ElderCreekWatershed","EleanorCreekWatershed","ElkBayouWatershed","ElkCreekWatershed","EmigrantWashWatershed","EricksenDryLakeWatershed","EscondidoCreekWatershed","EstrellaRiverWatershed","EticueraCreekWatershed","FallRiverWatershed","FallsCreekTuolumneRiverWatershed","FancherCreekFancherCreekCanalWatershed","FarallonIslandsWatershed","FiddlerGulchGolerGulchWatershed","FineGoldCreekWatershed","FishCanyonPanamintValleyWatershed","FishCreekWatershed","FishCreekWashWatershed","FivemileCreekSanJoaquinRiverWatershed","FletcherCreekBolesCreekWatershed","FoothillDitchOutsideCreekWatershed","FordWellWatershed","FortyninePalmsCanyonShortzLakeWatershed","FrenchCampSloughWatershed","FrenchCreekScottRiverWatershed","FreshwaterCreekWatershed","FrontalSantaMonicaBaySanPedroBayWatershed","FurnaceCreekFrontalFishLakeValleyWatershed","FurnaceCreekWashWatershed","GarapitoCreekFrontalSantaMonicaBayWatershed","GarciaRiverWatershed","GeneralCreekFrontalLakeTahoeWatershed","GilsizerSloughSnakeRiverWatershed","GoatMountainKeysLakeWatershed","GoldenTroutCreekKernRiverWatershed","GoldstoneLakeWatershed","GooseLakeWatershed","GooseLakeCanalWatershed","GooseLakeSloughJerrySloughWatershed","GraniteCreekWatershed","GrapevineCanyonWatershed","GrapevineCreekWatershed","GreenhornCreekWatershed","GreenwaterCanyonAmargosaRiverWatershed","GreenwaterValleyWatershed","GrindstoneCreekWatershed","GriswoldCreekWatershed","GuadalupeRiverFrontalSanFranciscoBayEstuariesWatershed","GualalaRiverWatershed","HaiweeReservoirsWatershed","HalloranWashWatershed","HamiltonBranchWatershed","HarperLakeWatershed","HatCreekWatershed","HayfieldLakeLakeTamariskWatershed","HeadwatersApplegateRiverWatershed","HeadwatersCuyamaRiverWatershed","HeadwatersEastWalkerRiverWatershed","HeadwatersMercedRiverWatershed","HeadwatersNorthForkFeatherRiverWatershed","HeadwatersPosoCreekWatershed","HeadwatersRussianRiverWatershed","HeadwatersSantaAnaRiverWatershed","HeadwatersSantaClaraRiverWatershed","HeadwatersSantaYnezRiverWatershed","HeadwatersSouthForkKernRiverWatershed","HeadwatersTuolumneRiverWatershed","HeadwatersWhitewaterRiverWatershed","HiddenSpringsCanyonFrontalSaltonSeaWatershed","HoncutCreekWatershed","HoneyLakeWatershed","HoneyLakeValleyFrontalHoneyLakeWatershed","HorseCreekWatershed","HorseCreekKaweahRiverWatershed","HorseCreekKlamathRiverWatershed","HorseLakeWillowCreekWatershed","HorseLintoCreekTrinityRiverWatershed","HortonCreekOwensRiverWatershed","HotCreekOwensRiverWatershed","HuasnaRiverWatershed","HuerhueroCreekWatershed","HumboldtBayFrontalPacificOceanWatershed","HumbugCreekKlamathRiverWatershed","HuntoonValleyWatershed","HutchinsonCreekReedsCreekWatershed","ImperialValleyFrontalSaltonSeaWatershed","IndainWashAmericanGirlWashWatershed","IndianCreekWatershed","IndianCreekScottRiverWatershed","IndianValleySalinasRiverWatershed","IngalsbeSloughMercedRiverWatershed","IngramCreekSanJoaquinRiverWatershed","InscriptionCanyonWatershed","IronGateReservoirKlamathRiverWatershed","IronMountainTunnelSandDrawWatershed","IronRidgeGalwayLakeWatershed","IronwoodWashDanbyLakeWatershed","IvanpahLakeWatershed","JacalitosCreekWatershed","JacksonCreekWatershed","JacobsSloughFrontalTulareLakeBedWatershed","JailCanyonWarmSulphurSpringsWatershed","JalamaCreekFrontalSantaBarbaraChannelWatershed","JamesBypassWatershed","JawboneCanyonWatershed","JessValleySouthForkPitRiverWatershed","JewettCreekSacramentoRiverWatershed","JubileeWashAmargosaRiverWatershed","JuniperCreekWatershed","KaiserCreekSanJoaquinRiverWatershed","KelloggCreekBigBreakWatershed","KelseyCreekClearLakeWatershed","KelsoCreekWatershed","KennedyPondFresnoSloughWatershed","KidderCreekScottRiverWatershed","KingstonPeakWatershed","KnightsLandingRidgeCutTuleCanalWatershed","KoehnLakeWatershed","KoskCreekPitRiverWatershed","LaBreaCreekWatershed","LagunaWatershed","LagunitasCreekWatershed","LakePalmdalePiutePondsWatershed","LakePaulinaComancheCreekWatershed","LakeShastinaShastaRiverWatershed","LakeTahoeWatershed","LangfordWellLakeWatershed","LarabeeCreekWatershed","LariousCreekSilverCreekWatershed","LastChanceCreekWatershed","LavaHillsWatershed","LeMontaineCreekEllerSloughWatershed","LeachLakeWatershed","LeeViningCreekFrontalMonoLakeWatershed","LeeWashWatershed","LewisCreekWatershed","LightsCreekWatershed","LittleCowCreekWatershed","LittleDixieWashWatershed","LittleDryCreekWatershed","LittleKernRiverWatershed","LittleLastChanceCreekWatershed","LittleMorongoCreekMorongoWashWatershed","LittlePanocheCreekWatershed","LittleRockWashWatershed","LittleShastaRiverWatershed","LittleStonyCreekWatershed","LittleTruckeeRiverWatershed","LittlejohnsCreekWatershed","LiveoakCanyonPastoriaCreekWatershed","LlagasCreekWatershed","LoganCreekWatershed","LonePineCreekOwensRiverWatershed","LoneTreeCreekWatershed","LoneTreeCreekSanJoaquinRiverWatershed","LosGatosCreekWatershed","LowerAlkaliLakeWatershed","LowerBearCreekWatershed","LowerBearRiverWatershed","LowerBorregoValleyWatershed","LowerButteCreekWatershed","LowerCacheCreekWatershed","LowerCarrizoCreekWatershed","LowerChemehueviWashWatershed","LowerChowchillaRiverWatershed","LowerCosumnesRiverWatershed","LowerCottonwoodCreekWatershed","LowerCoyoteCreekFrontalSanFranciscoBayEstuariesWatershed","LowerCrossCreekWatershed","LowerCuyamaRiverWatershed","LowerDeathValleyWashWatershed","LowerDeerCreekWatershed","LowerDryCreekWatershed","LowerEastForkCarsonRiverWatershed","LowerEurekaValleyWatershed","LowerFeatherRiverWatershed","LowerFremontWashWatershed","LowerFresnoRiverWatershed","LowerHayforkCreekWatershed","LowerHomerWashWatershed","LowerIndianCreekWatershed","LowerKelsoWashWatershed","LowerKernRiverFloodCanalKernRiverChannelWatershed","LowerKingstonWashWatershed","LowerKlamathLakeWatershed","LowerLongValleyCreekFrontalHoneyLakeWatershed","LowerLosAngelesRiverWatershed","LowerLosBanosCreekWatershed","LowerMadRiverWatershed","LowerMiddleForkAmericanRiverWatershed","LowerMiddleForkEelRiverWatershed","LowerMiddleForkFeatherRiverWatershed","LowerMiddleForkStanislausRiverWatershed","LowerMilpitasWashWatershed","LowerMokelumneRiverWatershed","LowerNorthForkAmericanRiverWatershed","LowerNorthForkFeatherRiverWatershed","LowerNorthForkMokelumneRiverWatershed","LowerNorthYubaRiverWatershed","LowerPanocheCreekWatershed","LowerPineCreekEagleLakeWatershed","LowerPintoWashWatershed","LowerPiruCreekWatershed","LowerPiuteWashWatershed","LowerPosoCreekWatershed","LowerPutahCreekWatershed","LowerRussianRiverWatershed","LowerSaltCreekWatershed","LowerSanBenitoRiverWatershed","LowerSanDiegoRiverWatershed","LowerSanFelipeCreekWatershed","LowerSanGabrielRiverWatershed","LowerSanJacintoRiverWatershed","LowerSanJuanCreekWatershed","LowerSanLuisReyRiverWatershed","LowerSantaAnaRiverWatershed","LowerSantaClaraRiverWatershed","LowerSantaYsabelCreekWatershed","LowerSisquocRiverWatershed","LowerSouthForkAmericanRiverWatershed","LowerSouthForkCottonwoodCreekWatershed","LowerSouthForkEelRiverWatershed","LowerSouthForkKernRiverWatershed","LowerSouthForkKingsRiverWatershed","LowerSouthForkSanJoaquinRiverWatershed","LowerSouthForkTrinityRiverWatershed","LowerSouthYubaRiverWatershed","LowerSpringCanyonCreekWatershed","LowerStanislausRiverWatershed","LowerStonyCreekWatershed","LowerSusanRiverFrontalHoneyLakeWatershed","LowerSweetwaterRiverWatershed","LowerTemeculaCreekWatershed","LowerThomesCreekWatershed","LowerTuleRiverWatershed","LowerVanDuzenRiverWatershed","LowerWarmSpringsFrontalSaltLakeWatershed","LowerWatsonWashWatershed","LowerWhiteRiverWatershed","LowerWhitewaterRiverWatershed","LucyGrayMountainsFrontalIvanpahLakeWatershed","LytleCreekWatershed","MalibuCreekWatershed","ManixWashMojaveRiverWatershed","MarbleCanyonWatershed","MarbleForkKaweahRiverKaweahRiverWatershed","MarbleMountainsWatershed","MarkWestCreekWatershed","MarletteLakeFrontalLakeTahoeWatershed","MarshCreekWatershed","MartinsWellDanbyLakeWatershed","MattoleRiverWatershed","MaxwellCreekMercedRiverWatershed","McAfeeCanyonFrontalFishLakeValleyWatershed","McCloudRiverArmShastaLakeWatershed","McCoySpringWatershed","McCoyWashWatershed","McGrathLakeFrontalPacificOceanWatershed","MeansLakeEmersonLakeWatershed","MedicineLakePaynesCreekWatershed","MescalCreekRockyButtesWatershed","MesquiteFlatWatershed","MesquiteLakeWatershed","MesquiteSpringWatershed","MesquiteValleyWatershed","MesquitoSpringWatershed","MiddleAlkaliLakeWatershed","MiddleBearRiverWatershed","MiddleBranchCrossCreekWatershed","MiddleButteCreekWatershed","MiddleCottonwoodCreekWatershed","MiddleCreekWatershed","MiddleCrossCreekWatershed","MiddleCuyamaRiverWatershed","MiddleDeathValleyWashWatershed","MiddleDeerCreekWatershed","MiddleEastForkCarsonRiverWatershed","MiddleForkCosumnesRiverWatershed","MiddleForkCottonwoodCreekWatershed","MiddleForkKaweahRiverWatershed","MiddleForkKingsRiverWatershed","MiddleForkMokelumneRiverWatershed","MiddleForkSanJoaquinRiverWatershed","MiddleForkSmithRiverWatershed","MiddleForkTuleRiverWatershed","MiddleFresnoRiverWatershed","MiddleMadRiverWatershed","MiddleMiddleForkFeatherRiverWatershed","MiddleNorthForkFeatherRiverWatershed","MiddleNorthYubaRiverWatershed","MiddlePineCreekWatershed","MiddlePintoWashWatershed","MiddlePosoCreekWatershed","MiddlePutahCreekWatershed","MiddleRiverSanJoaquinRiverWatershed","MiddleRussianRiverWatershed","MiddleSanFelipeCreekWatershed","MiddleSanJacintoRiverWatershed","MiddleSanLuisReyRiverWatershed","MiddleSantaAnaRiverWatershed","MiddleSantaClaraRiverWatershed","MiddleSisquocRiverWatershed","MiddleSouthForkAmericanRiverWatershed","MiddleSouthForkEelRiverWatershed","MiddleSouthForkKernRiverWatershed","MiddleSouthForkTrinityRiverWatershed","MiddleStonyCreekWatershed","MiddleTuolumneRiverWatershed","MiddleWestWalkerRiverWatershed","MiddleWhitewaterRiverWatershed","MiddleYubaRiverWatershed","MillCanyonPanamintValleyWatershed","MillCreekWatershed","MillFlatCreekKingsRiverWatershed","MissionBayWatershed","MissionBeachFrontalPacificOceanWatershed","MoccasinCreekTuolumneRiverWatershed","MoffettCreekWatershed","MonoCreekWatershed","MonoLakeWatershed","MontereyBayWatershed","MormonSloughWatershed","MorrisonCreekWatershed","MorroBayFrontalEsteroBayWatershed","MountDiabloCreekFrontalSuisunBayEstuariesWatershed","MountGeneralWatershed","MowitzCreekClearLakeWatershed","MudCreekWatershed","MudCreekMcCloudRiverWatershed","MudSloughWatershed","MudSloughSanJoaquinRiverWatershed","MurphySloughFresnoSloughWatershed","MurrietaCreekWatershed","MyrickSpringWatershed","NacimientoRiverWatershed","NapaRiverWatershed","NavarroRiverWatershed","NelsonLakeBicycleLakeWatershed","NewRiverWatershed","NewportBayFrontalPacificOceanWatershed","NinemileCanyonWatershed","NorthForkBattleCreekWatershed","NorthForkCacheCreekWatershed","NorthForkCalaverasRiverWatershed","NorthForkCosumnesRiverWatershed","NorthForkCottonwoodCreekWatershed","NorthForkEelRiverWatershed","NorthForkKaweahRiverWatershed","NorthForkKingsRiverWatershed","NorthForkKingsRiverKingsRiverWatershed","NorthForkMercedRiverWatershed","NorthForkMiddleForkAmericanRiverWatershed","NorthForkPitRiverWatershed","NorthForkSalmonRiverWatershed","NorthForkSmithRiverWatershed","NorthForkStanislausRiverWatershed","NorthForkStonyCreekWatershed","NorthForkTrinityRiverWatershed","NorthForkTuleRiverWatershed","NorthForkTuolumneRiverWatershed","NorthForkWillowCreekWillowCreekWatershed","NorthLucerneValleyWatershed","NoyoRiverWatershed","OatCreekSacramentoRiverWatershed","OldChannelPosoCreekAlpaughIrrigationDistrictCanalWatershed","OldCowCreekWatershed","OldRiverWatershed","OrangeBlossomWashWatershed","OrcuttCreekCorralitosCanyonWatershed","OrestimbaCreekWatershed","OtayRiverWatershed","OutletCreekWatershed","OwensCreekWatershed","OwensLakeWatershed","OwlLakeWatershed","PachecoCreekWatershed","PackardWellWatershed","PajaroRiverWatershed","PalenLakeWatershed","PalmCanyonWashWatershed","PalmettoWashFrontalFishLakeValleyWatershed","PaloVerdeValleyWatershed","PanchoRicoCreekSalinasRiverWatershed","ParkerCreekWatershed","ParksCreekShastaRiverWatershed","PasoRoblesCreekSalinasRiverWatershed","PaynesCreekWatershed","PeasleeCreekTuolumneRiverWatershed","PeerlessValleyWatershed","PescaderoCreekWatershed","PetalumaRiverFrontalSanPabloBayEstuariesWatershed","PicachoWashColoradoRiverWatershed","PilotKnobValleyWatershed","PineCreekWatershed","PineCreekSouthForkPitRiverWatershed","PineFlatReservoirKingsRiverWatershed","PineTreeCanyonWatershed","PineValleyCreekWatershed","PinkhamWashBoxCanyonWashWatershed","PipesWashWatershed","PismoCreekFrontalPacificOceanWatershed","PitRiverArmShastaLakeWatershed","PleasantGroveCreekCrossCanalWatershed","PleititoCreekKernLakeBedWatershed","PointSaintGeorgeFrontalPacificOceanWatershed","PoisonCanyonWatershed","PopeCreekWatershed","PowayCreekWatershed","PriceCreekEelRiverWatershed","ProsserCreekTruckeeRiverWatershed","PuddingCreekFrontalPacificOceanWatershed","QuackenbushLakeBullionWashWatershed","QuailWashWatershed","RacetrackValleyWatershed","RagGulchWatershed","RancheriaCreekWatershed","RattlesnakeCanyonWatershed","RattlesnakeCreekKernRiverWatershed","RedBankCreekWatershed","RedCloverCreekWatershed","RedPassLakeSaltCreekWatershed","RedRockValleyAntelopeCreekWatershed","RedrockCanyonSantaYnezRiverWatershed","RedwoodCreekWatershed","ReedsCreekWatershed","RiceForkWatershed","RiggsWashSaltCreekWatershed","RinconCreekFrontalPacificOceanWatershed","RioHondoWatershed","RoaringCreekPitRiverWatershed","RoaringRiverWatershed","RockCreekWatershed","RockCreekBuckhornLakeWatershed","RockCreekKernRiverWatershed","RockCreekKlamathRiverWatershed","RogersLakeWatershed","RootCreekSanJoaquinRiverWatershed","RosamondLakeWatershed","RoseValleyWatershed","RubiconRiverWatershed","RushCreekWatershed","RushCreekAshCreekWatershed","SacataraCreekKingsCanyonWatershed","SacramentoRiverWatershed","SacramentoRiverArmShastaLakeWatershed","SacramentoWashWatershed","SaddlePeakHillsAmargosaRiverWatershed","SaladoCreekSanJoaquinRiverWatershed","SalmonCreekFrontalPacificOceanWatershed","SalmonRiverWatershed","SalsipuedesCreekSantaYnezRiverWatershed","SaltCreekWatershed","SaltLakeWatershed","SaltRiverEelRiverWatershed","SaltSloughWatershed","SaltonSeaWatershed","SanAntonioCreekWatershed","SanAntonioCreekSouthForkCalaverasRiverWatershed","SanAntonioRiverWatershed","SanDiegoBayWatershed","SanDiegoCreekWatershed","SanDieguitoRiverWatershed","SanEmigdioCreekFrontalBuenaVistaLakeBedWatershed","SanFranciscoBayWatershed","SanGorgonioRiverWatershed","SanGregorioCreekFrontalPacificOceanWatershed","SanJoseCreekWatershed","SanJuanCreekWatershed","SanLorenzoCreekWatershed","SanLorenzoCreekFrontalSanFranciscoBayEstuariesWatershed","SanLorenzoRiverWatershed","SanLuisCreekWatershed","SanMarcosCreekFrontalGulfofSantaCatalinaWatershed","SanMateoCreekWatershed","SanMateoCreekFrontalSanFranciscoBayEstuariesWatershed","SanMiguelIslandSantaRosaIslandWatershed","SanNicholasIslandSantaCatalinaIslandWatershed","SanOnofreCreekFrontalGulfofSantaCatalinaWatershed","SanPabloBayWatershed","SanPabloCreekFrontalSanPabloBayEstuariesWatershed","SanPedroCreekFrontalSantaBarbaraChannelWatershed","SanTimoteoWashWatershed","SanVicenteCreekWatershed","SandCreekWatershed","SandyCreekFrontalBuenaVistaLakeBedWatershed","SantaCruzCreekWatershed","SantaCruzIslandWatershed","SantaMargaritaCreekSalinasRiverWatershed","SantaMargaritaLakeSalinasRiverWatershed","SantaMargaritaRiverWatershed","SantaMariaRiverWatershed","SantaRosaCreekFrontalPacificOceanWatershed","SantaRosaWashWatershed","SantiagoCreekWatershed","SaratogaCreekFrontalSanFranciscoBayEstuariesWatershed","SchulylerWashWatershed","ScottsCreekWatershed","SearlesLakeWatershed","SearlesValleyWatershed","SeiadCreekKlamathRiverWatershed","SespeCreekWatershed","SheepCreekElMirageLakeWatershed","SheepHoleMountainsWatershed","ShepherdCreekOwensRiverWatershed","ShermanLakeSacramentoRiverWatershed","ShipCreekFordDryLakeWatershed","ShumanCanyonFrontalPacificOceanWatershed","SidneyPeakWatershed","SierraValleyWatershed","SilverCreekWatershed","SilverCreekRabbitLakeWatershed","SilverForkAmericanRiverWatershed","SilverLakeWatershed","SkedaddleCreekWatershed","SlateCreekSacramentoRiverWatershed","SmithRiverWatershed","SmithneckCreekWatershed","SnodgrassSloughWatershed","SodaLakeWatershed","SonomaCreekFrontalSanPabloBayEstuariesWatershed","SouthCowCreekWatershed","SouthForkBattleCreekWatershed","SouthForkCosumnesRiverWatershed","SouthForkFeatherRiverWatershed","SouthForkKaweahRiverWatershed","SouthForkMercedRiverWatershed","SouthForkMokelumneRiverWatershed","SouthForkSalmonRiverWatershed","SouthForkSmithRiverWatershed","SouthForkStanislausRiverWatershed","SouthForkTuleRiverWatershed","SouthForkTuolumneRiverWatershed","SouthForkWillowCreekWatershed","SouthForkWillowSloughWatershed","SpanishCreekWatershed","SquawCreekWatershed","SquawValleyCreekWatershed","SteelheadCreekWatershed","StevensonCreekSanJoaquinRiverWatershed","StillwaterCreekWatershed","StoddardValleyWatershed","StoneCorralCreekWatershed","StonewallCreekSalinasRiverWatershed","StuartForkWatershed","SuisunBayWatershed","SunshinePeakLavicLakeWatershed","SuperiorLakeWatershed","SuperstitionHillsFrontalSaltonSeaWatershed","SurpriseCanyonPanamintValleyWatershed","SurpriseSpringsDeadmanLakeWatershed","SutterBasinWatershed","SutterCreekWatershed","SwiftCreekTrinityRiverWatershed","SycamoreSloughWatershed","TangleBlueCreekTrinityRiverWatershed","TankSpringRiceValleyWatershed","TaylorReservoirWatershed","TeagleWashWatershed","TecateCreekWatershed","TecopaHotSpringsAmargosaRiverWatershed","TectahCreekKlamathRiverWatershed","TecuyaCreekFrontalKernLakeBedWatershed","TehachapiCreekWatershed","TejonCreekWatershed","TembladeroSloughWatershed","TemescalWashWatershed","TenMileRiverWatershed","TequisquitaSloughWatershed","TheButtesWatershed","ThirdCreekFrontalLakeTahoeWatershed","ThompsonCreekKlamathRiverWatershed","TinemahaCreekOwensRiverWatershed","TomalesBayBodegaBayWatershed","TomkiCreekWatershed","ToomesCreekWatershed","TownofIvanpahFrontalIvanpahLakeWatershed","TownofKramerJunctionTownofJimgreyWatershed","TownofMendotaFresnoSloughWatershed","TownofOldDaleDogWashWatershed","TownofPearblossomWatershed","TownofPittvillePitRiverWatershed","TownofPoplarFrontalTulareLakeBedWatershed","TownofRichgroveTownofAllensworthWatershed","TresPinosCreekWatershed","TropicoHillOakCreekWatershed","TroyLakeWatershed","TulareLakeBedWatershed","TuleLakeWatershed","TulucayCreekFrontalSanPabloBayEstuariesWatershed","TumeyGulchFresnoSloughWatershed","TurnerCreekWatershed","TurwarCreekKlamathRiverWatershed","TwentymileCreekWatershed","UbehebePeakWatershed","UkonomCreekKlamathRiverWatershed","UlatisCreekWatershed","UpperAlkaliLakeWatershed","UpperBearCreekWatershed","UpperBearRiverWatershed","UpperButteCreekWatershed","UpperCacheCreekWatershed","UpperCarrizoCreekWatershed","UpperChemehueviWashWatershed","UpperChowchillaRiverWatershed","UpperCosumnesRiverWatershed","UpperCottonwoodCreekWatershed","UpperCoyoteCreekWatershed","UpperCrossCreekWatershed","UpperCuyamaRiverWatershed","UpperDeathValleyWashWatershed","UpperDeerCreekWatershed","UpperDryCreekWatershed","UpperEastForkCarsonRiverWatershed","UpperEastWalkerRiverWatershed","UpperEurekaValleyWatershed","UpperFeatherRiverWatershed","UpperFremontWashWatershed","UpperFresnoRiverWatershed","UpperHayforkCreekWatershed","UpperHomerWashWatershed","UpperIndianCreekWatershed","UpperKelsoWashWatershed","UpperKernRiverFloodCanalWatershed","UpperKingstonWashWatershed","UpperLongValleyCreekWatershed","UpperLosAngelesRiverWatershed","UpperLosBanosCreekWatershed","UpperMadRiverWatershed","UpperMiddleForkAmericanRiverWatershed","UpperMiddleForkEelRiverWatershed","UpperMiddleForkFeatherRiverWatershed","UpperMiddleForkStanislausRiverWatershed","UpperMokelumneRiverWatershed","UpperNorthForkAmericanRiverWatershed","UpperNorthForkFeatherRiverWatershed","UpperNorthForkMokelumneRiverWatershed","UpperNorthYubaRiverWatershed","UpperPanocheCreekWatershed","UpperPineCreekWatershed","UpperPintoWashWatershed","UpperPiruCreekWatershed","UpperPosoCreekWatershed","UpperPutahCreekWatershed","UpperRussianRiverWatershed","UpperSaltCreekWatershed","UpperSanBenitoRiverWatershed","UpperSanDiegoRiverWatershed","UpperSanFelipeCreekWatershed","UpperSanGabrielRiverWatershed","UpperSanJacintoRiverWatershed","UpperSanJuanCreekWatershed","UpperSanLuisReyRiverWatershed","UpperSantaAnaRiverWatershed","UpperSantaClaraRiverWatershed","UpperSantaYsabelCreekWatershed","UpperSisquocRiverWatershed","UpperSouthForkAmericanRiverWatershed","UpperSouthForkCottonwoodCreekWatershed","UpperSouthForkEelRiverWatershed","UpperSouthForkKernRiverWatershed","UpperSouthForkKingsRiverWatershed","UpperSouthForkSanJoaquinRiverWatershed","UpperSouthForkTrinityRiverWatershed","UpperSouthYubaRiverWatershed","UpperSpringCanyonCreekWatershed","UpperStanislausRiverWatershed","UpperStonyCreekWatershed","UpperSusanRiverWatershed","UpperSweetwaterRiverWatershed","UpperTemeculaCreekWatershed","UpperThomesCreekWatershed","UpperTruckeeRiverFrontalLakeTahoeWatershed","UpperTuleRiverWatershed","UpperVanDuzenRiverWatershed","UpperWatsonWashWatershed","UpperWestWalkerRiverWatershed","UpperWhiteRiverWatershed","UpperWhitewaterRiverWatershed","UsalCreekFrontalPacificOceanWatershed","UvasCreekWatershed","VallecitoCreekWatershed","ValleyMountainWatershed","VanLoanCreekMadelinePlainsWatershed","VenturaRiverWatershed","VidalWashWatershed","WaddellCreekFrontalAnoNuevoBayWatershed","WagonCreekSacramentoRiverWatershed","WalkerBasinCreekWatershed","WalkerCreekWatershed","WallStreetCanyonWatershed","WalnutCreekWatershed","WalnutCreekFrontalSuisinBayEstuariesWatershed","WarmSpringsValleyPitRiverWatershed","WarthanCreekWatershed","WaterCanyonPanamintValleyWatershed","WaucobaWashWatershed","WeaverCreekTrinityRiverWatershed","WeberCreekWatershed","WestBranchFeatherRiverWatershed","WestForkCarsonRiverWatershed","WestForkMojaveRiverWatershed","WestForkSanGabrielRiverWatershed","WestSideCanalWatershed","WidowValleyCreekPitRiverWatershed","WildWashWatershed","WildroseWashWatershed","WillowCreekWatershed","WillowCreekFrontalGooseLakeWatershed","WillowSloughWatershed","WillowWashWatershed","WilsonCreekWatershed","WingateWashWatershed","WolfCreekWatershed","WoodenValleyCreekFrontalSuisunBayEstuariesWatershed","WoodmanCreekEelRiverWatershed","WoodsCreekWatershed","WooleyCreekWatershed","YagerCreekWatershed","YellowCreekWatershed","YokohlCreekWatershed","YosemiteCreekMercedRiverWatershed","YrekaCreekShastaRiverWatershed","YubaRiverWatershed","ZacaCreekSantaYnezRiverWatershed","ZapatoChinoCreekWatershed"]}}
2 |
--------------------------------------------------------------------------------
/cfo/tests/test_utils.py:
--------------------------------------------------------------------------------
1 | import os
2 | import builtins
3 | import mock
4 | import requests
5 |
6 | from cfo import utils
7 |
8 | # get authentication inputs
9 | try:
10 | email = os.environ["CFO_EMAIL"]
11 | password = os.environ["CFO_PASS"]
12 | except KeyError:
13 | email = "bad@example.com"
14 | password = "badpassword"
15 |
16 |
17 | def test_connection():
18 | """Test internet connectivity"""
19 | url = "http://httpbin.org/get"
20 | body = {"content": "testing"}
21 | response = requests.get(url, body)
22 | assert response.status_code == 200
23 | assert response.json()["args"] == body
24 |
25 |
26 | def test_endpoints():
27 | """Tests connections to API endpoints"""
28 | entries = list(utils.ENDPOINTS.keys())
29 | for entry in entries:
30 | url = "{host}{endpoint}".format(host=utils.URL, endpoint=utils.ENDPOINTS[entry])
31 | response = requests.get(url)
32 | assert response.status_code != 404
33 |
34 |
35 | def test_get_input():
36 | """Tests user input"""
37 | with mock.patch.object(builtins, "input", lambda _: email):
38 | assert utils.get_input(email) == email
39 | assert utils.get_input(email) != password
40 |
41 |
42 | def test_API():
43 | """Tests creation/functions of the CFO API class"""
44 | firetower = utils.API()
45 | methods = dir(firetower)
46 | assert "authenticate" in methods
47 | assert "help" in methods
48 | assert "list_categories" in methods
49 | assert "list_geographies" in methods
50 | assert "list_geography_types" in methods
51 | assert "list_metrics" in methods
52 | assert "search" in methods
53 |
--------------------------------------------------------------------------------
/cfo/utils.py:
--------------------------------------------------------------------------------
1 | """Convenience functions for interacting with the CFO catalog in the Salo Sciences REST API"""
2 | from functools import wraps
3 | import re
4 | import logging
5 | import tempfile
6 | import json
7 | import gzip
8 | import os
9 | import sys
10 | from getpass import getpass
11 |
12 | import requests
13 | from retrying import retry
14 |
15 | # global parameters
16 | URL = "https://api.salo.ai"
17 | CATALOG = "cfo"
18 |
19 | # logging setup
20 | logging.basicConfig(
21 | level=logging.WARNING,
22 | format=("%(asctime)s %(levelname)s %(name)s [%(funcName)s] | %(message)s"),
23 | stream=sys.stdout,
24 | )
25 | LOGGER = logging.getLogger(__name__)
26 |
27 | # define the endpoints
28 | ENDPOINTS = {
29 | "auth": "/users/auth",
30 | "refresh": "/users/auth/refresh",
31 | "search": "/data/search",
32 | "fetch": "/data/fetch",
33 | "pixel_pick": "/data/pixel_pick",
34 | "public_key": "/data/public_key",
35 | "styles": "/data/styles",
36 | }
37 |
38 | # set the path to package data
39 | package_path = os.path.realpath(__file__)
40 | package_dir = os.path.dirname(package_path)
41 | json_path = os.path.join(package_dir, "data", "paths.json")
42 | with open(json_path, "r+") as f:
43 | PATHS = json.loads(f.read())
44 |
45 | # create a temp directory to store the authentication data
46 | TMP_DIR = os.path.join(tempfile.gettempdir(), "cfo")
47 | if not os.path.exists(TMP_DIR):
48 | os.mkdir(TMP_DIR)
49 | TMP_KEY = tempfile.NamedTemporaryFile(mode="w+", dir=TMP_DIR, delete=True)
50 | TMP_FILE = os.path.join(TMP_DIR, "token")
51 |
52 |
53 | def auth_required():
54 | """Decorator to require authorization before an API request is made"""
55 |
56 | def decorator(view):
57 | @wraps(view)
58 | def wrapper(*args, **kwargs):
59 |
60 | self = args[0]
61 | name = view.__name__
62 | warning = f"Authentication is required for function .{name}()"
63 |
64 | # first run auth
65 | if "Authorization" not in self._session.headers:
66 | status = self.authenticate(ignore_temp=False)
67 | if status != 200:
68 | LOGGER.warning(warning)
69 | return None
70 |
71 | if not self._session.headers["Authorization"].startswith("Bearer "):
72 | LOGGER.warning("Authorization header is not a bearer type")
73 | LOGGER.warning(warning)
74 | return None
75 |
76 | matches = re.match(r"^Bearer (\S+)$", self._session.headers["Authorization"])
77 | if not matches:
78 | LOGGER.warning("Invalid bearer token format")
79 | LOGGER.warning(warning)
80 | return None
81 |
82 | return view(*args, **kwargs)
83 |
84 | return wrapper
85 |
86 | return decorator
87 |
88 |
89 | def get_input(data_type: str):
90 | """
91 | Gets command line user input
92 | :param data_type: the data type to prompt the user to request
93 | :return user_input: the user entered content
94 | """
95 | prompt = f"CFO {data_type}: "
96 | try:
97 | if data_type.lower() == "password":
98 | user_input = getpass(prompt)
99 | else:
100 | user_input = input(prompt)
101 |
102 | return user_input
103 |
104 | except Exception as error:
105 | LOGGER.exception(error)
106 |
107 |
108 | def get_email_pass():
109 | """
110 | Gets CFO email/password from environment variables or user input
111 | :return (email, password): tuple of strings for the users input email/password
112 | """
113 |
114 | # check environment variables first
115 | email = os.getenv("CFO_EMAIL")
116 | password = os.getenv("CFO_PASS")
117 |
118 | # get user input otherwise
119 | if email is None:
120 | email = get_input("E-mail")
121 |
122 | if password is None:
123 | password = get_input("Password")
124 |
125 | return email, password
126 |
127 |
128 | def construct_asset_id(
129 | geography: str = None,
130 | category: str = None,
131 | metric: str = None,
132 | year: int = None,
133 | timeOfYear: str = None,
134 | resolution: int = None,
135 | ):
136 | """
137 | Constructs a CFO-format asset id string
138 | :param geography: see list from API.list_geographies()
139 | :param category: see list from API.list_categories()
140 | :param metric: see list from API.list_metrics()
141 | :param year: julian year
142 | :param timeOfYear: can be a date ('0825') or more general ('Fall')
143 | :param resolution: the spatial resolution in meters
144 | :return asset_id: a formatted string
145 | """
146 | # handle None
147 | if geography is None:
148 | geography = "*"
149 | if category is None:
150 | category = "*"
151 | if metric is None:
152 | metric = "*"
153 | if timeOfYear is None:
154 | timeOfYear = "*"
155 |
156 | # handle numerical cases
157 | if year is None:
158 | year = "*"
159 | else:
160 | year = f"{year:04d}"
161 |
162 | if resolution is None:
163 | resolution = "*"
164 | else:
165 | resolution = f"{resolution:05d}m"
166 |
167 | # join everything together
168 | asset_id = "-".join([geography, category, metric, year, timeOfYear, resolution])
169 |
170 | # replace common wildcards with the sql format wildcard
171 | wildcard = "%"
172 | finders = ["*", "?"]
173 | for finder in finders:
174 | asset_id = asset_id.replace(finder, wildcard)
175 |
176 | return asset_id
177 |
178 |
179 | def check(response: object):
180 | """
181 | Evaluates the response code and message returned by a search request
182 | :return [success, msg]: a boolean success/fail on the request and the response message
183 | """
184 | if response.status_code == 200:
185 | success = True
186 | msg = "slugs rule"
187 | else:
188 | success = False
189 | msg = response.content
190 |
191 | return [success, msg]
192 |
193 |
194 | def read_token_file(path: str):
195 | """
196 | Reads a gzipped token tempfile
197 | :param path: the path to the gzipped file
198 | :return token: a token string
199 | """
200 | with gzip.open(path, "rb") as f:
201 | return f.read().decode()
202 |
203 |
204 | def write_token_file(token: str, path: str):
205 | """
206 | Writes token data to a gzipped tempfile
207 | :param token: a string containing the token data
208 | :param path: the path to the output tempfile
209 | :return:
210 | """
211 | with gzip.open(path, "wb") as f:
212 | f.write(token.encode("utf-8"))
213 |
214 |
215 | def write_public_key(tf, data: dict):
216 | """
217 | Writes json key data to a temporary file
218 | :param tf: the tempfile NamedTemporaryFile object
219 | :param data: the public key auth data
220 | :return none: no object returned; an environment variable is updated
221 | """
222 | # write the json data
223 | tf.file.write(json.dumps(data, indent=2) + "\n")
224 | tf.file.flush()
225 |
226 | # point the google auth to this file path
227 | global os
228 | os.environ["GOOGLE_APPLICATION_CREDENTIALS"] = tf.name
229 |
230 |
231 | def validate_geography(lon: float, lat: float):
232 | """
233 | Verifies that latitude and longitude values are valid
234 | :param lon: longitude value in degrees
235 | :param lat: latitude value in degrees
236 | :return valid: boolean for whether the lon/lat values are valid
237 | """
238 | lon_valid = lon >= -180 and lon <= 180
239 | lat_valid = lat >= -90 and lat <= 90
240 | valid = lon_valid and lat_valid
241 | if not valid:
242 | return False
243 | else:
244 | return True
245 |
246 |
247 | class API(object):
248 | """Utility class for Salo API requests"""
249 |
250 | def __init__(self):
251 | """API class constructor"""
252 |
253 | # create the REST session
254 | self._session = requests.Session()
255 |
256 | def help(self):
257 | """Returns the docstring for the main class"""
258 | return self.__doc__
259 |
260 | def list_categories(self):
261 | """
262 | Lists the different categories of data available
263 | :return categories: list
264 | """
265 | return PATHS["category"]
266 |
267 | def list_metrics(self, category: str = None):
268 | """
269 | Lists the metrics available by category
270 | :param category: the category of data for each metric (see .list_categories())
271 | :return metrics: a list if category is specified, a dictionary with each metric if not
272 | """
273 | if category is None:
274 | return PATHS["metric"]
275 | else:
276 | try:
277 | return PATHS["metric"][category]
278 | except KeyError:
279 | LOGGER.warning(f"Unsupported category: {category}")
280 | LOGGER.warning(f"Must be one of {', '.join(self.list_categories())}")
281 | return None
282 |
283 | def list_fuel_metrics(self):
284 | """
285 | Lists the veg metrics needed to create a landscape file
286 | :return metrics: a list of "Vegetation" metrics used to generate landscape files
287 | """
288 | return [
289 | "SurfaceFuels",
290 | "CanopyCover",
291 | "CanopyHeight",
292 | "CanopyBaseHeight",
293 | "CanopyBulkDensity",
294 | ]
295 |
296 | def list_geography_types(self):
297 | """
298 | Lists the broad geography classes (state, watershed, etc.)
299 | :return types: list
300 | """
301 | return list(PATHS["geography"].keys())
302 |
303 | def list_geographies(self, by: str = None):
304 | """
305 | Lists the specific geographic areas available
306 | :param by: the type of geography to list (see .list_geography_types())
307 | :return geographies: a list if type is specified, a dictionary with each geography if not
308 | """
309 | if type is None:
310 | return PATHS["geography"]
311 | else:
312 | try:
313 | return PATHS["geography"][by]
314 | except KeyError:
315 | LOGGER.warning(f"Unsupported category: {by}")
316 | LOGGER.warning(f"Must be one of {', '.join(self.list_geography_types())}")
317 | return None
318 |
319 | def list_fetch_types(self):
320 | """
321 | Lists the different link types that can be retrieved from the fetch() routine
322 | :returns fetch_types: list of strings
323 | """
324 | return ["wms", "signed_url", "uri", "url", "wms_preview"]
325 |
326 | def list_styles(self):
327 | """
328 | Lists the WMS styles available
329 | :returns styles: list of style strings
330 | """
331 | response = self._styles_request()
332 | success, msg = check(response)
333 | if success:
334 | styles = response.json()["styles"]
335 | return styles
336 | else:
337 | LOGGER.warning(msg)
338 | raise
339 |
340 | def authenticate(self, ignore_temp: bool = True):
341 | """
342 | Retrieves a JWT authentication token. Requires a forestobservatory.com account.
343 | :return status_code: the API response status code
344 | """
345 | # check for a stored token
346 | login = True
347 | if not ignore_temp:
348 | if os.path.exists(TMP_FILE):
349 | try:
350 | token = read_token_file(TMP_FILE)
351 | LOGGER.info("Loaded cfo token")
352 | auth = {"Authorization": f"Bearer {token}"}
353 | self._session.headers.update(auth)
354 | login = False
355 | status = 200
356 |
357 | # get the public auth key
358 | response = self._public_key_request()
359 | if response.status_code == 200:
360 | write_public_key(TMP_KEY, response.json())
361 |
362 | except PermissionError:
363 | LOGGER.warning("Unable to read token from temp file")
364 |
365 | # otherwise
366 | if login:
367 | email, password = get_email_pass()
368 | token, status = self._auth_request(email, password)
369 | del password
370 | if status == 200:
371 | LOGGER.info("Authentication successful")
372 | auth = {"Authorization": f"Bearer {token}"}
373 | self._session.headers.update(auth)
374 |
375 | # write it to a temp file for convenience
376 | try:
377 | write_token_file(token, TMP_FILE)
378 | except PermissionError:
379 | pass
380 |
381 | # get the public auth key
382 | response = self._public_key_request()
383 | if response.status_code == 200:
384 | write_public_key(TMP_KEY, response.json())
385 |
386 | else:
387 | LOGGER.warning(f"Authentication failed with status code {status}")
388 |
389 | return status
390 |
391 | def search(
392 | self,
393 | geography: str = None,
394 | category: str = None,
395 | metric: str = None,
396 | year: int = None,
397 | timeOfYear: str = None,
398 | resolution: int = None,
399 | asset_id: str = None,
400 | bbox: list = None,
401 | description: str = None,
402 | raw: bool = False,
403 | just_assets: bool = True,
404 | ):
405 | """
406 | Queries the CFO API for datasets.
407 | :param geography: see list from API.list_geographies()
408 | :param category: see list from API.list_categories()
409 | :param metric: see list from API.list_metrics()
410 | :param year: julian year
411 | :param timeOfYear: can be a date ('0825') or more general ('Fall')
412 | :param resolution: the spatial resolution in meters
413 | :param asset_id: an asset id to search by. this is constructed by the above if not passed
414 | :param bbox: returns only results that intersect this box [xmin, ymin, xmax, ymax] (in lat/lon)
415 | :param description: a string that may match the dataset description
416 | :param raw: specifies whether to return the full response object. default is just json
417 | :param just_assets: specified whether to return just the asset IDs of the search result.
418 | :return response: the api search result
419 | """
420 | # construct an asset ID if not explicitly passed
421 | if asset_id is None:
422 | asset_id = construct_asset_id(
423 | geography=geography,
424 | category=category,
425 | metric=metric,
426 | year=year,
427 | timeOfYear=timeOfYear,
428 | resolution=resolution,
429 | )
430 |
431 | # send the request
432 | response = self._search_request(asset_id=asset_id, bbox=bbox, description=description)
433 |
434 | # check for failures
435 | success, msg = check(response)
436 |
437 | # return the data on a success
438 | if success:
439 | if raw:
440 | return response
441 | elif just_assets:
442 | features = response.json()["features"]
443 | asset_ids = [feature["asset_id"] for feature in features]
444 | return asset_ids
445 | else:
446 | return response.json()["features"]
447 |
448 | # otherwise, debug
449 | else:
450 | LOGGER.warning(msg)
451 | return msg
452 |
453 | def download(self, asset_id: str, path: str = None):
454 | """
455 | Downloads a CFO asset to your local machine
456 | :param asset_id: a CFO asset ID string (often returned from search())
457 | :param path: the output file path. Set to ./{asset_id}.tif by default. Appends '.tif' if not set.
458 | :return:
459 | """
460 | if path is None:
461 | path = os.path.join(os.getcwd(), f"{asset_id}.tif")
462 | else:
463 | if ".tif" not in path.lower():
464 | path = f"{path}.tif"
465 |
466 | # fetch the url by asset ID
467 | url = self.fetch(asset_id, dl=True)
468 |
469 | # then stream the file to disk
470 | r = requests.get(url, stream=True)
471 | if r.ok:
472 | LOGGER.info(f"Beginning download for: {asset_id}")
473 | with open(path, "wb") as f:
474 | for chunk in r.iter_content(chunk_size=128):
475 | f.write(chunk)
476 |
477 | # check that it worked
478 | if os.stat(path).st_size > 0:
479 | LOGGER.info(f"Successfully downloaded {asset_id} to file: {path}")
480 |
481 | def fetch(
482 | self,
483 | asset_id: str,
484 | dl: bool = False,
485 | wms: bool = False,
486 | gdal: bool = False,
487 | bucket: bool = False,
488 | fetch_types: list = [],
489 | ):
490 | """
491 | Fetches the download / map / file url for an asset
492 | :param asset_id: a CFO asset ID string (often returned from search() )
493 | :param dl: returns the asset download url (a google cloud signed url)
494 | :param wms: returns a wms url (for web mapping applications)
495 | :param gdal: returns a vsicurl address to read the data using GDAL
496 | :param bucket: returns a google cloud bucket url to the asset id
497 | :param fetch_types: the full range of fetch options accepted by the API (from get_fetch_types())
498 | :return response: the api fetch result. returns a string if only one boolean parameter passed, otherwise a dict.
499 | """
500 | # handle multiple pathways of parameter setting
501 | responses = dict()
502 | params = list()
503 | n_params = 0
504 | link = "link"
505 |
506 | # make sure something is set
507 | if True not in [dl, wms, bucket, gdal] and len(fetch_types) == 0:
508 | # set a default option
509 | dl = True
510 |
511 | # check each fetch type
512 | if dl:
513 | param = "dl"
514 | response = self._fetch_request(asset_id, fetch_type="signed_url")
515 | success, msg = check(response)
516 | if success:
517 | responses[param] = response.json()[link]
518 | params.append(param)
519 | n_params += 1
520 | else:
521 | LOGGER.warning(msg)
522 | raise
523 | if wms:
524 | param = "wms"
525 | response = self._fetch_request(asset_id, fetch_type="wms")
526 | success, msg = check(response)
527 | if success:
528 | responses[param] = response.json()[link]
529 | params.append(param)
530 | n_params += 1
531 | else:
532 | LOGGER.warning(msg)
533 | raise
534 | if gdal:
535 | param = "gdal"
536 | response = self._fetch_request(asset_id, fetch_type="uri")
537 | success, msg = check(response)
538 | if success:
539 | uri = response.json()[link]
540 | vsi = f"/vsigs/{uri[5:]}"
541 | responses[param] = vsi
542 | params.append(param)
543 | n_params += 1
544 | else:
545 | LOGGER.warning(msg)
546 | raise
547 | if bucket:
548 | param = "bucket"
549 | response = self._fetch_request(asset_id, fetch_type="uri")
550 | success, msg = check(response)
551 | if success:
552 | responses[param] = response.json()[link]
553 | params.append(param)
554 | n_params += 1
555 | else:
556 | LOGGER.warning(msg)
557 | raise
558 |
559 | # run through types last
560 | if len(fetch_types) != 0:
561 | supported = set(self.list_fetch_types())
562 | if supported.intersection(set(fetch_types)) != supported:
563 | LOGGER.warning(f"Unsupported type parameter passed: [{', '.join(fetch_types)}]")
564 | LOGGER.warning(f"Supported type parameters: [{', '.join(supported)}]")
565 | return None
566 | else:
567 | for fetch_type in fetch_types:
568 | response = self._fetch_request(asset_id, fetch_type)
569 | success, msg = check(response)
570 | if success:
571 | responses[fetch_type] = response.json()[link]
572 | n_params += 1
573 | else:
574 | LOGGER.warning(msg)
575 | raise
576 |
577 | # determine what you return based on the number of passed options
578 | if n_params == 1:
579 | return responses[params[0]] # just the link url
580 | else:
581 | return responses # the multi-param dictionary
582 |
583 | def pixel_pick(self, asset_id: str, lon: float, lat: float):
584 | """
585 | Returns the pixel value at a point coordinate from a CFO asset
586 | :param asset_id: a CFO asset ID string (often returned from search())
587 | :param lon: the longitude (x) location in decimal degrees
588 | :param lat: the latitude (y) location in decimal degrees
589 | :return response: the pixel_pick api response.
590 | """
591 | # verify the geometry is valid
592 | if not validate_geography(lon, lat):
593 | LOGGER.warning(f"Invalid longitude/latidude values: {lat:0.2f}/{lon:0.2f}")
594 | LOGGER.warning("Must be in range [-180, 180] and [-90, 90], respectively.")
595 | return None
596 |
597 | # verify the asset ID is valid
598 | response = self._search_request(asset_id=asset_id)
599 | success, msg = check(response)
600 | if not success:
601 | LOGGER.warning(f"Invalid asset_id: {asset_id}")
602 | LOGGER.warning(msg)
603 | return None
604 |
605 | # then get the dang pixel value
606 | response = self._pixel_pick_request(asset_id, lon, lat)
607 | if not success:
608 | LOGGER.warning(msg)
609 | else:
610 | return response.json()["val"]
611 |
612 | @retry(wait_exponential_multiplier=1000, wait_exponential_max=10000)
613 | def _auth_request(self, email: str, password: str):
614 | """
615 | Retrieves a JWT token for the email/password combo
616 | :param email: registered email address
617 | :param password: CFO account password
618 | :return: (token, status_code)
619 | """
620 | endpoint = ENDPOINTS["auth"]
621 | request_url = f"{URL}{endpoint}"
622 | body = {"email": email, "password": password}
623 | response = self._session.post(request_url, json=body)
624 |
625 | # hope for success
626 | if response.status_code == 200:
627 | token = response.json()["token"]
628 |
629 | else:
630 | token = None
631 | LOGGER.warning("Authentication failed. Try and run .authenticate(ignore_temp=True)")
632 | LOGGER.warning(response.content)
633 |
634 | return token, response.status_code
635 |
636 | @auth_required()
637 | @retry(wait_exponential_multiplier=1000, wait_exponential_max=10000)
638 | def _search_request(
639 | self,
640 | catalog: str = CATALOG,
641 | asset_id: str = None,
642 | bbox: list = None,
643 | date: str = None,
644 | description: str = None,
645 | ):
646 | """
647 | Submits the POST request to the search endpoint
648 | :param catalog: the data catalog to query
649 | :param asset_id: a partial/full cfo asset id to search for
650 | :param bbox: a lat/lon bounding box of [xmin, ymin, xmax, ymax] extent
651 | :param date: a utc datetime to query by
652 | :param description: a partial/full dataset description to search by
653 | :return response: the request response
654 | """
655 | endpoint = ENDPOINTS["search"]
656 | request_url = f"{URL}{endpoint}"
657 | body = {
658 | "catalog_list": catalog,
659 | "asset_id": asset_id,
660 | "bounding_box": bbox,
661 | "datetime": date,
662 | "description": description,
663 | }
664 | response = self._session.post(request_url, json=body)
665 |
666 | return response
667 |
668 | @auth_required()
669 | @retry(wait_exponential_multiplier=1000, wait_exponential_max=10000)
670 | def _fetch_request(self, asset_id: str, fetch_type: str, catalog: str = CATALOG):
671 | """
672 | Submits the POST request to the search endpoint
673 | :param asset_id: a full cfo asset id to fetch
674 | :param fetch_type: the type of url to return
675 | :param catalog: the data catalog to query
676 | :return response: the request response
677 | """
678 | endpoint = ENDPOINTS["fetch"]
679 | request_url = f"{URL}{endpoint}"
680 | body = {
681 | "catalog": catalog,
682 | "asset_id": asset_id,
683 | "type": fetch_type,
684 | }
685 | response = self._session.post(request_url, json=body)
686 |
687 | return response
688 |
689 | @retry(wait_exponential_multiplier=1000, wait_exponential_max=10000)
690 | def _styles_request(self):
691 | """
692 | Submits the GET request to the styles endpoint
693 | :return response: the request response
694 | """
695 | endpoint = ENDPOINTS["styles"]
696 | request_url = f"{URL}{endpoint}"
697 | response = self._session.get(request_url)
698 |
699 | return response
700 |
701 | @auth_required()
702 | @retry(wait_exponential_multiplier=1000, wait_exponential_max=10000)
703 | def _public_key_request(self):
704 | """
705 | Submits the GET request to the public_key endpoint
706 | :return response: the request response
707 | """
708 | endpoint = ENDPOINTS["public_key"]
709 | request_url = f"{URL}{endpoint}"
710 | response = self._session.get(request_url)
711 |
712 | return response
713 |
714 | def _pixel_pick_request(self, asset_id: str, lon: float, lat: float, catalog: str = CATALOG):
715 | """
716 | Submits the POST request to the pixel_pick endpoint
717 | :param asset_id: a full cfo asset id to request pixel values from
718 | :param lon: the longitude location to request pixel values from
719 | :param lat: the latitude location to request pixel values from
720 | :param catalog: the data catalog to query
721 | :return response: the request response
722 | """
723 | endpoint = ENDPOINTS["pixel_pick"]
724 | request_url = f"{URL}{endpoint}"
725 | body = {
726 | "catalog": catalog,
727 | "asset_id": asset_id,
728 | "lng": lon,
729 | "lat": lat,
730 | }
731 | response = self._session.post(request_url, json=body)
732 |
733 | return response
734 |
--------------------------------------------------------------------------------
/demos/api-introduction.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {},
6 | "source": [
7 | "# Forest Observatory Webinar API demo\n",
8 | "\n",
9 | "This notebook walks through the central `cfo` Python API functions and demonstrates some potential applications. This includes searching for data, downloading it locally, rendering map tiles & clipping data using other spatial datasets.\n",
10 | "\n",
11 | "This notebook is running in the cfo `conda` environment. We created this simple environment to include a series of useful geospatial/data science packages we use on a regular basis (`gdal`, `otb`, `geopandas`, `sklearn`, etc.). If you have conda [installed](https://docs.conda.io/projects/conda/en/latest/user-guide/install/), you can run the following to run this notebook:\n",
12 | "\n",
13 | "```bash\n",
14 | "git clone https://github.com/forestobservatory/cfo-api.git\n",
15 | "cd cfo-api\n",
16 | "conda env update\n",
17 | "conda activate cfo\n",
18 | "jupyter notebook\n",
19 | "```\n",
20 | "\n",
21 | "### What we'll cover\n",
22 | "\n",
23 | "The `cfo` package is pretty simple. We designed it to make it easy for users to access and use CFO data. This notebook will address the following topics:\n",
24 | "\n",
25 | "- Searching for data\n",
26 | "- Downloading data\n",
27 | "- Loading web maps\n",
28 | "\n",
29 | "You'll need a CFO account to run everything in this notebook. Sign up at [forestobservatory.com](https://forestobservatory.com).\n",
30 | "\n",
31 | "### A note on cloud data storage\n",
32 | "\n",
33 | "This notebook review how to download the data using Salo Science's API. But if you want to skip the middle man (erm, the middle alien) you can find the data on our publicly-accessible Google Cloud Storage Bucket ([link here](https://console.cloud.google.com/storage/browser/cfo-public)). If you use `gsutil`, you can access the data via the `gs://cfo-public` bucket)"
34 | ]
35 | },
36 | {
37 | "cell_type": "code",
38 | "execution_count": null,
39 | "metadata": {},
40 | "outputs": [],
41 | "source": [
42 | "# !!!!!!!!!!!!!!!!!\n",
43 | "# change this to a directory on your local machine to determine where downloads will go\n",
44 | "output_directory = '/home/cba/cfo'"
45 | ]
46 | },
47 | {
48 | "cell_type": "code",
49 | "execution_count": null,
50 | "metadata": {},
51 | "outputs": [],
52 | "source": [
53 | "# package prep\n",
54 | "import os\n",
55 | "import cfo\n",
56 | "import gdal\n",
57 | "import ipyleaflet\n",
58 | "import rasterio\n",
59 | "import numpy as np\n",
60 | "from matplotlib import pyplot as plt\n",
61 | "from ipyleaflet import Map, WMSLayer, LayersControl, basemaps\n",
62 | "\n",
63 | "# set plotting style\n",
64 | "%matplotlib notebook\n",
65 | "\n",
66 | "# create the output directory if it doesn't exist\n",
67 | "if not os.path.exists(output_directory):\n",
68 | " os.mkdir(output_directory)"
69 | ]
70 | },
71 | {
72 | "cell_type": "markdown",
73 | "metadata": {},
74 | "source": [
75 | "# Searching for data\n",
76 | "\n",
77 | "Forest Observatory data are organized by `asset_id`, and you'll need to acquire these IDs before you can do anything else. We built the `search` function to facilitate this. It helps to understand the asset ID format:\n",
78 | "\n",
79 | "```python\n",
80 | "{geography}-{category}-{metric}-{year}-{timeOfYear}-{resolution}\n",
81 | "```\n",
82 | "\n",
83 | "We'll explore these in more detail below.\n",
84 | "\n",
85 | "When you run a `search` command it returns a `list` of asset IDs"
86 | ]
87 | },
88 | {
89 | "cell_type": "code",
90 | "execution_count": null,
91 | "metadata": {},
92 | "outputs": [],
93 | "source": [
94 | "# first, we'll create an api class instance\n",
95 | "forest = cfo.api()"
96 | ]
97 | },
98 | {
99 | "cell_type": "code",
100 | "execution_count": null,
101 | "metadata": {},
102 | "outputs": [],
103 | "source": [
104 | "# search for all California-wide vegetation datasets\n",
105 | "ca = forest.search(geography='California', category='Vegetation')\n",
106 | "\n",
107 | "# list the results\n",
108 | "ca.sort()\n",
109 | "for asset in ca:\n",
110 | " print(asset)"
111 | ]
112 | },
113 | {
114 | "cell_type": "code",
115 | "execution_count": null,
116 | "metadata": {},
117 | "outputs": [],
118 | "source": [
119 | "# you can search the daily weather datasets we produce, which are deleted from the api after two weeks\n",
120 | "\n",
121 | "# list the wind speed assets\n",
122 | "wind = forest.search(metric='WindSpeed')\n",
123 | "wind.sort()\n",
124 | "for asset in wind:\n",
125 | " print(asset)"
126 | ]
127 | },
128 | {
129 | "cell_type": "code",
130 | "execution_count": null,
131 | "metadata": {},
132 | "outputs": [],
133 | "source": [
134 | "# all the CFO data on the website have been clipped by County, Watershed and Municipality. \n",
135 | "# you can search those, too. Try it using wildcards\n",
136 | "\n",
137 | "# we'll search an ambiguous area\n",
138 | "sc = forest.search(geography='santacruz*')\n",
139 | "sc.sort()\n",
140 | "for asset in sc:\n",
141 | " print(asset)"
142 | ]
143 | },
144 | {
145 | "cell_type": "markdown",
146 | "metadata": {},
147 | "source": [
148 | "### Cool! But, what if I don't already know what to enter into those fancy category=\"blah blah blah\" fields?\n",
149 | "\n",
150 | "We've built some convenience functions to help you out! The search function accepts keywords that match the `asset_id` formatting above. So, `forest.search(geography=str, category=str, metric=str, year=int, timeOfYear=str, resolution=int)`.\n",
151 | "\n",
152 | "The convenience functions (under `forest.list_*` can guide some suitable inputs for each."
153 | ]
154 | },
155 | {
156 | "cell_type": "code",
157 | "execution_count": null,
158 | "metadata": {},
159 | "outputs": [],
160 | "source": [
161 | "# list the categories of data we generate\n",
162 | "forest.list_categories()"
163 | ]
164 | },
165 | {
166 | "cell_type": "code",
167 | "execution_count": null,
168 | "metadata": {},
169 | "outputs": [],
170 | "source": [
171 | "# list the metrics in the Vegetation category\n",
172 | "forest.list_metrics('Vegetation')"
173 | ]
174 | },
175 | {
176 | "cell_type": "code",
177 | "execution_count": null,
178 | "metadata": {},
179 | "outputs": [],
180 | "source": [
181 | "# and the weather metrics\n",
182 | "forest.list_metrics('Weather')"
183 | ]
184 | },
185 | {
186 | "cell_type": "code",
187 | "execution_count": null,
188 | "metadata": {},
189 | "outputs": [],
190 | "source": [
191 | "# list the different types of geography we slice data by\n",
192 | "forest.list_geography_types()"
193 | ]
194 | },
195 | {
196 | "cell_type": "code",
197 | "execution_count": null,
198 | "metadata": {},
199 | "outputs": [],
200 | "source": [
201 | "# list the first few county names\n",
202 | "forest.list_geographies('County')[:5]"
203 | ]
204 | },
205 | {
206 | "cell_type": "code",
207 | "execution_count": null,
208 | "metadata": {},
209 | "outputs": [],
210 | "source": [
211 | "# which states do we cover?\n",
212 | "forest.list_geographies('State')"
213 | ]
214 | },
215 | {
216 | "cell_type": "markdown",
217 | "metadata": {},
218 | "source": [
219 | ":sunglasses:"
220 | ]
221 | },
222 | {
223 | "cell_type": "code",
224 | "execution_count": null,
225 | "metadata": {},
226 | "outputs": [],
227 | "source": [
228 | "# wanna be a rebel and just get every dang asset we've published?\n",
229 | "thewholeshebang = forest.search()\n",
230 | "print(f\"Number of CFO assets: {len(thewholeshebang)}\")"
231 | ]
232 | },
233 | {
234 | "cell_type": "markdown",
235 | "metadata": {},
236 | "source": [
237 | ":astonished:"
238 | ]
239 | },
240 | {
241 | "cell_type": "code",
242 | "execution_count": null,
243 | "metadata": {
244 | "scrolled": false
245 | },
246 | "outputs": [],
247 | "source": [
248 | "# for more help, run\n",
249 | "forest.search?"
250 | ]
251 | },
252 | {
253 | "cell_type": "markdown",
254 | "metadata": {},
255 | "source": [
256 | "### Gimme the highest resolution data you have!\n",
257 | "\n",
258 | "Thanks for asking nicely. We're still in the process of publishing our 3m datasets, and we appreciate your patience as we do so. Here's how you would search for the statewide datasets at 10m and 3m resolution."
259 | ]
260 | },
261 | {
262 | "cell_type": "code",
263 | "execution_count": null,
264 | "metadata": {},
265 | "outputs": [],
266 | "source": [
267 | "ca3 = forest.search(geography='california', resolution=3)\n",
268 | "ca10 = forest.search(geography='california', resolution=10)\n",
269 | "print(ca3)"
270 | ]
271 | },
272 | {
273 | "cell_type": "markdown",
274 | "metadata": {},
275 | "source": [
276 | "# Downloading data\n",
277 | "\n",
278 | "Though `search` returns a list of asset IDs, the `download` function requires string inputs. This is to reduce the risk of downloading a huge list of files by accident."
279 | ]
280 | },
281 | {
282 | "cell_type": "code",
283 | "execution_count": null,
284 | "metadata": {},
285 | "outputs": [],
286 | "source": [
287 | "# grab the most recent tree height data from grass valley\n",
288 | "gv = forest.search(geography=\"GrassValley*\", metric='CanopyHeight', year=2020)\n",
289 | "print(f\"Number of files found: {len(gv)}\")\n",
290 | "\n",
291 | "# iterate over the list to pass the asset id as a string\n",
292 | "for asset in gv:\n",
293 | " filename = os.path.join(output_directory, asset + '.tif')\n",
294 | " forest.download(asset, filename)"
295 | ]
296 | },
297 | {
298 | "cell_type": "code",
299 | "execution_count": null,
300 | "metadata": {},
301 | "outputs": [],
302 | "source": [
303 | "# to get all the veg metrics, just iterate over the list\n",
304 | "gv_time_series = forest.search(geography=\"GrassValley*\", category=\"Vegetation\")\n",
305 | "for asset in gv_time_series:\n",
306 | " filename = os.path.join(output_directory, asset + '.tif')\n",
307 | " forest.download(asset, filename)"
308 | ]
309 | },
310 | {
311 | "cell_type": "markdown",
312 | "metadata": {},
313 | "source": [
314 | "### What's happening under the hood?\n",
315 | "\n",
316 | "Great segue. Thanks for asking. The `download` function calls another routine, `fetch()` to get a URL to where the file is stored on our Google Cloud Storage Bucket. The fetch function is used to retrieve a series of different asset-specific URLs.\n",
317 | "\n",
318 | "Downloads use a \"signed url\", which means you can just directly download the file without needing to authenticate with Google first. We then make a `GET` request using this url to stream the file to disk."
319 | ]
320 | },
321 | {
322 | "cell_type": "code",
323 | "execution_count": null,
324 | "metadata": {},
325 | "outputs": [],
326 | "source": [
327 | "# print out the long and convoluted signed url\n",
328 | "for asset in gv:\n",
329 | " print(forest.fetch(asset, dl=True))"
330 | ]
331 | },
332 | {
333 | "cell_type": "code",
334 | "execution_count": null,
335 | "metadata": {},
336 | "outputs": [],
337 | "source": [
338 | "# alternatively you can just get the direct bucket uri\n",
339 | "for asset in gv:\n",
340 | " print(forest.fetch(asset, bucket=True))"
341 | ]
342 | },
343 | {
344 | "cell_type": "code",
345 | "execution_count": null,
346 | "metadata": {},
347 | "outputs": [],
348 | "source": [
349 | "# set multiple flags to return a dictionary of urls\n",
350 | "for asset in gv:\n",
351 | " urls = forest.fetch(asset, dl=True, bucket=True, wms=True, gdal=True)\n",
352 | " for key in list(urls.keys()):\n",
353 | " print(f\"{key}: {urls[key]}\")\n",
354 | " print(\"\")"
355 | ]
356 | },
357 | {
358 | "cell_type": "markdown",
359 | "metadata": {},
360 | "source": [
361 | "# Custom data clipping\n",
362 | "\n",
363 | "We clipped all of the 2020 10-meter Vegetation data by County, Municipality & Watershed based on feedback from the community that these were the most relevant areas and datasets of interest. You're welcome.\n",
364 | "\n",
365 | "But we imagine many people are going to be interested in analyzing custom areas of interest. How do you download data from an AOI vector file?\n",
366 | "\n",
367 | "The best way to do this with the API is through `gdal`, referencing the statewide datasets.\n",
368 | "\n",
369 | "`gdalwarp` has a really nice driver for handling [cloud datasets](https://gdal.org/user/virtual_file_systems.html) that allows you to clip rasters on Google Cloud Storage. \n",
370 | "\n",
371 | "We'll run through an example now to use a `geojson` file to download canopy height data from the perimeter of the CZU fire in the Santa Cruz Mountains. This will use `gdal`'s python bindings, but we'll also show what the command line version would look like."
372 | ]
373 | },
374 | {
375 | "cell_type": "code",
376 | "execution_count": null,
377 | "metadata": {},
378 | "outputs": [],
379 | "source": [
380 | "# this vector is in cfo-api/demos\n",
381 | "vector = os.path.join(os.getcwd(), \"czu-perimeter.geojson\")\n",
382 | "\n",
383 | "# get the 2020 10m canopy height asset id\n",
384 | "czu_search = forest.search(geography='California', metric='CanopyHeight', year=2020, resolution=10)\n",
385 | "czu = czu_search[0]\n",
386 | "\n",
387 | "# and get the gdal file path reference\n",
388 | "input_file = forest.fetch(czu, gdal=True)\n",
389 | "print(f\"We'll download from: {input_file}\")"
390 | ]
391 | },
392 | {
393 | "cell_type": "code",
394 | "execution_count": null,
395 | "metadata": {},
396 | "outputs": [],
397 | "source": [
398 | "# set the output raster file\n",
399 | "output_file = os.path.join(output_directory, \"CZU-perimeter-CanopyHeight-2020.tif\")\n",
400 | "\n",
401 | "# set the gdalwarp options\n",
402 | "options = gdal.WarpOptions(\n",
403 | " creationOptions = [\"COMPRESS=DEFLATE\", \"TILED=YES\", \"BIGTIFF=YES\", \"NUM_THREADS=ALL_CPUS\"],\n",
404 | " cutlineDSName = vector,\n",
405 | " cropToCutline = True\n",
406 | ")\n",
407 | "\n",
408 | "# and run the command\n",
409 | "warp = gdal.Warp(output_file, input_file, options=options)\n",
410 | "warp.FlushCache()"
411 | ]
412 | },
413 | {
414 | "cell_type": "markdown",
415 | "metadata": {},
416 | "source": [
417 | "The above is akin to running something like this at the command line:\n",
418 | "\n",
419 | "```\n",
420 | "gdalwarp /vsigs/cfo-public/vegetation/California-Vegetation-CanopyHeight-2020-Summer-00010m.tif /home/cba/cfo/California-Vegetation-CanopyHeight-2020-Summer-00010m.tif -cutline /home/cba/src/cfo-api/demos/czu-perimeter.geojson -crop_to_cutline\n",
421 | "```"
422 | ]
423 | },
424 | {
425 | "cell_type": "code",
426 | "execution_count": null,
427 | "metadata": {},
428 | "outputs": [],
429 | "source": [
430 | "# read and mask the data\n",
431 | "source = rasterio.open(output_file)\n",
432 | "height = source.read(1).astype(float)\n",
433 | "height[height == source.nodata] = np.nan\n",
434 | "\n",
435 | "# get the range to show\n",
436 | "vmin = np.nanpercentile(height, 5)\n",
437 | "vmax = np.nanpercentile(height, 95)\n",
438 | "\n",
439 | "# and plot\n",
440 | "plt.plot(figsize=(15,15), dpi=100)\n",
441 | "height_map = plt.imshow(height, vmin=vmin, vmax=vmax, cmap=plt.cm.cividis)\n",
442 | "plt.title(\"Canopy height inside the\\nburn perimeter of the CZU fire\")\n",
443 | "colorbar = plt.colorbar(height_map)\n",
444 | "colorbar.set_label(\"Canopy Height (m)\")\n",
445 | "plt.tight_layout()"
446 | ]
447 | },
448 | {
449 | "cell_type": "markdown",
450 | "metadata": {},
451 | "source": [
452 | "# Web mapping"
453 | ]
454 | },
455 | {
456 | "cell_type": "code",
457 | "execution_count": null,
458 | "metadata": {},
459 | "outputs": [],
460 | "source": [
461 | "forest.fetch(\"MendocinoCounty-Vegetation-CanopyHeight-2020-Summer-00010m\", wms=True)"
462 | ]
463 | },
464 | {
465 | "cell_type": "markdown",
466 | "metadata": {},
467 | "source": [
468 | "WMS URLs don't always easily plug and play with different rendering services, but they should work with a little nudging. Here's how to use the above URL to visualize these data with `ipyleaflet`."
469 | ]
470 | },
471 | {
472 | "cell_type": "code",
473 | "execution_count": null,
474 | "metadata": {},
475 | "outputs": [],
476 | "source": [
477 | "wms = WMSLayer(\n",
478 | " url='https://maps.salo.ai/geoserver/cfo/wms?p0=0.0&p2=1.44&p25=18.0&p30=21.599999999999998&p50=36.0&p60=43.199999999999996&p75=54.0&p90=64.8&p98=70.56&p100=72.0',\n",
479 | " layers=\"cfo:MendocinoCounty-Vegetation-CanopyHeight-2020-Summer-00010m\",\n",
480 | " name=\"Mendocino Canopy Height\",\n",
481 | " styles=\"vegetation\",\n",
482 | " format=\"image/png8\",\n",
483 | " transparent=True,\n",
484 | " attribution=\"Forest Observatory © Salo Sciences\",\n",
485 | ")\n",
486 | "m = Map(basemap=basemaps.Stamen.Terrain, center=(39.39,-123.33), zoom=10)\n",
487 | "m.add_layer(wms)\n",
488 | "control = LayersControl(position='topright')\n",
489 | "m.add_control(control)\n",
490 | "m"
491 | ]
492 | }
493 | ],
494 | "metadata": {
495 | "kernelspec": {
496 | "display_name": "Python 3",
497 | "language": "python",
498 | "name": "python3"
499 | },
500 | "language_info": {
501 | "codemirror_mode": {
502 | "name": "ipython",
503 | "version": 3
504 | },
505 | "file_extension": ".py",
506 | "mimetype": "text/x-python",
507 | "name": "python",
508 | "nbconvert_exporter": "python",
509 | "pygments_lexer": "ipython3",
510 | "version": "3.7.8"
511 | }
512 | },
513 | "nbformat": 4,
514 | "nbformat_minor": 4
515 | }
516 |
--------------------------------------------------------------------------------
/demos/czu-perimeter.geojson:
--------------------------------------------------------------------------------
1 | {
2 | "type": "FeatureCollection",
3 | "name": "czu-perimeter",
4 | "crs": { "type": "name", "properties": { "name": "urn:ogc:def:crs:OGC:1.3:CRS84" } },
5 | "features": [
6 | { "type": "Feature", "properties": { "AREA": 485725.65567214595, "PERIMETER": 2795.3435221367599 }, "geometry": { "type": "Polygon", "coordinates": [ [ [ -122.297970184044004, 37.270360380625078 ], [ -122.281358893870419, 37.270989317353958 ], [ -122.280873707307137, 37.273605976855023 ], [ -122.273962497020079, 37.273765676257788 ], [ -122.273078936485149, 37.270757775240092 ], [ -122.271970868366623, 37.270803132927192 ], [ -122.271430824428265, 37.26926462362227 ], [ -122.25692814635255, 37.269120828825983 ], [ -122.256845678930759, 37.268803175987351 ], [ -122.253874698899565, 37.269056922760186 ], [ -122.253236740897421, 37.264364074727638 ], [ -122.250423740191763, 37.264030233559922 ], [ -122.250812750067141, 37.26206573036383 ], [ -122.23963469250856, 37.261837096489181 ], [ -122.236147282295079, 37.25695192093184 ], [ -122.23203865952037, 37.256803910600446 ], [ -122.23115994999057, 37.252949258648833 ], [ -122.222812191223483, 37.252714044268721 ], [ -122.22255885932185, 37.252358987595386 ], [ -122.220997977220463, 37.252315825593726 ], [ -122.21955277050975, 37.250418675521573 ], [ -122.217062811411267, 37.250587586212596 ], [ -122.217023088603355, 37.250297096696542 ], [ -122.214043917777332, 37.250478478749748 ], [ -122.213591283438646, 37.246364575452723 ], [ -122.208575598700435, 37.246024250795081 ], [ -122.208251572188274, 37.243652578374835 ], [ -122.205993770232723, 37.243588634601309 ], [ -122.205687726663513, 37.243159472240336 ], [ -122.203991031218536, 37.243097939428303 ], [ -122.203987392589397, 37.243065856875909 ], [ -122.20035499322212, 37.243286612558869 ], [ -122.200067276466143, 37.237150712383453 ], [ -122.197529318643731, 37.237015121641875 ], [ -122.196185210798106, 37.235129738490102 ], [ -122.187090341331995, 37.235744529028459 ], [ -122.18700380683417, 37.227681583440749 ], [ -122.185890784278698, 37.227548813726585 ], [ -122.186073458281996, 37.221532434705971 ], [ -122.17638808523273, 37.222353820863852 ], [ -122.175541414083369, 37.216074435533628 ], [ -122.178054404565387, 37.215711561122106 ], [ -122.177951850551551, 37.214337142107041 ], [ -122.175836092883145, 37.214533430692015 ], [ -122.174784395545274, 37.21093371763299 ], [ -122.166672650856228, 37.211301082080496 ], [ -122.16663600426358, 37.209697947708889 ], [ -122.163754860477127, 37.209571791841597 ], [ -122.163569185394437, 37.202612000165026 ], [ -122.160801304893695, 37.20222789676054 ], [ -122.160773780019127, 37.196129962891149 ], [ -122.158062733123629, 37.195805794295786 ], [ -122.158239914805137, 37.191862826024995 ], [ -122.150344818663754, 37.191685010751023 ], [ -122.150283334051139, 37.191368075493507 ], [ -122.147755199661859, 37.191767841492833 ], [ -122.146889475618494, 37.188410543466944 ], [ -122.144389025581418, 37.188607579232297 ], [ -122.144477516606216, 37.186972159665459 ], [ -122.141111282159272, 37.186436485398382 ], [ -122.141113794738473, 37.184312911655482 ], [ -122.138554845128311, 37.184154296012011 ], [ -122.138551222975707, 37.181930259788729 ], [ -122.138424176937548, 37.181910038631223 ], [ -122.138434772125905, 37.173206560762587 ], [ -122.135539463623147, 37.172621504507084 ], [ -122.135577735922524, 37.168580886691359 ], [ -122.132830339801416, 37.167963513259046 ], [ -122.132909568646767, 37.160828627907499 ], [ -122.132903735490913, 37.160827180843441 ], [ -122.132910488907328, 37.160745754635869 ], [ -122.132949074240386, 37.157270985738663 ], [ -122.132940862931406, 37.157271288242377 ], [ -122.13264656485056, 37.156666389305997 ], [ -122.132151585132036, 37.156655162820911 ], [ -122.131827856439074, 37.154983619761964 ], [ -122.131782946239809, 37.154891311542727 ], [ -122.130114483413166, 37.154554007345524 ], [ -122.130132774547619, 37.152713430219855 ], [ -122.108404370845562, 37.151469393017642 ], [ -122.108378607395167, 37.139061221377062 ], [ -122.103026658678957, 37.138067883593813 ], [ -122.102855966714458, 37.130005626573997 ], [ -122.09761651217012, 37.129164645095642 ], [ -122.097578419128695, 37.122805987442838 ], [ -122.106449914053727, 37.12222405350105 ], [ -122.112976576079092, 37.130983184753262 ], [ -122.119212000097306, 37.131340425252233 ], [ -122.119261200271978, 37.119372835586454 ], [ -122.117244074786427, 37.119263565578407 ], [ -122.116543469834269, 37.114979236843489 ], [ -122.115329150044602, 37.114785508784408 ], [ -122.114404811361609, 37.114735411753408 ], [ -122.11438846720921, 37.114635435746429 ], [ -122.111054435166196, 37.11410353668483 ], [ -122.111082801238013, 37.109920254650874 ], [ -122.108122643363558, 37.109320894290988 ], [ -122.108295071257174, 37.09285249261282 ], [ -122.106009000926548, 37.092968570372648 ], [ -122.106413070180267, 37.087318461634673 ], [ -122.105898313815388, 37.087256599202711 ], [ -122.105868043154288, 37.084307944738327 ], [ -122.105681400282236, 37.084270138239518 ], [ -122.105693661329468, 37.083093969553182 ], [ -122.10315827902582, 37.082835487407131 ], [ -122.103102808487364, 37.081163089854002 ], [ -122.092693091974695, 37.08141512507104 ], [ -122.092807449220345, 37.055088683724634 ], [ -122.087323013541393, 37.054211937745364 ], [ -122.087325743568414, 37.052738131724318 ], [ -122.083790556104432, 37.052326823691686 ], [ -122.083861441690331, 37.048059452213693 ], [ -122.083615271226591, 37.048045637057719 ], [ -122.083773447457091, 37.045917355117126 ], [ -122.08361671951937, 37.045904807837147 ], [ -122.083953843285201, 37.042496799024818 ], [ -122.083977792612203, 37.041055029536203 ], [ -122.08193243762976, 37.040769235391728 ], [ -122.08270102945167, 37.034438322284828 ], [ -122.090283305542243, 37.034555967059632 ], [ -122.090677870973394, 37.032970002082529 ], [ -122.095255858666633, 37.033076921857266 ], [ -122.095860794897078, 37.024216415460742 ], [ -122.101077609698166, 37.024200995070025 ], [ -122.101101138410883, 37.020384996085056 ], [ -122.10508746903686, 37.019726955307803 ], [ -122.10525504783422, 37.016650593246254 ], [ -122.107331929355553, 37.016763586722604 ], [ -122.107752406149629, 37.015071450814034 ], [ -122.115566683934688, 37.015861705991014 ], [ -122.115551285776064, 37.022148138937979 ], [ -122.117619655626115, 37.022142739672482 ], [ -122.11871140157885, 37.017746724846909 ], [ -122.121676045322928, 37.017961346414189 ], [ -122.121760797921965, 37.017692388636142 ], [ -122.128644273187632, 37.0179450240094 ], [ -122.129344778330776, 37.022229347942343 ], [ -122.134213299701869, 37.022492841832104 ], [ -122.13454608277965, 37.024527127917523 ], [ -122.14361992934785, 37.025206518047419 ], [ -122.143344903838255, 37.030855280728012 ], [ -122.140373947877592, 37.031167858832944 ], [ -122.140370627894882, 37.031669578988506 ], [ -122.14316548510223, 37.032058789380528 ], [ -122.143119404549054, 37.053878938380976 ], [ -122.154474574378099, 37.053960314232718 ], [ -122.154562616761524, 37.051273796122537 ], [ -122.155337871166836, 37.051121391237523 ], [ -122.155338427864322, 37.051111459537367 ], [ -122.155428179217139, 37.051103637854986 ], [ -122.156699692005716, 37.050853675056956 ], [ -122.157091220427205, 37.036551776040966 ], [ -122.160422416035175, 37.03648499443991 ], [ -122.160436254063811, 37.036134228546821 ], [ -122.166156121738155, 37.036128585542308 ], [ -122.166152676762607, 37.035982830008599 ], [ -122.168754746574947, 37.035748649764962 ], [ -122.169441085058068, 37.033566476683283 ], [ -122.169514421830598, 37.033566862377604 ], [ -122.169532215523404, 37.03350342352207 ], [ -122.177629811275636, 37.033604741980845 ], [ -122.178170734391443, 37.030699161616141 ], [ -122.18018286479014, 37.030654072890037 ], [ -122.180753838872121, 37.027128455449493 ], [ -122.209516480300394, 37.027323551824338 ], [ -122.210780793275816, 37.036320131196291 ], [ -122.223155680370809, 37.036863438268803 ], [ -122.229758997099935, 37.036751768293847 ], [ -122.229799694373639, 37.037155137075416 ], [ -122.233130620926048, 37.037301378082709 ], [ -122.23287131579616, 37.047582475886209 ], [ -122.232710849286391, 37.047590223544198 ], [ -122.23283873724975, 37.050801647887845 ], [ -122.237101868242817, 37.051379518126183 ], [ -122.237366331446424, 37.056556689961326 ], [ -122.243114309613716, 37.056626912277416 ], [ -122.243972311826639, 37.05994259536147 ], [ -122.253572630913382, 37.060248525155934 ], [ -122.253771171320622, 37.06128978755099 ], [ -122.254621117171993, 37.061308271847331 ], [ -122.257263944314147, 37.064964445473194 ], [ -122.259796627920124, 37.065498280759833 ], [ -122.259832730911029, 37.068518188983738 ], [ -122.261050553359368, 37.070202964444682 ], [ -122.266384610341575, 37.070836997295089 ], [ -122.266554917748365, 37.073534138527393 ], [ -122.269749830510747, 37.073598414625131 ], [ -122.27021331425172, 37.075104858238689 ], [ -122.271868156076195, 37.07527126763857 ], [ -122.271968804513534, 37.078115245804341 ], [ -122.276334825258843, 37.078809829158374 ], [ -122.27646184564604, 37.082274642045221 ], [ -122.280412298193269, 37.082668264403132 ], [ -122.280411081739075, 37.086679965686194 ], [ -122.282776772687598, 37.086661873082242 ], [ -122.283148062632009, 37.093815198327434 ], [ -122.283253601569001, 37.093834105926817 ], [ -122.283252809339928, 37.095833263404003 ], [ -122.283271608736101, 37.0961954552631 ], [ -122.287138473029472, 37.096630272208778 ], [ -122.293344991532805, 37.105153475599181 ], [ -122.304212000334431, 37.106018968228469 ], [ -122.304401254342253, 37.111129201850915 ], [ -122.304631383276444, 37.111132880971311 ], [ -122.305241148762008, 37.113816755472044 ], [ -122.31098915748467, 37.114165437235194 ], [ -122.311035885235157, 37.120597168296982 ], [ -122.311141450188899, 37.123536569224399 ], [ -122.315581665166761, 37.124591558240986 ], [ -122.315584436733346, 37.125376868237325 ], [ -122.316726208266545, 37.125581000219341 ], [ -122.316726467458622, 37.132561017934627 ], [ -122.319499132476906, 37.133143404916645 ], [ -122.320172765637693, 37.133199278013173 ], [ -122.320182523380538, 37.133286948389539 ], [ -122.321056491873847, 37.133470521908102 ], [ -122.321060404112615, 37.133777195396064 ], [ -122.338952571656009, 37.134362394984123 ], [ -122.339107157425033, 37.140514562278277 ], [ -122.339181479439901, 37.14076721920555 ], [ -122.344675235953815, 37.141632398805676 ], [ -122.344700577120548, 37.148241278640796 ], [ -122.344733841052403, 37.148799294135024 ], [ -122.34470274193913, 37.148805855087325 ], [ -122.344712292510039, 37.151296607631231 ], [ -122.33907952085066, 37.152484905862167 ], [ -122.338621901272376, 37.161002041662023 ], [ -122.333370009981053, 37.161466952709588 ], [ -122.33335698366092, 37.162949547810392 ], [ -122.333352974162494, 37.163406048646827 ], [ -122.334731763527827, 37.163303388686757 ], [ -122.335022205819882, 37.168927286830893 ], [ -122.3374235130442, 37.169307591961953 ], [ -122.337449986237971, 37.169779288127629 ], [ -122.337981296323761, 37.169774483352761 ], [ -122.338114510790035, 37.170544594848053 ], [ -122.338792719394604, 37.170651398213479 ], [ -122.338788043109602, 37.174438278441514 ], [ -122.339053666491154, 37.175973844549809 ], [ -122.338786091796521, 37.176018462060512 ], [ -122.338782431922667, 37.178982247186767 ], [ -122.340952952324756, 37.178943619135666 ], [ -122.341522525553927, 37.184498967625466 ], [ -122.340287445034065, 37.184645667699563 ], [ -122.344382903309707, 37.190373194285627 ], [ -122.349628259472482, 37.19089644110776 ], [ -122.349931139802933, 37.196526633759078 ], [ -122.349806417830038, 37.196538015027762 ], [ -122.349913908512804, 37.198536111223461 ], [ -122.344419006508915, 37.199037522453033 ], [ -122.344528250187693, 37.202653705179152 ], [ -122.337703644499825, 37.203025679487517 ], [ -122.33743087484234, 37.20400402390289 ], [ -122.336678893519007, 37.204004133843 ], [ -122.336545837616654, 37.214973649002872 ], [ -122.33803468247504, 37.215014295187366 ], [ -122.338727545374596, 37.220781882886968 ], [ -122.336469615351405, 37.221257634000636 ], [ -122.336454520450388, 37.222502101495401 ], [ -122.333047397624767, 37.223069779537099 ], [ -122.332590947761389, 37.234993564686221 ], [ -122.330712959132214, 37.235068114049795 ], [ -122.330699459064334, 37.23599058968616 ], [ -122.325127150294634, 37.236918560149853 ], [ -122.32453837187326, 37.240105492501357 ], [ -122.32465885931822, 37.240103367516561 ], [ -122.324714949167131, 37.240651217330722 ], [ -122.326925060602221, 37.240612196649501 ], [ -122.327493998369945, 37.246167549441793 ], [ -122.326165475565674, 37.246325046675551 ], [ -122.326171764172656, 37.24638646173004 ], [ -122.323974458553494, 37.246646927820748 ], [ -122.324061597094158, 37.247498152580654 ], [ -122.321307066505099, 37.247824616039779 ], [ -122.321278496241575, 37.250449449103129 ], [ -122.318354431876486, 37.250999364760446 ], [ -122.318120572408063, 37.268712669844497 ], [ -122.311684430796262, 37.269156791576897 ], [ -122.309861350096952, 37.269499468723055 ], [ -122.309832554046494, 37.272654145015863 ], [ -122.302323258572486, 37.273955691057537 ], [ -122.301903815670158, 37.272681520657905 ], [ -122.297918893937421, 37.27271661382246 ], [ -122.297970184044004, 37.270360380625078 ] ], [ [ -122.127690430225087, 37.136049881195632 ], [ -122.127620404218533, 37.133959791324656 ], [ -122.12541365888228, 37.134133417161003 ], [ -122.126799574028098, 37.136043345255942 ], [ -122.127690430225087, 37.136049881195632 ] ] ] } }
7 | ]
8 | }
9 |
--------------------------------------------------------------------------------
/environment.yml:
--------------------------------------------------------------------------------
1 | name: cfo
2 |
3 | channels:
4 | - conda-forge
5 |
6 | dependencies:
7 | - python=3.7
8 | - jupyter=1.0.0
9 | - matplotlib=3.2.1
10 | - black
11 | - earthengine-api
12 | - flake8
13 | - folium
14 | - gdal>=3.0
15 | - geopandas
16 | - ipython
17 | - ipyleaflet
18 | - isort
19 | - mock
20 | - pandas
21 | - pre-commit
22 | - pytest
23 | - pytest-cov
24 | - rasterio
25 | - rtree
26 | - scikit-learn
27 | - shapely
28 | - pip
29 | - pip:
30 | - .
31 | - -r file:requirements.txt
32 | - pystac
33 |
--------------------------------------------------------------------------------
/img/cfo-fire.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/forestobservatory/cfo-api/fd3a8156f02226937e2a2b1f783ceb39fb22ff15/img/cfo-fire.jpg
--------------------------------------------------------------------------------
/img/cfo-height.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/forestobservatory/cfo-api/fd3a8156f02226937e2a2b1f783ceb39fb22ff15/img/cfo-height.png
--------------------------------------------------------------------------------
/img/cfo-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/forestobservatory/cfo-api/fd3a8156f02226937e2a2b1f783ceb39fb22ff15/img/cfo-logo.png
--------------------------------------------------------------------------------
/img/cfo-terrain.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/forestobservatory/cfo-api/fd3a8156f02226937e2a2b1f783ceb39fb22ff15/img/cfo-terrain.jpg
--------------------------------------------------------------------------------
/img/cfo-understory.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/forestobservatory/cfo-api/fd3a8156f02226937e2a2b1f783ceb39fb22ff15/img/cfo-understory.png
--------------------------------------------------------------------------------
/img/ipyleaflet-example.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/forestobservatory/cfo-api/fd3a8156f02226937e2a2b1f783ceb39fb22ff15/img/ipyleaflet-example.jpg
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | requests>=2.23
2 | retrying>=1.3.3
3 |
--------------------------------------------------------------------------------
/setup.py:
--------------------------------------------------------------------------------
1 | from setuptools import find_packages, setup
2 |
3 | version = open("cfo/__version__.py").read().strip('"\n')
4 | long_description = open("README.md", "r", encoding="utf-8").read()
5 |
6 | setup(
7 | name="cfo",
8 | url="https://github.com/forestobservatory/cfo-api",
9 | license="MIT",
10 | description="Python wrappers for accessing Forest Observatory data via the Salo API",
11 | long_description=long_description,
12 | long_description_content_type="text/markdown",
13 | keywords=[
14 | "ecology",
15 | "conservation",
16 | "remote sensing",
17 | "wildfire",
18 | "california",
19 | ],
20 | packages=find_packages(exclude="tests"),
21 | version=version,
22 | python_requires=">=3.0",
23 | platforms="any",
24 | install_requires=["requests", "retrying"],
25 | author="Salo Sciences",
26 | author_email="cba@salo.ai",
27 | include_package_data=True,
28 | package_data={"cfo": ["data/paths.json", "data/public.json"]},
29 | classifiers=[
30 | "Programming Language :: Python :: 3",
31 | "License :: OSI Approved :: MIT License",
32 | "Operating System :: OS Independent",
33 | ],
34 | )
35 |
--------------------------------------------------------------------------------