Commit ba143996 authored by Antoine Berchet's avatar Antoine Berchet
Browse files

Adding Empa NetCDF footprints

parent 0596f010
...@@ -3,7 +3,7 @@ from logging import debug ...@@ -3,7 +3,7 @@ from logging import debug
import numpy as np import numpy as np
import pandas as pd import pandas as pd
from .read import read_flexpart_grid from ...utils.read import read_flexpart_grid
def flux_contribution(self, mode, subdir, dataobs, def flux_contribution(self, mode, subdir, dataobs,
......
...@@ -3,7 +3,7 @@ import numpy as np ...@@ -3,7 +3,7 @@ import numpy as np
import pandas as pd import pandas as pd
from logging import debug from logging import debug
from .read import read_flexpart_gridinit from ...utils.read import read_flexpart_gridinit
def inicond_contribution(self, mode, subdir, dataobs, def inicond_contribution(self, mode, subdir, dataobs,
......
...@@ -7,7 +7,7 @@ import xarray as xr ...@@ -7,7 +7,7 @@ import xarray as xr
from logging import info, debug from logging import info, debug
from ..utils.flexpart_header import read_header from ..utils.flexpart_header import read_header
from pycif.plugins.models.flexpart.io.inputs.read import read_flexpart_grid, read_flexpart_gridinit from ..utils.read import read_flexpart_grid, read_flexpart_gridinit
def native2inputs_adj( def native2inputs_adj(
......
...@@ -8,6 +8,7 @@ import numpy as np ...@@ -8,6 +8,7 @@ import numpy as np
from scipy.io import FortranFile from scipy.io import FortranFile
import datetime import datetime
from logging import info from logging import info
from netCDF4 import Dataset
def read_flexpart_grid(subdir, file_name, fp_header, **kwargs): def read_flexpart_grid(subdir, file_name, fp_header, **kwargs):
...@@ -27,12 +28,29 @@ def read_flexpart_grid(subdir, file_name, fp_header, **kwargs): ...@@ -27,12 +28,29 @@ def read_flexpart_grid(subdir, file_name, fp_header, **kwargs):
# Numeric scaling factor # Numeric scaling factor
numscale = np.float(kwargs.get("numscale", 1.E12)) numscale = np.float(kwargs.get("numscale", 1.E12))
file_dates = os.path.join(subdir, 'dates') file_dates = os.path.join(subdir, 'dates')
path_file = os.path.join(subdir, file_name) path_file = os.path.join(subdir, file_name)
scaleconc = 1.e12 scaleconc = 1.e12
if "nc" in path_file:
grid_fp, ngrid, gtime_dt = \
read_grid_nc(path_file, file_dates, fp_header)
else:
grid_fp, ngrid, gtime_dt = \
read_grid(path_file, file_dates, fp_header, scaleconc)
# Convert from ppt to ppmv or ppbv
# Convert s.m3/kg to s.m2/kg and apply numerical scaling
grid_fp = grid_fp / (fp_header.outheight[0] * numscale)
return grid_fp, gtime_dt, ngrid
def read_grid(path_file, file_dates, fp_header, scaleconc):
days = [] days = []
times = [] times = []
counts_i = [] counts_i = []
...@@ -49,69 +67,74 @@ def read_flexpart_grid(subdir, file_name, fp_header, **kwargs): ...@@ -49,69 +67,74 @@ def read_flexpart_grid(subdir, file_name, fp_header, **kwargs):
spi = f.read_ints('i4') spi = f.read_ints('i4')
r = f.read_ints('i4') r = f.read_ints('i4')
spr = f.read_reals('f4') spr = f.read_reals('f4')
days.append(yyyymmdd) days.append(yyyymmdd)
times.append(hhmmss) times.append(hhmmss)
counts_i.extend(i) counts_i.extend(i)
sparse_i.extend(spi) sparse_i.extend(spi)
counts_r.extend(r) counts_r.extend(r)
sparse_r.extend(spr) sparse_r.extend(spr)
except TypeError: except TypeError:
break break
gtime_dt = [datetime.datetime.strptime('{}{}'.format(d, h), '%Y%m%d%H%M%S') gtime_dt = [datetime.datetime.strptime('{}{}'.format(d, h), '%Y%m%d%H%M%S')
for d, h in zip(days, times)][::-1] for d, h in zip(days, times)][::-1]
ngrid = len(gtime_dt) ngrid = len(gtime_dt)
grid_fp = np.zeros((fp_header.numx, fp_header.numy, ngrid + 2)) grid_fp = np.zeros((fp_header.numx, fp_header.numy, ngrid + 2))
if len(sparse_r) > 0: if len(sparse_r) > 0:
sign = np.sign(sparse_r) sign = np.sign(sparse_r)
cum_counts = np.unique(np.cumsum(counts_r) % sign.size) cum_counts = np.unique(np.cumsum(counts_r) % sign.size)
signchange = ((np.roll(sign, 1) - sign) != 0) signchange = ((np.roll(sign, 1) - sign) != 0)
signchange[cum_counts] = True signchange[cum_counts] = True
inds_out = np.zeros((len(sparse_r)), dtype=np.int) inds_out = np.zeros((len(sparse_r)), dtype=np.int)
inds_out[signchange] = sparse_i inds_out[signchange] = sparse_i
mask = inds_out == 0 mask = inds_out == 0
idx = np.where(~mask, np.arange(mask.size), 0) idx = np.where(~mask, np.arange(mask.size), 0)
np.maximum.accumulate(idx, out=idx) np.maximum.accumulate(idx, out=idx)
inds_out = inds_out[idx] + np.arange(mask.size) \ inds_out = inds_out[idx] + np.arange(mask.size) \
- idx - fp_header.numx * fp_header.numy - idx - fp_header.numx * fp_header.numy
jy, jx = np.unravel_index(inds_out, (fp_header.numy, fp_header.numx)) jy, jx = np.unravel_index(inds_out, (fp_header.numy, fp_header.numx))
jt = np.zeros((len(sparse_r)), dtype=np.int) jt = np.zeros((len(sparse_r)), dtype=np.int)
jt[cum_counts] = np.arange(ngrid)[np.array(counts_r) > 0] jt[cum_counts] = np.arange(ngrid)[np.array(counts_r) > 0]
np.maximum.accumulate(jt, out=jt) np.maximum.accumulate(jt, out=jt)
jt = ngrid - jt - 1 jt = ngrid - jt - 1
grid_fp[jx, jy, jt] = np.abs(sparse_r) * scaleconc grid_fp[jx, jy, jt] = np.abs(sparse_r) * scaleconc
# grid_fp, ngrid, gtime = mod_flexpart.read_grid(
# path_file, file_dates, fp_header.numx, fp_header.numy,
# fp_header.maxngrid, fp_header.xshift, fp_header.ndgrid, fp_header.trajdays)
# Convert from ppt to ppmv or ppbv return grid_fp, ngrid, gtime_dt
# Convert s.m3/kg to s.m2/kg and apply numerical scaling
grid_fp = grid_fp / (fp_header.outheight[0] * numscale)
# # Convert grid times to datetime format def read_grid_nc(path_file, file_dates, fp_header):
# gtime_dt = [] with Dataset(path_file) as nc:
# for i in range(len(gtime)): # spec001 has dimension nageclass, numpoint, time, level, lat, lon
# # gtime_dt[i] = flexpart_header.Flexpartheader.j2d(gtime[i]) # Assume that there is 1 numpoint/station per file
# if gtime[i] == 0.: shape = nc['spec001'].shape
# break if shape[0] > 1 or shape[1] > 1:
# info('WARNING: There are more than 1 station in the flexpart file.')
# # gtime_dt.append(fp_header.j2d(gtime[i])) if shape[3] > 1:
# gtime_dt.append(j2d(gtime[i])) info('INFO: Select the bottom layer of the grid')
return grid_fp, gtime_dt, ngrid grid = nc['spec001'][0, 0, :, 0, :, :] # time, lat, lon
# swap axes to get it to lon, lat, time
grid_fp = np.swapaxes(grid, 0, -1)
times = np.sort(nc['time'][:])
enddate = datetime.strptime(nc.getncattr('iedate'), '%Y%m%d')
gtime = []
for t in times:
gtime.append(enddate + datetime.timedelta(seconds=int(t)))
grid_fp *= 1e12 # This is applied in mod_flexpart
return grid_fp, len(gtime), gtime
def read_flexpart_gridinit(subdir, filename, fp_header, def read_flexpart_gridinit(subdir, filename, fp_header,
scaleconc=1, **kwargs): scaleconc=1, **kwargs):
path_file = os.path.join(subdir, filename) path_file = os.path.join(subdir, filename)
with FortranFile(path_file, 'r') as f: with FortranFile(path_file, 'r') as f:
yyyymmdd = f.read_ints('i4')[0].astype(str) yyyymmdd = f.read_ints('i4')[0].astype(str)
...@@ -120,7 +143,7 @@ def read_flexpart_gridinit(subdir, filename, fp_header, ...@@ -120,7 +143,7 @@ def read_flexpart_gridinit(subdir, filename, fp_header,
sparse_i = f.read_ints('i4') sparse_i = f.read_ints('i4')
sp_count_r = f.read_ints('i4')[0] sp_count_r = f.read_ints('i4')[0]
sparse_r = f.read_reals('f4') sparse_r = f.read_reals('f4')
nx = fp_header.numx nx = fp_header.numx
ny = fp_header.numy ny = fp_header.numy
nz = (fp_header.outheight != 0.).sum() nz = (fp_header.outheight != 0.).sum()
...@@ -131,10 +154,10 @@ def read_flexpart_gridinit(subdir, filename, fp_header, ...@@ -131,10 +154,10 @@ def read_flexpart_gridinit(subdir, filename, fp_header,
cum_counts = np.unique(np.cumsum(sp_count_r) % sign.size) cum_counts = np.unique(np.cumsum(sp_count_r) % sign.size)
signchange = ((np.roll(sign, 1) - sign) != 0) signchange = ((np.roll(sign, 1) - sign) != 0)
signchange[cum_counts] = True signchange[cum_counts] = True
inds_out = np.zeros((len(sparse_r)), dtype=np.int) inds_out = np.zeros((len(sparse_r)), dtype=np.int)
inds_out[signchange] = sparse_i inds_out[signchange] = sparse_i
mask = inds_out == 0 mask = inds_out == 0
idx = np.where(~mask, np.arange(mask.size), 0) idx = np.where(~mask, np.arange(mask.size), 0)
np.maximum.accumulate(idx, out=idx) np.maximum.accumulate(idx, out=idx)
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment