NCAS-CMS / cf-python

A CF-compliant Earth Science data analysis library
http://ncas-cms.github.io/cf-python
MIT License
125 stars 19 forks source link

Encounter error when reproducing recipe #705

Open Nemo1166 opened 11 months ago

Nemo1166 commented 11 months ago

UFuncTypeError: Cannot cast ufunc 'subtract' output from dtype('float64') to dtype('int64') with casting rule 'same_kind'

Expectation

Same with recipe 1 in documentation.

Reproduction

Run plot_01_recipe.ipynb, with data file cru_ts4.06.1901.2021.tmp.dat.nc (link).

Traceback info

here ``` { "name": "UFuncTypeError", "message": "Cannot cast ufunc 'subtract' output from dtype('float64') to dtype('int64') with casting rule 'same_kind'", "stack": "--------------------------------------------------------------------------- UFuncTypeError Traceback (most recent call last) c:\\Users\\10502\\Desktop\\dataset-derived-near-surface-meteorological-variables-a2eeaa79-acc2-4c4a-9e90-b5b6ecd9c3f9\\plot_01_recipe.ipynb 单元格 22 line 1 ----> 1 annual_global_avg = global_avg.collapse(\"T: mean\", group=cf.Y()) 2 cfp.lineplot( 3 annual_global_avg, 4 color=\"red\", 5 title=\"Annual global mean surface temperature\", 6 ) File c:\\Users\\10502\\miniforge3\\envs\\cf311\\Lib\\site-packages\\cf\\decorators.py:71, in _deprecated_kwarg_check..deprecated_kwarg_check_decorator..precede_with_kwarg_deprecation_check(self, *args, **kwargs) 62 pass_in_kwarg = {depr_kwarg: True} 63 _DEPRECATION_ERROR_KWARGS( 64 self, 65 operation_method.__name__, (...) 68 removed_at=removed_at, 69 ) # pragma: no cover ---> 71 operation_method_result = operation_method(self, *args, **kwargs) 73 # Decorated method has same return signature as if undecorated: 74 return operation_method_result File c:\\Users\\10502\\miniforge3\\envs\\cf311\\Lib\\site-packages\\cfdm\\decorators.py:171, in _manage_log_level_via_verbosity..verbose_override_wrapper(*args, **kwargs) 168 # After method completes, re-set any changes to log level or 169 # enabling 170 try: --> 171 return method_with_verbose_kwarg(*args, **kwargs) 172 except Exception: 173 raise File c:\\Users\\10502\\miniforge3\\envs\\cf311\\Lib\\site-packages\\cf\\field.py:7941, in Field.collapse(self, method, axes, squeeze, mtol, weights, ddof, a, inplace, group, regroup, within_days, within_years, over_days, over_years, coordinate, group_by, group_span, group_contiguous, measure, scale, radius, great_circle, verbose, remove_vertical_crs, _create_zero_size_cell_bounds, _update_cell_methods, i, _debug, **kwargs) 7937 g_weights = None 7939 axis = [a for a in collapse_axes][0] -> 7941 f = f._collapse_grouped( 7942 method, 7943 axis, 7944 within=within, 7945 over=over, 7946 within_days=within_days, 7947 within_years=within_years, 7948 over_days=over_days, 7949 over_years=over_years, 7950 group=group, 7951 group_span=group_span, 7952 group_contiguous=group_contiguous, 7953 regroup=regroup, 7954 mtol=mtol, 7955 ddof=ddof, 7956 measure=measure, 7957 weights=g_weights, 7958 squeeze=squeeze, 7959 coordinate=coordinate, 7960 group_by=group_by, 7961 axis_in=axes_in[0], 7962 verbose=verbose, 7963 ) 7965 if regroup: 7966 # Grouped collapse: Return the numpy array 7967 return f File c:\\Users\\10502\\miniforge3\\envs\\cf311\\Lib\\site-packages\\cfdm\\decorators.py:171, in _manage_log_level_via_verbosity..verbose_override_wrapper(*args, **kwargs) 168 # After method completes, re-set any changes to log level or 169 # enabling 170 try: --> 171 return method_with_verbose_kwarg(*args, **kwargs) 172 except Exception: 173 raise File c:\\Users\\10502\\miniforge3\\envs\\cf311\\Lib\\site-packages\\cf\\field.py:8893, in Field._collapse_grouped(self, method, axis, within, over, within_days, within_years, over_days, over_years, group, group_span, group_contiguous, mtol, ddof, regroup, coordinate, measure, weights, squeeze, group_by, axis_in, verbose) 8887 classification.fill(-1) 8889 lower, upper, lower_limit, upper_limit = _tyu( 8890 coord, group_by, True 8891 ) -> 8893 classification, n = _time_interval( 8894 classification, 8895 0, 8896 coord=coord, 8897 interval=group, 8898 lower=lower, 8899 upper=upper, 8900 lower_limit=lower_limit, 8901 upper_limit=upper_limit, 8902 group_by=group_by, 8903 ) 8905 if group_span is True or group_span is None: 8906 # Use the group definition as the group span 8907 group_span = group File c:\\Users\\10502\\miniforge3\\envs\\cf311\\Lib\\site-packages\\cf\\field.py:8397, in Field._collapse_grouped.._time_interval(classification, n, coord, interval, lower, upper, lower_limit, upper_limit, group_by, extra_condition) 8395 while lower <= upper_limit: 8396 lower, upper = interval.interval(lower) -> 8397 classification, n, lower, upper = _ddddd( 8398 classification, 8399 n, 8400 lower, 8401 upper, 8402 True, 8403 coord, 8404 group_by_coords, 8405 extra_condition, 8406 ) 8407 else: 8408 # Decreasing dimension coordinate 8409 lower, upper = interval.bounds(upper) File c:\\Users\\10502\\miniforge3\\envs\\cf311\\Lib\\site-packages\\cf\\field.py:8336, in Field._collapse_grouped.._ddddd(classification, n, lower, upper, increasing, coord, group_by_coords, extra_condition) 8333 if extra_condition: 8334 q &= extra_condition -> 8336 index = q.evaluate(coord).array 8337 classification[index] = n 8339 if increasing: File c:\\Users\\10502\\miniforge3\\envs\\cf311\\Lib\\site-packages\\cf\\mixin\\propertiesdata.py:2437, in PropertiesData.array(self) 2434 if data is None: 2435 raise AttributeError(f\"{self.__class__.__name__} has no data\") -> 2437 return data.array File c:\\Users\\10502\\miniforge3\\envs\\cf311\\Lib\\site-packages\\cf\\data\\data.py:5096, in Data.array(self) 5054 @property 5055 def array(self): 5056 \"\"\"A numpy array copy of the data. 5057 5058 In-place changes to the returned numpy array do not affect the (...) 5094 5095 \"\"\" -> 5096 array = self.compute().copy() 5097 if not isinstance(array, np.ndarray): 5098 array = np.asanyarray(array) File c:\\Users\\10502\\miniforge3\\envs\\cf311\\Lib\\site-packages\\cf\\data\\data.py:2652, in Data.compute(self) 2620 def compute(self): # noqa: F811 2621 \"\"\"A numpy view the data. 2622 2623 In-place changes to the returned numpy array *might* affect (...) 2650 2651 \"\"\" -> 2652 a = self.to_dask_array().compute() 2654 if np.ma.isMA(a): 2655 if self.hardmask: File c:\\Users\\10502\\miniforge3\\envs\\cf311\\Lib\\site-packages\\dask\\base.py:342, in DaskMethodsMixin.compute(self, **kwargs) 318 def compute(self, **kwargs): 319 \"\"\"Compute this dask collection 320 321 This turns a lazy Dask collection into its in-memory equivalent. (...) 340 dask.compute 341 \"\"\" --> 342 (result,) = compute(self, traverse=False, **kwargs) 343 return result File c:\\Users\\10502\\miniforge3\\envs\\cf311\\Lib\\site-packages\\dask\\base.py:628, in compute(traverse, optimize_graph, scheduler, get, *args, **kwargs) 625 postcomputes.append(x.__dask_postcompute__()) 627 with shorten_traceback(): --> 628 results = schedule(dsk, keys, **kwargs) 630 return repack([f(r, *a) for r, (f, a) in zip(results, postcomputes)]) File c:\\Users\\10502\\miniforge3\\envs\\cf311\\Lib\\site-packages\\cf\\data\\dask_utils.py:643, in cf_units(a, from_units, to_units) 606 def cf_units(a, from_units, to_units): 607 \"\"\"Convert array values to have different equivalent units. 608 609 .. versionadded:: 3.14.0 (...) 641 642 \"\"\" --> 643 return Units.conform( 644 a, from_units=from_units, to_units=to_units, inplace=False 645 ) File c:\\Users\\10502\\miniforge3\\envs\\cf311\\Lib\\site-packages\\cf\\units.py:29, in Units.conform(*args, **kwargs) 27 @staticmethod 28 def conform(*args, **kwargs): ---> 29 return cfUnits.conform(*args, **kwargs) File c:\\Users\\10502\\miniforge3\\envs\\cf311\\Lib\\site-packages\\cfunits\\units.py:2297, in Units.conform(cls, x, from_units, to_units, inplace) 2293 _cv_free(cv_converter) 2295 offset *= scale.item() -> 2297 x -= offset 2299 return x UFuncTypeError: Cannot cast ufunc 'subtract' output from dtype('float64') to dtype('int64') with casting rule 'same_kind'" } ```

Env

# cf.environment(paths=False)
Platform: Windows-10-10.0.22631-SP0
HDF5 library: 1.14.2
netcdf library: 4.9.2
udunits2 library: C:\Users\10502\miniforge3\envs\cf311\Scripts\udunits2.dll
esmpy/ESMF: 8.4.2
Python: 3.11.6
dask: 2023.11.0
netCDF4: 1.6.5
psutil: 5.9.5
packaging: 23.2
numpy: 1.26.2
scipy: 1.11.4
matplotlib: 3.8.2
cftime: 1.6.3
cfunits: 3.3.6
cfplot: 3.2.23
cfdm: 1.10.1.2
cf: 3.15.4
Nemo1166 commented 11 months ago

error also occurred when reproducing this in Docs:Analysis.

Nemo1166 commented 11 months ago

It seems can be solved by following modification:

In pkg cfunits, file units.py, line 2297:

-  x -= offset
+  x = x - offset

I haven't check other components to avoid potential problems.

sadielbartholomew commented 11 months ago

Thanks for reporting this! We'll look into it soon. I'll comment here with any updates from when we get a chance to work on it.