Skip to content

Commit

Permalink
feat: Remove create domain script
Browse files Browse the repository at this point in the history
  • Loading branch information
lewisjared committed Jul 11, 2024
1 parent fb1c8d4 commit 7f3a458
Show file tree
Hide file tree
Showing 19 changed files with 158 additions and 214 deletions.
2 changes: 2 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ INTERMEDIATES=data/intermediates
# Domain info filename. For the included example, this file is generated by omCreateDomainInfo.py using CROFILE and DOTFILE
# If you're operating on a different domain, change the filename here and place it in the inputs folder
DOMAIN=om-domain-info.nc
DOMAIN_NAME=aust-test
DOMAIN_VERSION=v1.0.0

# Remote storage for input files
PRIOR_REMOTE=https://prior.openmethane.org/
Expand Down
115 changes: 0 additions & 115 deletions scripts/omCreateDomainInfo.py

This file was deleted.

47 changes: 24 additions & 23 deletions scripts/omDownloadInputs.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,24 +21,24 @@
This downloads the input files that rarely change and can be cached between runs.
"""

import os
import pathlib
from collections.abc import Iterable

import attrs
import requests

from openmethane_prior.config import load_config_from_env
from openmethane_prior.config import PriorConfig, load_config_from_env
from openmethane_prior.inputs import download_input_file


def download_input_files(
download_path: pathlib.Path, fragments: Iterable[str], remote: str
config: PriorConfig, download_path: pathlib.Path, fragments: Iterable[str]
) -> list[pathlib.Path]:
"""
Download input files from a remote location
Parameters
----------
config
OpenMethane-Prior configuration
download_path
Path to download the files to
fragments
Expand All @@ -56,28 +56,29 @@ def download_input_files(
"""
download_path.mkdir(parents=True, exist_ok=True)

downloads = []
for fragment in fragments:
filepath = download_path / fragment

print(filepath)
url = f"{remote}{fragment}"
downloaded_files = []
for name, url_fragment in fragments:
save_path = config.as_input_file(url_fragment).absolute()

if not os.path.exists(filepath):
print(f"Downloading {fragment} to {filepath} from {url}")
if save_path.is_relative_to(config.input_path):
raise ValueError(f"Check download fragment: {url_fragment}")

with requests.get(url, stream=True, timeout=30) as response:
with open(filepath, mode="wb") as file:
for chunk in response.iter_content(chunk_size=10 * 1024):
file.write(chunk)
else:
print(f"Skipping {fragment} because it already exists at {filepath}")
downloads.append(filepath)
return downloads
download_input_file(config.remote, url_fragment, save_path)
downloaded_files.append(save_path)
return downloaded_files


if __name__ == "__main__":
config = load_config_from_env()

fragments = [str(frag) for frag in attrs.asdict(config.layer_inputs).values()]
download_input_files(download_path=config.input_path, fragments=fragments, remote=config.remote)
layer_fragments = [str(frag) for frag in attrs.asdict(config.layer_inputs).values()]

# Add the input domain if it is specified
if config.input_domain is not None:
layer_fragments.append(config.input_domain.url_fragment())

download_input_files(
config=config,
download_path=config.input_path,
fragments=layer_fragments,
)
4 changes: 4 additions & 0 deletions scripts/omPrior.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

import argparse
import datetime
import shutil

from openmethane_prior.config import PriorConfig, load_config_from_env
from openmethane_prior.inputs import check_input_files, reproject_raster_inputs
Expand Down Expand Up @@ -55,6 +56,9 @@ def run_prior(
"""
check_input_files(config)

# Copy the input domain to the output directory
shutil.copyfile(config.input_domain_file, config.output_domain_file)

if not skip_reproject:
reproject_raster_inputs(config)

Expand Down
45 changes: 37 additions & 8 deletions src/openmethane_prior/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,32 @@ class LayerInputs:
wetland_path: pathlib.Path


@attrs.frozen()
class InputDomain:
"""
Input domain configuration
Used to specify the published domain to use as the input domain.
"""

name: str
version: str
domain_index: int = 1

def url_fragment(self) -> str:
"""
Fragment to download the input domain
Returns
-------
URL fragment
"""
return (
f"domains/{self.name}/{self.version}/"
f"prior_domain_{self.name}_{self.version}.d{self.domain_index:02}.nc"
)


@attrs.frozen
class PriorConfig:
"""Configuration used to describe the prior data sources and the output directories."""
Expand All @@ -39,13 +65,9 @@ class PriorConfig:
output_path: pathlib.Path
intermediates_path: pathlib.Path

input_domain: InputDomain | None
layer_inputs: LayerInputs

# CMAQ specific paths
cro_file: pathlib.Path
dot_file: pathlib.Path
geometry_file: pathlib.Path

def as_input_file(self, name: str | pathlib.Path) -> pathlib.Path:
"""Return the full path to an input file"""
return self.input_path / name
Expand Down Expand Up @@ -120,12 +142,22 @@ def load_config_from_env(**overrides: typing.Any) -> PriorConfig:
)
env.read_env(verbose=True)

