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

Index calculation framework & CI/CD framework #15

Merged
merged 20 commits into from
Apr 17, 2024
Merged
Show file tree
Hide file tree
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
Original file line number Diff line number Diff line change
@@ -1,27 +1,29 @@
name: PR pytest checking
name: PR pytest unittest

on:
on:
pull_request:
branches:
- develop
- main
paths:
- './'
branches:
- develop
- main

jobs:
checking_json:
runs-on: ubuntu-20.04
unittest:
runs-on: ubuntu-latest

steps:
- name: Checkout repo
uses: actions/checkout@v4

- name: Setup Micromamba ${{ matrix.python-version }}
- name: Setup Micromamba
uses: mamba-org/setup-micromamba@v1
with:
environment-file: regional_mom6.yml
init-shell: bash

- name: Setup package config file
shell: bash -l {0}
run: cp config.json.template config.json

- name: pytesting
shell: bash -l {0}
run: pytest
29 changes: 29 additions & 0 deletions .github/workflows/gha_pytest_push.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
name: push pytest unittest

on:
push:
branches:
- develop
- main

jobs:
unittest:
runs-on: ubuntu-latest

steps:
- name: Checkout repo
uses: actions/checkout@v4

- name: Setup Micromamba
uses: mamba-org/setup-micromamba@v1
with:
environment-file: regional_mom6.yml
init-shell: bash

- name: Setup package config file
shell: bash -l {0}
run: cp config.json.template config.json

- name: pytesting
shell: bash -l {0}
run: pytest
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
[![unittest](https://github.com/NOAA-PSL/regional_mom6/actions/workflows/gha_pytest_push.yml/badge.svg)](https://github.com/NOAA-PSL/regional_mom6/actions/workflows/gha_pytest_push.yml)

NOAA Climate, Ecosystems, and Fisheries Initiative (CEFI) - Data Portal Team
========

Expand Down
84 changes: 47 additions & 37 deletions mom6/mom6_module/mom6_indexes.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,11 @@
Indexes include:
1. Gulf stream index
"""
from typing import (
Literal,
List,
Union
)
import os

import warnings
import numpy as np
import xarray as xr
import xesmf as xe
from mom6 import DATA_PATH
from mom6.mom6_module import mom6_process as mp


warnings.simplefilter("ignore")
xr.set_options(keep_attrs=True)
Expand All @@ -28,30 +20,30 @@ class GulfStreamIndex:
"""
The class is use to recreate the Gulf Stream Index calculation in detail.
Original sources are [Ross et al., 2023](https://gmd.copernicus.org/articles/16/6943/2023/).
and [GFDL CEFI github repository](https://github.com/NOAA-GFDL/CEFI-regional-MOM6/blob/main/diagnostics/physics/ssh_eval.py).
and [GFDL CEFI github repository]
(https://github.com/NOAA-GFDL/CEFI-regional-MOM6/blob/main/diagnostics/physics/ssh_eval.py).

"""

def __init__(
self,
data_type : Literal['forecast','historical'] = 'forecast',
grid : Literal['raw','regrid'] = 'regrid'
ds_data : xr.Dataset,
ssh_name : str = 'ssh'
) -> None:
"""
input for the class to determine what data the user
want the index to be calculated from.
"""_summary_

Parameters
----------
data_type : Literal['forecast','historical'], optional
This determine the data type the user want to use
to calculate the indexes, by default 'forecast'
grid : Literal['raw','regrid'], optional
This determine the type of grid solution the user
want to use to calculate the indexes, by default 'regrid'
ds_data : xr.Dataset
The sea level height dataset one want to use to
derived the gulf stream index. The coordinate
must have the name "lon" and "lat" exactly
ssh_name : str
The sea level height variable name in the dataset
"""
self.data_type = data_type
self.grid = grid
self.dataset = ds_data
self.varname = ssh_name


@staticmethod
def __region_focus(
Expand Down Expand Up @@ -95,7 +87,7 @@ def __region_focus(
xr.Dataset
the regridded Dataset structure
"""


# longitude coordinate change -180 180 to 0 360
if lon_max < 0. :
Expand All @@ -120,27 +112,37 @@ def __region_focus(
def generate_index(
self,
) -> xr.Dataset:

"""Generate the gulf stream index

Returns
-------
xr.Dataset
dataset containing the gulf_stream_index
variables.
"""

# getting the dataset
if self.data_type in ['historical']:
ds_data = mp.MOM6Historical.get_mom6_all('ssh',grid=self.grid)
elif self.data_type in ['forecast']:
ds_data = mp.MOM6Forecast.get_mom6_all('ssh',grid=self.grid)
ds_data = self.dataset

# change longitude range from -180 180 to 0 360
ds_data['geolon'] = ds_data['geolon']+360.
try:
lon = ds_data['lon'].data
except KeyError as e:
raise KeyError("Coordinates should have 'lon' and 'lat' with exact naming") from e
lon_ind = np.where(lon<0)
lon[lon_ind] += 360.
ds_data['lon'].data = lon
# ds_data = ds_data.sortby('lon')

# Define Regridding data structure
ds_regrid = self.__region_focus()

# use xesmf to create regridder
if self.grid in ['raw']:
ds_data = ds_data.rename({'geolon':'lon','geolat':'lat'})
regridder = xe.Regridder(ds_data, ds_regrid, "bilinear", unmapped_to_nan=True)

# perform regrid for each field
ds_regrid = xr.Dataset()
ds_regrid['ssh'] = regridder(ds_data['ssh'])
ds_regrid['ssh'] = regridder(ds_data[self.varname])

# Calculate the Sea Surface Height (SSH) anomaly
# We calculate the anomaly based on the monthly climatology.
Expand All @@ -163,17 +165,25 @@ def generate_index(

# Calculate the Gulf Stream Index
# - use the maximum latitude index to find the SSH anomaly along the line shown above.
# - calculate the longitude mean of the SSH anomaly (time dependent)
# - calculate the longitude mean of the SSH anomaly (time dependent)
# $$\text{{SSHa}}$$
# - calculate the stardarde deviation of the $\text{{SSHa}}$
# $$\text{{SSHa\_std}}$$
# - calculate the index
# $$\text{{Gulf Stream Index}} = \frac{\text{{SSHa}}}{\text{{SSHa\_std}}}$$
da_ssh_mean_along_gs = da_regrid_anom.isel(lat=da_lat_ind_maxstd).mean('lon')
da_ssh_mean_std_along_gs = da_regrid_anom.isel(lat=da_lat_ind_maxstd).mean('lon').std('time')
da_ssh_mean_along_gs = (
da_regrid_anom
.isel(lat=da_lat_ind_maxstd)
.mean('lon')
)
da_ssh_mean_std_along_gs = (
da_regrid_anom
.isel(lat=da_lat_ind_maxstd)
.mean('lon')
.std('time')
)
da_gs_index = da_ssh_mean_along_gs/da_ssh_mean_std_along_gs
ds_gs = xr.Dataset()
ds_gs['gulf_stream_index'] = da_gs_index


return ds_gs
Loading