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

Feature/calculate columns #328

Open
wants to merge 2 commits into
base: develop
Choose a base branch
from
Open
Changes from all commits
Commits
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
88 changes: 76 additions & 12 deletions melodies_monet/util/tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from builtins import range

import numpy as np
import xarray as xr

__author__ = 'barry'

Expand Down Expand Up @@ -277,7 +278,6 @@ def get_epa_region_df(df):

def resample_stratify(da, levels, vertical, axis=1,interpolation='linear',extrapolation='nan'):
import stratify
import xarray as xr

result = stratify.interpolate(levels, vertical.chunk().data, da.chunk().data, axis=axis,
interpolation = interpolation,extrapolation = extrapolation)
Expand All @@ -294,7 +294,6 @@ def resample_stratify(da, levels, vertical, axis=1,interpolation='linear',extrap
return out

def vert_interp(ds_model,df_obs,var_name_list):
import xarray as xr
from pandas import merge_asof, Series

var_out_list = []
Expand All @@ -313,13 +312,7 @@ def vert_interp(ds_model,df_obs,var_name_list):
var_out_list.append(out)

df_model = xr.merge(var_out_list).to_dataframe().reset_index()
for time in df_model.time.unique():
if df_model[df_model.time == time].pressure_obs.unique() > df_model[df_model.time == time].pressure_model.max():
df_model.fillna({'pressure_model':df_model[df_model.time == time].pressure_obs},inplace=True)
elif df_model[df_model.time == time].pressure_obs.unique() < df_model[df_model.time == time].pressure_model.min():
df_model.fillna({'pressure_model':df_model[df_model.time == time].pressure_obs},inplace=True)
print('Warning: You are pairing obs data above the model top. This is not recommended.')
print(time)
df_model.fillna({'pressure_model':df_model.pressure_obs},inplace=True)
df_model.drop(labels=['x','y','z','pressure_obs','time_obs'], axis=1, inplace=True)
df_model.rename(columns={'pressure_model':'pressure_obs'}, inplace=True)

Expand All @@ -330,7 +323,6 @@ def vert_interp(ds_model,df_obs,var_name_list):
return final_df_model

def mobile_and_ground_pair(ds_model,df_obs, var_name_list):
import xarray as xr
from pandas import merge_asof, Series

var_out_list = []
Expand All @@ -353,7 +345,7 @@ def mobile_and_ground_pair(ds_model,df_obs, var_name_list):

final_df_model = merge_asof(df_obs, df_model,
by=['latitude', 'longitude'],
on='time', direction='nearest', suffixes=('', '_new'))
on='time', direction='nearest')

return final_df_model

Expand All @@ -376,7 +368,6 @@ def find_obs_time_bounds(files=[],time_var=None):
"""
import os
import monetio as mio
import xarray as xr

if isinstance(files,str):
files = [files]
Expand Down Expand Up @@ -508,3 +499,76 @@ def convert_std_to_amb_bc(ds,convert_vars=[],temp_var=None,pres_var=None):
for var in convert_vars:
ds[var] = ds[var]*convert_std_to_amb_bc


def calc_partialcolumn(modobj, var="NO2"):
"""Calculates the partial column of a species from its concentration.

Parameters
----------
modobj : xr.Dataset
Model data
var : str
variable to calculate the partial column from

Returns
-------
xr.DataArray
DataArray containing the partial column of the species.
"""
R = 8.314 # m3 * Pa / K / mol
NA = 6.022e23
ppbv2molmol = 1e-9
m2_to_cm2 = 1e4
fac_units = ppbv2molmol * NA / m2_to_cm2
partial_col = (
modobj[var]
* modobj["pres_pa_mid"]
* modobj["dz_m"]
* fac_units
/ (R * modobj["temperature_k"])
)
partial_col.attrs = {"units": "molecules/cm2", "description": f"{var} partial column"}
return partial_col


def calc_totalcolumn(modobj, var="NO2"):
"""Calculates the total column of a species from its concentration.

Parameters
----------
modobj : xr.Dataset
Model data
var : str
variable to calculate the total column from

Returns
-------
xr.DataArray
DataArray containing the total column of the species.
"""
data = calc_partialcolumn(modobj, var)
return data.sum(dim='z', keep_attrs=True)


def calc_localgeotime(modobj):
"""Calculates the local (geographic) time based on the longitude.

Parameters
----------
modobj : xr.Dataset
Model data

Returns
-------
xr.DataArray
DataArray containing the local time based on longitude.
"""
# Make sure that lon is in the range [-180, 180]
# This should be guaranteed by the reader, and it isn't needed,
# but it is very cheap to redo and should make us be safer.

hrs2ms = 3600000
timedelta = (modobj["longtidue"].values * hrs2ms / 15).astype('timedelta64[ms]')
localtime = modobj["time"] + timedelta
localtime.attrs['description'] = 'Geographic local time, based on longitude'
return localtime
Loading