I am running the following code to create a simple line graph:
import matplotlib.pyplot as plt
import iris
import iris.coord_categorisation as iriscc
import iris.plot as iplt
import iris.quickplot as qplt
import iris.analysis.cartography
import matplotlib.dates as mdates
def main():
#bring in all the files we need and give them a name
TestFile= '/exports/csce/datastore/geos/users/s0XXXX/Climate_Modelling/AFR_44_tas/Historical/1950-2005/tas_AFR-44_MOHC-HadGEM2-ES_historical_r1i1p1_CLMcom-CCLM4-8-17_v1_mon_194912-200512.nc'
#Load exactly one cube from given file
TestFile = iris.load_cube(TestFile)
print TestFile
#adjust longitude as data is out by 180degrees
#remove flat latitude and longitude and only use grid latitude and grid longitude which are in the 3rd and 4th column of the file
lats = iris.coords.DimCoord(TestFile.coords()[3].points[:,0], \
standard_name='latitude', units='degrees')
lons = TestFile.coords()[4].points[0]
for i in range(len(lons)):
if lons[i]>100.:
lons[i] = lons[i]-360.
lons = iris.coords.DimCoord(lons, \
standard_name='longitude', units='degrees')
TestFile.remove_coord('latitude')
TestFile.remove_coord('longitude')
TestFile.remove_coord('grid_latitude')
TestFile.remove_coord('grid_longitude')
TestFile.add_dim_coord(lats, 1)
TestFile.add_dim_coord(lons, 2)
#we are only interested in the latitude and longitude relevant to Malawi
Malawi = iris.Constraint(longitude=lambda v: 32.5 <= v <= 36., \
latitude=lambda v: -17. <= v <= -9.)
TestFile = TestFile.extract(Malawi)
#data is in Kelvin, but we would like to show it in Celcius
TestFile.convert_units('Celsius')
#We are interested in plotting the graph with time along the x ais, so we need a mean of all the coordinates, i.e. mean temperature across whole country
iriscc.add_year(TestFile, 'time')
TestFile = TestFile.aggregated_by('year', iris.analysis.MEAN)
TestFile.coord('latitude').guess_bounds()
TestFile.coord('longitude').guess_bounds()
TestFile_grid_areas = iris.analysis.cartography.area_weights(TestFile)
TestFile_mean = TestFile.collapsed(['latitude', 'longitude'],
iris.analysis.MEAN,
weights=TestFile_grid_areas)
#set major plot indicators for x-axis
plt.gca().xaxis.set_major_locator(mdates.YearLocator(5))
#assign the line colours
qplt.plot(TestFile_mean, label='TestFile', lw=1.5, color='blue')
#create a legend and set its location to under the graph
plt.legend(loc="upper center", bbox_to_anchor=(0.5,-0.05), fancybox=True, shadow=True, ncol=5)
#create a title
plt.title('Mean Near Surface Temperature for Malawi', fontsize=11)
#create the graph
plt.grid()
iplt.show()
if __name__ == '__main__':
main()
This is working well for the majority of the files, but two climate models, are coming up with Constraint Mismatch Errors:
runfile('/exports/csce/datastore/geos/users/s0XXXX/Climate_Modelling/Python Code and Output Images/Line_Graph_Temp_Test.py', wdir='/exports/csce/datastore/geos/users/s0XXXX/Climate_Modelling/Python Code and Output Images')
Traceback (most recent call last):
File "<ipython-input-83-4f4457568a8f>", line 1, in <module> runfile('/exports/csce/datastore/geos/users/s0XXXX/Climate_Modelling/Python Code and Output Images/Line_Graph_Temp_Test.py', wdir='/exports/csce/datastore/geos/users/s0XXXX/Climate_Modelling/Python Code and Output Images')
File "/usr/lib/python2.7/site-packages/spyderlib/widgets/externalshell/sitecustomize.py", line 685, in runfile
execfile(filename, namespace)
File "/usr/lib/python2.7/site-packages/spyderlib/widgets/externalshell/sitecustomize.py", line 78, in execfile
builtins.execfile(filename, *where)
File "/exports/csce/datastore/geos/users/s0XXXX/Climate_Modelling/Python Code and Output Images/Line_Graph_Temp_Test.py", line 84, in <module>
main()
File "/exports/csce/datastore/geos/users/s0XXXX/Climate_Modelling/Python Code and Output Images/Line_Graph_Temp_Test.py", line 21, in main
TestFile = iris.load_cube(TestFile)
File "/usr/lib64/python2.7/site-packages/iris/__init__.py", line 338, in load_cube
raise iris.exceptions.ConstraintMismatchError(str(e))
ConstraintMismatchError: failed to merge into a single cube.
cube.standard_name differs: None != u'air_temperature'
cube.long_name differs: None != u'Near-Surface Air Temperature'
cube.var_name differs: u'rotated_pole' != u'tas'
cube.units differs: Unit('no_unit') != Unit('K')
cube.attributes keys differ: 'grid_north_pole_latitude', 'grid_north_pole_longitude', 'grid_mapping_name'
cube.cell_methods differ
cube.shape differs: () != (660, 201, 194)
cube data dtype differs: |S1 != float32
cube data fill_value differs: '\x00' != 1e+20
Similarly, I get this error when trying to run the observed data (cru_ts4.00.1901.2015.tmp.dat.nc)
ConstraintMismatchError: failed to merge into a single cube.
cube.long_name differs: u'near-surface temperature' != None
cube.var_name differs: u'tmp' != u'stn'
cube.units differs: Unit('degrees Celsius') != Unit('1')
cube.attributes keys differ: 'correlation_decay_distance', 'description'
cube data dtype differs: float32 != int32
cube data fill_value differs: 9.96921e+36 != -2147483647
Any ideas on how I can fix this?
I received a response from Andrew Dawson on the Iris User Google Group. Posting here in case it is of any help to someone else. This helped me!
The function iris.load_cube is used to load exactly 1 and only 1 cube from the given file matching the given constraints. You haven't provided constraints which means you are expecting the file(s) your a loading from to reduce to exactly 1 cube. The ConstraintMismatchError from iris.load_cube is telling you that this is not possible due to some mismatched data. From the error it looks like you have more than 1 variable in your input file(s) for those models. You should consider adding an explicit constraint when loading, perhaps like:
iris.load_cube(filename, 'name_of_variable_here')
where the name_of_variable should be the name that cube would be loaded with, i.e. the result of cube.name(). This is different from the netcdf variable name. To work out how you need to do this I suggest loading all the cubes from one of the problematic datasets with
cubes = iris.load(the_filename) # load all the cubes in the input file
and then printing the names of the cubes
for cube in cubes:
print(cube.name())