@@ -1737,6 +1737,7 @@ def _create_generic_cf_array_var(
17371737 element_dims = None ,
17381738 fill_value = None ,
17391739 compression_kwargs = None ,
1740+ packing_controls : dict | None = None ,
17401741 is_dataless = False ,
17411742 ):
17421743 """Create theCF-netCDF variable given dimensional_metadata.
@@ -1864,7 +1865,10 @@ def _create_generic_cf_array_var(
18641865 else :
18651866 element_type = type (element ).__name__
18661867 data = self ._ensure_valid_dtype (data , element_type , element )
1867- dtype = data .dtype .newbyteorder ("=" )
1868+ if not packing_controls :
1869+ dtype = data .dtype .newbyteorder ("=" )
1870+ else :
1871+ dtype = packing_controls ["dtype" ]
18681872
18691873 # Check if this is a dim-coord.
18701874 is_dimcoord = cube is not None and element in cube .dim_coords
@@ -1897,6 +1901,10 @@ def _create_generic_cf_array_var(
18971901
18981902 # Add the data to the CF-netCDF variable.
18991903 if not is_dataless :
1904+ if packing_controls :
1905+ # We must set packing attributes (if any), before assigning values.
1906+ for key , value in packing_controls ["attributes" ]:
1907+ _setncattr (cf_var , key , value )
19001908 self ._lazy_stream_data (data = data , cf_var = cf_var )
19011909
19021910 # Add names + units
@@ -2331,11 +2339,10 @@ def _create_cf_data_variable(
23312339 # Get the values in a form which is valid for the file format.
23322340 is_dataless = cube .is_dataless ()
23332341
2334- if not is_dataless :
2342+ packing_controls = None
2343+ if packing and not is_dataless :
23352344 data = self ._ensure_valid_dtype (cube .core_data (), "cube" , cube )
2336- if not packing :
2337- dtype = data .dtype .newbyteorder ("=" )
2338- elif isinstance (packing , dict ):
2345+ if isinstance (packing , dict ):
23392346 if "dtype" not in packing :
23402347 msg = "The dtype attribute is required for packing."
23412348 raise ValueError (msg )
@@ -2373,26 +2380,14 @@ def _create_cf_data_variable(
23732380 else :
23742381 add_offset = cmin + 2 ** (n - 1 ) * scale_factor
23752382
2376- def set_packing_ncattrs (cfvar ):
2377- """Set netCDF packing attributes.
2378-
2379- NOTE: cfvar needs to be a _thread_safe_nc._ThreadSafeWrapper subclass.
2383+ packing_controls = {
2384+ "dtype" : dtype ,
2385+ "attributes" : [
2386+ ("scale_factor" , scale_factor ),
2387+ ("add_offset" , add_offset ),
2388+ ],
2389+ }
23802390
2381- """
2382- assert hasattr (cfvar , "THREAD_SAFE_FLAG" )
2383- if packing :
2384- if scale_factor :
2385- _setncattr (cfvar , "scale_factor" , scale_factor )
2386- if add_offset :
2387- _setncattr (cfvar , "add_offset" , add_offset )
2388-
2389- # cf_name = self._get_element_variable_name(cube_or_mesh=None, element=cube)
2390- # while cf_name in self._dataset.variables:
2391- # cf_name = self._increment_name(cf_name)
2392- #
2393- # cf_var = self._dataset.createVariable(
2394- # cf_name, dtype, dimension_names, fill_value=fill_value, **kwargs
2395- # )
23962391 # Create the cube CF-netCDF data variable with data payload.
23972392 cf_name = self ._create_generic_cf_array_var (
23982393 cube ,
@@ -2401,28 +2396,13 @@ def set_packing_ncattrs(cfvar):
24012396 element_dims = dimension_names ,
24022397 fill_value = fill_value ,
24032398 compression_kwargs = kwargs ,
2399+ packing_controls = packing_controls ,
24042400 is_dataless = is_dataless ,
24052401 )
24062402 cf_var = self ._dataset .variables [cf_name ]
24072403
2408- if not is_dataless :
2409- set_packing_ncattrs (cf_var )
2410-
2411- # if cube.standard_name:
2412- # _setncattr(cf_var, "standard_name", cube.standard_name)
2413- #
2414- # if cube.long_name:
2415- # _setncattr(cf_var, "long_name", cube.long_name)
2416- #
2417- # if cube.units.is_udunits():
2418- # _setncattr(cf_var, "units", str(cube.units))
2419- #
2420- # # Add the CF-netCDF calendar attribute.
2421- # if cube.units.calendar:
2422- # _setncattr(cf_var, "calendar", cube.units.calendar)
2423-
2424- # Set attributes: NB this part is cube-specific (not the same for components)
2425- # - therefore 'set_cf_var_attributes' doesn't set attributes if element is a Cube
2404+ # Set general attrs: NB this part is cube-specific (not the same for components)
2405+ # - so 'set_cf_var_attributes' *doesn't* set these, if element is a Cube
24262406 if iris .FUTURE .save_split_attrs :
24272407 attr_names = cube .attributes .locals .keys ()
24282408 else :
0 commit comments