Source code for pycif.plugins.models.iconart.io.inputs.tv_scalef_oem

from logging import warning

import xarray as xr
import pandas as pd
import numpy as np
import os

from ......utils.hdf5 import _hdf5_lock


[docs] def create_oem_tv_scaling_factors(self, ddi, ddf, data, oem_dir, tfactors_oem_group): """Write the OEM temporal scaling-factor file for one sub-period. When ``self.use_hourofyear=True``, extracts the hourly temporal profiles for the period ``[ddi, ddf]`` from the full-year profile file and writes a reduced ``hour_of_year.nc`` to *oem_dir* that ICON-ART reads at runtime. Args: self: ICON-ART model plugin instance. ddi (datetime): period start date. ddf (datetime): period end date. data (xr.Dataset): CIF flux data for the period. oem_dir (str): OEM output directory. tfactors_oem_group: OEM temporal-factor group object. """ # Create and update the OEM hour-of-year scaling factors if self.use_hourofyear: t_profiles_file = os.path.join(oem_dir, f'hour_of_year.nc') hourly_time = pd.date_range( data.time[0].values, data.time[-1].values + pd.Timedelta(self.input_resolution), freq="1h") with _hdf5_lock: ds_tf = xr.open_dataset(t_profiles_file) \ if os.path.exists(t_profiles_file) else xr.Dataset() ds_tf[tfactors_oem_group] = xr.DataArray( np.ones((hourly_time.shape[0], data.shape[1])), coords=[np.arange(hourly_time.shape[0]), np.arange(data.shape[1])], dims=['hourofyear', 'country'] ) def relative_hour_of_year(current_date): return int((current_date - ddi).total_seconds() // 3600) hourofyear_idxs = [relative_hour_of_year( dd) for dd in hourly_time] # TODO: check its fine data_hourly = data.interp(time=hourly_time, kwargs={ "fill_value": "extrapolate"}) tf = data_hourly / data.mean(dim='time') tf = tf.fillna(1) # TODO: Is there really any nan left ? ds_tf[tfactors_oem_group][hourofyear_idxs, :] = tf.data if os.path.exists(t_profiles_file): os.remove(t_profiles_file) with _hdf5_lock: ds_tf.to_netcdf(t_profiles_file) else: warning("Careful, deriving hourofday, dayofweek and " "monthofyear temporal files is only relevant " "if the fluxes follow such a temporal periodicity.\n" "Prefer the 'use_hourofyear' option if you think it " "is not the case.") for time_type, time_len, file_name, time_variable in zip( ['hourofday', 'dayofweek', 'monthofyear'], [24, 7, 12], ['hour_of_day', 'day_of_week', 'month_of_year'], ['hour', 'dayofweek', 'month'] ): t_profiles_file = os.path.join(oem_dir, f'{file_name}.nc') with _hdf5_lock: ds_tf = xr.open_dataset(t_profiles_file) \ if os.path.exists(t_profiles_file) else xr.Dataset() if tfactors_oem_group in ds_tf: continue ds_tf[tfactors_oem_group] = xr.DataArray( np.ones((time_len, data.shape[1])), coords=[np.arange(time_len), np.arange(data.shape[1])], dims=[time_type, 'country'] ) tf = data.groupby(f'time.{time_variable}').mean() if len(tf[time_variable]) == time_len: tf = tf / tf.mean(dim=time_variable) tf = tf.fillna(1) ds_tf[tfactors_oem_group][:] = tf.data if os.path.exists(t_profiles_file): os.remove(t_profiles_file) with _hdf5_lock: ds_tf.to_netcdf(t_profiles_file) # Create the vertical scaling factors files v_profiles_file = os.path.join(oem_dir, 'vertical_profile.nc') ds_v = xr.Dataset( data_vars={ 'layer_bot': ('level', [0., 20., 92., 184., 324., 522., 781.]), 'layer_mid': ('level', [10., 56, 138, 254, 423, 651.5, 943.5]), 'layer_top': ('level', [20., 92., 184., 324., 522., 781., 1106.]), 'ground_emissions': ('level', [1., 0., 0., 0., 0., 0., 0.]), # Ground emissions are all emitted on the smallest level }, ) if os.path.exists(v_profiles_file): os.remove(v_profiles_file) with _hdf5_lock: ds_v.to_netcdf(v_profiles_file)