# ---
# jupyter:
# jupytext:
# text_representation:
# extension: .py
# format_name: percent
# format_version: '1.3'
# jupytext_version: 1.19.1
# kernelspec:
# display_name: Python 3 (ipykernel)
# language: python
# name: python3
# ---
# %% [markdown] toc=true
#
Table of Contents
#
# %% [markdown]
# # Handling 3D Inputs with PICASO
#
# Many GCM groups have their files stored as `netCDF` files. Therefore, you may already be used to `xarray` format. If that is the case you will be able to directly input your xarray formatted data to `PICASO` to get out post-processed spectra. If not though, this tutorial will walk you through how to structure your data in xarray format.
#
# What you will learn:
#
# 1. How to convert traditional numpy arrays to `xarray` formatted data, which is common for 3D GCM output
# 2. How to regrid using `xarray` and `xesmf`'s `regridder`
# 3. How to use `PICASO` built in function (which use #2)
#
#
# %%
import pandas as pd
import numpy as np
from picaso import justdoit as jdi
# %% [markdown]
# Two new packages you will need, that are not required components of other models: xesmf and xarray. You can read more about the installing these packages here:
#
# [Install XESMF](https://xesmf.readthedocs.io/en/latest/installation.html)
# - will only be needed if you want to use their really handy regridding tools
#
# [Install xarray](http://xarray.pydata.org/en/stable/getting-started-guide/installing.html)
# - needed for all `PICASO` 3d operations
# %%
import xesmf as xe
import xarray as xr
# %% [markdown]
# We will begin with an example file from the MIT GCM group (courtesy of Tiffany Kataria).
# %%
gcm_out = jdi.HJ_pt_3d()
# %% [markdown]
# We are going to go through the motions of converting basic `numpy` arrays to `xarray` format. **If you already understand xarrays you may skip to** the [`picaso` section](#regrid-3d-gcm-with-picaso)
# %%
gcm_out.keys()
# %% [markdown]
# In this example, pressure, temperature, and kzz are all on a coordinate system that is :
#
# n_longitude (128) x n_latitude (64) x n_pressure (53)
#
# %%
gcm_out['temperature'].shape, len(gcm_out['longitude']), len(gcm_out['latitude'])
# %% [markdown]
# ## `xarray` tutorial: Convert `numpy` arrays to `xarray` DataSet
#
# The comments with `required` next to them indicate that they are required for `picaso` to create a spectrum
# %%
# create data
data = gcm_out['temperature']
# create coords
lon = gcm_out['longitude']
lat = gcm_out['latitude']
pres = gcm_out['pressure'][0,0,:]
# put data into a dataset
ds = xr.Dataset(
data_vars=dict(
temperature=(["lon", "lat","pressure"], data,{'units': 'Kelvin'})#, required
#kzz = (["x", "y","z"], gcm_out['kzz'])#could add other data components if wanted
),
coords=dict(
lon=(["lon"], lon,{'units': 'degrees'}),#required
lat=(["lat"], lat,{'units': 'degrees'}),#required
pressure=(["pressure"], pres,{'units': 'bar'})#required*
),
attrs=dict(description="coords with vectors"),
)
# %%
ds
# %% [markdown]
# ## `xarray` tutorial: Easy plotting
# %%
ds['temperature'].isel(pressure=50).plot(x='lon',y='lat')
# %% [markdown]
# ## `xesmf` tutorial: Step-by-step regrid 3D GCM
#
# The biggest complication with moving to 3D is making sure that the latitude/longitude grids of some users GCM and `picaso` line up properly. `picaso` computes a flux integration on specific `gauss` and `tchebychev` angles. **Meaning, your GCM input will need to be regridded to fit our angles.** Luckily, as you will see below, it is very easy to do this!
#
# First, we will show you how this is done using `xesmf`, then we will introduce the `PICASO` function that leverages these same techniques.
#
# ### Step 1) Get latitude/longitude grid used by `picaso`
#
# **G**auss angles are essentially equivalent to lon**G**itudes
#
# **T**chebychev angles are essentially equivalent to la**T**itudes.
# %%
n_gauss_angles =10
n_chebychev_angles=10
gangle, gweight, tangle, tweight = jdi.get_angles_3d(n_gauss_angles, n_chebychev_angles)
ubar0, ubar1, cos_theta, latitude, longitude = jdi.compute_disco(n_gauss_angles, n_chebychev_angles, gangle, tangle, phase_angle=0)
# %% [markdown]
# ### Step 2) Create the `xesmf` regridder
# %%
ds_out = xr.Dataset({'lon': (['lon'], longitude*180/np.pi),
'lat': (['lat'], latitude*180/np.pi),
}
)
regridder = xe.Regridder(ds, ds_out, 'bilinear')
ds_out = regridder(ds,keep_attrs=True)
# %% [markdown]
# All done!
# %%
ds_out['temperature'].isel(pressure=10).plot(x='lon', y ='lat')
# %% [markdown]
# ## Regrid 3D GCM with PICASO
#
# The above code is all the PICASO built in function does -- in addition to completing some checks to make sure that your model run is on the same grid as what you are wanting PICASO run.
# %%
ds = jdi.HJ_pt_3d(as_xarray=True)
# %% [markdown]
# ### DIY Option 1
#
# For completeness, first here is the function `picaso` uses internally. You might use this if you want to manipulate results before supplying `picaso` with your final input.
# %%
#regrid yourself
out_ds = jdi.regrid_xarray(ds, num_gangle=20,
num_tangle=20, phase_angle=0)
#then supply to picaso
case_3d = jdi.inputs()
case_3d.phase_angle(0, num_gangle=20, num_tangle=20)
#here, regrid is false because you have already done it yourself
case_3d.atmosphere_3d(out_ds,regrid=False,plot=True,verbose=True)
# %% [markdown]
# ### Easiest Option 2
# %% [markdown]
# Use the regular `PICASO` workflow to regrid your 3d input
# %%
case_3d = jdi.inputs()
case_3d.phase_angle(0, num_gangle=20, num_tangle=20)
#regrid is True as you will do it within the function
case_3d.atmosphere_3d(ds,regrid=True,plot=True,verbose=True)
# %% [markdown]
# We have solved regridding our temperature-pressure profile. However, PICASO has notified us of another step we must take before running a spectrum: *verbose=True;Only one data variable included. Make sure to add in chemical abundances before trying to run spectra.*
#
# In the next notebook you will see how to add chemistry and/or clouds to your 3D input.