- Versioning of the model output NOT ONLY applies to changes in the computational logic of the model, but also to input parameters, calibration or setup.
- Special cases:
- If you are running a different version of an existing model, we recommend you agree on a naming convention with the authors of the first version. You could, for example, name your model [model-name]-[institution-acronym], but if you are using different input data, you could name it [model-name]-[settings-identifier]
- If you develop further versions of your own model, the names of these versions should be distinguishable. For example, you can use a simple version numbering (e.g., MODEL-v1, MODEL-v2 ), follow a semantic versioning (e.g., MODEL-2.0.0, for version 2.0.0), or use the year of application of the model (e.g., MODEL-2020)
- If you are using the same model version but producing different outputs by using different input parameters, calibration or setup, we need to be able to distinguish such outputs; see notes for ISIMIP3 and water regional data below
- If you have any doubt, please contact our data management team.
Note for ISIMIP3 round:
- To ensure consistency between ISIMIP3a and ISIMIP3b, as well as between the different experiments within a simulation round, we require that modelling groups use the same version of an impact model for the experiments in ISIMIP3a and ISIMIP3b. If you cannot fulfill this, please indicate that by using a suffix for your model name: use a simple version numbering or semantic versioning. If model versions are not reported, we will name them according to the simulation round; e.g., MODEL-isimip3a.
- We require strict versioning to ensure that differences between model results are fully attributable to the changes in model forcings.
- If possible, indicate the data set in the ISIMIP2b run with the the corresponding consistent calibration within the metadata of your ISIMIP3 files (as global attribute).
Note for water regional models:
- As different basins use different calibrations, we only need consistency per basin. This means, regardless of what produces your new calibration of a same basin (e.g., different climate input data used for calibration), the only way to keep both files available is to upload the new files under a new model output name.
- The different calibrations (basin, climate forcing for calibration, target variables and method) should be described in the model documentation website and also uploaded in a file under “Attachments”.
- Indicate which data set was used for calibration as a global attribute (called “calibration-data”) in the metadata of your NetCDF files.
We developed a quality checking tool that will allow us to test your newly generated files against the definitions, patterns and schemas from our machine-readable protocols for ISIMIP2 and ISIMIP3.
The tool is ready to work on Windows, MacOS and Linux machines with Python>=3.7 installed. You can find install and usage instructions on its GitHub page: https://github.com/ISI-MIP/isimip-qc
Applying the tool to your own files before submitting them to DKRZ could lower the chance of time-consuming email conversations about inconsistencies in the submitted NetCDF files. However, if you are not able to use this tool, our data management team will of course proceed as before.
The tool mainly checks for proper NetCDF headers including the dimension variables, the data variable, requested global attributes, and the number of time steps to be consistent with the specifiers given in the file name. The tool is not able to fix wrong data types of variables.
For the ISIMIP3 round, this tool will soon also test whether all values of a variable are valid, based on valid-value ranges that still need to be added to the ISIMIP3 protocol.
The tool has already been tested on a substantial part of ISIMIP2b data, but if you experience crashes or unexpected behavior, please let us know by filing an issue on the GitHub page or writing an email to isimip-data@pik-potsdam.de.
A demo script for using the tool is here.
Our data management team runs a series of checks that identify severe and fixable errors, and correct files with fixable (non-severe) errors. This is the summary of quality checks performed:
- NetCDF format: NetCDF4 Classic ZIP and .nc4 or .nc extension (depending on simulation round)
- File name: lower case, correct model and scenario names (severe), gcm/climate_driver/social_scenario/co2_scenario combinations according to protocol
- Variable: same file name and NetCDF variable name (severe), units according to protocol, only one variable per submitted file (severe; with some exceptions)
- Grid: names and units of grid coordinates, grid type, grid increments, grid mask (severe), missing_value, _FillValue, _ChunkSizes (only for global data)
- Time axis: name of time dimension (severe), time units, time increment (severe), reference date, number of time steps (severe), start and end year in agreement to simulation period and file name (severe)
- Global metadata: contact and institution, and metadata for variables with varying depth layers (when it applies)
- gcm/climate_driver/social_scenario/co2_scenario combinations.
The QC process produces a report of the checks and fixes performed. Modelers can consult this report (and log files) at the DKRZ folder: /work/bb0820/ISIMIP/[SIMULATION-ROUND]/UploadArea/[SECTOR]/[MODEL]/_qc_reports/ . Non-severe issues will be fixed by the data managers, but all others will need your assistance. Please check this folder on a regular basis and get in touch with our data management team at isimip-data@pik-potsdam.de to discuss fixes on the files.
Files that successfully pass the Quality Checks will appear in the Output folder: /work/bb0820/ISIMIP/[SIMULATION-ROUND]/OutputData. Such files will be available to all ISIMIP participants.
Files should be provided in compressed NetCDF format, a self-describing, machine-independent data format that support the creation, access, and sharing of array-oriented scientific data. It can be read/written/processed for example by:
- ncdump (inspecting NetCDF headers and raw data), belonging to NetCDF software.
- ncview (simple data exploration and graphics).
- Command line tools, e.g. Climate Data Operators (CDO) (Help), netCDF Operator (NCO) and UVCDAT: show, convert, split, merge, write and perform arithmetic and statistical operations on NetCDF data.
- Command line graphics, e.g UVCDAT and R.
- Other applications and programming language modules, e.g. Python, Matlab, Ferret, Panoply and many more.
In this section you will find the general formatting specifications that your submitted files should follow, in terms of: File naming, Format, Grid, Simulation periods, Global attributes, Variables and dimensions, Time axis, Temporal resolution
Some formatting issues have easy solutions –like wrong chunk sizes, wrong NetCDF format, inverted grid, or wrong variable and dimension names–, please check our easy fixes within every subsection. For further instructions, please give a look at the NetCDF utilities mentioned above.
Standard NetCDF header
A proper NetCDF header for daily global data, shown with ncdump -h FILE should look like this:
dimensions:
lon = 720 ;
lat = 360 ;
time = UNLIMITED ;
variables:
double lon(lon) ;
lon:standard_name = "longitude" ;
lon:long_name = "Longitude" ;
lon:units = "degrees_east" ;
lon:axis = "X" ;
double lat(lat) ;
lat:standard_name = "latitude" ;
lat:long_name = "Latitude" ;
lat:units = "degrees_north" ;
lat:axis = "Y" ;
double time(time) ;
time:standard_name = "time" ;
lat:long_name = "Time" ;
time:units = "days since 1661-01-01 00:00:00" ;
time:calendar = "proleptic_gregorian" ;
time:axis = "T" ;
float tas(time, lat, lon) ;
tas:_FillValue = 1.e+20f ;
tas:missing_value = 1.e+20f ;
tas:units = “K" ;
tas:standard_name = "air_temperature" ;
tas:long_name = “Near-Surface Air Temperature" ;
// global attributes:
:contact = "ISIMIP Coordination Team <info@isimip.org>";
:institution = "Potsdam-Institute for Climate Impact Research (PIK)";
:comment = "Data prepared for ISIMIP2b" ;
File naming
Within every protocol there is a section dedicated to the conventions on file naming, which applies to all sectors.
File names consist of a series of identifiers, separated by underscores. Identifiers depend on the simulation round, temporal resolution and may be dependent on the sector (see details below).
- Report one variable per file (there are few exceptions, see below).
- In filenames, use lowercase letters only.
- Use underscore (“_”) to separate identifiers.
- Use hyphens (”-“) to separate strings within an identifier, e.g. in a model or in a variable's name.
- NetCDF file extension is .nc4 (for simulations belonging to ISIMIP3a/b, extension is .nc).
- Use only the combinations of scenarios specified in the protocols.
- Start and end years should correspond to reporting period and temporal resolution (different for global and local simulations).
In general, file names should follow this convention:
<model-name>_<gcm/observations>_<bias-correction>_<climate-scenario>_<socio-econ-scenario>_<sens-scenarios>_<variable>_<region>_<timestep>_<start-year>_<end-year>.nc4
Here you'll find example file names for the biomes and global water sector.
Format
You can check a file's format with command "cdo showformat FILE".
- Gridded NetCDF4 classic internally zipped.
- If internal compression is not possible, deliver unzipped files.
Easy fix of NetCDF format
nccopy -k4 -d5 IFILE OFILE
Grid
- Global grid ranges 89.75 to -89.75° latitude, and ‐179.75 to 179.75° longitude, i.e. 0.5° grid spacing, 360 rows and 720 columns, or 259200 grid cells total (corresponding to the resolution of the climate input data).
- Please report the output data row-wise starting at 89.75 and -179.75, and ending at -89.75 and 179.75.
- Reporting intervals are 0.5 degrees_east for longitude, and -0.5 degrees_north for latitude.
- Submitting data at lower resolution than 0.5x0.5 degrees is only encouraged in exceptional cases.
- Regional data has specific grid requirements (see below).
- CDO gridtype should be lonlat (not generic). This requires the longitude and latitude variable and dimension to be named 'lon' and 'lat'.
- Grid points you do not simulate should be filled with the missing_value and _FillValue marker (1.e+20f).
Easy fix of inverted gid, i.e. to reverse the latitude index
cdo -s invertlat IFILE OFILE
Variables and dimensions
Please note that regional data, multidimensional data, variables with fixed levels (depth layers) and variables with varying levels have additional specifications.
- Every dimension should have an associated coordinate variable
- Precision of output variable is float
- Precision of lon, lat and time should be double
- First dimension should always be time
- Identifier of dimensions and variables are all lowercase without spaces
- For internal name of dimensions (coordinate variables), standard_name, long_name, unit and axis follow the conventions in the table below – the long_name definitions are not critical for the dimensions, but will give us warnings during the format checks.
Easy fix of output variable name:
This implies changing the name of the output variable from VAROLD to VARNEW:
ncrename -O -h -v VAROLD,VARNEW IFILE
Easy fix of dimension name:
This implies changing both the name of the dimension (from DIMOLD to DIMNEW) and coordinate variable (from DIMNAMEOLD to DIMNAMENEW):
ncrename -O -h -d DIMOLD,DIMNEW -v DIMNAMEOLD,DIMNAMENEW IFILE
Note on simulation periods:
Some input data for ISIMIP3a has been taken from ISIMIP2a and is in the process of being extended. Please contact us if you have any doubts.
Chunk sizes
NetCDF4 internally chunks the data into subsets. Usually one chunk is defined by a record, i.e. a combination of one horizontal field at one time step and one vertical layer. Chunking the data differently makes operations on the data extremely more time consuming. More info here.
You can check the chunk sizes with command "ncdump -hs FILE".
- For global 2d data:
variable:_ChunkSizes = 1, 360, 720 ; - For global 3d data (in this case, assuming 10 vertical layers):
variable:_ChunkSizes = 1, 10, 360, 720 ;
also accepted:
variable:_ChunkSizes = 1, 1, 360, 720 ;
Easy fix of chunk sizes
If your file does not have correct chunk sizes, try rewriting the data with:
2d: nccopy -k4 -d5 -c "time/1,lat/360,lon/720" IFILE OFILE
3d: nccopy -k4 -d5 -c "time/1,depth/10,lat/360,lon/720" IFILE OFILE or
3d: nccopy -k4 -d5 -c "time/1,depth/1,lat/360,lon/720" IFILE OFILE
In some cases, when all dimensions are set as contiguous, the commands above might not work. In those cases, try:
cdo -f nc4c -z zip -copy IFILE OFILE
In some sectors, a same simulation must be reported for several locations or disaggregated into different cohorts. In such cases, please explain in the online model documentation; contact the ISIMIP coordination team in case of questions.
- If data are disaggregated e.g. by age group, gender, etc., they should be reported as additional dimensions in the NetCDF files. The meaning of these dimensions should be explained in a comment attribute.
- If data are reported for a limited number of locations (cities/regions/countries), then these should be indicated through the <region> specifier in the file name and each location is reported in an individual file.
- If data are reported for more than ~20 locations, then the <region> specifier in the file name should either be “global”, or indicate a world region or country; the individual locations should be reported as additional dimensions in the NetCDF files. The meaning of these dimensions should be explained in a comment attribute.
For variables with fixed levels (e.g. layers whose depths do not change over time nor over space), we require the following:
- In every level, the data for the simulated variable indicates the midpoint or layer-accumulated data or data linked to a certain class (e.g. dbh_class)
- The levels are contained in a level dimension and has a specific name per sector: levlak for the lakes sector, lev for the water regional sector or dbh_class for forestry models.
- This dimension depends on a level variable with the same name, e.g. depth(depth).
- The simulated variable depends on the level dimension as well; e.g. soilmoist(time, lev, lat, lon).
- The level variable data type is float.
- The specifications of every level (e.g. within depth) should be indicated either in metric units (preferred; see NetCDF header example below) or online within a model's documentation or within the NetCDF file as a comment within the level dimension's attributes.
- If you want to introduce lower and upper boundaries to every level, you should also introduce an additional boundaries dimension (e.g. depth_bnds) and an index (bnds), and in this case the following applies:
- the lower and upper boundaries of every layer are specified within depth_bnds
- depth_bnds data type is float
- depth_bnds depends on the level dimension and on bnds; e.g. depth_bnds(lev, bnds)
- bnds contains two entries, and what each entry indicates should be specified either in units, or within the comments of dimension depth_bnds; e.g. depth_bnds:comment = "bnds=0 for the top of the layer, and bnds=1 for the bottom of the layer"
- To reduce the size of these files, store them in netcdf4_classic format and compress the data with zip level 9 (try command: ncks -7 -L 9 IFILE OFILE). For more info, check http://nco.sourceforge.net/nco.html#Compression and http://nco.sourceforge.net/nco.html#File-Formats-and-Conversion.
Specific uses:
- As the global and local lakes models use several setups of vertical layer definitions within the same sector they are asked to always define a unitless vertical dimension "levlak" as an index for the layers. "depth" variable is then defined dependent on levlak only, i.e. depth(levlak)
- For variables where it is possible to have layers or not (e.g. variable “harv” in Foresty Models), add global attribute dbhclass_profile and use label "true" if the file contains layers (e.g. multiple dbh classes) or "false" depending on the case.
Example NetCDF header for variables with globally and temporary fixed levels (except lakes sector)
A proper NetCDF header printed with "ncdump -h FILE" of a variable with fixed depth layers.
Lines with a trailing triple asterisk indicate the optional usage of layer boundaries.
dimensions:
lon = 720 ;
lat = 360 ;
time = UNLIMITED ; // (2400 currently)
depth = 5 ;
bnds = 2 ;
variables:
double lon(lon) ;
lon:long_name = "longitude" ;
lon:units = "degrees_east" ;
lon:standard_name = "Longitude" ;
lon:axis = "X";
double lat(lat) ;
lat:long_name = "latitude" ;
lat:units = "degrees_north" ;
lat:standard_name = "Latitude" ;
lat:axis = "Y";
double time(time) ;
time:units = "days since 1661-01-01" ;
time:calendar = "proleptic_gregorian" ;
time:standard_name = "time";
time:long_name = "Time";
time:axis = "T";
float depth(depth) ;
depth:units = "m" ;
depth:bounds = "depth_bnds" ;
depth:standard_name = "depth_below_surface" ;
depth:long_name = "Depth of Vertical Layer Center Below Surface" ;
depth:positive = "down" ;
depth:axis = "Z" ;
float depth_bnds(depth, bnds) ;
depth_bnds:units = "m" ;
float soilmoist(time, depth, lat, lon) ;
soilmoist:standard_name = "soilmoist" ;
soilmoist:long_name = "Total Soil Moisture Content" ;
soilmoist:units = "kg m-2" ;
soilmoist:_FillValue = 1.e+20f ;
soilmoist:missing_value = 1.e+20f ;
// global attributes:
:contact = "Name <email@place.com>";
:institution = "Institution of Affiliation (ACRONYM)" ;
:comment = "Data prepared for ISIMIP2b" ;
dimensions:
lon = 720 ;
lat = 360 ;
time = UNLIMITED ;
levlak = 20 ;
bnds = 2 ;
variables:
double lon(lon) ;
lon:long_name = "longitude" ;
lon:units = "degrees_east" ;
lon:standard_name = "Longitude" ;
lon:axis = "X";
double lat(lat) ;
lat:long_name = "latitude" ;
lat:units = "degrees_north" ;
lat:standard_name = "Latitude" ;
lat:axis = "Y";
double time(time) ;
time:units = "days since 1661-01-01" ;
time:calendar = "proleptic_gregorian" ;
time:standard_name = "time";
time:long_name = "Time";
time:axis = "T";
float levlak(levlak) ;
levlak:long_name = "Vertical Water Layer Index" ;
levlak:standard_name = "water_layer" ;
levlak:units = "-" ;
levlak:positive = "down" ;
levlak:axis = "Z" ;
float bnds(bnds) ;
bnds:positive = "down" ;
float depth_bnds(time, bnds, levlak, lat, lon) ;
depth_bnds:standard_name = "depth_bounds" ;
depth_bnds:long_name = "Depth of Layer\'s Top and Bottom Below Surface" ;
depth_bnds:units = "1" ;
depth_bnds:positive = "down" ;
depth_bnds:comment = "bnds=0 for the top of the layer, and bnds=1 for the bottom of the layer" ;
float depth(levlak) ;
depth:standard_name = "depth_below_surface" ;
depth:long_name = "Depth of Vertical Layer Center Below Surface" ;
depth:units = "m" ;
depth:positive = "down" ;
depth:axis = "Z" ;
depth:bounds = "depth_bnds" ;
float watertemp(time, levlak, lat, lon) ;
watertemp:standard_name = "watertemp" ;
watertemp:long_name = "Temperature of Lake Water" ;
watertemp:units = "K" ;
watertemp:_FillValue = 1.e+20f ;
watertemp:missing_value = 1.e+20f ;
// global attributes:
:contact = "Name <email@place.com>";
:institution = "Institution of Affiliation (ACRONYM)" ;
:comment = "Data prepared for ISIMIP3b" ;
For variables with a fixed number of vertical layers that vary over time and/or over space (e.g. layers that can get deeper or shallower over time or have different depths at different locations), we request the following additional attributes:
- In every level, the data for the simulated variable indicates the midpoint or layer-accumulated data
- The simulated variable depends on a level-index variable introducing an equally named dimension (e.g. "lev" or "levlak") and a "depth" variable depending on this dimension and the geographical coordinates or time plus the geographical coordinates, i.e.
- depth(lev,lat,lon) or depth(levlak,lat,lon) or
- depth(time,lev,lat,lon) or depth(time,levlak,lat,lon)
(the rear examples show usage in lakes sector) - The level-index variable is of type integer or float
- The level-index variable and dimension name is specified in the variable comments of the protocol
If you want to introduce lower and upper boundaries to every level, you should also introduce a boundaries dimension (depth_bnds) and an index (bnds). In this case the following applies:
- The lower and upper boundaries of every layer are specified within depth_bnds
- depth_bnds is float
- depth_bnds depends on the level index and on bnds; e.g. depth_bnds(time, bnds, lev, lat, lon)
- bnds contains two entries, and what each entry indicates should be specified within the comments of dimension depth_bnds; e.g. depth_bnds:comment = "bnds=0 for the top of the layer, and bnds=1 for the bottom of the layer"
Specific uses: For variables where depth of layers varies over time, add global attribute time_varying_layer_depth and use label "true" or "false" depending on the case. For variables where depth of layers varies per grid cell, add global attribute location_varying_layer_depth and use label "true" or "false" depending on the case.
Example NetCDF header for variables with levels varying over time and space
Note: The level index "levlak" is used in lakes sector only. "depth" can either depend on space or time and space depending on the models capabilities:
- depth(levlak,lat,lon) or
- depth(time,levlak,lat,lon)
Lines with a trailing triple asterisk indicate the optional usage of layer boundaries.
dimensions:
time = UNLIMITED ;
bnds = 2 ;
levlak = 13 ;
lat = 360 ;
lon = 720 ;
variables:
double time(time) ;
time:standard_name = "time" ;
time:long_name = "Time" ;
time:units = "days since 1661-01-01 00:00:00" ;
time:calendar = "proleptic_gregorian" ;
time:axis = "T";
double lon(lon) ;
lon:standard_name = "longitude" ;
lon:long_name = "Longitude" ;
lon:units = "degrees_east" ;
lon:axis = "X" ;
double lat(lat) ;
lat:standard_name = "latitude" ;
lat:long_name = "Latitude" ;
lat:units = "degrees_north" ;
lat:axis = "Y" ;
float levlak(levlak) ;
lev:standard_name = "water_layer" ;
lev:long_name = "Vertical Water Layer Index" ;
lev:units = "-" ;
lev:axis = "Z" ;
lev:positive = "down" ;
float bnds(bnds) ;
bnds:positive = "down" ;
float depth_bnds(time, bnds, levlak, lat, lon) ;
depth_bnds:standard_name = "depth_bounds" ;
depth_bnds:long_name = "Depth of Layer\'s Top and Bottom Below Surface" ;
depth_bnds:units = "1" ;
depth_bnds:positive = "down" ;
depth_bnds:comment = "bnds=0 for the top of the layer, and bnds=1 for the bottom of the layer" ;
float depth(time, levlak, lat, lon) ;
depth:standard_name = "depth_below_surface" ;
depth:long_name = "Depth of Vertical Layer Center Below Surface" ;
depth:units = "m" ;
lev:axis = "Z" ;
depth:missing_value = 1.e+20 ;
depth:_FillValue = 1.e+20f;
depth:positive = "down" ;
depth:bounds = "depth_bnds" ;
float soilmoist(time, levlak, lat, lon) ;
soilmoist:standard_name = "soilmoist" ;
soilmoist:long_name = "Total Soil Moisture Content" ;
soilmoist:units = "kg m-2" ;
soilmoist:missing_value = 1.e+20f;
soilmoist:_FillValue = 1.e+20f ;
// global attributes:
:contact = "Name <email@place.com>";
:institution = "Institution of Affiliation (ACRONYM)" ;
:comment = "Data prepared for ISIMIP2b" ;
:time_varying_layer_depth = "true" ;
:location_varying_layer_depth = "true" ;
Here are instructions for converting your global daily ASCII data into a NetCDF file with the required meta data. The tools cdo and ncatted (from NCO) are needed (see links above).
- Prepare ASCII data with one data value per line sorted by time in data.txt
- Import data starting at 179.75°W,89.75°N on a proleptic-gregorian calendar:
cdo --history -f nc4c -z zip -setmissval,1e+20 -setunit,"UNIT" -setname,VARIABLE -setreftime,1661-01-01,00:00:00,1days -settaxis,STARTYEAR-01-01,00:00:00,1days -input,grid.txt data.nc4 < data.txt
ncatted -O -h -a contact,global,o,c,"NAME <EMAIL>" -a institution,global,o,c,"INSTITUTION (SHORT)" -a long_name,VARIABLE,o,c,"VARIABLE LONG NAME" data.nc