Skip to content

Commit

Permalink
Merge pull request #722 from PCMDI/709-updates-for-mip-cmor-tables
Browse files Browse the repository at this point in the history
Updates for mip-cmor-tables
  • Loading branch information
mauzey1 authored Jan 26, 2024
2 parents 047fd2c + fb5afce commit c2f7450
Show file tree
Hide file tree
Showing 17 changed files with 1,144 additions and 32 deletions.
6 changes: 3 additions & 3 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ aliases:
export ACTIVATE=$WORKDIR/miniconda/bin/activate
python $BUILD_SCRIPT -w $WORKDIR -l $VERSION -B 0 -p $PKG_NAME -r $PKG_NAME -b $CIRCLE_BRANCH \
--do_rerender --conda_env rerender_env --ignore_conda_missmatch --conda_activate $ACTIVATE --organization PCMDI
--do_rerender --conda_env base --ignore_conda_missmatch --conda_activate $ACTIVATE --organization PCMDI
- &conda_build
name: conda_build
Expand All @@ -60,7 +60,7 @@ aliases:
export ACTIVATE=$WORKDIR/miniconda/bin/activate
python $BUILD_SCRIPT -w $WORKDIR -p $PKG_NAME --build_version $PYTHON_VERSION --do_build \
--conda_env build_env --extra_channels conda-forge --conda_activate $ACTIVATE $CONDA_BUILD_EXTRA
--conda_env base --extra_channels conda-forge --conda_activate $ACTIVATE $CONDA_BUILD_EXTRA
- &run_cmor_tests
name: run_cmor_tests
Expand Down Expand Up @@ -115,7 +115,7 @@ jobs:
executor: << parameters.os >>
environment:
PKG_NAME: "cmor"
VERSION: "3.7.3"
VERSION: "3.8.0"
PYTHON_VERSION: << parameters.python_version >>
CHANNELS: "-c conda-forge"
steps:
Expand Down
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
[submodule "cmip6-cmor-tables"]
path = cmip6-cmor-tables
url = https://github.com/PCMDI/cmip6-cmor-tables.git
[submodule "mip-cmor-tables"]
path = mip-cmor-tables
url = https://github.com/PCMDI/mip-cmor-tables.git
4 changes: 2 additions & 2 deletions .zenodo.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
"description": "<p>Climate Model Output Rewriter</p>",
"access_right": "open",
"license": "BSD-3-Clause",
"title": "PCMDI/CMOR: CMOR v3.7.3",
"version": "v3.7.3",
"title": "PCMDI/CMOR: CMOR v3.8.0",
"version": "v3.8.0",
"upload_type": "software",
"publication_date": "2023-10-17",
"creators": [
Expand Down
4 changes: 2 additions & 2 deletions INSTALL
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
INSTALLATION INSTRUCTIONS
-------------------------
Climate Model Output Rewriter (CMOR) version 3.7.3 installation instructions.
Climate Model Output Rewriter (CMOR) version 3.8.0 installation instructions.


DOWNLOAD
Expand All @@ -13,7 +13,7 @@ cd CMOR

INSTALLATION
------------
CMOR 3.7.3 requires external packages that need to be installed first.
CMOR 3.8.0 requires external packages that need to be installed first.
It can be compiled/linked against either NetCDF3 or NetCDF4. If you
decide to go with NetCDF4 be sure to build NetCDF4 with the
--enable-netcdf-4 option!
Expand Down
1 change: 1 addition & 0 deletions Makefile.in
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,7 @@ test_python: python
env TEST_NAME=Test/test_cmor_python_not_enough_data.py make test_a_python
env TEST_NAME=Test/test_cmor_python_not_enough_times_written.py make test_a_python
env TEST_NAME=Test/test_python_forecast_coordinates.py make test_a_python
env TEST_NAME=Test/test_cmor_CMIP6Plus.py make test_a_python
test_cmip6_cv: python
env TEST_NAME=Test/test_python_CMIP6_CV_sub_experimentnotset.py make test_a_python
env TEST_NAME=Test/test_python_CMIP6_CV_sub_experimentbad.py make test_a_python
Expand Down
14 changes: 4 additions & 10 deletions Src/cmor.c
Original file line number Diff line number Diff line change
Expand Up @@ -2939,16 +2939,10 @@ int cmor_setGblAttr(int var_id)
/* first check if the variable itself has a realm */
/* -------------------------------------------------------------------- */
if (cmor_tables[nVarRefTblID].vars[ref_var_id].realm[0] != '\0') {
szToken = strtok(cmor_tables[nVarRefTblID].vars[ref_var_id].realm, " ");
if (szToken != NULL) {
cmor_set_cur_dataset_attribute_internal(GLOBAL_ATT_REALM,
szToken, 0);
} else {
cmor_set_cur_dataset_attribute_internal(GLOBAL_ATT_REALM,
cmor_tables
[nVarRefTblID].vars
[ref_var_id].realm, 0);
}
cmor_set_cur_dataset_attribute_internal(GLOBAL_ATT_REALM,
cmor_tables
[nVarRefTblID].vars
[ref_var_id].realm, 0);
} else {
/* -------------------------------------------------------------------- */
/* ok it didn't so we're using the value from the table */
Expand Down
2 changes: 1 addition & 1 deletion Src/cmor_fortran_interface.f90
Original file line number Diff line number Diff line change
Expand Up @@ -806,7 +806,7 @@ end function cmor_close_cff
integer, parameter:: CMOR_EXIT_ON_MAJOR = 0
integer, parameter:: CMOR_EXIT_ON_WARNING = 2

real, parameter:: CMOR_VERSION = 3.7
real, parameter:: CMOR_VERSION = 3.8
real, parameter:: CMOR_CF_VERSION = 1.7

integer, parameter:: CMOR_WARNING = 20
Expand Down
71 changes: 70 additions & 1 deletion Src/cmor_tables.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include "cmor_locale.h"
#include <json-c/json.h>
#include <json-c/json_tokener.h>
#include <json-c/arraylist.h>
#include <sys/stat.h>

/************************************************************************/
Expand Down Expand Up @@ -171,6 +172,9 @@ int cmor_set_variable_entry(cmor_table_t * table,
char msg[CMOR_MAX_STRING];
int nVarId;
char *szTableId;
array_list *jsonArray;
json_object *jsonItem;
size_t k, arrayLen;
cmor_var_def_t *variable;
cmor_table_t *cmor_table;
cmor_table = &cmor_tables[cmor_ntables];
Expand Down Expand Up @@ -208,7 +212,26 @@ int cmor_set_variable_entry(cmor_table_t * table,
if (attr[0] == '#')
continue;

strcpy(szValue, json_object_get_string(value));
/* -------------------------------------------------------------------- */
/* Attribute values that are arrays will have their array elements */
/* combined into space-separated lists. */
/* -------------------------------------------------------------------- */
if(json_object_is_type(value, json_type_array)) {
jsonArray = json_object_get_array(value);
arrayLen = array_list_length(jsonArray);
for (k = 0; k < arrayLen; k++) {
jsonItem = (json_object *) array_list_get_idx(jsonArray, k);
if (k == 0) {
strcpy(szValue, json_object_get_string(jsonItem));
} else {
strcat(szValue, " ");
strcat(szValue, json_object_get_string(jsonItem));
}
}
} else {
strcpy(szValue, json_object_get_string(value));
}

cmor_set_var_def_att(variable, attr, szValue);
}
cmor_pop_traceback();
Expand Down Expand Up @@ -772,6 +795,18 @@ int cmor_load_table_internal(char szTable[CMOR_MAX_STRING], int *table_id)
return (TABLE_ERROR);
}

/* -------------------------------------------------------------------- */
/* check for null values in JSON */
/* -------------------------------------------------------------------- */
if(cmor_validate_json(json_obj) != 0) {
snprintf(msg, CMOR_MAX_STRING,
"There are invalid null values in table: %s",
szTable);
cmor_handle_error(msg, CMOR_CRITICAL);
cmor_pop_traceback();
return (TABLE_ERROR);
}

json_object_object_foreach(json_obj, key, value) {

if (key[0] == '#') {
Expand Down Expand Up @@ -985,3 +1020,37 @@ int cmor_load_table_internal(char szTable[CMOR_MAX_STRING], int *table_id)
json_object_put(json_obj);
return (TABLE_SUCCESS);
}


/************************************************************************/
/* cmor_validate_json() */
/************************************************************************/
int cmor_validate_json(json_object *json)
{
json_object *value;
array_list *array;
size_t length, k;

if (json_object_is_type(json, json_type_null)) {
// null is invalid
return 1;
} else if (json_object_is_type(json, json_type_object)) {
// validate values within JSON object
json_object_object_foreach(json, key, value) {
if (cmor_validate_json(value) == 1)
return 1;
}
} else if (json_object_is_type(json, json_type_array)) {
// validate values within JSON list
array = json_object_get_array(json);
length = array_list_length(array);
for (k = 0; k < length; k++) {
value = (json_object *) array_list_get_idx(array, k);
if (cmor_validate_json(value) == 1)
return 1;
}
}

return 0;

}
40 changes: 40 additions & 0 deletions Test/CMIP6Plus_user_input.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
{
"branch_method": "standard",
"calendar": "360_day",
"experiment_id": "hist-lu",
"institution_id": "MOHC",
"license": "CMIP6Plus model data produced by the Met Office Hadley Centre is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License (https://creativecommons.org/licenses). Consult https://pcmdi.llnl.gov/CMIP6Plus/TermsOfUse for terms of use governing CMIP6Plus 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.",
"activity_id": "LESFMIP",
"mip_era": "CMIP6Plus",
"source_id": "HadGEM3-GC31-LL",
"source_type": "AOGCM BGC AER CHEM",
"outpath": ".",
"sub_experiment_id": "f2023",
"variant_label": "r1i1p1f2",
"grid": "Native N96 grid; 192 x 144 longitude/latitude",
"grid_label": "gn",
"nominal_resolution": "250 km",
"parent_experiment_id": "piControl",
"parent_mip_era": "CMIP6Plus",
"parent_source_id": "HadGEM3-GC31-LL",
"parent_time_units": "days since 1850-01-01",
"parent_variant_label": "r1i1p1f2",
"history": "2023-11-03T11:41:57Z MIP Convert v2.6.0.dev0, Python v3.8.17, iris v3.4.1, numpy v1.24.4, cftime v1.6.2, pyproj v3.5.0",
"#_cmip6_option": "CMIP6",
"realization_index": "1",
"initialization_index": "1",
"physics_index": "1",
"forcing_index": "2",
"cv_version": "0.0.1",
"experiment": "Single forcing historical simulations",
"sub_experiment": "Forcings 2023",
"tracking_prefix": "hdl:21.14100",
"parent_activity_id": "CMIP",
"_controlled_vocabulary_file": "TestTables/CMIP6Plus_CV.json",
"_AXIS_ENTRY_FILE": "mip-cmor-tables/Auxillary_files/MIP_coordinate.json",
"_FORMULA_VAR_FILE": "mip-cmor-tables/Auxillary_files/MIP_formula_terms.json",
"further_info_url": "https://furtherinfo.es-doc.org/",
"mo_runid": "u-be509",
"branch_time_in_parent": 59400.0,
"branch_time_in_child": 59400.0
}
58 changes: 58 additions & 0 deletions Test/test_cmor_CMIP6Plus.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import cmor
import numpy
import unittest


class TestCMIP6Plus(unittest.TestCase):

def test_multiple_modeling_realms(self):
ntimes_passed = 12

self.assertEqual(
cmor.setup(inpath='mip-cmor-tables/Tables',
netcdf_file_action=cmor.CMOR_REPLACE),
0)
self.assertEqual(cmor.dataset_json("Test/CMIP6Plus_user_input.json"),
0)

self.assertEqual(cmor.load_table("MIP_OPmon.json"), 0)

axes = [
{
'table_entry': 'time',
'units': 'months since 2010-1-1',
'coord_vals': numpy.arange(0, ntimes_passed, 1),
'cell_bounds': numpy.arange(0, ntimes_passed+1, 1)
},
{
'table_entry': 'latitude',
'units': 'degrees_north',
'coord_vals': [0],
'cell_bounds': [-1, 1]
},
{
'table_entry': 'longitude',
'units': 'degrees_east',
'coord_vals': [90],
'cell_bounds': [89, 91]
}
]

axis_ids = [cmor.axis(**axis) for axis in axes]

ivar = cmor.variable('hfsifrazil2d', units='W m-2', axis_ids=axis_ids)

data = [280., ] * ntimes_passed

self.assertEqual(
cmor.write(ivar, data, ntimes_passed=ntimes_passed),
0)

realms = cmor.get_cur_dataset_attribute('realm')
self.assertEqual(realms, "ocean seaIce")

self.assertEqual(cmor.close(), 0)


if __name__ == '__main__':
unittest.main()
Loading

0 comments on commit c2f7450

Please sign in to comment.