{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## *NOTE* Frequency indices T?90, R??mm, N??? have errors in them. Output files deleted.\n",
    "\n",
    "Need to address the underlying function to count days above threshold per ensemble member."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "This script generates the ETCCDI temperature indices from a single historical run of CESM2-WACCM daily temperature maxima (TX) and temperature minima (TN).\n",
    "\n",
    "Outputs one file per index:\n",
    "\n",
    "* TXX  \n",
    "* TXN  \n",
    "* TNN   \n",
    "* TNX  \n",
    "* TN90  \n",
    "* TN10  \n",
    "* TX90  \n",
    "* TX10  \n",
    "* SU   \n",
    "* TR  \n",
    "* ID \n",
    "* FD  \n",
    "\n",
    "GSL Growing season length is not computed here. Script yet to be developed."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "import warnings\n",
    "warnings.filterwarnings('ignore')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np # data arrays\n",
    "import xarray as xr # data array manipulation\n",
    "import pandas as pd\n",
    "import datetime as dt\n",
    "import os\n",
    "import glob"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Define the precipitation functions"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "from importlib import reload\n",
    "import config\n",
    "import tempex_func\n",
    "import utils #pyclimdex by B Groenks\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Read in each of the datasets in turn, calculate indices, then write the output to netcdf."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "iDir = \"/glade/work/maritye/Data/ARISE-MCB/Dailies/TREFHT/\"\n",
    "otnDir = \"/glade/work/maritye/Data/ARISE-MCB/ETCCDI/TREFHTMN/\"\n",
    "otxDir = '/glade/work/maritye/Data/ARISE-MCB/ETCCDI/TREFHTMX/'"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Create standard information to include with each data set"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "years = np.arange(2035,2070)\n",
    "dates= '2035-2069'\n",
    "member=range(10)\n",
    "lat = np.linspace(-90,90,num=192)\n",
    "lon = np.linspace(0,358.75,num=288)\n",
    "dims = ('member','year', 'lat', 'lon')\n",
    "coords = dict(member = member, year=years, lat=lat, lon=lon)\n",
    "attribs = dict(description='Temperature Extreme Indices based on ETCCDI definitions. MCB scenarios with 5% global seeding', \n",
    "                history='Created by Mari Tye November 2023.' ),\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "read in thresholds from SSP245 take the mean of the ensemble as the threshold for these runs."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "with xr.open_dataset('/glade/work/maritye/Data/ARISE-SAI/ETCCDI/SSP245/TREFHTMN/b.e21.BWSSP245cmip6.f09_g17.CMIP6-SSP2-4.5-WACCM.cam.h1.QN10.2015-2070.nc') as dsn10:\n",
    "    dn10 = dsn10.mean(dim='members')\n",
    "\n",
    "with xr.open_dataset('/glade/work/maritye/Data/ARISE-SAI/ETCCDI/SSP245/TREFHTMN/b.e21.BWSSP245cmip6.f09_g17.CMIP6-SSP2-4.5-WACCM.cam.h1.QN90.2015-2070.nc') as dsn90:\n",
    "    dn90 = dsn90.mean(dim='members')\n",
    "    \n",
    "with xr.open_dataset('/glade/work/maritye/Data/ARISE-SAI/ETCCDI/SSP245/TREFHTMX/b.e21.BWSSP245cmip6.f09_g17.CMIP6-SSP2-4.5-WACCM.cam.h1.QX10.2015-2070.nc') as dsx10:\n",
    "    dx10 = dsx10.mean(dim='members')\n",
    "\n",
    "with xr.open_dataset('/glade/work/maritye/Data/ARISE-SAI/ETCCDI/SSP245/TREFHTMX/b.e21.BWSSP245cmip6.f09_g17.CMIP6-SSP2-4.5-WACCM.cam.h1.QX90.2015-2070.nc') as dsx90:\n",
    "    dx90 = dsx90.mean(dim='members')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Daily minimum temperatures"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Create some blank arrays to fill with each index for each ensemble member. Write these out at the end with netcdf"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "TNX = xr.DataArray(None, coords=coords, dims=dims, attrs=attribs, name='TNX')\n",
    "TNN = xr.DataArray(None, coords=coords,  dims=dims, attrs=attribs, name='TNN')\n",
    "TN90 = xr.DataArray(None, coords=coords, dims=dims, attrs=attribs, name='TN90')\n",
    "TN10 = xr.DataArray(None, coords=coords, dims=dims, attrs=attribs, name='TN10')\n",
    "TR = xr.DataArray(None, coords=coords, dims=dims, attrs=attribs, name='TR')\n",
    "FD = xr.DataArray(None, coords=coords, dims=dims, attrs=attribs, name='FD')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "list the files - glob includes the filepath"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [],
   "source": [
    "files = glob.glob(iDir + '*.TREFHTMN.*')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0\n",
      "tnx\n",
      "tnn\n",
      "tr\n",
      "fd\n",
      "TN90\n",
      "TN10\n"
     ]
    }
   ],
   "source": [
    "for eff in range(1):\n",
    "    print(eff)\n",
    "    fp = files[eff]\n",
    "    ds = xr.open_dataset(fp)\n",
    "    ds = ds.sel(time=slice('2015-01-01', '2069-12-31'))\n",
    "\n",
    "        ### Fixed index\n",
    "    TNX[eff,:,:,:] = tempex_func.warmest_night(ds)    # Warmest night\n",
    "    print('tnx')\n",
    "    TNN[eff,:,:,:] = tempex_func.coolest_night(ds)    # Coolest night\n",
    "    print('tnn')\n",
    "\n",
    "        ## Fixed threshold count of days\n",
    "    TR[eff,:,:,:] = tempex_func.tropical_nights(ds)   # Tropical Nights Tn>20C\n",
    "    print('tr')\n",
    "    FD[eff,:,:,:] = tempex_func.frost_days(ds) # Nights with TN<Oc\n",
    "    print('fd')\n",
    "\n",
    "    # Locally defined threshold\n",
    "    TN90[eff,:,:,:] = tempex_func.annualnum_above_q(ds, dn90, varname='TREFHTMN')\n",
    "    print('TN90')\n",
    "    TN10[eff,:,:,:] = tempex_func.annualnum_below_q(ds, dn10, threshold=0.1, varname='TREFHTMN')\n",
    "    print('TN10')\n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "fileintro = 'b.e21.BSSP245smbb.f09_g17.MCB-050PCT.001-010.cam.h1.'\n",
    "\n",
    "tnnnm = os.path.join(otnDir , (fileintro + 'TNN.' + dates+ \".nc\"))\n",
    "tnxnm = os.path.join(otnDir , (fileintro + 'TNX.' + dates+ \".nc\"))\n",
    "trnm = os.path.join(otnDir , (fileintro + 'TR.' + dates+ \".nc\"))\n",
    "fdnm = os.path.join(otnDir , (fileintro + 'FD.' + dates+ \".nc\"))\n",
    "tn90nm = os.path.join(otnDir , (fileintro + 'TN90.' + dates + \".nc\"))\n",
    "tn10nm = os.path.join(otnDir , (fileintro + 'TN10.' + dates+ \".nc\"))\n",
    "\n",
    "    \n",
    "TNX = TNX.assign_attrs(units='Celsius',\n",
    "                       longname = 'Warmest Night per year')\n",
    "TNN = TNN.assign_attrs(units='Celsius',\n",
    "                       longname = 'Coldest Night per year')\n",
    "TR = TR.assign_attrs(units='Days per year',\n",
    "                       longname = 'Tropical Nights; daily minimum above 20C')\n",
    "FD = FD.assign_attrs(units='Days per year',\n",
    "                       longname = 'Frost Days; daily minimum below 0C')\n",
    "TN90 = TN90.assign_attrs(units='Days per year',\n",
    "                       longname = 'Warm Nights above 90th Percentile')\n",
    "TN10 = TN10.assign_attrs(units='Days per year',\n",
    "                       longname = 'Cool Nights below 10th Percentile')\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "tags": []
   },
   "source": [
    "and write out to netcdf"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "TNN.to_netcdf(tnnnm)\n",
    "TNX.to_netcdf(tnxnm)\n",
    "TR.to_netcdf(trnm)\n",
    "FD.to_netcdf(fdnm)\n",
    "TN90.to_netcdf(tn90nm)\n",
    "TN10.to_netcdf(tn10nm)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "tags": []
   },
   "source": [
    "## Daily maximum temperature"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "TXX = xr.DataArray(None, coords=coords, dims=dims, attrs=attribs, name='TXX')\n",
    "TXN = xr.DataArray(None, coords=coords, dims=dims, attrs=attribs, name='TXN')\n",
    "TX10 = xr.DataArray(None, coords=coords, dims=dims, attrs=attribs, name='TX10')\n",
    "TX90 = xr.DataArray(None, coords=coords, dims=dims, attrs=attribs, name='TX90')\n",
    "SU = xr.DataArray(None, coords=coords, dims=dims, attrs=attribs, name='SU')\n",
    "ID = xr.DataArray(None, coords=coords, dims=dims, attrs=attribs, name='ID')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "/glade/work/maritye/Data/ARISE-MCB/Dailies/TREFHT/b.e21.BSSP245smbb.f09_g17.MCB-050PCT.007.cam.h1.TREFHTMX.20350101-20691231.nc\n",
      "txx\n",
      "txn\n",
      "su\n",
      "id\n",
      "TX90\n",
      "TX10\n",
      "/glade/work/maritye/Data/ARISE-MCB/Dailies/TREFHT/b.e21.BSSP245smbb.f09_g17.MCB-050PCT.001.cam.h1.TREFHTMX.20350101-20691231.nc\n",
      "txx\n",
      "txn\n",
      "su\n",
      "id\n",
      "TX90\n",
      "TX10\n",
      "/glade/work/maritye/Data/ARISE-MCB/Dailies/TREFHT/b.e21.BSSP245smbb.f09_g17.MCB-050PCT.010.cam.h1.TREFHTMX.20350101-20691231.nc\n",
      "txx\n",
      "txn\n",
      "su\n",
      "id\n",
      "TX90\n",
      "TX10\n",
      "/glade/work/maritye/Data/ARISE-MCB/Dailies/TREFHT/b.e21.BSSP245smbb.f09_g17.MCB-050PCT.003.cam.h1.TREFHTMX.20350101-20691231.nc\n",
      "txx\n",
      "txn\n",
      "su\n",
      "id\n",
      "TX90\n",
      "TX10\n",
      "/glade/work/maritye/Data/ARISE-MCB/Dailies/TREFHT/b.e21.BSSP245smbb.f09_g17.MCB-050PCT.002.cam.h1.TREFHTMX.20350101-20691231.nc\n",
      "txx\n",
      "txn\n",
      "su\n",
      "id\n",
      "TX90\n",
      "TX10\n",
      "/glade/work/maritye/Data/ARISE-MCB/Dailies/TREFHT/b.e21.BSSP245smbb.f09_g17.MCB-050PCT.009.cam.h1.TREFHTMX.20350101-20691231.nc\n",
      "txx\n",
      "txn\n",
      "su\n",
      "id\n",
      "TX90\n",
      "TX10\n",
      "/glade/work/maritye/Data/ARISE-MCB/Dailies/TREFHT/b.e21.BSSP245smbb.f09_g17.MCB-050PCT.004.cam.h1.TREFHTMX.20350101-20691231.nc\n",
      "txx\n",
      "txn\n",
      "su\n",
      "id\n",
      "TX90\n",
      "TX10\n",
      "/glade/work/maritye/Data/ARISE-MCB/Dailies/TREFHT/b.e21.BSSP245smbb.f09_g17.MCB-050PCT.006.cam.h1.TREFHTMX.20350101-20691231.nc\n",
      "txx\n",
      "txn\n",
      "su\n",
      "id\n",
      "TX90\n",
      "TX10\n",
      "/glade/work/maritye/Data/ARISE-MCB/Dailies/TREFHT/b.e21.BSSP245smbb.f09_g17.MCB-050PCT.005.cam.h1.TREFHTMX.20350101-20691231.nc\n",
      "txx\n",
      "txn\n",
      "su\n",
      "id\n",
      "TX90\n",
      "TX10\n",
      "/glade/work/maritye/Data/ARISE-MCB/Dailies/TREFHT/b.e21.BSSP245cmip6.f09_g17.CMIP6-MCB-050PCT.000.cam.h1.TREFHTMX.20350101-20691231.nc\n",
      "txx\n",
      "txn\n",
      "su\n",
      "id\n",
      "TX90\n",
      "TX10\n"
     ]
    }
   ],
   "source": [
    "files = glob.glob(iDir + '*.TREFHTMX.*')\n",
    "for eff in range(10): \n",
    "    print(files[eff])\n",
    "    #### Open file\n",
    "    fp = files[eff]\n",
    "    ds = xr.open_dataset(fp)\n",
    "    ds = ds.sel(time=slice('2015-01-01', '2069-12-31'))\n",
    "\n",
    "        ### Fixed thresholds\n",
    "    TXX[eff,:,:,:] = tempex_func.warmest_day(ds)\n",
    "    print('txx')\n",
    "    TXN[eff,:,:,:] = tempex_func.coolest_day(ds)\n",
    "    print('txn')\n",
    "\n",
    "        ## Fixed threshold count of days\n",
    "    SU[eff,:,:,:] = tempex_func.summer_days(ds) \n",
    "    print('su')\n",
    "    ID[eff,:,:,:] = tempex_func.ice_days(ds) \n",
    "    print('id')\n",
    "    \n",
    "    #local threshold\n",
    "    TX90[eff,:,:,:] = tempex_func.annualnum_above_q(ds, dx90, varname='TREFHTMX')\n",
    "    print('TX90')\n",
    "    TX10[eff,:,:,:] = tempex_func.annualnum_below_q(ds, dx10, threshold=0.1, varname='TREFHTMX')\n",
    "    print('TX10')\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "txxnm = os.path.join(otxDir , (fileintro + 'TXX.' + dates + '.nc'))\n",
    "txnnm = os.path.join(otxDir , (fileintro + 'TXN.' + dates + '.nc'))\n",
    "sunm = os.path.join(otxDir , (fileintro + 'SU.' + dates + '.nc'))\n",
    "idnm = os.path.join(otxDir , (fileintro + 'ID.' + dates + '.nc'))\n",
    "tx90nm = os.path.join(otxDir , (fileintro + 'TX90.' + dates + '.nc'))\n",
    "tx10nm = os.path.join(otxDir , (fileintro + 'TX10.' + dates + '.nc'))\n",
    "\n",
    "TXX = TXX.assign_attrs(units='Celsius',\n",
    "                       longname = 'Warmest Day per year')\n",
    "TXN = TXN.assign_attrs(units='Celsius',\n",
    "                       longname = 'Coldest Day per year')\n",
    "SU = SU.assign_attrs(units='Days per year',\n",
    "                       longname = 'Summer Days; daily maximum above 25C')\n",
    "ID = ID.assign_attrs(units='Days per year',\n",
    "                       longname = 'Ice Days; daily maximum below 0C')\n",
    "TX90 = TX90.assign_attrs(units='Days per year',\n",
    "                       longname = 'Warm Days above 90th Percentile')\n",
    "TX10 = TX10.assign_attrs(units='Days per year',\n",
    "                       longname = 'Cool Days below 10th Percentile')\n",
    "\n",
    "\n",
    "    # and write out to netcdf\n",
    "TXN.to_netcdf(txnnm)\n",
    "TXX.to_netcdf(txxnm)\n",
    "SU.to_netcdf(sunm)\n",
    "ID.to_netcdf(idnm)\n",
    "TX90.to_netcdf(tx90nm)\n",
    "TX10.to_netcdf(tx10nm)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python [conda env:miniconda-npl2023a_mrt]",
   "language": "python",
   "name": "conda-env-miniconda-npl2023a_mrt-py"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.15"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
