Source code for pycif.plugins.models.iconart.io.outputs.process_output

import os
import glob
import copy
import xarray as xr
import numpy as np
import pandas as pd
import time as tm
import multiprocessing as mp
from logging import debug
from itertools import repeat
from ..utils import (
    OUTPUT_DIRNAME,
    OUTPUT_PATTERN,
)
from ......utils.hdf5 import _hdf5_lock

try:
    from sklearn.neighbors import BallTree
except ImportError:
    pass

from logging import debug, warning, info

# ---------------------------------------------------------
# -- CONSTANTS
# ---------------------------------------------------------

R_EARTH = 6371  # Radius of earth [km]
N_AVO = 6.022e23  # Avogadro number
M_DRYAIR = 28.97e-3  # Molecular weight of dry air [kg/mol]

# ---------------------------------------------------------
# -- SIDE FUNCTIONS
# ---------------------------------------------------------


[docs] def reduce_size(file, output_path, cells, levs, nlev, ncells, model_timestep): """ Reduce the size of the file by selecting relevant cells and levels only. Args: file (str): Path of the file output_path (str): Path of the output directory cells (list): List of indexes to cells levs (list): List of indexes to levels nlev (int): Number of levels ncells (int): Number of cells model_timestep (float): Timestep of the model """ # Open the dataset with _hdf5_lock: ds = xr.open_dataset(file) # Find name of relevant dimensions dim_height = [dim for (dim, ndim) in ds.dims.items() if ndim == nlev][0] dim_cell = [dim for (dim, ndim) in ds.dims.items() if ndim == ncells][0] # Build hlay [m] dim_height_ifc = [dim for dim in ds["z_ifc"].dims if "height" in dim][0] hlay = -ds["z_ifc"].diff(dim=dim_height_ifc) hlay = hlay.rename({dim_height_ifc: dim_height}) hlay = hlay.expand_dims({"time": ds["time"]}) hlay[dim_height] = ds[dim_height] ds["hlay"] = hlay # Build dpressure [Pa] dim_pres_ifc = [dim for dim in ds["pres_ifc"].dims if "height" in dim][0] dpressure = ds["pres_ifc"].diff(dim=dim_pres_ifc) dpressure = dpressure.rename({dim_pres_ifc: dim_height}) dpressure[dim_height] = ds[dim_height] ds["dpressure"] = dpressure # Build airm [molecules/cm3] ds["airm"] = ds["rho"] * (1 - ds["qv"]) * 1e-6 * N_AVO / M_DRYAIR # Build pressure [Pa] ds = ds.rename({"pres": "pressure"}) # Add time dimension to z_mc ds["z_mc"] = ds["z_mc"].expand_dims({"time": ds["time"]}) # Select relevant indexes dim_height = [dim for (dim, ndim) in ds.dims.items() if ndim == nlev][0] dim_cell = [dim for (dim, ndim) in ds.dims.items() if ndim == ncells][0] vars2fetch = [var for var in list(ds.data_vars) if ds.data_vars[var].dims == ("time", dim_height, "ncells")] ds = ds[vars2fetch].sel({dim_height: levs, dim_cell: cells}) ds["ncells"] = cells # Offset the time [trick to get first timestep AFTER restart] # ds["time"] = ds.time - pd.Timedelta(seconds=model_timestep) new_date = pd.to_datetime(ds["time"][0].values).strftime("__%Y%m%dT%H%M%SZ") filename_out = os.path.join(output_path, "reduced", os.path.basename(file).split("__")[0] + new_date + "_short.nc") # Save the dataset with _hdf5_lock: ds.to_netcdf(filename_out, format="NETCDF4_CLASSIC")
[docs] def concatenate_byday(output_path, files2concatenate): """ Concatenate the files by day to make the subsequent processing faster. """ with _hdf5_lock: ds_var = xr.open_mfdataset(files2concatenate, concat_dim="time", combine="nested") ds_var["time"] = pd.to_datetime(ds_var["time"]) filename_begin = os.path.basename(files2concatenate[0]) filename_out = os.path.join(output_path, "concatenated_byday", f"{filename_begin[:-3]}.nc") if os.path.isfile(filename_out): os.remove(filename_out) with _hdf5_lock: ds_var.to_netcdf(filename_out, format="NETCDF4_CLASSIC")
# TODO: remove occurences of "height"", not supposed to know the name # If all observations are processed
[docs] def apply_interpolation_by_chunk_full(segment_idx_obs, ds_icon, ds_interp, all_trcrs): """Apply full 3-D horizontal+vertical interpolation to a chunk of observations. Identical in semantics to :func:`apply_interpolation.apply_interpolation_by_chunk_full` but operates on a reduced ICON output with dimension names ``height`` and ``ncells``. Args: segment_idx_obs (tuple[int, int]): (start, end) observation slice. ds_icon (xr.Dataset): reduced ICON output on the icosahedral grid. ds_interp (xr.Dataset): pre-computed interpolation metadata. all_trcrs (list[str]): tracer variable names. Returns: xr.Dataset: interpolated concentrations for the observation chunk. """ debug(f"Segment {segment_idx_obs} : started...") idx_obs_start, idx_obs_end = segment_idx_obs # Get interpolation data for the right indexes ds_interp_red = ds_interp.isel(index=slice(idx_obs_start, idx_obs_end)) # Fetch interpolation data ilev_below = ds_interp_red["ilev_below"].astype(int) ilev_above = ds_interp_red["ilev_above"].astype(int) iadjcells = ds_interp_red["iadjcells"] vert_scaling_fact = ds_interp_red["vert_scale_fact"] inv_dist_adjcells = ds_interp_red["inv_dist_adjcells"] tsteps = ds_interp_red["tstep"] parameters = ds_interp_red["parameter"] # Convert interpolation data to DataArrays vals_lev_above = ilev_above.values + 1 vals_lev_above = xr.DataArray(vals_lev_above, dims=("obs", "adjcell")) vals_lev_below = ilev_below.values + 1 vals_lev_below = xr.DataArray(vals_lev_below, dims=("obs", "adjcell")) vals_cell = iadjcells.values vals_cell = xr.DataArray(vals_cell, dims=("obs", "adjcell")) vals_time = ds_icon["time"][tsteps].values vals_time = xr.DataArray(vals_time, dims=("obs")) vals_vert_scal = vert_scaling_fact.rename({"index": "obs"}) vals_inv_dist = inv_dist_adjcells.rename({"index": "obs"}) # Apply interpolation to model values ds_above_adj = ds_icon[all_trcrs].sel(time=vals_time, height=vals_lev_above, ncells=vals_cell) ds_below_adj = ds_icon[all_trcrs].sel(time=vals_time, height=vals_lev_below, ncells=vals_cell) ds_adj = ds_below_adj + vals_vert_scal * (ds_above_adj - ds_below_adj) ds_out = (ds_adj * vals_inv_dist).sum(dim="adjcell") / vals_inv_dist.sum(dim="adjcell") # Change the index new_index = ds_interp_red.index.values ds_out["obs"] = new_index # Add parameter information ds_out["parameter"] = xr.DataArray(data=parameters.values, dims="obs", coords={"obs": ds_out.obs}) debug(f"Segment {segment_idx_obs} : completed!") return ds_out.load()
# If observations are grouped by index
[docs] def apply_interpolation_by_chunk_reduced(segment_idx_obs, ds_icon, ds_interp, all_trcrs): """Apply reduced (level-fixed) horizontal interpolation to a chunk of observations. Identical in semantics to :func:`apply_interpolation.apply_interpolation_by_chunk_reduced` but operates on a pre-reduced ICON output dataset. Args: segment_idx_obs (tuple[int, int]): (start, end) observation slice. ds_icon (xr.Dataset): reduced ICON output on the icosahedral grid. ds_interp (xr.Dataset): pre-computed interpolation metadata. all_trcrs (list[str]): tracer variable names. Returns: xr.Dataset: interpolated concentrations for the observation chunk. """ idx_obs_start, idx_obs_end = segment_idx_obs ds_interp_red = ds_interp.isel(index=slice(idx_obs_start, idx_obs_end)) # Process data that do not need to be interpolated vertically mask_alt_nan = np.isnan(ds_interp_red["ilev_below"][:, 0].values) iadjcells = ds_interp_red["iadjcells"][mask_alt_nan] inv_dist_adjcells = ds_interp_red["inv_dist_adjcells"][mask_alt_nan] tsteps = ds_interp_red["tstep"][mask_alt_nan] parameters = ds_interp_red["parameter"][mask_alt_nan] vals_cell = iadjcells.values vals_cell = xr.DataArray(vals_cell, dims=("obs_red", "adjcell")) vals_time = ds_icon["time"][tsteps].values vals_time = xr.DataArray(vals_time, dims=("obs_red")) vals_inv_dist = inv_dist_adjcells.rename({"index": "obs_red"}) # Unroll model values using all levels min_lev = int(ds_icon["height"].min().values) max_lev = int(ds_icon["height"].max().values) nlev = max_lev + 1 - min_lev ds_adj = ds_icon[all_trcrs].sel( time=vals_time, height=slice(min_lev, max_lev + 1), ncells=vals_cell, ) ds_adj["obs_red"] = vals_inv_dist.obs_red # Perform horizontal interpolation ds_out = (ds_adj * vals_inv_dist).sum(dim="adjcell") / vals_inv_dist.sum(dim="adjcell") ds_out = ds_out.reindex(height=list(reversed(ds_out.height))) ds_out = ds_out.stack(obs=("obs_red", "height"), create_index=False) ds_out = ds_out.drop_vars("height") # Change the index new_index = ds_interp_red.index[mask_alt_nan].values new_index = np.repeat(new_index, (max_lev - min_lev + 1)) ds_out["obs"] = new_index # Solve duplicates due to time averaging u, c = np.unique(ds_interp_red.index, return_counts=True) index_dup = u[c > 1] if len(index_dup) != 0: mask_dup = np.isin(new_index, index_dup) da_out = ds_out.to_array().load() index_in = np.arange(len(new_index))[mask_dup] array_in = ds_out.isel(obs=index_in).to_array().values indices_in = np.vstack( ( np.hstack(np.split(np.arange(len(index_in)), len(index_in) // nlev)[::2]), np.hstack(np.split(np.arange(len(index_in)), len(index_in) // nlev)[1::2]), ) ).ravel("F") da_out[:, index_in] = copy.deepcopy(array_in[:, indices_in]) ds_out = da_out.to_dataset(dim="variable") # Add parameter information ds_out["parameter"] = xr.DataArray( data=np.repeat(parameters.values, (max_lev - min_lev + 1)), dims="obs", coords={"obs": new_index} ) # Process data that need to be interpolated vertically if np.sum(~mask_alt_nan): # Fetch interpolation data ilev_below = ds_interp_red["ilev_below"][~mask_alt_nan] ilev_above = ds_interp_red["ilev_above"][~mask_alt_nan] iadjcells = ds_interp_red["iadjcells"][~mask_alt_nan] vert_scaling_fact = ds_interp_red["vert_scale_fact"][~mask_alt_nan] inv_dist_adjcells = ds_interp_red["inv_dist_adjcells"][~mask_alt_nan] tsteps = ds_interp_red["tstep"][~mask_alt_nan] parameters = ds_interp_red["parameter"][~mask_alt_nan] # Convert interpolation data to DataArrays vals_ilev_above = ilev_above.values vals_ilev_above = xr.DataArray(vals_ilev_above, dims=("obs", "adjcell")) vals_ilev_below = ilev_below.values vals_ilev_below = xr.DataArray(vals_ilev_below, dims=("obs", "adjcell")) vals_icell = xr.DataArray(iadjcells.values, dims=("obs", "adjcell")) vals_itime = xr.DataArray(tsteps.values, dims=("obs")) vals_vert_scal = vert_scaling_fact.rename({"index": "obs"}) vals_inv_dist = inv_dist_adjcells.rename({"index": "obs"}) # Apply interpolation to model values ds_above_adj = ds_icon[all_trcrs].isel(time=vals_itime, height=vals_ilev_above, ncells=vals_icell) ds_below_adj = ds_icon[all_trcrs].isel(time=vals_itime, height=vals_ilev_below, ncells=vals_icell) ds_adj = ds_below_adj + vals_vert_scal * (ds_above_adj - ds_below_adj) ds_out_with_alt = (ds_adj * vals_inv_dist).sum(dim="adjcell") / vals_inv_dist.sum(dim="adjcell") ds_out_with_alt["obs"] = ds_interp_red.index[~mask_alt_nan].values # Add parameter information ds_out_with_alt["parameter"] = xr.DataArray(data=parameters.values, dims="obs", coords={"obs": ds_out.obs}) # Concatenate the two datasets and sort it with obs index ds_out = xr.concat([ds_out, ds_out_with_alt], dim="obs") ds_out = ds_out.sortby("obs") return ds_out.load()
# --------------------------------------------------------- # -- MAIN FUNCTION # ---------------------------------------------------------
[docs] def process_output(self, runsubdir, ddi): """Post-process ICON-ART output: reduce size, concatenate, and interpolate. 1. Reduces each output NetCDF to the observation-relevant cells and levels using :func:`reduce_size` to limit disk and memory usage. 2. Concatenates daily files using :func:`concatenate_byday`. 3. Applies horizontal + vertical interpolation to all observation locations using :func:`apply_interpolation_by_chunk_full` or :func:`apply_interpolation_by_chunk_reduced`. Results are stored in ``self.sim_data`` for later extraction by ``read_sim``. Args: self: ICON-ART model plugin instance. runsubdir (str): path to the period run directory. ddi (datetime): sub-simulation period start. """ NADJ = self.output_interp_neighbors output_path = os.path.join(runsubdir, OUTPUT_DIRNAME) # --------------------------------------------------------- # -- Initialize interpolation data # --------------------------------------------------------- # Get outputs files list_files = glob.glob(os.path.join(output_path, OUTPUT_PATTERN)) list_files = sorted(list_files) # Find index of maximum height (indices start at 0) with _hdf5_lock: f0 = xr.open_dataset(list_files[0]) da_alt = f0["z_mc"] # Check obs.csv exists if not os.path.isfile(f"{runsubdir}/obs.csv"): warning("No obs.csv file found") return # Extract station information data_obs = pd.read_csv(f"{runsubdir}/obs.csv", na_values=-999, index_col=0) data_obs["i"] = data_obs["i"].astype(int) data_obs["tstep"] = data_obs["tstep"].astype(int) # min_ilevel = int(data_obs['icon_ilevel'].min()) + 1 # height dim is 1..nlev+1 # max_ilevel = int(data_obs['icon_ilevel'].max()) + 1 # height dim is 1..nlev+1 nobs = len(data_obs) icells_obs = data_obs["i"].values lons_obs = data_obs["lon"].values lats_obs = data_obs["lat"].values tsteps_obs = data_obs["tstep"].values tracers_obs = data_obs["parameter"].values index_obs = data_obs.index.values # Create a Dataset to store all the information. # icell and ilev starts at 0 # BUT, coord cell starts at 0 and coord height starts at 1 # so icell ~= coord cell but coord height ~= ilev + 1 # initialization to -1 ds_interp = xr.Dataset( data_vars=dict( icell=(["index"], icells_obs), tstep=(["index"], tsteps_obs), parameter=(["index"], tracers_obs), iadjcells=(["index", "adjcell"], np.nan * np.ones((nobs, NADJ))), alt_adjcells=(["index", "adjcell"], np.nan * np.ones((nobs, NADJ))), ilev_below=(["index", "adjcell"], np.nan * np.ones((nobs, NADJ))), ilev_above=(["index", "adjcell"], np.nan * np.ones((nobs, NADJ))), vert_scale_fact=(["index", "adjcell"], np.nan * np.ones((nobs, NADJ))), inv_dist_adjcells=(["index", "adjcell"], np.nan * np.ones((nobs, NADJ))), ), coords=dict(index=index_obs, icon_ilevel=range(1, self.domain.nlev + 1)), ) ds_interp["icell"] = ds_interp["icell"].astype(int) # ------------------------------------------------------------ # Horizontal interpolation parameters # ------------------------------------------------------------ info("Calculating horizontal interpolation parameters...") # Get grid data with _hdf5_lock: ds_grid = xr.open_dataset(self.domain.dynamics_grid) # Create a BallTree for speeding up interpolation grid_centers_coords_rad = np.vstack([ds_grid["clat"].values, ds_grid["clon"].values]).T tree = BallTree(grid_centers_coords_rad, metric="haversine") # Format inputs for the tree query obs_coords_rad = np.deg2rad(np.vstack([lats_obs, lons_obs]).T) # Find the closest cells using the tree query = tree.query(obs_coords_rad, k=NADJ) distances_sorted = query[0] * R_EARTH iadjcells_sorted = query[1] # Store the data ds_interp["iadjcells"][:] = iadjcells_sorted ds_interp["iadjcells"] = ds_interp["iadjcells"].astype(int) ds_interp["inv_dist_adjcells"][:] = 1 / distances_sorted # ------------------------------------------------------------ # Vertical interpolation parameters # ------------------------------------------------------------ info("Calculating vertical interpolation parameters...") # Get relevant data from obs.csv alt_obs = data_obs["alt"].values ilevels_obs = data_obs["icon_ilevel"].values # Extract height coordinate height_dimname = da_alt.dims[0] # If full interpolation, using ilevel to fill missing altitude if self.full_interpolation: info("Using full interpolation...") mask_nan_alt = np.isnan(alt_obs) if np.sum(mask_nan_alt): vals_levels = ilevels_obs[mask_nan_alt] + 1 vals_levels = xr.DataArray(vals_levels.astype(int), dims="index") vals_cells = icells_obs[mask_nan_alt] vals_cells = xr.DataArray(vals_cells, dims="index") # TODO: get altitude of level using an inverse-weighted average of all adjacent cells alt_obs[mask_nan_alt] = da_alt.loc[vals_levels, vals_cells].values # Duplicate and store the altitude of observations for the adjacent cells mask_nan_alt = np.isnan(alt_obs) ds_interp["alt_adjcells"][:] = np.tile(alt_obs.reshape(-1, 1), NADJ) # If altitude data exists, find the adjacent levels and # calculate the interpolation factors # TODO: accelerate this part like apply_interpolation_by_chunk_full nobs_with_alt = np.sum(~mask_nan_alt) if nobs_with_alt: # Finding the heights levels of each observation for timestep 0 iadjcells_obs_flatten = ds_interp["iadjcells"][~mask_nan_alt].values.flatten() alt_adjcells = ds_interp["alt_adjcells"][~mask_nan_alt].values.flatten() alt_model_adjcells = da_alt.sel(ncells=iadjcells_obs_flatten) # Check if there is NaN values in output heights nan_in_height = np.any(np.isnan(alt_model_adjcells)) negative_in_height = np.any(alt_model_adjcells < 0) if nan_in_height: warning("WARNING: NaNs detected in z_mc at cells" " matching the observations!") if negative_in_height: warning("WARNING: Negative values detected in z_mc" " at cells matching the observations!") mask_below = alt_model_adjcells <= alt_adjcells ilev_adjcells_below = mask_below.argmax(dim=height_dimname).values ilev_adjcells_above = ilev_adjcells_below - 1 mask_nolevelbelow = np.sum(mask_below, axis=0) == 0 mask_nolevelabove = np.sum(mask_below, axis=0) == self.domain.nlev ilev_adjcells_below[mask_nolevelbelow] = ilev_adjcells_above[mask_nolevelbelow] = self.domain.nlev - 1 ilev_adjcells_below[mask_nolevelabove] = ilev_adjcells_above[mask_nolevelabove] = 0 ilev_adjcells_both = np.vstack([ilev_adjcells_above, ilev_adjcells_below]) vertical_distances = np.take_along_axis((alt_model_adjcells - alt_adjcells).values, ilev_adjcells_both, axis=0) vertical_distances = np.abs(vertical_distances) vert_scaling_fact = vertical_distances[1] / vertical_distances.sum(axis=0) vert_scaling_fact[mask_nolevelbelow] = 0 vert_scaling_fact[mask_nolevelabove] = 0 ds_interp["vert_scale_fact"][~mask_nan_alt] = vert_scaling_fact.reshape((nobs_with_alt, NADJ)) ds_interp["ilev_below"][~mask_nan_alt] = ilev_adjcells_below.reshape((nobs_with_alt, NADJ)) ds_interp["ilev_above"][~mask_nan_alt] = ilev_adjcells_above.reshape((nobs_with_alt, NADJ)) min_ilevel = int(ilev_adjcells_above.min()) max_ilevel = int(ilev_adjcells_below.max()) # Save the dataset with _hdf5_lock: ds_interp.to_netcdf(os.path.join(output_path, "interpolation/ds_data_interpolation.nc")) # --------------------------------------------------------- # -- Reduce the sizes of the files # --------------------------------------------------------- info("Reducing the sizes...") # Get indexes to save cells2save = np.unique(iadjcells_sorted) levs2save = range(min_ilevel + 1, max_ilevel + 2) # Reduce func_arguments = zip( list_files, repeat(output_path), repeat(cells2save), repeat(levs2save), repeat(self.domain.nlev), repeat(self.domain.nlon), repeat(self.timestep), ) with mp.Pool(min(len(list_files), 36)) as pool: pool.starmap(reduce_size, func_arguments) # --------------------------------------------------------- # -- Concatenate the reduced files by day # --------------------------------------------------------- info("Concatenating the reduced files by day...") file_path_reduced = os.path.join(output_path, "reduced", OUTPUT_PATTERN) list_files_reduced = sorted(glob.glob(str(file_path_reduced))) with _hdf5_lock: f0 = xr.open_dataset(list_files_reduced[0]) fn = xr.open_dataset(list_files_reduced[-1]) time = pd.date_range(f0.time.values[0], fn.time.values[-1], freq=self.output_resolution) df = pd.DataFrame(list_files_reduced, columns=["file"], index=time) list_files2concatenate = df["file"].groupby(pd.Grouper(freq="D")).apply(list).tolist() # Process func_arguments = zip(repeat(output_path), list_files2concatenate) with mp.Pool(min(len(list_files2concatenate), 36)) as pool: pool.starmap(concatenate_byday, func_arguments) # ------------------------------------------------------------ # Concatenate the files over the full period # ------------------------------------------------------------ info("Concatenating the files over the full period...") file_path_day = os.path.join(output_path, "concatenated_byday", OUTPUT_PATTERN) list_files_day = sorted(glob.glob(str(file_path_day))) with _hdf5_lock: ds_icon = xr.open_mfdataset(list_files_day, concat_dim="time", combine="nested") # Extract variable information dim_height = ds_icon["z_mc"].dims[1] all_trcrs = [tr for tr in list(ds_icon.data_vars) if ds_icon.data_vars[tr].dims == ("time", dim_height, "ncells")] # Apply the interpolation for every chunk info( f"Applying horizontal and vertical interpolation with {self.interpolation_apply_nchunks} chunks..." ) nobs = len(ds_interp.index) if self.interpolation_apply_nchunks > 1: nobs_per_chunk = int(np.ceil(nobs / self.interpolation_apply_nchunks)) bounds_idx_obs = list(range(0, nobs, nobs_per_chunk)) + [nobs] list_segments_idx_obs = [ [idx_start, idx_end] for (idx_start, idx_end) in zip(bounds_idx_obs[:-1], bounds_idx_obs[1:]) ] func_arguments = zip(list_segments_idx_obs, repeat(ds_icon), repeat(ds_interp), repeat(all_trcrs)) with mp.Pool(min(self.interpolation_apply_nchunks, 36)) as pool: if self.full_interpolation: list_ds_out = pool.starmap(apply_interpolation_by_chunk_full, func_arguments) else: list_ds_out = pool.starmap(apply_interpolation_by_chunk_reduced, func_arguments) # Concatenate the data info("Concatenating outputs from multiprocessing...") ds_out_concat = xr.concat(list_ds_out, dim="obs") else: if self.full_interpolation: ds_out_concat = apply_interpolation_by_chunk_full([0, nobs], ds_icon, ds_interp, all_trcrs) else: ds_out_concat = apply_interpolation_by_chunk_reduced([0, nobs], ds_icon, ds_interp, all_trcrs) # Fill dataout with interpolated data info("Filling output DataFrame with calculated data...") dataout = pd.DataFrame(index=ds_out_concat.obs, columns=all_trcrs + ["parameter"]) dataout.loc[:, "parameter"] = ds_out_concat["parameter"].values ds_out_concat = ds_out_concat.drop(["parameter"]) dataout.loc[:, all_trcrs] = ds_out_concat.to_array().values.T # Save the dataset info("Saving the DataFrame as a NetCDF file...") filepath_dataout = os.path.join(output_path, "dataout/dataout.nc") with _hdf5_lock: dataout.to_xarray().to_netcdf(filepath_dataout) info("Output processing and interpolation are complete!")
# # --------------------------------------------------------- # # -- MAIN # # --------------------------------------------------------- # if __name__ == "__main__": # start_time = tm.time() # # PARAMETERS # # runsubdir = sys.argv[1] # # LOGFILE = sys.argv[2] # # self.domain.dynamics_grid = sys.argv[3] # # OUTPUT_DIRNAME = sys.argv[4] # # OUTPUT_PATTERN = sys.argv[5] # # self.output_resolution = sys.argv[6] # # NADJ = int(sys.argv[7]) # # self.domain.nlev = int(sys.argv[8]) # # self.domain.nlon = int(sys.argv[9]) # # self.timestep = int(sys.argv[10]) # # self.full_interpolation = bool(int(sys.argv[11])) # runsubdir = "/scratch/snx3000/jthanwer/cif_workdirs/cif_workdir_ensrf_co2_intercomp/ensemble/20190101-00:00_to_20190121-00:00/batch_sampling/obsoperator/fwd_0000/2019-01-01_00-00" # LOGFILE = "/scratch/snx3000/jthanwer/cif_workdirs/cif_workdir_ensrf_co2_intercomp/ensemble/20190101-00:00_to_20190121-00:00/batch_sampling/obsoperator/fwd_0000/2019-01-01_00-00/outputs_log.std" # self.domain.dynamics_grid = "/scratch/snx3000/jthanwer/cif_workdirs/cif_workdir_ensrf_co2_intercomp/ensemble/20190101-00:00_to_20190121-00:00/batch_sampling/obsoperator/fwd_0000/2019-01-01_00-00/dyn_grid.nc" # OUTPUT_DIRNAME = 'outputs' # OUTPUT_PATTERN = 'OUTPUT_*.nc' # self.output_resolution = '1H' # NADJ = 5 # self.domain.nlev = 60 # self.domain.nlon = 21344 # self.timestep = 120 # self.full_interpolation = True # self.interpolation_apply_nchunks = 10 # # Process # process_output(runsubdir, self.domain.dynamics_grid, OUTPUT_RESOLUTION, # NADJ, self.domain.nlev, self.domain.nlon, self.timestep, # self.full_interpolation, self.interpolation_apply_nchunks)