diff --git a/.github/workflows/schema-ci.yml b/.github/workflows/schema-ci.yml index ffefc14..5604996 100644 --- a/.github/workflows/schema-ci.yml +++ b/.github/workflows/schema-ci.yml @@ -8,8 +8,13 @@ on: workflow_dispatch: env: - SCHEMA_DIR: au.org.access-nri/model/output/file-metadata/2-0-0 - TEST_DIR: tests/2-0-0 + SCHEMA_DIRS: | + au.org.access-nri/model/output/file-metadata/2-0-0 + au.org.access-nri/model/output/file-metadata/2-1-0 + # TEST_DIRS need to have matching SCHEMA_DIRS in the same order + TEST_DIRS: | + tests/2-0-0 + tests/2-1-0 jobs: schema-tests: @@ -18,16 +23,31 @@ jobs: - uses: actions/checkout@v4 - name: Install the Sourcemeta JSON Schema CLI - uses: sourcemeta/jsonschema@v11.8.3 + uses: sourcemeta/jsonschema@f0b6672d82955e58a73efd320068284a4e7a4483 #v14.14.2 - name: Check schemas against their metaschemas - run: jsonschema metaschema --verbose $SCHEMA_DIR + run: jsonschema metaschema --verbose $SCHEMA_DIRS - name: Check schemas are formatted - run: jsonschema fmt --check --verbose $SCHEMA_DIR + run: jsonschema fmt --check --verbose $SCHEMA_DIRS - name: Lint schemas - run: jsonschema lint --verbose --exclude enum_with_type $SCHEMA_DIR + run: | + jsonschema lint --verbose \ + --exclude enum_with_type \ + --exclude description_trailing_period \ + --exclude top_level_examples \ + $SCHEMA_DIRS - name: Run test suite - run: jsonschema test --verbose $TEST_DIR --resolve $SCHEMA_DIR + run: | + # Need to iterate through each pair of DIRS since there will be name + # collisions with different versions of the same schema + # Turn the strings into arrays of strings first + test_arr=($TEST_DIRS) + schema_arr=($SCHEMA_DIRS) + for i in "${!test_arr[@]}"; do + test_dir=${test_arr[i]} + schema_dir=${schema_arr[i]} + jsonschema test --verbose $test_dir --resolve $schema_dir + done diff --git a/au.org.access-nri/model/output/file-metadata/2-1-0/2-1-0.json b/au.org.access-nri/model/output/file-metadata/2-1-0/2-1-0.json new file mode 100644 index 0000000..9c40887 --- /dev/null +++ b/au.org.access-nri/model/output/file-metadata/2-1-0/2-1-0.json @@ -0,0 +1,28 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "title": "ACCESS ESM1.6 Model Output Data Specification", + "description": "The metadata associated with a file containing or referencing climate model data", + "type": "object", + "required": [ "global", "variables" ], + "properties": { + "global": { + "$ref": "global.json" + }, + "variables": { + "type": "object", + "properties": { + "time": { + "$ref": "variable/time.json" + }, + "time_bnds": { + "$ref": "variable/time_bnds.json" + } + }, + "patternProperties": { + "^.+$": { + "$ref": "variable.json" + } + } + } + } +} diff --git a/au.org.access-nri/model/output/file-metadata/2-1-0/global.json b/au.org.access-nri/model/output/file-metadata/2-1-0/global.json new file mode 100644 index 0000000..b9d3ca0 --- /dev/null +++ b/au.org.access-nri/model/output/file-metadata/2-1-0/global.json @@ -0,0 +1,101 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "global.json", + "title": "ACCESS Global Attributes", + "description": "File-level metadata for ACCESS ESM1.6 data", + "type": "object", + "required": [ + "base_configuration", + "contact", + "Conventions", + "date_created", + "data_specification", + "experiment_repo", + "experiment_uuid", + "frequency", + "geospatial_lat_max", + "geospatial_lat_min", + "geospatial_lon_max", + "geospatial_lon_min", + "license", + "model_version", + "model", + "realm", + "run_id", + "title" + ], + "properties": { + "title": { + "$ref": "global/title.json" + }, + "Conventions": { + "$ref": "global/Conventions.json" + }, + "base_configuration": { + "$ref": "global/base_configuration.json" + }, + "contact": { + "$ref": "global/contact.json" + }, + "data_specification": { + "$ref": "global/data_specification.json" + }, + "date_created": { + "$ref": "global/date_created.json" + }, + "date_metadata_modified": { + "$ref": "global/date_metadata_modified.json" + }, + "date_modified": { + "$ref": "global/date_modified.json" + }, + "experiment_repo": { + "$ref": "global/experiment_repo.json" + }, + "experiment_uuid": { + "$ref": "global/experiment_uuid.json" + }, + "frequency": { + "$ref": "global/frequency.json" + }, + "geospatial_lat_max": { + "$ref": "global/geospatial_lat_max.json" + }, + "geospatial_lat_min": { + "$ref": "global/geospatial_lat_min.json" + }, + "geospatial_lat_units": { + "$ref": "global/geospatial_lat_units.json" + }, + "geospatial_lon_max": { + "$ref": "global/geospatial_lon_max.json" + }, + "geospatial_lon_min": { + "$ref": "global/geospatial_lon_min.json" + }, + "geospatial_lon_units": { + "$ref": "global/geospatial_lon_units.json" + }, + "grid": { + "$ref": "global/grid.json" + }, + "license": { + "$ref": "global/license.json" + }, + "model": { + "$ref": "global/model.json" + }, + "model_version": { + "$ref": "global/model_version.json" + }, + "realm": { + "$ref": "global/realm.json" + }, + "run_id": { + "$ref": "global/run_id.json" + }, + "variable_id": { + "$ref": "global/variable_id.json" + } + } +} diff --git a/au.org.access-nri/model/output/file-metadata/2-1-0/global/Conventions.json b/au.org.access-nri/model/output/file-metadata/2-1-0/global/Conventions.json new file mode 100644 index 0000000..4b29b77 --- /dev/null +++ b/au.org.access-nri/model/output/file-metadata/2-1-0/global/Conventions.json @@ -0,0 +1,8 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "global/Conventions.json", + "title": "Conventions", + "description": "Convention(s) used with their versions, as a comma separated list", + "examples": [ "CF-1.11,ACDD-1.3" ], + "type": "string" +} diff --git a/au.org.access-nri/model/output/file-metadata/2-1-0/global/base_configuration.json b/au.org.access-nri/model/output/file-metadata/2-1-0/global/base_configuration.json new file mode 100644 index 0000000..2e307ec --- /dev/null +++ b/au.org.access-nri/model/output/file-metadata/2-1-0/global/base_configuration.json @@ -0,0 +1,8 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "global/base_configuration.json", + "title": "base_configuration", + "description": "Configuration modified for experiment, see configs repo: https://github.com/ACCESS-NRI/access-esm1.6-configs", + "examples": [ "release-preindustrial+concentrations-2.0" ], + "type": "string" +} diff --git a/au.org.access-nri/model/output/file-metadata/2-1-0/global/contact.json b/au.org.access-nri/model/output/file-metadata/2-1-0/global/contact.json new file mode 100644 index 0000000..bd3f229 --- /dev/null +++ b/au.org.access-nri/model/output/file-metadata/2-1-0/global/contact.json @@ -0,0 +1,8 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "global/contact.json", + "title": "contact", + "description": "Email address or other contact details for who to contact regarding this data.", + "examples": [ "access.nri@anu.edu.au", "John Smith (john.smith@email.com)" ], + "type": "string" +} diff --git a/au.org.access-nri/model/output/file-metadata/2-1-0/global/data_specification.json b/au.org.access-nri/model/output/file-metadata/2-1-0/global/data_specification.json new file mode 100644 index 0000000..458d921 --- /dev/null +++ b/au.org.access-nri/model/output/file-metadata/2-1-0/global/data_specification.json @@ -0,0 +1,8 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "global/data_specification.json", + "title": "data_specification", + "description": "Version of this data specification used to generate the data", + "examples": [ "ACCESS Output Data Specification v2-1-0 XX.XXXX/zenodo.XXXXX" ], + "type": "string" +} diff --git a/au.org.access-nri/model/output/file-metadata/2-1-0/global/date_created.json b/au.org.access-nri/model/output/file-metadata/2-1-0/global/date_created.json new file mode 100644 index 0000000..399599b --- /dev/null +++ b/au.org.access-nri/model/output/file-metadata/2-1-0/global/date_created.json @@ -0,0 +1,10 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "global/date_created.json", + "title": "date_created", + "description": "Date and time the file was created. Follow ISO 8601, i.e. 'YYYY-MM-DDTHH:MM:SSZ'", + "$comment": "", + "examples": [ "2025-10-07T11:10:00Z" ], + "type": "string", + "pattern": "^\\d{4}-(1[012]|0[1-9])-(3[01]|[12][0-9]|0[1-9])T([01][0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9]Z$" +} diff --git a/au.org.access-nri/model/output/file-metadata/2-1-0/global/date_metadata_modified.json b/au.org.access-nri/model/output/file-metadata/2-1-0/global/date_metadata_modified.json new file mode 100644 index 0000000..20b8255 --- /dev/null +++ b/au.org.access-nri/model/output/file-metadata/2-1-0/global/date_metadata_modified.json @@ -0,0 +1,10 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "global/date_metadata_modified.json", + "title": "date_metadata_modified", + "description": "Date and time the metadata for this file was last modified. Note that this applied just to the metadata, not the data. Follow ISO 8601, i.e. 'YYYY-MM-DDTHH:MM:SSZ'", + "$comment": "", + "examples": [ "2025-10-07T11:10:00Z" ], + "type": "string", + "pattern": "^\\d{4}-(1[012]|0[1-9])-(3[01]|[12][0-9]|0[1-9])T([01][0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9]Z$" +} diff --git a/au.org.access-nri/model/output/file-metadata/2-1-0/global/date_modified.json b/au.org.access-nri/model/output/file-metadata/2-1-0/global/date_modified.json new file mode 100644 index 0000000..68afc46 --- /dev/null +++ b/au.org.access-nri/model/output/file-metadata/2-1-0/global/date_modified.json @@ -0,0 +1,10 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "global/date_modified.json", + "title": "date_modified", + "description": "Date and time the data for this file was last modified. Note that this applied just to the data, not the metadata. Follow ISO 8601, i.e. 'YYYY-MM-DDTHH:MM:SSZ'", + "$comment": "", + "examples": [ "2025-10-07T11:10:00Z" ], + "type": "string", + "pattern": "^\\d{4}-(1[012]|0[1-9])-(3[01]|[12][0-9]|0[1-9])T([01][0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9]Z$" +} diff --git a/au.org.access-nri/model/output/file-metadata/2-1-0/global/experiment_repo.json b/au.org.access-nri/model/output/file-metadata/2-1-0/global/experiment_repo.json new file mode 100644 index 0000000..91c2acb --- /dev/null +++ b/au.org.access-nri/model/output/file-metadata/2-1-0/global/experiment_repo.json @@ -0,0 +1,10 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "global/experiment_repo.json", + "title": "experiment_repo", + "description": "Git repository URL that describes the experiment", + "examples": [ + "https://github.com/ACCESS-Community-Hub/access-esm1.6-dev-experiments" + ], + "type": "string" +} diff --git a/au.org.access-nri/model/output/file-metadata/2-1-0/global/experiment_uuid.json b/au.org.access-nri/model/output/file-metadata/2-1-0/global/experiment_uuid.json new file mode 100644 index 0000000..0ef48f9 --- /dev/null +++ b/au.org.access-nri/model/output/file-metadata/2-1-0/global/experiment_uuid.json @@ -0,0 +1,8 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "global/experiment_uuid.json", + "title": "experiment_uuid", + "description": "The experiment UUID generated by Payu. Note: this may be the same as id.", + "examples": [ "698E600B-BECF-4CBA-994F-A663A22FCDDF" ], + "type": "string" +} diff --git a/au.org.access-nri/model/output/file-metadata/2-1-0/global/frequency.json b/au.org.access-nri/model/output/file-metadata/2-1-0/global/frequency.json new file mode 100644 index 0000000..85780d2 --- /dev/null +++ b/au.org.access-nri/model/output/file-metadata/2-1-0/global/frequency.json @@ -0,0 +1,34 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "global/frequency.json", + "title": "frequency", + "description": "Sampling frequency of the data", + "examples": [ "12hr", "1day", "1yr" ], + "type": "string", + "oneOf": [ + { + "pattern": "^fx$" + }, + { + "pattern": "^subhr$" + }, + { + "pattern": "^\\d+min$" + }, + { + "pattern": "^\\d+hr$" + }, + { + "pattern": "^\\d+day$" + }, + { + "pattern": "^\\d+mon$" + }, + { + "pattern": "^\\d+yr$" + }, + { + "pattern": "^\\d+dec$" + } + ] +} diff --git a/au.org.access-nri/model/output/file-metadata/2-1-0/global/geospatial_lat_max.json b/au.org.access-nri/model/output/file-metadata/2-1-0/global/geospatial_lat_max.json new file mode 100644 index 0000000..d9cce1a --- /dev/null +++ b/au.org.access-nri/model/output/file-metadata/2-1-0/global/geospatial_lat_max.json @@ -0,0 +1,8 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "global/geospatial_lat_max.json", + "title": "geospatial_lat_max", + "description": "Specifies the northernmost latitude covered by the dataset. Units should be \"degrees North\".", + "examples": [ 90, 12.98 ], + "type": "number" +} diff --git a/au.org.access-nri/model/output/file-metadata/2-1-0/global/geospatial_lat_min.json b/au.org.access-nri/model/output/file-metadata/2-1-0/global/geospatial_lat_min.json new file mode 100644 index 0000000..a950d73 --- /dev/null +++ b/au.org.access-nri/model/output/file-metadata/2-1-0/global/geospatial_lat_min.json @@ -0,0 +1,8 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "global/geospatial_lat_min.json", + "title": "geospatial_lat_min", + "description": "Specifies the southernmost latitude covered by the dataset. Units should be \"degrees North\".", + "examples": [ -90, -57.97 ], + "type": "number" +} diff --git a/au.org.access-nri/model/output/file-metadata/2-1-0/global/geospatial_lat_units.json b/au.org.access-nri/model/output/file-metadata/2-1-0/global/geospatial_lat_units.json new file mode 100644 index 0000000..5a9b18a --- /dev/null +++ b/au.org.access-nri/model/output/file-metadata/2-1-0/global/geospatial_lat_units.json @@ -0,0 +1,7 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "global/geospatial_lat_units.json", + "title": "geospatial_lat_units", + "description": "Units for the latitude axis described in \"geospatial_lat_min\" and \"geospatial_lat_max\" attributes. These should be \"degrees_north\".", + "const": "degrees_north" +} diff --git a/au.org.access-nri/model/output/file-metadata/2-1-0/global/geospatial_lon_max.json b/au.org.access-nri/model/output/file-metadata/2-1-0/global/geospatial_lon_max.json new file mode 100644 index 0000000..58b69e9 --- /dev/null +++ b/au.org.access-nri/model/output/file-metadata/2-1-0/global/geospatial_lon_max.json @@ -0,0 +1,8 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "global/geospatial_lon_max.json", + "title": "geospatial_lon_max", + "description": "Specifies the easternmost longitude covered by the dataset. Units should be \"degrees East\". Cases where geospatial_lon_min is greater than geospatial_lon_max indicate the bounding box extends from geospatial_lon_max, through the longitude range discontinuity meridian (e.g. the antimeridian for -180:180 values ranges) to geospatial_lon_min; for example, geospatial_lon_min=170 and geospatial_lon_max=-175 incorporates 15 degrees of longitude (ranges 170 to 180 and -180 to -175).", + "examples": [ 180, -152.61 ], + "type": "number" +} diff --git a/au.org.access-nri/model/output/file-metadata/2-1-0/global/geospatial_lon_min.json b/au.org.access-nri/model/output/file-metadata/2-1-0/global/geospatial_lon_min.json new file mode 100644 index 0000000..e028416 --- /dev/null +++ b/au.org.access-nri/model/output/file-metadata/2-1-0/global/geospatial_lon_min.json @@ -0,0 +1,8 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "global/geospatial_lon_min.json", + "title": "geospatial_lon_min", + "description": "Specifies the westernmost latitude covered by the dataset. Units should be \"degrees East\". See also geospatial_lon_max.", + "examples": [ -180, 88.48 ], + "type": "number" +} diff --git a/au.org.access-nri/model/output/file-metadata/2-1-0/global/geospatial_lon_units.json b/au.org.access-nri/model/output/file-metadata/2-1-0/global/geospatial_lon_units.json new file mode 100644 index 0000000..85cce73 --- /dev/null +++ b/au.org.access-nri/model/output/file-metadata/2-1-0/global/geospatial_lon_units.json @@ -0,0 +1,7 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "global/geospatial_lon_units.json", + "title": "geospatial_lon_units", + "description": "Units for the longitude axis described in \"geospatial_lon_min\" and \"geospatial_lon_max\" attributes. These should be \"degrees_east\".", + "const": "degrees_east" +} diff --git a/au.org.access-nri/model/output/file-metadata/2-1-0/global/grid.json b/au.org.access-nri/model/output/file-metadata/2-1-0/global/grid.json new file mode 100644 index 0000000..0c6da87 --- /dev/null +++ b/au.org.access-nri/model/output/file-metadata/2-1-0/global/grid.json @@ -0,0 +1,8 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "global/grid.json", + "title": "grid", + "description": "Brief description of output grid characteristics or reference to grid specification. Should be included if the grid is not defined by the dimensions in the file.", + "examples": [], + "type": "string" +} diff --git a/au.org.access-nri/model/output/file-metadata/2-1-0/global/license.json b/au.org.access-nri/model/output/file-metadata/2-1-0/global/license.json new file mode 100644 index 0000000..772b0b5 --- /dev/null +++ b/au.org.access-nri/model/output/file-metadata/2-1-0/global/license.json @@ -0,0 +1,8 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "global/license.json", + "title": "license", + "description": "Information on the license for the data to ensure all users have access to the terms of use. Use SPDX license identifiers where possible. The default license for ACCESS-NRI is CC-BY-4.0, users should change as needed.", + "examples": [ "CC-BY-4.0" ], + "type": "string" +} diff --git a/au.org.access-nri/model/output/file-metadata/2-1-0/global/model.json b/au.org.access-nri/model/output/file-metadata/2-1-0/global/model.json new file mode 100644 index 0000000..5f76674 --- /dev/null +++ b/au.org.access-nri/model/output/file-metadata/2-1-0/global/model.json @@ -0,0 +1,8 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "global/model.json", + "title": "model", + "description": "Name of the model used to create the data", + "examples": [ "ACCESS-ESM1.6" ], + "type": "string" +} diff --git a/au.org.access-nri/model/output/file-metadata/2-1-0/global/model_version.json b/au.org.access-nri/model/output/file-metadata/2-1-0/global/model_version.json new file mode 100644 index 0000000..e56a33b --- /dev/null +++ b/au.org.access-nri/model/output/file-metadata/2-1-0/global/model_version.json @@ -0,0 +1,12 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "global/model_version.json", + "title": "model_version", + "description": "Version of the model used to create the data. Please note here if the model has been modified from an official release, ideally with links to the changes.", + "$comment": "", + "examples": [ + "2025.06.001", + "2025.06.001 (modified by John Smith, [link to repo/paper describing modifications])" + ], + "type": "string" +} diff --git a/au.org.access-nri/model/output/file-metadata/2-1-0/global/realm.json b/au.org.access-nri/model/output/file-metadata/2-1-0/global/realm.json new file mode 100644 index 0000000..989a8d1 --- /dev/null +++ b/au.org.access-nri/model/output/file-metadata/2-1-0/global/realm.json @@ -0,0 +1,20 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "global/realm.json", + "title": "realm", + "description": "Realm where the data variable is defined", + "examples": [ "atmos", "landIce" ], + "type": "string", + "enum": [ + "aerosol", + "atmos", + "atmosChem", + "land", + "landIce", + "none", + "ocean", + "ocnBgchem", + "seaIce", + "unknown" + ] +} diff --git a/au.org.access-nri/model/output/file-metadata/2-1-0/global/run_id.json b/au.org.access-nri/model/output/file-metadata/2-1-0/global/run_id.json new file mode 100644 index 0000000..156ef63 --- /dev/null +++ b/au.org.access-nri/model/output/file-metadata/2-1-0/global/run_id.json @@ -0,0 +1,8 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "global/run_id.json", + "title": "run_id", + "description": "Git hash for the commit associated with the experiment run", + "examples": [ "3a38fe4", "3a38fe435e156700ab649c4921e99f7c68a168bc" ], + "type": "string" +} diff --git a/au.org.access-nri/model/output/file-metadata/2-1-0/global/title.json b/au.org.access-nri/model/output/file-metadata/2-1-0/global/title.json new file mode 100644 index 0000000..e53ddaa --- /dev/null +++ b/au.org.access-nri/model/output/file-metadata/2-1-0/global/title.json @@ -0,0 +1,8 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "global/title.json", + "title": "title", + "description": "Name of the dataset. Typically following the Payu naming scheme detailed here - https://payu.readthedocs.io/en/stable/usage.html#experiment-names", + "examples": [ "my_expt-perturb-416af8c6" ], + "type": "string" +} diff --git a/au.org.access-nri/model/output/file-metadata/2-1-0/global/variable_id.json b/au.org.access-nri/model/output/file-metadata/2-1-0/global/variable_id.json new file mode 100644 index 0000000..cf3cbaf --- /dev/null +++ b/au.org.access-nri/model/output/file-metadata/2-1-0/global/variable_id.json @@ -0,0 +1,8 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "global/variable_id.json", + "title": "variable_id", + "description": "A list of short variable names, separated by commas, for the data variable/s that appear in this file (e.g. tas for surface temperature but not time/latitude/longitude). These names should match the netCDF variable names.", + "examples": [ "tas", "huss", "uas,vas" ], + "type": "string" +} diff --git a/au.org.access-nri/model/output/file-metadata/2-1-0/variable.json b/au.org.access-nri/model/output/file-metadata/2-1-0/variable.json new file mode 100644 index 0000000..f1de758 --- /dev/null +++ b/au.org.access-nri/model/output/file-metadata/2-1-0/variable.json @@ -0,0 +1,21 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "variable.json", + "title": "Output variable", + "description": "A coordinate or data output variable", + "type": "object", + "properties": { + "cell_methods": { + "$ref": "variable/cell_methods.json" + }, + "long_name": { + "$ref": "variable/long_name.json" + }, + "standard_name": { + "$ref": "variable/standard_name.json" + }, + "units": { + "$ref": "variable/units.json" + } + } +} diff --git a/au.org.access-nri/model/output/file-metadata/2-1-0/variable/cell_methods.json b/au.org.access-nri/model/output/file-metadata/2-1-0/variable/cell_methods.json new file mode 100644 index 0000000..c2d8078 --- /dev/null +++ b/au.org.access-nri/model/output/file-metadata/2-1-0/variable/cell_methods.json @@ -0,0 +1,12 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "variable/cell_methods.json", + "title": "cell_methods", + "description": "A string comprising a list of space-separated pairs, \"name:method\", which indicate that for axis \"name\" the values representing the fields have been determined by \"method\".", + "examples": [ + "time: point", + "time: mean (interval: 1 hour)", + "time: maximum (interval: 1D) time: mean (interval: 1M)" + ], + "type": "string" +} diff --git a/au.org.access-nri/model/output/file-metadata/2-1-0/variable/long_name.json b/au.org.access-nri/model/output/file-metadata/2-1-0/variable/long_name.json new file mode 100644 index 0000000..b07ce4e --- /dev/null +++ b/au.org.access-nri/model/output/file-metadata/2-1-0/variable/long_name.json @@ -0,0 +1,12 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "variable/long_name.json", + "title": "long_name", + "description": "A long descriptive name which may, for example, be used for labelling plots.", + "examples": [ + "Near-Surface Air Temperature", + "latitude", + "Potential Evapotranspiration" + ], + "type": "string" +} diff --git a/au.org.access-nri/model/output/file-metadata/2-1-0/variable/standard_name.json b/au.org.access-nri/model/output/file-metadata/2-1-0/variable/standard_name.json new file mode 100644 index 0000000..aacee36 --- /dev/null +++ b/au.org.access-nri/model/output/file-metadata/2-1-0/variable/standard_name.json @@ -0,0 +1,12 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "variable/standard_name.json", + "title": "standard_name", + "description": "Where possible use the CF standard_name of the variable, otherwise use a unique short phrase separated by underscores to describe the variable.", + "examples": [ + "air_pressure_at_sea_level", + "latitude", + "water_potential_evaporation_flux" + ], + "type": "string" +} diff --git a/au.org.access-nri/model/output/file-metadata/2-1-0/variable/time.json b/au.org.access-nri/model/output/file-metadata/2-1-0/variable/time.json new file mode 100644 index 0000000..4fc45c1 --- /dev/null +++ b/au.org.access-nri/model/output/file-metadata/2-1-0/variable/time.json @@ -0,0 +1,29 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "variable/time.json", + "title": "time", + "description": "The time variable for the dataset.", + "type": "object", + "required": [ "axis", "calendar", "long_name", "standard_name", "units" ], + "properties": { + "axis": { + "const": "T" + }, + "bounds": { + "const": "time_bnds" + }, + "calendar": { + "$ref": "time/calendar.json" + }, + "long_name": { + "const": "time" + }, + "standard_name": { + "const": "time" + }, + "units": { + "$ref": "time/units.json" + } + }, + "additionalProperties": false +} diff --git a/au.org.access-nri/model/output/file-metadata/2-1-0/variable/time/calendar.json b/au.org.access-nri/model/output/file-metadata/2-1-0/variable/time/calendar.json new file mode 100644 index 0000000..0109b53 --- /dev/null +++ b/au.org.access-nri/model/output/file-metadata/2-1-0/variable/time/calendar.json @@ -0,0 +1,19 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "variable/time/calendar.json", + "title": "calendar", + "description": "Calendar defines the set of valid datetimes and their order. Follows the CF-Convention names using lower-case strings. It is recommended that \"proleptic_gregorian\" is used for data with leap days and \"no_leap\"/\"365_day\" for data without leap days.", + "type": "string", + "enum": [ + "standard", + "julian", + "proleptic_gregorian", + "no_leap", + "365_day", + "all_leap", + "366_day", + "360_day", + "utc", + "tai" + ] +} diff --git a/au.org.access-nri/model/output/file-metadata/2-1-0/variable/time/units.json b/au.org.access-nri/model/output/file-metadata/2-1-0/variable/time/units.json new file mode 100644 index 0000000..a358c57 --- /dev/null +++ b/au.org.access-nri/model/output/file-metadata/2-1-0/variable/time/units.json @@ -0,0 +1,14 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "variable/time/units.json", + "title": "units", + "description": "Units for time should be given as \"days since X\" where X is a date (yyyy-mm-dd) or a datetime (yyyy-mm-dd HH:MM or yyyy-mm-dd HH:MM:SS)", + "examples": [ + "days since 0001-01-01 00:00:00", + "days since 0001-01-01 00:00", + "days since 1970-01-01", + "days since -5000-12-25" + ], + "type": "string", + "pattern": "^days since -?\\d{4}-(1[012]|0[1-9])-(3[01]|[12][0-9]|0[1-9])( ([01][0-9]|2[0-3]):[0-5][0-9](:[0-5][0-9])?)?$" +} diff --git a/au.org.access-nri/model/output/file-metadata/2-1-0/variable/time_bnds.json b/au.org.access-nri/model/output/file-metadata/2-1-0/variable/time_bnds.json new file mode 100644 index 0000000..41147fd --- /dev/null +++ b/au.org.access-nri/model/output/file-metadata/2-1-0/variable/time_bnds.json @@ -0,0 +1,7 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "variable/time_bnds.json", + "title": "time_bnds", + "description": "The time_bnds variable for the dataset. Note this variable has no attributes.", + "const": {} +} diff --git a/au.org.access-nri/model/output/file-metadata/2-1-0/variable/units.json b/au.org.access-nri/model/output/file-metadata/2-1-0/variable/units.json new file mode 100644 index 0000000..68f64ef --- /dev/null +++ b/au.org.access-nri/model/output/file-metadata/2-1-0/variable/units.json @@ -0,0 +1,8 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "variable/units.json", + "title": "units", + "description": "The units of measurement for the variable", + "examples": [ "K", "m-2 s-1" ], + "type": "string" +} diff --git a/tests/2-1-0/global/test_geospatial_lat_max.json b/tests/2-1-0/global/test_geospatial_lat_max.json new file mode 100644 index 0000000..7cc5aeb --- /dev/null +++ b/tests/2-1-0/global/test_geospatial_lat_max.json @@ -0,0 +1,25 @@ +{ + "target": "../../../au.org.access-nri/model/output/file-metadata/2-1-0/global/geospatial_lat_max.json", + "tests": [ + { + "description": "Valid lat_max - -90", + "valid": true, + "data": -90 + }, + { + "description": "Valid lat_max - 90", + "valid": true, + "data": 90 + }, + { + "description": "Valid lat_max - explicit float", + "valid": true, + "data": 12.3456 + }, + { + "description": "Invalid lat_max - string", + "valid": false, + "data": "-90" + } + ] +} diff --git a/tests/2-1-0/global/test_geospatial_lat_min.json b/tests/2-1-0/global/test_geospatial_lat_min.json new file mode 100644 index 0000000..b2417d4 --- /dev/null +++ b/tests/2-1-0/global/test_geospatial_lat_min.json @@ -0,0 +1,25 @@ +{ + "target": "../../../au.org.access-nri/model/output/file-metadata/2-1-0/global/geospatial_lat_min.json", + "tests": [ + { + "description": "Valid lat_min - -90", + "valid": true, + "data": -90 + }, + { + "description": "Valid lat_min - 90", + "valid": true, + "data": 90 + }, + { + "description": "Valid lat_min - explicit float", + "valid": true, + "data": 12.3456 + }, + { + "description": "Invalid lat_min - string", + "valid": false, + "data": "-90" + } + ] +} diff --git a/tests/2-1-0/global/test_geospatial_lon_max.json b/tests/2-1-0/global/test_geospatial_lon_max.json new file mode 100644 index 0000000..746a956 --- /dev/null +++ b/tests/2-1-0/global/test_geospatial_lon_max.json @@ -0,0 +1,25 @@ +{ + "target": "../../../au.org.access-nri/model/output/file-metadata/2-1-0/global/geospatial_lon_max.json", + "tests": [ + { + "description": "Valid lon_max - -180", + "valid": true, + "data": -180 + }, + { + "description": "Valid lon_max - 180", + "valid": true, + "data": 180 + }, + { + "description": "Valid lon_max - explicit float", + "valid": true, + "data": 12.3456 + }, + { + "description": "Invalid lon_max - string", + "valid": false, + "data": "-90" + } + ] +} diff --git a/tests/2-1-0/global/test_geospatial_lon_min.json b/tests/2-1-0/global/test_geospatial_lon_min.json new file mode 100644 index 0000000..2956ee3 --- /dev/null +++ b/tests/2-1-0/global/test_geospatial_lon_min.json @@ -0,0 +1,25 @@ +{ + "target": "../../../au.org.access-nri/model/output/file-metadata/2-1-0/global/geospatial_lon_min.json", + "tests": [ + { + "description": "Valid lon_min - -180", + "valid": true, + "data": -180 + }, + { + "description": "Valid lon_min - 180", + "valid": true, + "data": 180 + }, + { + "description": "Valid lon_min - explicit float", + "valid": true, + "data": 12.3456 + }, + { + "description": "Invalid lon_min - string", + "valid": false, + "data": "-90" + } + ] +} diff --git a/tests/2-1-0/test.json b/tests/2-1-0/test.json new file mode 100644 index 0000000..4f99a82 --- /dev/null +++ b/tests/2-1-0/test.json @@ -0,0 +1,67 @@ +{ + "target": "../../au.org.access-nri/model/output/file-metadata/2-1-0/2-1-0.json", + "tests": [ + { + "description": "Full ESM1.6", + "valid": true, + "data": { + "global": { + "base_configuration": "release-preindustrial+concentrations-2.0", + "contact": "data.access.nri@anu.edu.au", + "Conventions": "CF-1.11", + "date_created": "2025-12-03T11:22:00Z", + "data_specification": "ACCESS Output Data Specification v0.1 XX.XXXX/zenodo.XXXXX", + "experiment_repo": "x", + "experiment_uuid": "F6B536FA-766D-4609-B767-754C9424440A", + "id": "F6B536FA-766D-4609-B767-754C9424440A", + "frequency": "1hr", + "grid": "grid goes here", + "geospatial_lat_min": -90, + "geospatial_lat_max": 90, + "geospatial_lat_units": "degrees_north", + "geospatial_lon_min": -180, + "geospatial_lon_max": 180, + "geospatial_lon_units": "degrees_east", + "license": "CC-BY-4.0", + "model_version": "2025.06.001", + "model": "ACCESS-ESM1.6", + "naming_authority": "au.org.access-nri", + "realm": "atmos", + "run_id": "00b0e8d102733a0e36093a96b273ed2853ac2006", + "title": "this is a title", + "variable_id": "tas" + }, + "variables": { + "tas": { + "units": "K", + "long_name": "Near-surface Air Temperature", + "standard_name": "air_temperature", + "cell_methods": "time: point (interval: 1H) time: mean (interval: 1M)", + "_FillValue": -2147483647 + }, + "lat": { + "_FillValue": 1.0e+20, + "standard_name": "latitude", + "units": "degrees_north", + "long_name": "latitude" + }, + "time": { + "axis": "T", + "bounds": "time_bnds", + "calendar": "proleptic_gregorian", + "long_name": "time", + "standard_name": "time", + "units": "days since 0001-01-01 00:00" + }, + "time_bnds": { + } + } + } + }, + { + "description": "Empty", + "valid": false, + "data": {} + } + ] +} diff --git a/tests/2-1-0/test_global.json b/tests/2-1-0/test_global.json new file mode 100644 index 0000000..d57314d --- /dev/null +++ b/tests/2-1-0/test_global.json @@ -0,0 +1,64 @@ +{ + "target": "../../au.org.access-nri/model/output/file-metadata/2-1-0/global.json", + "tests": [ + { + "description": "Valid global attrs", + "valid": true, + "data": { + "base_configuration": "release-preindustrial+concentrations-2.0", + "contact": "data.access.nri@anu.edu.au", + "Conventions": "CF-1.11", + "date_created": "2025-12-03T11:22:00Z", + "data_specification": "ACCESS Output Data Specification v0.1 XX.XXXX/zenodo.XXXXX", + "experiment_repo": "x", + "experiment_uuid": "F6B536FA-766D-4609-B767-754C9424440A", + "id": "F6B536FA-766D-4609-B767-754C9424440A", + "frequency": "1hr", + "grid": "grid goes here", + "geospatial_lat_min": -90, + "geospatial_lat_max": 90, + "geospatial_lat_units": "degrees_north", + "geospatial_lon_min": -180, + "geospatial_lon_max": 180, + "geospatial_lon_units": "degrees_east", + "license": "CC-BY-4.0", + "model_version": "2025.06.001", + "model": "ACCESS-ESM1.6", + "naming_authority": "au.org.access-nri", + "realm": "atmos", + "run_id": "00b0e8d102733a0e36093a96b273ed2853ac2006", + "title": "this is a title", + "variable_id": "tas" + } + }, + { + "description": "Invalid global - missing required 'frequency'", + "valid": false, + "data": { + "base_configuration": "release-preindustrial+concentrations-2.0", + "contact": "data.access.nri@anu.edu.au", + "Conventions": "CF-1.11", + "date_created": "2025-12-03T11:22:00Z", + "data_specification": "ACCESS Output Data Specification v0.1 XX.XXXX/zenodo.XXXXX", + "experiment_repo": "x", + "experiment_uuid": "F6B536FA-766D-4609-B767-754C9424440A", + "id": "F6B536FA-766D-4609-B767-754C9424440A", + "grid": "grid goes here", + "geospatial_lat_min": -90, + "geospatial_lat_max": 90, + "geospatial_lat_units": "degrees_north", + "geospatial_lon_min": -180, + "geospatial_lon_max": 180, + "geospatial_lon_units": "degrees_east", + "license": "CC-BY-4.0", + "model_version": "2025.06.001", + "model": "ACCESS-ESM1.6", + "naming_authority": "au.org.access-nri", + "realm": "atmos", + "run_id": "00b0e8d102733a0e36093a96b273ed2853ac2006", + "title": "this is a title", + "variable_id": "tas" + } + } + ] +} diff --git a/tests/2-1-0/variable/test_time.json b/tests/2-1-0/variable/test_time.json new file mode 100644 index 0000000..0b8b407 --- /dev/null +++ b/tests/2-1-0/variable/test_time.json @@ -0,0 +1,51 @@ +{ + "target": "../../../au.org.access-nri/model/output/file-metadata/2-1-0/variable/time.json", + "tests": [ + { + "description": "Full valid time variable", + "valid": true, + "data": { + "axis": "T", + "bounds": "time_bnds", + "calendar": "proleptic_gregorian", + "long_name": "time", + "standard_name": "time", + "units": "days since 0000-01-01" + } + }, + { + "description": "Full valid time variable without bounds", + "valid": true, + "data": { + "axis": "T", + "calendar": "proleptic_gregorian", + "long_name": "time", + "standard_name": "time", + "units": "days since 0000-01-01" + } + }, + { + "description": "Missing required (long_name)", + "valid": false, + "data": { + "axis": "T", + "bounds": "time_bnds", + "calendar": "proleptic_gregorian", + "standard_name": "time", + "units": "days since 0000-01-01" + } + }, + { + "description": "Const doesn't match", + "valid": false, + "data": { + "axis": "T", + "bounds": "time_bounds", + "calendar": "proleptic_gregorian", + "long_name": "time", + "standard_name": "time", + "units": "days since 0000-01-01" + } + } + ] +} diff --git a/tests/2-1-0/variable/time/test_calendar.json b/tests/2-1-0/variable/time/test_calendar.json new file mode 100644 index 0000000..c011919 --- /dev/null +++ b/tests/2-1-0/variable/time/test_calendar.json @@ -0,0 +1,25 @@ +{ + "target": "../../../../au.org.access-nri/model/output/file-metadata/2-1-0/variable/time/calendar.json", + "tests": [ + { + "description": "Valid calendar", + "valid": true, + "data": "proleptic_gregorian" + }, + { + "description": "Valid calendar but capitalised", + "valid": false, + "data": "PROLEPTIC_GREGORIAN" + }, + { + "description": "Invalid calendar", + "valid": false, + "data": "invalid_calendar" + }, + { + "description": "Not even a string", + "valid": false, + "data": 6 + } + ] +} diff --git a/tests/2-1-0/variable/time/test_units.json b/tests/2-1-0/variable/time/test_units.json new file mode 100644 index 0000000..0a202d9 --- /dev/null +++ b/tests/2-1-0/variable/time/test_units.json @@ -0,0 +1,40 @@ +{ + "target": "../../../../au.org.access-nri/model/output/file-metadata/2-1-0/variable/time/units.json", + "tests": [ + { + "description": "Valid units for time", + "valid": true, + "data": "days since 0001-01-01 00:00:00" + }, + { + "description": "Valid units for time - no seconds", + "valid": true, + "data": "days since 0001-01-01 00:00" + }, + { + "description": "Valid units for time - no time", + "valid": true, + "data": "days since 0001-01-01" + }, + { + "description": "Invalid units for time - not real time", + "valid": false, + "data": "days since 0001-01-01 00:00:61" + }, + { + "description": "Invalid units for time - not days", + "valid": false, + "data": "seconds since 0001-01-01 00:00:00" + }, + { + "description": "Invalid units for time", + "valid": false, + "data": "not even close to valid" + }, + { + "description": "Invalid units for time - not a string", + "valid": false, + "data": 5 + } + ] +}