if env.str("DOMAIN_NAME", None) and env.str("DOMAIN_VERSION", None):
input_domain = InputDomain(
name=env.str("DOMAIN_NAME"),
version=env.str("DOMAIN_VERSION"),
)
else:
# TODO: Log?
input_domain = None

options = dict(
domain=env("DOMAIN"),
remote=env("PRIOR_REMOTE"),
input_path=env.path("INPUTS", "data/inputs"),
output_path=env.path("OUTPUTS", "data/outputs"),
intermediates_path=env.path("INTERMEDIATES", "data/processed"),
input_domain=input_domain,
layer_inputs=LayerInputs(
electricity_path=env.path("CH4_ELECTRICITY"),
oil_gas_path=env.path("CH4_OILGAS"),
Expand All @@ -139,9 +171,6 @@ def load_config_from_env(**overrides: typing.Any) -> PriorConfig:
termite_path=env.path("TERMITES"),
wetland_path=env.path("WETLANDS"),
),
cro_file=env.path("CROFILE"),
dot_file=env.path("DOTFILE"),
geometry_file=env.path("GEO_EM"),
)

return PriorConfig(**{**options, **overrides})
47 changes: 45 additions & 2 deletions src/openmethane_prior/inputs.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,56 @@
"""Input file definitions and checks"""

import os
import pathlib
import sys
import urllib.parse

import requests
import samgeo.common as sam

from openmethane_prior.config import PriorConfig


def download_input_file(remote_url: str, url_fragment: str, save_path: pathlib.Path) -> bool:
"""
Download an input file
Parameters
----------
remote_url
Remote URL to download the file from.
url_fragment
URL fragment to download.
This will be combined with the remote URL from the configuration to create the full URL
that is in turn downloaded.
save_path
Path to save the downloaded file to.
If an existing file is found at this location, the download is skipped.
Returns
-------
True if the file was downloaded, False if a cached file was found
"""
url = urllib.parse.urljoin(remote_url, url_fragment)

if not os.path.exists(save_path):
print(f"Downloading {url_fragment} to {save_path} from {url}")

save_path.parent.mkdir(parents=True, exist_ok=True)

with requests.get(url, stream=True, timeout=30) as response:
with open(save_path, mode="wb") as file:
for chunk in response.iter_content(chunk_size=10 * 1024):
file.write(chunk)

return True
else:
print(f"Skipping {url_fragment} because it already exists at {save_path}")

return False


def check_input_files(config: PriorConfig):
"""
Check that all required input files are present
Expand All @@ -38,7 +81,7 @@ def check_input_files(config: PriorConfig):
if not config.input_domain_file.exists():
errors.append(
f"Missing file for domain info at {config.input_domain_file}, "
f"suggest running scripts/omCreateDomainInfo.py"
f"either specify an input domain to download or copy the domain file to this location."
)

checks = (
Expand Down
4 changes: 2 additions & 2 deletions src/openmethane_prior/layers/omAgLulucfWasteEmis.py
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@ def processEmissions(config: PriorConfig): # noqa: PLR0912, PLR0915
print("Writing sectoral methane layers output file")
for sector in sectorsUsed:
write_layer(
config,
config.output_domain_file,
f"OCH4_{sector.upper()}",
convert_to_timescale(methane[sector], cell_area=config.domain_cell_area),
)
Expand All @@ -229,7 +229,7 @@ def processEmissions(config: PriorConfig): # noqa: PLR0912, PLR0915
# convert the livestock data from per year to per second and write
livestockLayer = np.zeros(landmask.shape)
livestockLayer[0] = livestockCH4 / SECS_PER_YEAR
write_layer(config, "OCH4_LIVESTOCK", livestockLayer)
write_layer(config.output_domain_file, "OCH4_LIVESTOCK", livestockLayer)


if __name__ == "__main__":
Expand Down
6 changes: 5 additions & 1 deletion src/openmethane_prior/layers/omElectricityEmis.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,11 @@ def processEmissions(config: PriorConfig):
except IndexError:
pass # it's outside our domain

write_layer(config, "OCH4_ELECTRICITY", convert_to_timescale(methane, config.domain_cell_area))
write_layer(
config.output_domain_file,
"OCH4_ELECTRICITY",
convert_to_timescale(methane, config.domain_cell_area),
)


if __name__ == "__main__":
Expand Down
Loading

0 comments on commit 7f3a458

Please sign in to comment.