Closed mattjbr123 closed 5 months ago
Hi @mattjbr123 - thanks for the detailed report! I'll look into it ... David
Hi Matt - I've had a good look, and agree with you. Your suggested changed change seems to make sense, and all of the current unit tests pass with it in-place. Would you like to submit a PR with the fix (including a change log entry and unit test in cf/test/test_functions.functionTest.test_normalize_slice
)?
Thanks, David
Excellent, thanks David, will do
Done - #782
Changes introduced in v3.16.2 in this commit as part of #760 has caused calls to the subset command to fail when the subset produces indices for (at least?) one cyclic axis in the form of a slice which doesn't satisfy the condition step > 0 and start < 0 and stop > 0 (e.g. slice(-3, 0, 1)) [ CASE 1a ] OR step < 0 and start > 0 and stop < 0 (e.g. slice(0, 2, -1)) [ CASE 1b ] or does satisfy the condition: step > 0 and start < 0 and stop == -size (e.g. slice(-1,-3,1), size=3) [ CASE 2a ] OR step < 0 and stop < 0 and start == -size (e.g. slice(-3, -1, -1), size=3) [ CASE 2b ]
This arises from the following new code in cf.functions (the rest of the modifications to cf.functions in this commit are just refactors as far as I can tell):
in cf.functions.normalize_slice. This function determines whether or not a slice is cyclic, and these lines are designed to catch the cyclic cases after 'normalization' of the slice's start and stop indices by previous lines of the function. In cases 1a and 1b the normalization is skipped as the slices don't satisfy the conditions, in cases 2a and 2b, normalization is performed modifying the start or stop indices of the slice to 0. In both cases an IndexError is now raised by the function causing further modification of the slice and generation of the 'roll' variable in cf.functions.parse_indices to be skipped, whereas in v3.16.1 this modification would still take place, e.g. changing a slice of (-3, 0, 1) to (0, 3, 1) and generating roll = {:-3} If the condition is modified to
the function correctly determines the slice to be cyclic and thus the slice is modified appropriately. Without this modification, an object with a dimension of size 0 is returned when __getitem__ is called on a field's Data object when __getitem__ is called on a field as part of the cf.field.subset process, and thus the following error is raised in cf.field.__getitem__:
I have run the same example in a cf v3.16.1 and v3.16.2 environment, with debugging enabled and some additional print statements thrown in for good-measure:
Try with cf v3.16.2
Try with cf v3.16.1.
Ignore the fact that the other axis in indices is now a dask array instead of a np.array or list, I don't think that is relevant.
There may be other cases I've missed, but I thought this a suitable place to stop digging and ask for input!! I can see why the cases highlighted are not considered cyclic... A cyclic variable x = [0,1,2] with a slice of (-3, 0, 1) should produce [0,1,2], which happens in v3.16.1 as expected but not in v3.16.2 as explained.
The outputs from the cf.environment calls are:
For v3.16.2: Platform: Linux-3.10.0-1160.114.2.el7.x86_64-x86_64-with-glibc2.34 HDF5 library: 1.14.3 netcdf library: 4.9.2 udunits2 library: /home/users/mattjbr/miniconda3/envs/unifhytest/lib/libudunits2.so.0 esmpy/ESMF: 8.6.1 Python: 3.12.3 dask: 2024.4.2 netCDF4: 1.6.5 psutil: 5.9.8 packaging: 24.0 numpy: 1.26.4 scipy: 1.13.0 matplotlib: not available cftime: 1.6.3 cfunits: 3.3.7 cfplot: not available cfdm: 1.11.1.0 cf: 3.16.2
For v3.16.1: Platform: Linux-3.10.0-1160.114.2.el7.x86_64-x86_64-with-glibc2.34 HDF5 library: 1.14.3 netcdf library: 4.9.2 udunits2 library: /home/users/mattjbr/miniconda3/envs/unifhytest2/lib/libudunits2.so.0 esmpy/ESMF: 8.6.1 Python: 3.12.3 dask: 2024.5.0 netCDF4: 1.6.5 psutil: 5.9.8 packaging: 24.0 numpy: 1.26.4 scipy: 1.13.0 matplotlib: not available cftime: 1.6.3 cfunits: 3.3.7 cfplot: not available cfdm: 1.11.1.0 cf: 3.16.1