def test_RaggedIndexedContiguousArray_to_memory(self): """TODO DOCS.""" compressed_data = cfdm.Data([ 280.0, 281.0, 279.0, 278.0, 279.5, 281.0, 282.0, 278.0, 279.0, 277.5, ]) index = cfdm.Index(data=[0, 0, 0, 0, 1, 1, 1, 1]) cfdm.Count(data=[1, 3, 2, 2]) r = cfdm.RaggedIndexedContiguousArray( compressed_data, shape=(2, 2, 3), size=12, ndim=3, index_variable=index, count_variable=index, ) r.to_memory()
def test_netCDF_sample_dimension_groups(self): """Test sample dimension groups access NetCDF methods.""" c = cfdm.Count() c.nc_set_sample_dimension("ncvar") with self.assertRaises(ValueError): c.nc_set_sample_dimension_groups(["/forecast"]) attrs = c.nc_sample_dimension_groups() self.assertIsInstance(attrs, tuple) self.assertFalse(attrs) attrs = c.nc_clear_sample_dimension_groups() self.assertIsInstance(attrs, tuple) self.assertFalse(attrs) attrs = c.nc_sample_dimension_groups() self.assertIsInstance(attrs, tuple) self.assertFalse(attrs) c.nc_set_sample_dimension_groups(["forecast", "model"]) attrs = c.nc_sample_dimension_groups() self.assertIsInstance(attrs, tuple) self.assertEqual(attrs, ("forecast", "model")) self.assertEqual(c.nc_get_sample_dimension(), "/forecast/model/ncvar") attrs = c.nc_clear_sample_dimension_groups() self.assertIsInstance(attrs, tuple) self.assertEqual(attrs, ("forecast", "model")) attrs = c.nc_sample_dimension_groups() self.assertIsInstance(attrs, tuple) self.assertFalse(attrs) self.assertEqual(c.nc_get_sample_dimension(), "ncvar") c.nc_set_sample_dimension("ncvar") attrs = c.nc_sample_dimension_groups() self.assertIsInstance(attrs, tuple) self.assertEqual(attrs, ()) c.nc_set_sample_dimension("/ncvar") attrs = c.nc_sample_dimension_groups() self.assertIsInstance(attrs, tuple) self.assertFalse(attrs) c.nc_set_sample_dimension("/forecast/model/ncvar") attrs = c.nc_sample_dimension_groups() self.assertIsInstance(attrs, tuple) self.assertEqual(attrs, ("forecast", "model")) c.nc_del_sample_dimension() attrs = c.nc_sample_dimension_groups() self.assertIsInstance(attrs, tuple) self.assertFalse(attrs) with self.assertRaises(ValueError): c.nc_set_sample_dimension_groups(["forecast", "model"])
def test_DSG_contiguous(self): if self.test_only and inspect.stack()[0][3] not in self.test_only: return f = self.c.copy() self.assertEqual(len(f), 2) # Select the specific humidity field q = [g for g in f if g.get_property('standard_name') == 'specific_humidity'][0] self.assertTrue(q._equals(self.a, q.data.array)) cfdm.write(f, tempfile) g = cfdm.read(tempfile) self.assertEqual(len(g), len(f)) for i in range(len(f)): self.assertTrue(g[i].equals(f[i], verbose=3)) # ------------------------------------------------------------ # Test creation # ------------------------------------------------------------ # Define the ragged array values ragged_array = numpy.array([280, 282.5, 281, 279, 278, 279.5], dtype='float32') # Define the count array values count_array = [2, 4] # Create the count variable count_variable = cfdm.Count(data=cfdm.Data(count_array)) count_variable.set_property('long_name', 'number of obs for this timeseries') # Create the contiguous ragged array object array = cfdm.RaggedContiguousArray( compressed_array=cfdm.NumpyArray(ragged_array), shape=(2, 4), size=8, ndim=2, count_variable=count_variable) # Create the field construct with the domain axes and the ragged # array tas = cfdm.Field() tas.set_properties({'standard_name': 'air_temperature', 'units': 'K', 'featureType': 'timeSeries'}) # Create the domain axis constructs for the uncompressed array X = tas.set_construct(cfdm.DomainAxis(4)) Y = tas.set_construct(cfdm.DomainAxis(2)) # Set the data for the field tas.set_data(cfdm.Data(array), axes=[Y, X]) cfdm.write(tas, tempfile)
def test_DSG_create_contiguous(self): """Test the creation of a contiguous ragged array.""" # Define the ragged array values ragged_array = numpy.array([1, 3, 4, 3, 6], dtype="float32") # Define the count array values count_array = [2, 3] # Initialise the count variable count_variable = cfdm.Count(data=cfdm.Data(count_array)) count_variable.set_property( "long_name", "number of obs for this timeseries" ) # Initialise the contiguous ragged array object array = cfdm.RaggedContiguousArray( compressed_array=cfdm.Data(ragged_array), shape=(2, 3), size=6, ndim=2, count_variable=count_variable, ) # Initialize the auxiliary coordinate construct with the # ragged array and set some properties z = cfdm.AuxiliaryCoordinate( data=cfdm.Data(array), properties={ "standard_name": "height", "units": "km", "positive": "up", }, ) self.assertTrue( ( z.data.array == numpy.ma.masked_array( data=[[1.0, 3.0, 99], [4.0, 3.0, 6.0]], mask=[[False, False, True], [False, False, False]], fill_value=1e20, dtype="float32", ) ).all() ) self.assertEqual(z.data.get_compression_type(), "ragged contiguous") self.assertTrue( ( z.data.compressed_array == numpy.array([1.0, 3.0, 4.0, 3.0, 6.0], dtype="float32") ).all() ) self.assertTrue( (z.data.get_count().data.array == numpy.array([2, 3])).all() )
def setUp(self): # Disable log messages to silence expected warnings cfdm.log_level('DISABLE') # Note: to enable all messages for given methods, lines or calls (those # without a 'verbose' option to do the same) e.g. to debug them, wrap # them (for methods, start-to-end internally) as follows: # cfdm.log_level('DEBUG') # < ... test code ... > # cfdm.log_level('DISABLE') compressed_data = cfdm.Data([280.0, 281.0, 279.0, 278.0, 279.5]) count = cfdm.Count(data=[1, 3]) self.r = cfdm.RaggedContiguousArray(compressed_data, shape=(2, 3), size=6, ndim=2, count_variable=count)
def test_DSG_create_contiguous(self): if self.test_only and inspect.stack()[0][3] not in self.test_only: return # Define the ragged array values ragged_array = numpy.array([1, 3, 4, 3, 6], dtype='float32') # Define the count array values count_array = [2, 3] # Initialise the count variable count_variable = cfdm.Count(data=cfdm.Data(count_array)) count_variable.set_property('long_name', 'number of obs for this timeseries') # Initialise the contiguous ragged array object array = cfdm.RaggedContiguousArray( compressed_array=cfdm.Data(ragged_array), shape=(2, 3), size=6, ndim=2, count_variable=count_variable) # Initialize the auxiliary coordinate construct with the # ragged array and set some properties z = cfdm.AuxiliaryCoordinate( data=cfdm.Data(array), properties={'standard_name': 'height', 'units': 'km', 'positive': 'up'}) self.assertTrue((z.data.array == numpy.ma.masked_array( data=[[1.0, 3.0, 99], [4.0, 3.0, 6.0]], mask=[[False, False, True], [False, False, False]], fill_value=1e+20, dtype='float32')).all()) self.assertEqual(z.data.get_compression_type(), 'ragged contiguous') self.assertTrue((z.data.compressed_array == numpy.array( [1., 3., 4., 3., 6.], dtype='float32')).all()) self.assertTrue((z.data.get_count().data.array == numpy.array( [2, 3])).all())
def test_netCDF_variable_dimension(self): if self.test_only and inspect.stack()[0][3] not in self.test_only: return f = cfdm.Field() f.nc_set_variable('qwerty') self.assertTrue(f.nc_has_variable()) self.assertTrue(f.nc_get_variable() == 'qwerty') self.assertTrue(f.nc_get_variable(default=None) == 'qwerty') self.assertTrue(f.nc_del_variable() == 'qwerty') self.assertFalse(f.nc_has_variable()) self.assertTrue(f.nc_get_variable(default=None) == None) self.assertTrue(f.nc_del_variable(default=None) == None) d = cfdm.DomainAxis() d.nc_set_dimension('qwerty') self.assertTrue(d.nc_has_dimension()) self.assertTrue(d.nc_get_dimension() == 'qwerty') self.assertTrue(d.nc_get_dimension(default=None) == 'qwerty') self.assertTrue(d.nc_del_dimension() == 'qwerty') self.assertFalse(d.nc_has_dimension()) self.assertTrue(d.nc_get_dimension(default=None) == None) self.assertTrue(d.nc_del_dimension(default=None) == None) d = cfdm.Count() d.nc_set_sample_dimension('qwerty') self.assertTrue(d.nc_has_sample_dimension()) self.assertTrue(d.nc_get_sample_dimension() == 'qwerty') self.assertTrue(d.nc_get_sample_dimension(default=None) == 'qwerty') self.assertTrue(d.nc_del_sample_dimension() == 'qwerty') self.assertFalse(d.nc_has_sample_dimension()) self.assertTrue(d.nc_get_sample_dimension(default=None) == None) self.assertTrue(d.nc_del_sample_dimension(default=None) == None)
def test_netCDF_variable_dimension(self): """Test variable and dimension access NetCDF methods.""" f = cfdm.Field() f.nc_set_variable("qwerty") self.assertTrue(f.nc_has_variable()) self.assertEqual(f.nc_get_variable(), "qwerty") self.assertEqual(f.nc_get_variable(default=None), "qwerty") self.assertEqual(f.nc_del_variable(), "qwerty") self.assertFalse(f.nc_has_variable()) self.assertIsNone(f.nc_get_variable(default=None)) self.assertIsNone(f.nc_del_variable(default=None)) f.nc_set_variable("/ncvar") self.assertEqual(f.nc_get_variable(), "ncvar") f.nc_set_variable("/ncvar/qwerty") self.assertEqual(f.nc_get_variable(), "/ncvar/qwerty") for nc_var_name in self.nc_grouped_variable_names: with self.assertRaises(ValueError): f.nc_set_variable(nc_var_name) d = cfdm.DomainAxis() d.nc_set_dimension("qwerty") self.assertTrue(d.nc_has_dimension()) self.assertEqual(d.nc_get_dimension(), "qwerty") self.assertEqual(d.nc_get_dimension(default=None), "qwerty") self.assertEqual(d.nc_del_dimension(), "qwerty") self.assertFalse(d.nc_has_dimension()) self.assertIsNone(d.nc_get_dimension(default=None)) self.assertIsNone(d.nc_del_dimension(default=None)) d.nc_set_dimension("/ncdim") self.assertEqual(d.nc_get_dimension(), "ncdim") d.nc_set_dimension("/ncdim/qwerty") self.assertEqual(d.nc_get_dimension(), "/ncdim/qwerty") for nc_dim_name in self.nc_grouped_dimension_names: with self.assertRaises(ValueError): d.nc_set_dimension(nc_dim_name) d = cfdm.Count() d.nc_set_sample_dimension("qwerty") self.assertTrue(d.nc_has_sample_dimension()) self.assertEqual(d.nc_get_sample_dimension(), "qwerty") self.assertEqual(d.nc_get_sample_dimension(default=None), "qwerty") self.assertEqual(d.nc_del_sample_dimension(), "qwerty") self.assertFalse(d.nc_has_sample_dimension()) self.assertIsNone(d.nc_get_sample_dimension(default=None)) self.assertIsNone(d.nc_del_sample_dimension(default=None)) d.nc_set_sample_dimension("/ncdim") self.assertEqual(d.nc_get_sample_dimension(), "ncdim") d.nc_set_sample_dimension("/ncdim/qwerty") self.assertEqual(d.nc_get_sample_dimension(), "/ncdim/qwerty") for nc_dim_name in self.nc_grouped_dimension_names: with self.assertRaises(ValueError): d.nc_set_sample_dimension(nc_dim_name) # ------------------------------------------------------------ # Global attributes # ------------------------------------------------------------ # values keyword f = cfdm.Field() f.nc_set_global_attribute("Conventions", "CF-1.8") f.nc_set_global_attribute("project") f.nc_set_global_attribute("foo") f.set_property("Conventions", "Y") f.set_property("project", "X") self.assertEqual( f.nc_global_attributes(values=True), {"Conventions": "CF-1.8", "project": "X", "foo": None}, ) f = cfdm.Field() self.assertEqual(f.nc_clear_global_attributes(), {}) f.nc_set_global_attribute("Conventions") f.nc_set_global_attribute("project", "X") self.assertEqual( f.nc_global_attributes(), {"Conventions": None, "project": "X"} ) f.nc_set_global_attribute("project") f.nc_set_global_attribute("comment", None) self.assertEqual( f.nc_global_attributes(), {"Conventions": None, "project": None, "comment": None}, ) self.assertEqual( f.nc_clear_global_attributes(), {"Conventions": None, "project": None, "comment": None}, ) self.assertEqual(f.nc_global_attributes(), {}) f.nc_set_global_attribute("Conventions") f.nc_set_global_attribute("project") self.assertEqual( f.nc_global_attributes(), {"Conventions": None, "project": None} ) _ = f.nc_clear_global_attributes() f.nc_set_global_attributes({}) self.assertEqual(f.nc_global_attributes(), {}) f.nc_set_global_attributes({"comment": 123}, copy=False) self.assertEqual(f.nc_global_attributes(), {"comment": 123}) f.nc_set_global_attributes({"comment": None, "foo": "bar"}) self.assertEqual( f.nc_global_attributes(), {"comment": None, "foo": "bar"} ) f = cfdm.Field() f.set_properties({"foo": "bar", "comment": "variable comment"}) f.nc_set_variable("tas") d = f.set_construct(cfdm.DomainAxis(2)) f.set_data(cfdm.Data([8, 9]), axes=[d]) f2 = f.copy() f2.nc_set_variable("ua") cfdm.write( [f, f2], tempfile1, file_descriptors={"comment": "global comment", "qwerty": "asdf"}, ) g = cfdm.read(tempfile1) self.assertEqual(len(g), 2) for x in g: self.assertEqual( x.properties(), { "comment": "variable comment", "foo": "bar", "qwerty": "asdf", "Conventions": "CF-" + cfdm.CF(), }, ) self.assertEqual( x.nc_global_attributes(), { "comment": "global comment", "qwerty": None, "Conventions": None, }, ) cfdm.write(g, tempfile2) h = cfdm.read(tempfile2) for x, y in zip(h, g): self.assertEqual(x.properties(), y.properties()) self.assertEqual( x.nc_global_attributes(), y.nc_global_attributes() ) self.assertTrue(x.equals(y, verbose=3)) self.assertTrue(y.equals(x, verbose=3)) g[1].nc_set_global_attribute("comment", "different comment") cfdm.write(g, tempfile3) h = cfdm.read(tempfile3) for x, y in zip(h, g): self.assertEqual(x.properties(), y.properties()) self.assertEqual( x.nc_global_attributes(), {"comment": None, "qwerty": None, "Conventions": None}, ) self.assertTrue(x.equals(y, verbose=3)) self.assertTrue(y.equals(x, verbose=3))
count_variable = T.data.get_count() count_variable print(count_variable.data.array) cfdm.write(T, 'T_contiguous.nc') import numpy import cfdm # Define the ragged array values ragged_array = cfdm.Data([280, 281, 279, 278, 279.5]) # Define the count array values count_array = [1, 4] # Create the count variable count_variable = cfdm.Count(data=cfdm.Data(count_array)) count_variable.set_property('long_name', 'number of obs for this timeseries') # Create the contiguous ragged array object, specifying the # uncompressed shape array = cfdm.RaggedContiguousArray( compressed_array=ragged_array, shape=(2, 4), size=8, ndim=2, count_variable=count_variable) # Create the field construct with the domain axes and the ragged # array T = cfdm.Field() T.set_properties({'standard_name': 'air_temperature', 'units': 'K', 'featureType': 'timeSeries'})
def test_DSG_contiguous(self): """TODO DOCS.""" f = self.c.copy() self.assertEqual(len(f), 2) # Select the specific humidity field q = [ g for g in f if g.get_property("standard_name") == "specific_humidity" ][0] self.assertTrue(q._equals(self.a, q.data.array)) cfdm.write(f, tempfile) g = cfdm.read(tempfile) self.assertEqual(len(g), len(f)) for i in range(len(f)): self.assertTrue(g[i].equals(f[i], verbose=3)) # ------------------------------------------------------------ # Test creation # ------------------------------------------------------------ # Define the ragged array values ragged_array = numpy.array([280, 282.5, 281, 279, 278, 279.5], dtype="float32") # Define the count array values count_array = [2, 4] # Create the count variable count_variable = cfdm.Count(data=cfdm.Data(count_array)) count_variable.set_property("long_name", "number of obs for this timeseries") # Create the contiguous ragged array object array = cfdm.RaggedContiguousArray( compressed_array=cfdm.NumpyArray(ragged_array), shape=(2, 4), size=8, ndim=2, count_variable=count_variable, ) # Create the field construct with the domain axes and the ragged # array tas = cfdm.Field() tas.set_properties({ "standard_name": "air_temperature", "units": "K", "featureType": "timeSeries", }) # Create the domain axis constructs for the uncompressed array X = tas.set_construct(cfdm.DomainAxis(4)) Y = tas.set_construct(cfdm.DomainAxis(2)) # Set the data for the field tas.set_data(cfdm.Data(array), axes=[Y, X]) cfdm.write(tas, tempfile)
def test_netCDF_sample_dimension_groups(self): if self.test_only and inspect.stack()[0][3] not in self.test_only: return c = cfdm.Count() c.nc_set_sample_dimension('ncvar') with self.assertRaises(ValueError): c.nc_set_sample_dimension_groups(['/forecast']) attrs = c.nc_sample_dimension_groups() self.assertIsInstance(attrs, tuple) self.assertFalse(attrs) attrs = c.nc_clear_sample_dimension_groups() self.assertIsInstance(attrs, tuple) self.assertFalse(attrs) attrs = c.nc_sample_dimension_groups() self.assertIsInstance(attrs, tuple) self.assertFalse(attrs) c.nc_set_sample_dimension_groups(['forecast', 'model']) attrs = c.nc_sample_dimension_groups() self.assertIsInstance(attrs, tuple) self.assertEqual(attrs, ('forecast', 'model')) self.assertEqual(c.nc_get_sample_dimension(), '/forecast/model/ncvar') attrs = c.nc_clear_sample_dimension_groups() self.assertIsInstance(attrs, tuple) self.assertEqual(attrs, ('forecast', 'model')) attrs = c.nc_sample_dimension_groups() self.assertIsInstance(attrs, tuple) self.assertFalse(attrs) self.assertEqual(c.nc_get_sample_dimension(), 'ncvar') c.nc_set_sample_dimension('ncvar') attrs = c.nc_sample_dimension_groups() self.assertIsInstance(attrs, tuple) self.assertEqual(attrs, ()) c.nc_set_sample_dimension('/ncvar') attrs = c.nc_sample_dimension_groups() self.assertIsInstance(attrs, tuple) self.assertFalse(attrs) c.nc_set_sample_dimension('/forecast/model/ncvar') attrs = c.nc_sample_dimension_groups() self.assertIsInstance(attrs, tuple) self.assertEqual(attrs, ('forecast', 'model')) c.nc_del_sample_dimension() attrs = c.nc_sample_dimension_groups() self.assertIsInstance(attrs, tuple) self.assertFalse(attrs) with self.assertRaises(ValueError): c.nc_set_sample_dimension_groups(['forecast', 'model'])
def test_netCDF_variable_dimension(self): if self.test_only and inspect.stack()[0][3] not in self.test_only: return f = cfdm.Field() f.nc_set_variable('qwerty') self.assertTrue(f.nc_has_variable()) self.assertEqual(f.nc_get_variable(), 'qwerty') self.assertEqual(f.nc_get_variable(default=None), 'qwerty') self.assertEqual(f.nc_del_variable(), 'qwerty') self.assertFalse(f.nc_has_variable()) self.assertIsNone(f.nc_get_variable(default=None)) self.assertIsNone(f.nc_del_variable(default=None)) f.nc_set_variable('/ncvar') self.assertEqual(f.nc_get_variable(), 'ncvar') f.nc_set_variable('/ncvar/qwerty') self.assertEqual(f.nc_get_variable(), '/ncvar/qwerty') with self.assertRaises(ValueError): f.nc_set_variable(None) with self.assertRaises(ValueError): f.nc_set_variable('/') with self.assertRaises(ValueError): f.nc_set_variable('group/ncvar') with self.assertRaises(ValueError): f.nc_set_variable('group/') with self.assertRaises(ValueError): f.nc_set_variable('group/ncvar/') with self.assertRaises(ValueError): f.nc_set_variable('/group/ncvar/') d = cfdm.DomainAxis() d.nc_set_dimension('qwerty') self.assertTrue(d.nc_has_dimension()) self.assertEqual(d.nc_get_dimension(), 'qwerty') self.assertEqual(d.nc_get_dimension(default=None), 'qwerty') self.assertEqual(d.nc_del_dimension(), 'qwerty') self.assertFalse(d.nc_has_dimension()) self.assertIsNone(d.nc_get_dimension(default=None)) self.assertIsNone(d.nc_del_dimension(default=None)) d.nc_set_dimension('/ncdim') self.assertEqual(d.nc_get_dimension(), 'ncdim') d.nc_set_dimension('/ncdim/qwerty') self.assertEqual(d.nc_get_dimension(), '/ncdim/qwerty') with self.assertRaises(ValueError): d.nc_set_dimension(None) with self.assertRaises(ValueError): d.nc_set_dimension('/') with self.assertRaises(ValueError): d.nc_set_dimension('group/ncdim') with self.assertRaises(ValueError): d.nc_set_dimension('group/') with self.assertRaises(ValueError): d.nc_set_dimension('group/ncdim/') with self.assertRaises(ValueError): d.nc_set_dimension('/group/ncdim/') d = cfdm.Count() d.nc_set_sample_dimension('qwerty') self.assertTrue(d.nc_has_sample_dimension()) self.assertEqual(d.nc_get_sample_dimension(), 'qwerty') self.assertEqual(d.nc_get_sample_dimension(default=None), 'qwerty') self.assertEqual(d.nc_del_sample_dimension(), 'qwerty') self.assertFalse(d.nc_has_sample_dimension()) self.assertIsNone(d.nc_get_sample_dimension(default=None)) self.assertIsNone(d.nc_del_sample_dimension(default=None)) d.nc_set_sample_dimension('/ncdim') self.assertEqual(d.nc_get_sample_dimension(), 'ncdim') d.nc_set_sample_dimension('/ncdim/qwerty') self.assertEqual(d.nc_get_sample_dimension(), '/ncdim/qwerty') with self.assertRaises(ValueError): d.nc_set_sample_dimension(None) with self.assertRaises(ValueError): d.nc_set_sample_dimension('/') with self.assertRaises(ValueError): d.nc_set_sample_dimension('group/ncdim') with self.assertRaises(ValueError): d.nc_set_sample_dimension('group/') with self.assertRaises(ValueError): d.nc_set_sample_dimension('group/ncdim/') with self.assertRaises(ValueError): d.nc_set_sample_dimension('/group/ncdim/') # ------------------------------------------------------------ # Global attributes # ------------------------------------------------------------ # values keyword f = cfdm.Field() f.nc_set_global_attribute('Conventions', 'CF-1.8') f.nc_set_global_attribute('project') f.nc_set_global_attribute('foo') f.set_property('Conventions', 'Y') f.set_property('project', 'X') self.assertEqual(f.nc_global_attributes(values=True), {'Conventions': 'CF-1.8', 'project': 'X', 'foo': None}) f = cfdm.Field() self.assertEqual(f.nc_clear_global_attributes(), {}) f.nc_set_global_attribute('Conventions') f.nc_set_global_attribute('project', 'X') self.assertEqual(f.nc_global_attributes(), {'Conventions': None, 'project': 'X'}) f.nc_set_global_attribute('project') f.nc_set_global_attribute('comment', None) self.assertEqual(f.nc_global_attributes(), {'Conventions': None, 'project': None, 'comment': None}) self.assertEqual(f.nc_clear_global_attributes(), {'Conventions': None, 'project': None, 'comment': None}) self.assertEqual(f.nc_global_attributes(), {}) f.nc_set_global_attribute('Conventions') f.nc_set_global_attribute('project') self.assertEqual(f.nc_global_attributes(), {'Conventions': None, 'project': None}) _ = f.nc_clear_global_attributes() f.nc_set_global_attributes({}) self.assertEqual(f.nc_global_attributes(), {}) f.nc_set_global_attributes({'comment': 123}, copy=False) self.assertEqual(f.nc_global_attributes(), {'comment': 123}) f.nc_set_global_attributes({'comment': None, 'foo': 'bar'}) self.assertEqual(f.nc_global_attributes(), {'comment': None, 'foo': 'bar'}) f = cfdm.Field() f.set_properties({'foo': 'bar', 'comment': 'variable comment'}) f.nc_set_variable('tas') d = f.set_construct(cfdm.DomainAxis(2)) f.set_data(cfdm.Data([8, 9]), axes=[d]) f2 = f.copy() f2.nc_set_variable('ua') cfdm.write([f, f2], tempfile1, file_descriptors={'comment': 'global comment', 'qwerty': 'asdf'}) g = cfdm.read(tempfile1) self.assertEqual(len(g), 2) for x in g: self.assertEqual(x.properties(), {'comment': 'variable comment', 'foo': 'bar', 'qwerty': 'asdf', 'Conventions': 'CF-'+cfdm.CF()}) self.assertEqual(x.nc_global_attributes(), {'comment': 'global comment', 'qwerty': None, 'Conventions': None}) cfdm.write(g, tempfile2) h = cfdm.read(tempfile2) for x, y in zip(h, g): self.assertEqual(x.properties(), y.properties()) self.assertEqual(x.nc_global_attributes(), y.nc_global_attributes()) self.assertTrue(x.equals(y, verbose=3)) self.assertTrue(y.equals(x, verbose=3)) g[1].nc_set_global_attribute('comment', 'different comment') cfdm.write(g, tempfile3) h = cfdm.read(tempfile3) for x, y in zip(h, g): self.assertEqual(x.properties(), y.properties()) self.assertEqual(x.nc_global_attributes(), {'comment': None, 'qwerty': None, 'Conventions': None}) self.assertTrue(x.equals(y, verbose=3)) self.assertTrue(y.equals(x, verbose=3))