Hi,
I'm wondering if any further progress has been made on this issue since it was originally discussed above? I'm coming across the same problem in iris 1.4. Has the functionality mentioned by bjlittle been implemented in a later version, or is the add_missing_dims function now part of iris proper? I also think that the point by pbentley about the unlimited dimension (also mentioned below) is a bug and needs to be fixed (if it hasn't already). I also have a couple of points/questions/suggestions at the end of my post (sorry for the length!).
The essence of my problem is that if I load multiple pp-format files using iris I get a cube which looks like
mass_fraction_of_ozone_in_air / 1 (time: 12; model_level_number: 60;
latitude: 73; longitude: 96)
Dimension coordinates:
time x - - -
model_level_number - x - -
latitude - - x -
longitude - - - x
Auxiliary coordinates:
forecast_period x - - -
level_height - x - -
sigma - x - -
Scalar coordinates:
forecast_reference_time: 2160-12-01 00:00:00
Attributes:
STASH: m01s34i001
conversion_factor: 1.657
source: Data from Met Office Unified Model 7.03
Cell methods:
mean: time (1 hour)
When saving this field to netCDF I get a file which looks like:
netcdf ozone {
dimensions:
time = UNLIMITED ; // (12 currently)
model_level_number = 60 ;
latitude = 73 ;
longitude = 96 ;
bnds = 2 ;
variables:
float mass_fraction_of_ozone_in_air(time, model_level_number, latitude, longitude) ;
mass_fraction_of_ozone_in_air:standard_name = "mass_fraction_of_ozone_in_air" ;
mass_fraction_of_ozone_in_air:long_name = "O3 MMR in kg(O3)/kg(air)" ;
mass_fraction_of_ozone_in_air:units = "1" ;
mass_fraction_of_ozone_in_air:ukmo__um_stash_source = "m01s34i001" ;
mass_fraction_of_ozone_in_air:conversion_factor = 1.657 ;
mass_fraction_of_ozone_in_air:source = "Data from Met Office Unified Model 7.03" ;
mass_fraction_of_ozone_in_air:cell_methods = "time: mean (interval: 1 hour)" ;
mass_fraction_of_ozone_in_air:grid_mapping = "latitude_longitude" ;
mass_fraction_of_ozone_in_air:coordinates = "forecast_period forecast_reference_time level_height sigma" ;
int latitude_longitude ;
latitude_longitude:grid_mapping_name = "latitude_longitude" ;
latitude_longitude:longitude_of_prime_meridian = 0. ;
latitude_longitude:semi_major_axis = 6371229. ;
latitude_longitude:semi_minor_axis = 6371229. ;
double time(time) ;
time:axis = "T" ;
time:bounds = "time_bnds" ;
time:units = "hours since 1970-01-01 00:00:00" ;
time:standard_name = "time" ;
time:calendar = "360_day" ;
double time_bnds(time, bnds) ;
int model_level_number(model_level_number) ;
model_level_number:axis = "Z" ;
model_level_number:units = "1" ;
model_level_number:standard_name = "model_level_number" ;
model_level_number:positive = "up" ;
float latitude(latitude) ;
latitude:axis = "Y" ;
latitude:units = "degrees_north" ;
latitude:standard_name = "latitude" ;
float longitude(longitude) ;
longitude:axis = "X" ;
longitude:units = "degrees_east" ;
longitude:standard_name = "longitude" ;
int forecast_period(time) ;
forecast_period:units = "hours" ;
forecast_period:standard_name = "forecast_period" ;
double forecast_reference_time ;
forecast_reference_time:units = "hours since 1970-01-01 00:00:00" ;
forecast_reference_time:standard_name =
"forecast_reference_time" ;
forecast_reference_time:calendar = "360_day" ;
float level_height(model_level_number) ;
level_height:bounds = "level_height_bnds" ;
level_height:units = "m" ;
level_height:long_name = "level_height" ;
level_height:positive = "up" ;
float level_height_bnds(model_level_number, bnds) ;
float sigma(model_level_number) ;
sigma:bounds = "sigma_bnds" ;
sigma:units = "1" ;
sigma:long_name = "sigma" ;
float sigma_bnds(model_level_number, bnds) ;
// global attributes:
:Conventions = "CF-1.5" ;
}
which is all fine, and as to be expected.
However, when loading a single file, the time dimension is not included as a 'Dimension' - it now appears as a 'Scalar Coordinate'
mass_fraction_of_ozone_in_air / 1 (model_level_number: 60; latitude: 73;
longitude: 96)
Dimension coordinates:
model_level_number x - -
latitude - x -
longitude - - x
Auxiliary coordinates:
level_height x - -
sigma x - -
Scalar coordinates:
forecast_period: 6074640 hours
forecast_reference_time: 2160-12-01 00:00:00
time: 2863-12-16 00:00:00, bound=(2863-12-01 00:00:00, 2864-01-01 00:00:00)
Attributes:
STASH: m01s34i001
conversion_factor: 1.657
source: Data from Met Office Unified Model 7.03
Cell methods:
mean: time (1 hour)
Perhaps this is as expected. I have noticed that 2D fields such as surface temperature are not given a model_level_number. However, it does have knock-on consquences for saving this field to netCDF:
netcdf ozone {
dimensions:
model_level_number = UNLIMITED ; // (60 currently)
latitude = 73 ;
longitude = 96 ;
bnds = 2 ;
variables:
float mass_fraction_of_ozone_in_air(model_level_number, latitude, longitude) ;
mass_fraction_of_ozone_in_air:standard_name = "mass_fraction_of_ozone_in_air" ;
mass_fraction_of_ozone_in_air:long_name = "O3 MMR in kg(O3)/kg(air)" ;
mass_fraction_of_ozone_in_air:units = "1" ;
mass_fraction_of_ozone_in_air:ukmo__um_stash_source = "m01s34i001" ;
mass_fraction_of_ozone_in_air:conversion_factor = 1.657 ;
mass_fraction_of_ozone_in_air:source = "Data from Met Office Unified Model 7.03" ;
mass_fraction_of_ozone_in_air:cell_methods = "time: mean (interval: 1 hour)" ;
mass_fraction_of_ozone_in_air:grid_mapping = "latitude_longitude" ;
mass_fraction_of_ozone_in_air:coordinates = "forecast_period forecast_reference_time level_height sigma time" ;
int latitude_longitude ;
latitude_longitude:grid_mapping_name = "latitude_longitude" ;
latitude_longitude:longitude_of_prime_meridian = 0. ;
latitude_longitude:semi_major_axis = 6371229. ;
latitude_longitude:semi_minor_axis = 6371229. ;
int model_level_number(model_level_number) ;
model_level_number:axis = "Z" ;
model_level_number:units = "1" ;
model_level_number:standard_name = "model_level_number" ;
model_level_number:positive = "up" ;
float latitude(latitude) ;
latitude:axis = "Y" ;
latitude:units = "degrees_north" ;
latitude:standard_name = "latitude" ;
float longitude(longitude) ;
longitude:axis = "X" ;
longitude:units = "degrees_east" ;
longitude:standard_name = "longitude" ;
int forecast_period ;
forecast_period:units = "hours" ;
forecast_period:standard_name = "forecast_period" ;
double forecast_reference_time ;
forecast_reference_time:units = "hours since 1970-01-01 00:00:00" ;
forecast_reference_time:standard_name = "forecast_reference_time" ;
forecast_reference_time:calendar = "360_day" ;
float level_height(model_level_number) ;
level_height:bounds = "level_height_bnds" ;
level_height:units = "m" ;
level_height:long_name = "level_height" ;
level_height:positive = "up" ;
float level_height_bnds(model_level_number, bnds) ;
float sigma(model_level_number) ;
sigma:bounds = "sigma_bnds" ;
sigma:units = "1" ;
sigma:long_name = "sigma" ;
float sigma_bnds(model_level_number, bnds) ;
double time ;
time:bounds = "time_bnds" ;
time:units = "hours since 1970-01-01 00:00:00" ;
time:standard_name = "time" ;
time:calendar = "360_day" ;
double time_bnds(bnds) ;
// global attributes:
:Conventions = "CF-1.5" ;
}
When writing out the netCDF file, iris is assuming that the model_level_number is the record dimension - I guess it does that because the netCDF writing routines assume the 0 dimension to always be time, but as iris will read a single file without giving it a time dimension, this then breaks on the iris.save. I'm also guessing that this is a bug and not as intended.
This then leads to the following questions:
- Is it possible to add in a time dimension on a single file read, either:
- after the cube has been loaded, or
- during the iris.load command itself?
- If the answer to 1 is "no", is it possible to add the time dimension on the iris.save command?
- Extending the above questions to more than the record dimension, is it possible to force a 4-Dimensional field, e.g. for a surface field, make the number of model levels to be 1 (rather than not being included), or for a zonal mean field having the number of longitude points set to be 1 etc.? This then makes it easier to write code to analyse and manipulate fields, as the fields could be forced to have the dimensions (time,model_level_number,latitude,longitude), rather than this being different for different fields. I know that there could be issues with having a degenerate dimension (or dimensions).
The lack of a (correct) record dimension is quite serious, as it means that files cannot be catted together later. Unlimited dimensions are certainly required for the time (record) dimension, as without this, files cannot be concatenated by e.g.
ncrcat or
cdo mergetime etc.
Perhaps it could be possible to have a keyword on the iris.load call, e.g.
force_dim=, which could have the following values:
None could mean as it is now (the default),
time just mean add a single time dimension, and
4d add-in any other dimensions, e.g. time, height, or longitude etc.
Many thanks,
Luke