Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

HiTRes Inversion Options #1

Merged
merged 82 commits into from
Mar 3, 2023
Merged
Show file tree
Hide file tree
Changes from 79 commits
Commits
Show all changes
82 commits
Select commit Hold shift + click to select a range
3a9c723
add options to allow HiTRes inversions and add species_footprints option
hanchawn Sep 27, 2021
95648ef
Merge branch 'develop' into apo_inversion
hanchawn Oct 7, 2021
686a3a1
add HiTRes option which keeps all data until after timeseries is made…
hanchawn Oct 8, 2021
08b12d5
add HiTRes option which imports fluxes using the flux_for_HiTRes func…
hanchawn Oct 8, 2021
43c1f02
update docstring for timeseries_HiTRes
hanchawn Oct 8, 2021
71788f9
update footprints function for finding new HiTRes footprints and upda…
hanchawn Oct 18, 2021
98e32a3
add option to flux_for_HiTRes for multiple sources
hanchawn Oct 21, 2021
43ce71d
fix bug with getting hitres fluxes for emds
hanchawn Oct 21, 2021
e70ff9f
add chunking option to boundary_conditions function
hanchawn Oct 21, 2021
295a2f1
add mol mass for apo
hanchawn Oct 21, 2021
64274f5
add try except to reindexing in timeseries_HiTRes
hanchawn Oct 21, 2021
1c6fd0b
check dates in filenames before importing bcs, fps, and fluxes to avo…
hanchawn Oct 25, 2021
e6af71d
change building of timeseries in name.timeseries_HiTRes to avoid Impl…
Nov 2, 2021
993ac61
update import statements
hanchawn Nov 9, 2021
a7b986b
allow use of add_bc without footprints_data_merge
hanchawn Nov 9, 2021
58f7d49
add calc_timeseries option to fp_sensitivity so that we can avoid usi…
hanchawn Nov 15, 2021
c9ab558
tidy up fp_sensitivity
hanchawn Nov 15, 2021
5a5df26
avoid running timeseries_HiTRes twice, in footprints_data_merge and b…
hanchawn Nov 24, 2021
9d10960
use f strings in print statements
hanchawn Nov 24, 2021
c43ebd9
add conversion for distance between lat and lon points in degrees to …
hanchawn Nov 26, 2021
63cc571
edit latlon conversion
hanchawn Nov 26, 2021
015cb26
fix combine_diff_resolution to be able to use it with single value da…
hanchawn Nov 26, 2021
3e5f8e2
add option to add a flux uncertainty array to flux.write
hanchawn Dec 1, 2021
1b1b397
reduce lines in flux.write
hanchawn Dec 2, 2021
e5acd03
reduce lines in flux.write
hanchawn Dec 2, 2021
5d70d01
add chunk option to flux_for_HiTRes
hanchawn Dec 16, 2021
6524770
fix order that ts and mf map are returned by HiTRes timeseries in fp_…
hanchawn Dec 17, 2021
7073dcf
change default chunks for fpdm to avoid chunking if not specified
hanchawn Dec 20, 2021
fb42a7d
add units for apo
hanchawn Dec 20, 2021
50199a0
change apo units to work with fpdm
hanchawn Dec 21, 2021
1008d09
fix string bug when checking dates in filenames to import fluxes
hanchawn Jan 5, 2022
05b42f9
fix typo in cut_to_edge func in timevarying_BC.py
hanchawn Jan 7, 2022
a245188
correct typo in timevarying_BC cut_to_edge, and add a catch if overwr…
hanchawn Jan 10, 2022
f91811f
fix catch for overwriting files in timevarying_BC
hanchawn Jan 11, 2022
f0da1e3
add optional adjustment to timevarying_BCs for cases where there is a…
hanchawn Jan 13, 2022
4638999
Merge branch 'develop' into apo_inversion
hanchawn Jan 13, 2022
37dd290
fix bug in lat values when converting degrees to m
hanchawn Jan 20, 2022
5afff15
filter bc files by date needed
hanchawn Jan 21, 2022
1dee7d9
add start and end date when loading bc_sensitivity
hanchawn Jan 26, 2022
0fd5a4c
add function to name to filter files by date
hanchawn Jan 26, 2022
573b15e
fix bc warning message
hanchawn Jan 26, 2022
c403912
print species_footprint if not None
hanchawn Jan 26, 2022
30bc22f
add if for filtering basis bc files
hanchawn Jan 26, 2022
f5a3ce6
allow for fpdm without fp var
hanchawn Feb 14, 2022
cfece28
take out bc sensitivity start and end dates
hanchawn Feb 14, 2022
5faa035
change file filtering
hanchawn Feb 23, 2022
29f0a7e
fix file filtering
hanchawn Feb 24, 2022
8fc4363
change the species entered for flux_for_HiTRes when creating emds arr…
hanchawn Mar 2, 2022
f1539f7
Merge branch 'develop' into apo_inversion
hanchawn Mar 23, 2022
be867ff
take HiTRes option out of post processing
hanchawn Apr 1, 2022
fe30f90
take out HiTres option for post-processing
hanchawn Apr 6, 2022
b94df6a
Merge branch 'develop' into apo_inversion
hanchawn Apr 6, 2022
68a3bd5
Search for generic fps if species fp cannot be found
hanchawn Apr 7, 2022
e0be084
take pixel-latlon conversion out
hanchawn Apr 7, 2022
6af933b
add overwrite option to flux.write
hanchawn Apr 7, 2022
03cf2bb
print warning if overwriting file
hanchawn Apr 7, 2022
e93d66b
take out HiTRes comments from hbmcmc processing
hanchawn Apr 7, 2022
c2b97a3
use f-strings in flux.write
hanchawn Apr 7, 2022
e9e4ddd
add hbmcmc HiTRes option to changelog
hanchawn Apr 7, 2022
99f9a8d
resolve merge conflict
hanchawn Apr 8, 2022
e13f5b1
merge develop
hanchawn Apr 12, 2022
728af63
check for fp in site_ds when adding units
hanchawn Apr 12, 2022
67589d6
convert high time res emissions_name
hanchawn Apr 13, 2022
4d9cbb3
flexible climatology date
hanchawn Apr 19, 2022
79499d4
add units option
hanchawn Apr 22, 2022
400e0c9
dont change start date for HiTRes
hanchawn Apr 25, 2022
4c4f87c
adjust flux_for_HiTRes date range
hanchawn Apr 25, 2022
17a6409
add HiTRes tests
hanchawn Apr 25, 2022
c99842a
import all data needed for HiTRes
hanchawn Apr 25, 2022
3b61e49
add H_back to footprints_data_merge
hanchawn Apr 25, 2022
57cbc6f
Merge branch 'develop' into apo_inversion
hanchawn May 4, 2022
6ab2103
avoid 2 asserts in 1 test
hanchawn May 9, 2022
0632dad
add hitres ts test
hanchawn May 23, 2022
eea408d
separate HiTRes ts setup
hanchawn May 23, 2022
c2d0bad
use diff to find timestep
hanchawn May 23, 2022
4977005
fix problem with getting Dec climatology
hanchawn Jul 13, 2022
a403282
use dask for flux_HiTRes in fpdm
hanchawn Oct 19, 2022
a0d4bb6
resolve merge conflicts
hanchawn Feb 28, 2023
24b0d56
remove unused module imports
hanchawn Feb 28, 2023
2043377
remove height_coord
hanchawn Mar 2, 2023
2b71cc0
rmeove ref to fp_directory as dict
hanchawn Mar 2, 2023
e45efe9
add to changelog
hanchawn Mar 2, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ All calls to species_info.json and site_info.json are now made through the openg
- hbmcmc code now has a function (and relevant additions to output) that allows the inversion to be rerun (i.e. reproduced)
using only the output as inputs and ACRG repository.
- Country mask code has now been updated to allow ocean territories (Economic Exclusion Zone, EEZ) to be included.
- hbmcmc code now has options to use HiTRes processes for the set up
- Add function for embedding regional fields into larger fields, in acrg.name.emissions_helper_func

