|
13 | 13 | import tempfile |
14 | 14 | import warnings |
15 | 15 |
|
| 16 | +import numpy as np |
16 | 17 | import pytest |
17 | 18 |
|
18 | 19 | import iris |
@@ -93,7 +94,7 @@ def test_load_laea_grid(self): |
93 | 94 | float data(y, x) ; |
94 | 95 | data :standard_name = "toa_brightness_temperature" ; |
95 | 96 | data :units = "K" ; |
96 | | - data :grid_mapping = "mercator" ; |
| 97 | + data :grid_mapping = "mercator: x y" ; |
97 | 98 | int mercator ; |
98 | 99 | mercator:grid_mapping_name = "mercator" ; |
99 | 100 | mercator:longitude_of_prime_meridian = 0. ; |
@@ -131,6 +132,55 @@ def test_load_laea_grid(self): |
131 | 132 | } |
132 | 133 | """ |
133 | 134 |
|
| 135 | + multi_cs_osgb_wkt = """ |
| 136 | +netcdf osgb { |
| 137 | +dimensions: |
| 138 | + y = 5 ; |
| 139 | + x = 4 ; |
| 140 | +variables: |
| 141 | + double x(x) ; |
| 142 | + x:standard_name = "projection_x_coordinate" ; |
| 143 | + x:long_name = "Easting" ; |
| 144 | + x:units = "m" ; |
| 145 | + double y(y) ; |
| 146 | + y:standard_name = "projection_y_coordinate" ; |
| 147 | + y:long_name = "Northing" ; |
| 148 | + y:units = "m" ; |
| 149 | + double lat(y, x) ; |
| 150 | + lat:standard_name = "latitude" ; |
| 151 | + lat:units = "degrees_north" ; |
| 152 | + double lon(y, x) ; |
| 153 | + lon:standard_name = "longitude" ; |
| 154 | + lon:units = "degrees_east" ; |
| 155 | + float temp(y, x) ; |
| 156 | + temp:standard_name = "air_temperature" ; |
| 157 | + temp:units = "K" ; |
| 158 | + temp:coordinates = "lat lon" ; |
| 159 | + temp:grid_mapping = "crsOSGB: x y crsWGS84: lat lon" ; |
| 160 | + int crsOSGB ; |
| 161 | + crsOSGB:grid_mapping_name = "transverse_mercator" ; |
| 162 | + crsOSGB:semi_major_axis = 6377563.396 ; |
| 163 | + crsOSGB:inverse_flattening = 299.3249646 ; |
| 164 | + crsOSGB:longitude_of_prime_meridian = 0. ; |
| 165 | + crsOSGB:latitude_of_projection_origin = 49. ; |
| 166 | + crsOSGB:longitude_of_central_meridian = -2. ; |
| 167 | + crsOSGB:scale_factor_at_central_meridian = 0.9996012717 ; |
| 168 | + crsOSGB:false_easting = 400000. ; |
| 169 | + crsOSGB:false_northing = -100000. ; |
| 170 | + crsOSGB:unit = "metre" ; |
| 171 | + crsOSGB:crs_wkt = "PROJCRS[\\"unknown\\",BASEGEOGCRS[\\"unknown\\",DATUM[\\"Unknown based on Airy 1830 ellipsoid\\",ELLIPSOID[\\"Airy 1830\\",6377563.396,299.324964600004,LENGTHUNIT[\\"metre\\",1,ID[\\"EPSG\\",9001]]]],PRIMEM[\\"Greenwich\\",0,ANGLEUNIT[\\"degree\\",0.0174532925199433],ID[\\"EPSG\\",8901]]],CONVERSION[\\"unknown\\",METHOD[\\"Transverse Mercator\\",ID[\\"EPSG\\",9807]],PARAMETER[\\"Latitude of natural origin\\",49,ANGLEUNIT[\\"degree\\",0.0174532925199433],ID[\\"EPSG\\",8801]],PARAMETER[\\"Longitude of natural origin\\",-2,ANGLEUNIT[\\"degree\\",0.0174532925199433],ID[\\"EPSG\\",8802]],PARAMETER[\\"Scale factor at natural origin\\",0.9996012717,SCALEUNIT[\\"unity\\",1],ID[\\"EPSG\\",8805]],PARAMETER[\\"False easting\\",400000,LENGTHUNIT[\\"metre\\",1],ID[\\"EPSG\\",8806]],PARAMETER[\\"False northing\\",-100000,LENGTHUNIT[\\"metre\\",1],ID[\\"EPSG\\",8807]]],CS[Cartesian,2],AXIS[\\"(E)\\",east,ORDER[1],LENGTHUNIT[\\"metre\\",1,ID[\\"EPSG\\",9001]]],AXIS[\\"(N)\\",north,ORDER[2],LENGTHUNIT[\\"metre\\",1,ID[\\"EPSG\\",9001]]]]" ; |
| 172 | + int crsWGS84 ; |
| 173 | + crsWGS84:grid_mapping_name = "latitude_longitude" ; |
| 174 | + crsWGS84:longitude_of_prime_meridian = 0. ; |
| 175 | + crsWGS84:semi_major_axis = 6378137. ; |
| 176 | + crsWGS84:inverse_flattening = 298.257223563 ; |
| 177 | + crsWGS84: crs_wkt = "GEOGCRS[\\"unknown\\",DATUM[\\"Unknown based on WGS 84 ellipsoid\\",ELLIPSOID[\\"WGS 84\\",6378137,298.257223562997,LENGTHUNIT[\\"metre\\",1,ID[\\"EPSG\\",9001]]]],PRIMEM[\\"Greenwich\\",0,ANGLEUNIT[\\"degree\\",0.0174532925199433],ID[\\"EPSG\\",8901]],CS[ellipsoidal,2],AXIS[\\"longitude\\",east,ORDER[1],ANGLEUNIT[\\"degree\\",0.0174532925199433,ID[\\"EPSG\\",9122]]],AXIS[\\"latitude\\",north,ORDER[2],ANGLEUNIT[\\"degree\\",0.0174532925199433,ID[\\"EPSG\\",9122]]]]" ; |
| 178 | +data: |
| 179 | + x = 1,2,3,4,5 ; |
| 180 | + y = 1,2,3,4 ; |
| 181 | +} |
| 182 | +""" |
| 183 | + |
134 | 184 | def test_load_datum_wkt(self): |
135 | 185 | expected = "OSGB 1936" |
136 | 186 | nc_path = tlc.cdl_to_nc(self.datum_wkt_cdl) |
@@ -175,6 +225,22 @@ def test_no_load_datum_cf_var(self): |
175 | 225 | actual = str(test_crs.as_cartopy_crs().datum) |
176 | 226 | assert actual == "unknown" |
177 | 227 |
|
| 228 | + def test_load_multi_cs_wkt(self): |
| 229 | + nc_path = tlc.cdl_to_nc(self.multi_cs_osgb_wkt) |
| 230 | + with iris.FUTURE.context(datum_support=True): |
| 231 | + cube = iris.load_cube(nc_path) |
| 232 | + |
| 233 | + assert len(cube.coord_systems()) == 2 |
| 234 | + for name in ["projection_y_coordinate", "projection_y_coordinate"]: |
| 235 | + assert ( |
| 236 | + cube.coord(name).coord_system.grid_mapping_name == "transverse_mercator" |
| 237 | + ) |
| 238 | + for name in ["latitude", "longitude"]: |
| 239 | + assert ( |
| 240 | + cube.coord(name).coord_system.grid_mapping_name == "latitude_longitude" |
| 241 | + ) |
| 242 | + assert cube.extended_grid_mapping is True |
| 243 | + |
178 | 244 | def test_save_datum(self): |
179 | 245 | expected = "OSGB 1936" |
180 | 246 | saved_crs = iris.coord_systems.Mercator( |
@@ -214,6 +280,60 @@ def test_save_datum(self): |
214 | 280 | actual = str(test_crs.as_cartopy_crs().datum) |
215 | 281 | assert actual == expected |
216 | 282 |
|
| 283 | + def test_save_multi_cs_wkt(self): |
| 284 | + crsOSGB = iris.coord_systems.OSGB() |
| 285 | + crsLatLon = iris.coord_systems.GeogCS(6e6) |
| 286 | + |
| 287 | + dimx_coord = iris.coords.DimCoord( |
| 288 | + np.arange(4), "projection_x_coordinate", coord_system=crsOSGB |
| 289 | + ) |
| 290 | + dimy_coord = iris.coords.DimCoord( |
| 291 | + np.arange(5), "projection_y_coordinate", coord_system=crsOSGB |
| 292 | + ) |
| 293 | + |
| 294 | + auxlon_coord = iris.coords.AuxCoord( |
| 295 | + np.arange(20).reshape((5, 4)), |
| 296 | + standard_name="longitude", |
| 297 | + coord_system=crsLatLon, |
| 298 | + ) |
| 299 | + auxlat_coord = iris.coords.AuxCoord( |
| 300 | + np.arange(20).reshape((5, 4)), |
| 301 | + standard_name="latitude", |
| 302 | + coord_system=crsLatLon, |
| 303 | + ) |
| 304 | + |
| 305 | + test_cube = Cube( |
| 306 | + np.ones(20).reshape((5, 4)), |
| 307 | + standard_name="air_pressure", |
| 308 | + units="Pa", |
| 309 | + dim_coords_and_dims=( |
| 310 | + (dimy_coord, 0), |
| 311 | + (dimx_coord, 1), |
| 312 | + ), |
| 313 | + aux_coords_and_dims=( |
| 314 | + (auxlat_coord, (0, 1)), |
| 315 | + (auxlon_coord, (0, 1)), |
| 316 | + ), |
| 317 | + ) |
| 318 | + |
| 319 | + test_cube.extended_grid_mapping = True |
| 320 | + |
| 321 | + with self.temp_filename(suffix=".nc") as filename: |
| 322 | + iris.save(test_cube, filename) |
| 323 | + with iris.FUTURE.context(datum_support=True): |
| 324 | + cube = iris.load_cube(filename) |
| 325 | + |
| 326 | + assert len(cube.coord_systems()) == 2 |
| 327 | + for name in ["projection_y_coordinate", "projection_y_coordinate"]: |
| 328 | + assert ( |
| 329 | + cube.coord(name).coord_system.grid_mapping_name == "transverse_mercator" |
| 330 | + ) |
| 331 | + for name in ["latitude", "longitude"]: |
| 332 | + assert ( |
| 333 | + cube.coord(name).coord_system.grid_mapping_name == "latitude_longitude" |
| 334 | + ) |
| 335 | + assert cube.extended_grid_mapping is True |
| 336 | + |
217 | 337 |
|
218 | 338 | class TestLoadMinimalGeostationary(tests.IrisTest): |
219 | 339 | """Check we can load data with a geostationary grid-mapping, even when the |
|
0 commit comments