@@ -1738,6 +1738,7 @@ def _create_generic_cf_array_var(
17381738 element_dims = None ,
17391739 fill_value = None ,
17401740 compression_kwargs = None ,
1741+ packing_controls : dict | None = None ,
17411742 is_dataless = False ,
17421743 ):
17431744 """Create theCF-netCDF variable given dimensional_metadata.
@@ -1904,7 +1905,10 @@ def _create_generic_cf_array_var(
19041905 else :
19051906 element_type = type (element ).__name__
19061907 data = self ._ensure_valid_dtype (data , element_type , element )
1907- dtype = data .dtype .newbyteorder ("=" )
1908+ if not packing_controls :
1909+ dtype = data .dtype .newbyteorder ("=" )
1910+ else :
1911+ dtype = packing_controls ["dtype" ]
19081912
19091913 # Check if this is a dim-coord.
19101914 is_dimcoord = cube is not None and element in cube .dim_coords
@@ -1937,6 +1941,10 @@ def _create_generic_cf_array_var(
19371941
19381942 # Add the data to the CF-netCDF variable.
19391943 if not is_dataless :
1944+ if packing_controls :
1945+ # We must set packing attributes (if any), before assigning values.
1946+ for key , value in packing_controls ["attributes" ]:
1947+ _setncattr (cf_var , key , value )
19401948 self ._lazy_stream_data (data = data , cf_var = cf_var )
19411949
19421950 # Add names + units
@@ -2371,11 +2379,10 @@ def _create_cf_data_variable(
23712379 # Get the values in a form which is valid for the file format.
23722380 is_dataless = cube .is_dataless ()
23732381
2374- if not is_dataless :
2382+ packing_controls = None
2383+ if packing and not is_dataless :
23752384 data = self ._ensure_valid_dtype (cube .core_data (), "cube" , cube )
2376- if not packing :
2377- dtype = data .dtype .newbyteorder ("=" )
2378- elif isinstance (packing , dict ):
2385+ if isinstance (packing , dict ):
23792386 if "dtype" not in packing :
23802387 msg = "The dtype attribute is required for packing."
23812388 raise ValueError (msg )
@@ -2413,26 +2420,14 @@ def _create_cf_data_variable(
24132420 else :
24142421 add_offset = cmin + 2 ** (n - 1 ) * scale_factor
24152422
2416- def set_packing_ncattrs (cfvar ):
2417- """Set netCDF packing attributes.
2418-
2419- NOTE: cfvar needs to be a _thread_safe_nc._ThreadSafeWrapper subclass.
2423+ packing_controls = {
2424+ "dtype" : dtype ,
2425+ "attributes" : [
2426+ ("scale_factor" , scale_factor ),
2427+ ("add_offset" , add_offset ),
2428+ ],
2429+ }
24202430
2421- """
2422- assert hasattr (cfvar , "THREAD_SAFE_FLAG" )
2423- if packing :
2424- if scale_factor :
2425- _setncattr (cfvar , "scale_factor" , scale_factor )
2426- if add_offset :
2427- _setncattr (cfvar , "add_offset" , add_offset )
2428-
2429- # cf_name = self._get_element_variable_name(cube_or_mesh=None, element=cube)
2430- # while cf_name in self._dataset.variables:
2431- # cf_name = self._increment_name(cf_name)
2432- #
2433- # cf_var = self._dataset.createVariable(
2434- # cf_name, dtype, dimension_names, fill_value=fill_value, **kwargs
2435- # )
24362431 # Create the cube CF-netCDF data variable with data payload.
24372432 cf_name = self ._create_generic_cf_array_var (
24382433 cube ,
@@ -2441,28 +2436,13 @@ def set_packing_ncattrs(cfvar):
24412436 element_dims = dimension_names ,
24422437 fill_value = fill_value ,
24432438 compression_kwargs = kwargs ,
2439+ packing_controls = packing_controls ,
24442440 is_dataless = is_dataless ,
24452441 )
24462442 cf_var = self ._dataset .variables [cf_name ]
24472443
2448- if not is_dataless :
2449- set_packing_ncattrs (cf_var )
2450-
2451- # if cube.standard_name:
2452- # _setncattr(cf_var, "standard_name", cube.standard_name)
2453- #
2454- # if cube.long_name:
2455- # _setncattr(cf_var, "long_name", cube.long_name)
2456- #
2457- # if cube.units.is_udunits():
2458- # _setncattr(cf_var, "units", str(cube.units))
2459- #
2460- # # Add the CF-netCDF calendar attribute.
2461- # if cube.units.calendar:
2462- # _setncattr(cf_var, "calendar", cube.units.calendar)
2463-
2464- # Set attributes: NB this part is cube-specific (not the same for components)
2465- # - therefore 'set_cf_var_attributes' doesn't set attributes if element is a Cube
2444+ # Set general attrs: NB this part is cube-specific (not the same for components)
2445+ # - so 'set_cf_var_attributes' *doesn't* set these, if element is a Cube
24662446 if iris .FUTURE .save_split_attrs :
24672447 attr_names = cube .attributes .locals .keys ()
24682448 else :
0 commit comments