### Changed
Expand Down
70 changes: 45 additions & 25 deletions acrg/BC/timevarying_BC.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,15 +32,23 @@
-------

'''
if 'os' not in dir(): import os
if 'np' not in dir(): import numpy as np
if 'xr' not in dir(): import xarray as xr
if 'paths' not in dir(): from acrg_config.paths import paths
import os
import json
import numpy as np
import xarray as xr
from scipy import interpolate
from collections import OrderedDict

from acrg.name.name import open_ds
from acrg.config.paths import Paths
from acrg.convert import concentration
from acrg.countrymask import domain_volume


class BoundaryConditions:
def __init__(self, vmr_var, gph_height_var, dataset=None, filename=None,
file_dir=None, time_coord='time', height_coord='height', species=None,
domain='EUROPE', start_date=None):
file_dir=None, time_coord='time', species=None,
domain='EUROPE', start_date=None, adjust=None):
'''
vmr_var : str
The VMR variable name in the nesw dataset
Expand Down Expand Up @@ -73,13 +81,12 @@ def __init__(self, vmr_var, gph_height_var, dataset=None, filename=None,
if filename is None:
print('Please provide either a dataset or filename containing vmr')
elif os.path.isfile(filename):
from acrg_name.name import open_ds
dataset = open_ds(filename)
else:
print(f'Cannot find file: {filename}')

self.data_path = paths.data
self.acrg_path = paths.acrg
self.data_path = Paths.data
self.acrg_path = Paths.acrg

self.vmr_var = vmr_var
self.height_var = gph_height_var
Expand All @@ -91,7 +98,12 @@ def __init__(self, vmr_var, gph_height_var, dataset=None, filename=None,
# rename latitude and longitude to short version
if 'latitude' in dataset: dataset.rename({'latitude' : 'lat'})
if 'longitude' in dataset: dataset.rename({'longitude' : 'lon'})
self.dataset = dataset

if adjust is not None:
print(f'Adjusting vmr by {adjust}')
dataset[vmr_var] = dataset[vmr_var] + adjust

self.dataset = dataset

def make_bc_file(self, fp_directory=None, fp_height_coord='height', reverse=None,
convert_units=True, datasource=None, out_path=None, glob_attrs={},
Expand Down Expand Up @@ -145,7 +157,7 @@ def make_bc_file(self, fp_directory=None, fp_height_coord='height', reverse=None
if verbose: print('\nSaving to netcdf\n----------------')
# save to a netcdf file with a standardised filename
self.to_netcdf(datasource=datasource, out_path=out_path, glob_attrs=glob_attrs,
copy_glob_attrs=copy_glob_attrs, verbose=verbose)
copy_glob_attrs=copy_glob_attrs, verbose=verbose, overwrite=False)


def get_unit_conversion(self, verbose=True):
Expand Down Expand Up @@ -190,8 +202,6 @@ def cut_to_edge(self, fp_directory=None, fp_height_coord='height', convert_units
for north, south, east, and west
Can be accessed using BoundaryConditions_obj.edges
'''
from acrg_countrymask import domain_volume

fp_directory = os.path.join(self.data_path, 'LPDM', 'fp_NAME') if fp_directory is None else fp_directory
self.fp_lat, self.fp_lon, self.fp_height = domain_volume(self.domain, fp_directory=fp_directory)

Expand All @@ -205,16 +215,16 @@ def cut_to_edge(self, fp_directory=None, fp_height_coord='height', convert_units
lat_n -= 1

lat_s = (np.abs(self.dataset.coords['lat'].values - min(self.fp_lat))).argmin()
if self.dataset.coords['lat'].values[lat_s] > min(self.fp_lat) and lat_s != (len(dataset.coords['lat'].values)-1):
if self.dataset.coords['lat'].values[lat_s] > min(self.fp_lat) and lat_s != (len(self.dataset.coords['lat'].values)-1):
lat_s += 1

lon_e = (np.abs(self.dataset.coords['lon'].values - max(self.fp_lon))).argmin()
if self.dataset.coords['lon'].values[lon_e] < max(self.fp_lon) and lon_e != (len(dataset.coords['lon'].values)-1):
lat_s += 1
if self.dataset.coords['lon'].values[lon_e] < max(self.fp_lon) and lon_e != (len(self.dataset.coords['lon'].values)-1):
lon_e += 1

lon_w = (np.abs(self.dataset.coords['lon'].values - min(self.fp_lon))).argmin()
if self.dataset.coords['lon'].values[lon_w] > min(self.fp_lon) and lon_w != 0:
lat_w -= 1
lon_w -= 1

# Cut to these
north = self.dataset.sel(lat = self.dataset.coords['lat'][lat_n],
Expand Down Expand Up @@ -288,8 +298,6 @@ def interp_height_single(self, direction, height_coord='height', reverse=None, n
with a 3D VMR array interpolated to the NAME heights
Can be accessed using BoundaryConditions_obj.edges
'''
if 'interpolate' not in dir(): from scipy import interpolate

# get the axis along which to interpolate
# either 'longitude' (or 'lon', N or S) or 'latitude' (or 'lat', E or W)
latorlon = 'lon' if 'lon' in self.edges[direction] else 'lat'
Expand Down Expand Up @@ -358,8 +366,6 @@ def interp_latlon_single(self, direction=None, height_coord='height', reverse=No
with a 3D VMR array interpolated to the NAME latitudes and longitudes
Can be accessed using BoundaryConditions_obj.edges
'''
if 'interpolate' not in dir(): from scipy import interpolate

# get the axis along which to interpolate
# either 'longitude' (or 'lon', N or S) or 'latitude' (or 'lat', E or W)
latorlon = 'lon' if 'lon' in self.edges[direction] else \
Expand Down Expand Up @@ -418,7 +424,7 @@ def bc_filename(self, from_climatology=False, verbose=True):
if verbose: print(f'Output filename : {self.out_filename}')

def to_netcdf(self, datasource=None, out_path=None, glob_attrs={}, from_climatology=False,
copy_glob_attrs=False, verbose=True):
copy_glob_attrs=False, verbose=True, overwrite=False):
'''
Args
datasource (str, optional)
Expand Down Expand Up @@ -449,7 +455,7 @@ def to_netcdf(self, datasource=None, out_path=None, glob_attrs={}, from_climatol

Includes DataArrays for the n, s, e, and w boundaries
'''
edges = {dd : self.edges[dd].rename({self.vmr_var: f'vmr_{dd}'})
edges = {dd : self.edges[dd].rename({self.vmr_var: f'vmr_{dd[0]}'})
for dd in ['north', 'south', 'east', 'west']}

# merge the interpolated n, s, e, & w Datasets
Expand Down Expand Up @@ -479,8 +485,22 @@ def to_netcdf(self, datasource=None, out_path=None, glob_attrs={}, from_climatol
os.path.join(self.data_path, 'LPDM', 'bc', self.domain)

self.bc_filename(from_climatology=from_climatology, verbose=verbose)
if verbose: print(f'Saving boundary conditions to : {os.path.join(out_path, self.out_filename)}')
BC_edges.to_netcdf(path = os.path.join(out_path, self.out_filename), mode = 'w')
if overwrite and verbose:
save = True
if os.path.isfile(os.path.join(out_path, self.out_filename)):
print(f'Boundary condition file {os.path.join(out_path, self.out_filename)} already exists and is being overwritten.')
elif os.path.isfile(os.path.join(out_path, self.out_filename)) and not overwrite:
print(f'Boundary condition file {os.path.join(out_path, self.out_filename)} already exists.')
answer = input("You are about to overwrite an existing file, do you want to continue? Y/N ")
if answer.upper() == 'N':
save = False
elif answer.upper() == 'Y':
save = True
else:
save = True
if save == True:
if verbose: print(f'Saving boundary conditions to : {os.path.join(out_path, self.out_filename)}')
BC_edges.to_netcdf(path = os.path.join(out_path, self.out_filename), mode = 'w')



5 changes: 3 additions & 2 deletions acrg/convert.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@

acrg_path = Paths.acrg

import numpy as np

def molar_mass(species):
'''
This function extracts the molar mass of a species from the acrg_species_info.json file.
Expand Down Expand Up @@ -69,5 +71,4 @@ def convert_lons_0360(lons):

div = lons // 360

return lons - div*360

return lons - div*360
34 changes: 27 additions & 7 deletions acrg/hbmcmc/hbmcmc.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@
def fixedbasisMCMC(species, sites, domain, meas_period, start_date,
end_date, outputpath, outputname,
met_model = None,
species_footprint = None,
HiTRes = False,
xprior={"pdf":"lognormal", "mu":1, "sd":1},
bcprior={"pdf":"lognormal", "mu":0.004, "sd":0.02},
sigprior={"pdf":"uniform", "lower":0.5, "upper":3},
Expand Down Expand Up @@ -71,6 +73,11 @@ def fixedbasisMCMC(species, sites, domain, meas_period, start_date,
End time of inversion "YYYY-mm-dd"
outputname (str):
Unique identifier for output/run name.
species_footprint (str, optional):
species of the footprint to be imported, if different to the species
of interest (e.g. import co2 footprints for HiTRes studies)
HiTRes (bool)
True if using HiTRes footprints
outputpath (str):
Path to where output should be saved.
xprior (dict):
Expand Down Expand Up @@ -174,15 +181,23 @@ def fixedbasisMCMC(species, sites, domain, meas_period, start_date,
TO DO:
Add a wishlist...
"""
keep_missing = True if HiTRes else False
if verbose and species_footprint is not None:
print(f'species_footprint: {species_footprint}')

data = getobs.get_obs(sites, species, start_date = start_date, end_date = end_date,
average = meas_period, data_directory=obs_directory,
keep_missing=False,inlet=inlet, instrument=instrument, max_level=max_level)
fp_all = name.footprints_data_merge(data, domain=domain, met_model = met_model, calc_bc=True,
height=fpheight,
keep_missing=keep_missing,inlet=inlet, instrument=instrument,
max_level=max_level)
fp_all = name.footprints_data_merge(data, domain=domain, met_model = met_model, calc_bc=True,
HiTRes = HiTRes,
height = fpheight,
calc_timeseries = False,
fp_directory = fp_directory,
bc_directory = bc_directory,
flux_directory = flux_directory,
emissions_name=emissions_name)
emissions_name = emissions_name,
species_footprint = species_footprint)

for site in sites:
for j in range(len(data[site])):
Expand Down Expand Up @@ -221,10 +236,15 @@ def fixedbasisMCMC(species, sites, domain, meas_period, start_date,
basis_directory = tempdir
else:
basis_directory = basis_directory

fp_data = name.fp_sensitivity(fp_all, domain=domain, basis_case=fp_basis_case,basis_directory=basis_directory)
fp_data = name.bc_sensitivity(fp_data, domain=domain,basis_case=bc_basis_case)

fp_data = name.fp_sensitivity(fp_all, domain=domain, basis_case=fp_basis_case, basis_directory=basis_directory,
calc_timeseries = True)
fp_data = name.bc_sensitivity(fp_data, domain=domain, basis_case=bc_basis_case)

if HiTRes:
for site in sites:
fp_data[site] = fp_data[site].dropna(dim='time')

#apply named filters to the data
fp_data = name.filtering(fp_data, filters)

Expand Down
10 changes: 2 additions & 8 deletions acrg/hbmcmc/inversion_pymc3.py
Original file line number Diff line number Diff line change
Expand Up @@ -331,10 +331,6 @@ def inferpymc3_postprocessouts(xouts,bcouts, sigouts, convergence,
with {source_name: emissions_file_identifier} (e.g. {'anth':'co2-ff-mth'}). This way
multiple sources can be read in simultaneously if they are added as separate entries to
the emissions_name dictionary.
If using HiTRes footprints, both the high and low frequency emissions files must be specified
in a second dictionary like so: {'anth': {'high_freq':'co2-ff-2hr', 'low_freq':'co2-ff-mth'}}.
It is not a problem to have a mixture of sources, with some that use HiTRes footprints and some
that don't.
basis_directory (str, optional):
Directory containing basis function file
country_file (str, optional):
Expand Down Expand Up @@ -407,10 +403,8 @@ def inferpymc3_postprocessouts(xouts,bcouts, sigouts, convergence,
# it varies over the inversion period
emissions_flux = np.expand_dims(rerun_file.fluxapriori.values,2)
else:
if emissions_name == None:
emds = name.flux(domain, species, start = start_date, end = end_date, flux_directory=flux_directory)
else:
emds = name.flux(domain, list(emissions_name.values())[0], start = start_date, end = end_date, flux_directory=flux_directory)
spec = species if emissions_name == None else list(emissions_name.values())[0]
emds = name.flux(domain=domain, species=spec, start=start_date, end=end_date, flux_directory=flux_directory)
emissions_flux = emds.flux.values
flux = scalemap*emissions_flux[:,:,0]

Expand Down
Loading