{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "7108c0a5-cf7d-44fb-b124-a4f7479b23a9",
   "metadata": {},
   "source": [
    "# CMOR example with prototype CMIP7 tables/CVs"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d7565f6c-a9d2-4d7b-bb62-793857453200",
   "metadata": {},
   "source": [
    "This code is a demonstration of the use of CMOR with the MIP tables in this repository and prototype CVs. This requires a conda environment with CMOR v3.13 installed (see cmor_environment.yml in this repository)\n",
    "\n",
    "This example is up to date with the CMIP7 global attributes, including file and directory naming."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "8ea3ef77-a3f1-483e-8a9d-05781bceda6f",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CPU times: user 2 μs, sys: 1 μs, total: 3 μs\n",
      "Wall time: 5.72 μs\n"
     ]
    }
   ],
   "source": [
    "%time\n",
    "import cmor\n",
    "import numpy \n",
    "import json"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "db89936e-d806-4b95-942c-33d81f58d408",
   "metadata": {},
   "source": [
    "The following is adapted from the code at https://github.com/PCMDI/cmor/blob/main/Test/test_cmor_CMIP7.py"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e026c4e5-3bd2-4d8e-a34f-c7e1d81240c3",
   "metadata": {},
   "source": [
    "Construct the input json file for CMOR\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "a36f5a25-658b-4eb2-8195-ff389d37c058",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CPU times: user 2 μs, sys: 1e+03 ns, total: 3 μs\n",
      "Wall time: 5.01 μs\n"
     ]
    }
   ],
   "source": [
    "%time\n",
    "DATASET_INFO = {\n",
    "    \"_AXIS_ENTRY_FILE\": \"tables/CMIP7_coordinate.json\",\n",
    "    \"_FORMULA_VAR_FILE\": \"tables/CMIP7_formula_terms.json\",\n",
    "    \"_cmip7_option\": 1,\n",
    "    \"_controlled_vocabulary_file\": \"test/CMIP7-CV_for-cmor.json\",  # SEPARATE TO MIP TABLES FOR TESTING ONLY\n",
    "    \"activity_id\": \"CMIP\",\n",
    "    \"branch_method\": \"standard\",\n",
    "    \"branch_time_in_child\": 30.0,\n",
    "    \"branch_time_in_parent\": 10800.0,\n",
    "    \"calendar\": \"360_day\",\n",
    "    \"cv_version\": \"7.0.0.0\",\n",
    "    \"drs_specs\": \"MIP-DRS7\",\n",
    "    \"experiment_id\": \"historical\",\n",
    "    \"forcing_index\": \"f3\",\n",
    "    \"grid\": \"N96\",\n",
    "    \"grid_label\": \"gn\",\n",
    "    \"initialization_index\": \"i1\",\n",
    "    \"institution_id\": \"PCMDI\",\n",
    "    \"license_id\": \"CC BY 4.0\",\n",
    "    \"nominal_resolution\": \"250 km\",\n",
    "    \"outpath\": \".\",\n",
    "    \"parent_mip_era\": \"CMIP7\",\n",
    "    \"parent_time_units\": \"days since 1850-01-01\",\n",
    "    \"parent_activity_id\": \"CMIP\",\n",
    "    \"parent_source_id\": \"PCMDI-test-1-0\",\n",
    "    \"parent_experiment_id\": \"piControl\",\n",
    "    \"parent_variant_label\": \"r1i1p1f3\",\n",
    "    \"physics_index\": \"p1\",\n",
    "    \"realization_index\": \"r9\",\n",
    "    \"source_id\": \"PCMDI-test-1-0\",\n",
    "    \"source_type\": \"AOGCM CHEM BGC\",\n",
    "    \"tracking_prefix\": \"hdl:21.14107\",\n",
    "    \"host_collection\": \"CMIP7\",\n",
    "    \"frequency\": \"day\",\n",
    "    \"region\": \"glb\",\n",
    "    \"archive_id\": \"WCRP\",\n",
    "    \"mip_era\": \"CMIP7\",\n",
    "}\n",
    "\n",
    "# Adjustments for CVs table from esgvoc.\n",
    "# This should end up being same as the above, but isn't at the moment.\n",
    "DATASET_INFO[\"_controlled_vocabulary_file\"] = \"test/esgvoc-integration-cmor-cvs-table.json\"\n",
    "DATASET_INFO[\"grid_label\"] = \"g99\"\n",
    "DATASET_INFO[\"institution_id\"] = \"CCCma\"\n",
    "DATASET_INFO[\"license_id\"] = \"CC-BY-4-0\"\n",
    "DATASET_INFO[\"nominal_resolution\"] = \"100-km\"\n",
    "DATASET_INFO[\"parent_source_id\"] = \"CanESM6-MR\"\n",
    "DATASET_INFO[\"source_id\"] = \"CanESM6-MR\"\n",
    "DATASET_INFO[\"frequency\"] = \"mon\"\n",
    "# Should come from CMOR but doesn't seem to be?\n",
    "DATASET_INFO[\"branded_variable\"] = \"tos_tavg-u-hxy-sea\"\n",
    "\n",
    "with open('input.json', 'w') as fh:\n",
    "    json.dump(DATASET_INFO, fh, indent=2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "ea8c425e-0b11-4a7d-aab0-cf95df843d9f",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CPU times: user 2 μs, sys: 1e+03 ns, total: 3 μs\n",
      "Wall time: 4.29 μs\n"
     ]
    }
   ],
   "source": [
    "%time\n",
    "cmor.setup(inpath=\"tables\", netcdf_file_action=cmor.CMOR_REPLACE)\n",
    "\n",
    "cmor.dataset_json('input.json')\n",
    "\n",
    "tos = numpy.array([27, 27, 27, 27,\n",
    "                    27, 27, 27, 27,\n",
    "                    27, 27, 27, 27,\n",
    "                    27, 27, 27, 27,\n",
    "                    27, 27, 27, 27,\n",
    "                    27, 27, 27, 27\n",
    "                    ])\n",
    "tos.shape = (2, 3, 4)\n",
    "lat = numpy.array([10, 20, 30])\n",
    "lat_bnds = numpy.array([5, 15, 25, 35])\n",
    "lon = numpy.array([0, 90, 180, 270])\n",
    "lon_bnds = numpy.array([-45, 45,\n",
    "                        135,\n",
    "                        225,\n",
    "                        315\n",
    "                        ])\n",
    "time = numpy.array([15.0, 45.0])\n",
    "time_bnds = numpy.array([0.0, 30.0, 60.0])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "7cadff79-d0df-4fbd-8543-da5e96e13a30",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CPU times: user 2 μs, sys: 1 μs, total: 3 μs\n",
      "Wall time: 5.01 μs\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "0"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "%time\n",
    "realm = \"ocean\"\n",
    "cmor.load_table(f\"CMIP7_{realm}.json\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "c4590918-dc87-498b-a491-fa5c793b7423",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CPU times: user 1e+03 ns, sys: 1 μs, total: 2 μs\n",
      "Wall time: 4.77 μs\n"
     ]
    }
   ],
   "source": [
    "%time\n",
    "cmorlat = cmor.axis(\"latitude\",\n",
    "                    coord_vals=lat,\n",
    "                    cell_bounds=lat_bnds,\n",
    "                    units=\"degrees_north\")\n",
    "cmorlon = cmor.axis(\"longitude\",\n",
    "                    coord_vals=lon,\n",
    "                    cell_bounds=lon_bnds,\n",
    "                    units=\"degrees_east\")\n",
    "cmortime = cmor.axis(\"time\",\n",
    "                    coord_vals=time,\n",
    "                    cell_bounds=time_bnds,\n",
    "                    units=\"days since 2018\")\n",
    "axes = [cmortime, cmorlat, cmorlon]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "de92a25d-7528-4ed5-8ff5-9b4a80e689c6",
   "metadata": {},
   "outputs": [],
   "source": [
    "variable = \"tos_tavg-u-hxy-sea\"\n",
    "cmortos = cmor.variable(variable, \"degC\", axes)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "8e979027-9e52-48e0-b5cc-aa414362cdf3",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# manually apply cell measures\n",
    "region = DATASET_INFO['region']\n",
    "frequency = DATASET_INFO['frequency']\n",
    "cell_measures_key = \".\".join([realm] + variable.split(\"_\") + [frequency, region.upper()])\n",
    "\n",
    "with open('tables/CMIP7_cell_measures.json') as fh:\n",
    "    cell_measures = json.load(fh)\n",
    "\n",
    "# Check that cell_measures are valid ( option flags need to be manually replaced )\n",
    "variable_cell_measures = cell_measures[cell_measures_key]\n",
    "if variable_cell_measures in [\"::OPT\", \"::MODEL\"]:\n",
    "    raise RuntimeError(f\"found cell_measures '{variable_cell_measures}' which CMOR will not allow\")\n",
    "\n",
    "cmor.set_variable_attribute(cmortos, \"cell_measures\", \"c\", variable_cell_measures)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "f779b96a-20f7-4e5a-b915-c1755b8d9d1d",
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'./MIP-DRS7//CMIP7//CMIP//CCCma//CanESM6-MR//historical//r9i1p1f3//glb//mon//tos//tavg-u-hxy-sea//g99//v20251204/tos_tavg-u-hxy-sea_mon_glb_g99_CanESM6-MR_historical_r9i1p1f3_201801-201802.nc'"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "cmor.write(cmortos, tos)\n",
    "filename = cmor.close(cmortos, file_name=True)\n",
    "filename"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "71cd04d0-ea27-4877-b259-adf84bf3b694",
   "metadata": {},
   "source": [
    "Locate generated file"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "e878ab7a-f3c4-4203-8da6-abbdf3418cb3",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "MIP-DRS7/CMIP7/CMIP/CCCma/CanESM6-MR/historical/r9i1p1f3/glb/mon/tos/tavg-u-hxy-sea/g99/v20251204/tos_tavg-u-hxy-sea_mon_glb_g99_CanESM6-MR_historical_r9i1p1f3_201801-201802.nc\n"
     ]
    }
   ],
   "source": [
    "!find MIP-DRS7 -type f -name '*.nc'"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f7a3343c-95d6-4b94-b8b0-d9f4f35356e4",
   "metadata": {},
   "source": [
    "Dump header of generated file"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "0a6aee11-0970-405d-9b47-b03e190f21aa",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "netcdf tos_tavg-u-hxy-sea_mon_glb_g99_CanESM6-MR_historical_r9i1p1f3_201801-201802 {\n",
      "dimensions:\n",
      "\ttime = UNLIMITED ; // (2 currently)\n",
      "\tlat = 3 ;\n",
      "\tlon = 4 ;\n",
      "\tbnds = 2 ;\n",
      "variables:\n",
      "\tdouble time(time) ;\n",
      "\t\ttime:bounds = \"time_bnds\" ;\n",
      "\t\ttime:units = \"days since 2018\" ;\n",
      "\t\ttime:calendar = \"360_day\" ;\n",
      "\t\ttime:axis = \"T\" ;\n",
      "\t\ttime:long_name = \"Time Intervals\" ;\n",
      "\t\ttime:standard_name = \"time\" ;\n",
      "\tdouble time_bnds(time, bnds) ;\n",
      "\tdouble lat(lat) ;\n",
      "\t\tlat:bounds = \"lat_bnds\" ;\n",
      "\t\tlat:units = \"degrees_north\" ;\n",
      "\t\tlat:axis = \"Y\" ;\n",
      "\t\tlat:long_name = \"Latitude\" ;\n",
      "\t\tlat:standard_name = \"latitude\" ;\n",
      "\tdouble lat_bnds(lat, bnds) ;\n",
      "\tdouble lon(lon) ;\n",
      "\t\tlon:bounds = \"lon_bnds\" ;\n",
      "\t\tlon:units = \"degrees_east\" ;\n",
      "\t\tlon:axis = \"X\" ;\n",
      "\t\tlon:long_name = \"Longitude\" ;\n",
      "\t\tlon:standard_name = \"longitude\" ;\n",
      "\tdouble lon_bnds(lon, bnds) ;\n",
      "\tfloat tos(time, lat, lon) ;\n",
      "\t\ttos:standard_name = \"sea_surface_temperature\" ;\n",
      "\t\ttos:long_name = \"Sea Surface Temperature\" ;\n",
      "\t\ttos:units = \"degC\" ;\n",
      "\t\ttos:cell_methods = \"area: mean where sea time: mean\" ;\n",
      "\t\ttos:missing_value = 1.e+20f ;\n",
      "\t\ttos:_FillValue = 1.e+20f ;\n",
      "\t\ttos:cell_measures = \"area: areacello\" ;\n",
      "\t\ttos:history = \"2025-12-04T16:07:36Z altered by CMOR: Converted type from \\'l\\' to \\'f\\'.\" ;\n",
      "\n",
      "// global attributes:\n",
      "\t\t:Conventions = \"CF-1.12 CMIP-7.0\" ;\n",
      "\t\t:activity_id = \"CMIP\" ;\n",
      "\t\t:archive_id = \"WCRP\" ;\n",
      "\t\t:area_label = \"sea\" ;\n",
      "\t\t:branch_method = \"standard\" ;\n",
      "\t\t:branch_time_in_child = 30. ;\n",
      "\t\t:branch_time_in_parent = 10800. ;\n",
      "\t\t:branded_variable = \"tos_tavg-u-hxy-sea\" ;\n",
      "\t\t:branding_suffix = \"tavg-u-hxy-sea\" ;\n",
      "\t\t:creation_date = \"2025-12-04T16:07:36Z\" ;\n",
      "\t\t:cv_version = \"7.0.0.0\" ;\n",
      "\t\t:data_specs_version = \"MIPDS7-0p0p1\" ;\n",
      "\t\t:description = \"Simulation of the climate of the recent past (typically meaning 1850 to present-day)\" ;\n",
      "\t\t:drs_specs = \"MIP-DRS7\" ;\n",
      "\t\t:experiment = \"Simulation of the climate of the recent past (typically meaning 1850 to present-day)\" ;\n",
      "\t\t:experiment_id = \"historical\" ;\n",
      "\t\t:external_variables = \"areacello\" ;\n",
      "\t\t:forcing_index = \"f3\" ;\n",
      "\t\t:frequency = \"mon\" ;\n",
      "\t\t:grid = \"N96\" ;\n",
      "\t\t:grid_label = \"g99\" ;\n",
      "\t\t:history = \"2025-12-04T16:07:36Z ; CMOR rewrote data to be consistent with CMIP7, CF-1.12 CMIP-7.0 and CF standards.\" ;\n",
      "\t\t:horizontal_label = \"hxy\" ;\n",
      "\t\t:host_collection = \"CMIP7\" ;\n",
      "\t\t:initialization_index = \"i1\" ;\n",
      "\t\t:institution = \"Environment and Climate Change Canada\" ;\n",
      "\t\t:institution_id = \"CCCma\" ;\n",
      "\t\t:label = \"Context is wrong - label isn\\'t really a name. Label for plots etc.\" ;\n",
      "\t\t:label_extended = \"Context is wrong - extended label isn\\'t really an extended name. Long label with full detail about the source\" ;\n",
      "\t\t:license_id = \"CC-BY-4-0\" ;\n",
      "\t\t:mip_era = \"CMIP7\" ;\n",
      "\t\t:nominal_resolution = \"100-km\" ;\n",
      "\t\t:parent_activity_id = \"CMIP\" ;\n",
      "\t\t:parent_experiment_id = \"piControl\" ;\n",
      "\t\t:parent_mip_era = \"CMIP7\" ;\n",
      "\t\t:parent_source_id = \"CanESM6-MR\" ;\n",
      "\t\t:parent_time_units = \"days since 1850-01-01\" ;\n",
      "\t\t:parent_variant_label = \"r1i1p1f3\" ;\n",
      "\t\t:physics_index = \"p1\" ;\n",
      "\t\t:product = \"model-output\" ;\n",
      "\t\t:realization_index = \"r9\" ;\n",
      "\t\t:realm = \"ocean\" ;\n",
      "\t\t:region = \"glb\" ;\n",
      "\t\t:source = \"CanESM6-MR:\" ;\n",
      "\t\t:source_id = \"CanESM6-MR\" ;\n",
      "\t\t:source_type = \"AOGCM CHEM BGC\" ;\n",
      "\t\t:table_id = \"ocean\" ;\n",
      "\t\t:table_info = \"Creation Date:(2025-10-17 11:13:22) MD5:6ee08de6316a35cc1ed7164287b8be1e\" ;\n",
      "\t\t:temporal_label = \"tavg\" ;\n",
      "\t\t:title = \"CanESM6-MR output prepared for CMIP7\" ;\n",
      "\t\t:tracking_id = \"hdl:21.14107/7149b67e-a56a-4bd0-b931-29b1634ca019\" ;\n",
      "\t\t:variable_id = \"tos\" ;\n",
      "\t\t:variant_label = \"r9i1p1f3\" ;\n",
      "\t\t:vertical_label = \"u\" ;\n",
      "\t\t:license = \"CC-BY-4-0; CMIP7 data produced by CCCma is licensed under a Creative Commons Attribution 4.0 International License (https://creativecommons.org/licenses/by/4.0). Consult [TODO terms of use link] for terms of use governing CMIP7 output, including citation requirements and proper acknowledgment. The data producers and data providers make no warranty, either express or implied, including, but not limited to, warranties of merchantability and fitness for a particular purpose. All liabilities arising from the supply of the information (including any liability arising in negligence) are excluded to the fullest extent permitted by law.\" ;\n",
      "\t\t:cmor_version = \"3.13.0\" ;\n",
      "}\n"
     ]
    }
   ],
   "source": [
    "!ncdump -h MIP-DRS7/CMIP7/CMIP/CCCma/CanESM6-MR/historical/r9i1p1f3/glb/mon/tos/tavg-u-hxy-sea/g99/v*/tos_tavg-u-hxy-sea_mon_glb_g99_CanESM6-MR_historical_r9i1p1f3_201801-201802.nc"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "a8610a45-0034-4c5a-9ba2-a438caeaab6a",
   "metadata": {},
   "outputs": [],
   "source": [
    "# clean up\n",
    "#! rm -rf MIP-DRS7\n",
    "#! rm -rf input.json"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "06648fd0-abfe-4895-b137-6f6912653b85",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": ".conda-CMOR-3.13 Python (Conda)",
   "language": "python",
   "name": "conda-env-.conda-CMOR-3.13-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.13.7"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
