The following minimal example fails:
import netCDF4
import numpy as np
with netCDF4.Dataset("test_dim_autocomplex.nc", "w", auto_complex=True) as f:
f.createDimension("x", size=2)
f.createDimension("complex", size=2)
c_dim = f.createVariable("data_dim", np.float64, ("x", "complex"))
c_dim[:] = np.array([[1., 2.], [3., 4.]])
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
File src/netCDF4/_netCDF4.pyx:5601, in netCDF4._netCDF4.Variable.__setitem__()
ValueError: cannot reshape array of size 4 into shape (2,)
During handling of the above exception, another exception occurred:
ValueError Traceback (most recent call last)
Cell In[31], line 5
3 f.createDimension("complex", size=2)
4 c_dim = f.createVariable("data_dim", np.float64, ("x", "complex"))
----> 5 c_dim[:] = np.array([[1., 2.], [3., 4.]])
File src/netCDF4/_netCDF4.pyx:5603, in netCDF4._netCDF4.Variable.__setitem__()
File /tmp/mvce/.venv/lib/python3.13/site-packages/numpy/lib/_stride_tricks_impl.py:410, in broadcast_to(array, shape, subok)
367 @array_function_dispatch(_broadcast_to_dispatcher, module='numpy')
368 def broadcast_to(array, shape, subok=False):
369 """Broadcast an array to a new shape.
370
371 Parameters
(...) 408 [1, 2, 3]])
409 """
--> 410 return _broadcast_to(array, shape, subok=subok, readonly=True)
File /tmp/mvce/.venv/lib/python3.13/site-packages/numpy/lib/_stride_tricks_impl.py:349, in _broadcast_to(array, shape, subok, readonly)
346 raise ValueError('all elements of broadcast shape must be non-'
347 'negative')
348 extras = []
--> 349 it = np.nditer(
350 (array,), flags=['multi_index', 'refs_ok', 'zerosize_ok'] + extras,
351 op_flags=['readonly'], itershape=shape, order='C')
352 with it:
353 # never really has writebackifcopy semantics
354 broadcast = it.itviews[0]
ValueError: input operand has more dimensions than allowed by the axis remapping
This does work without auto_complex=True, and because the dtype isn't actually complex, auto_complex should really have no effect here because we're writing. Writing without auto_complex and then reading with auto_complex=True does work as expected, returning a complex array of length 2.
I think this is happening because we create a variable in the netCDF first, detect that it matches a complex variable and so do our complex-variable fixing up, and then try to fill it with something not actually complex.
The line numbers in the error messages don't quite match up for me, but I think it's this bit:
# reshape data array if needed to conform with start,count,stride.
if data.ndim != len(datashape) or\
(data.shape != datashape and data.ndim > 1): # issue #1083
# create a view so shape in caller is not modified (issue 90)
try: # if extra singleton dims, just reshape
data = data.view()
data.shape = tuple(datashape)
except ValueError: # otherwise broadcast
data = numpy.broadcast_to(data, datashape)
It also does work fine when writing the numpy struct version.
I'm not quite sure how to handle this off the top of my head. We probably need to do something like check if the variable dtype is complex and if it matches the passed in data, and if not, fall back to doing something else. Either writing it as the original dtype, or converting the passed in data to complex.
The following minimal example fails:
This does work without
auto_complex=True, and because the dtype isn't actuallycomplex,auto_complexshould really have no effect here because we're writing. Writing withoutauto_complexand then reading withauto_complex=Truedoes work as expected, returning acomplexarray of length 2.I think this is happening because we create a variable in the netCDF first, detect that it matches a
complexvariable and so do our complex-variable fixing up, and then try to fill it with something not actuallycomplex.The line numbers in the error messages don't quite match up for me, but I think it's this bit:
It also does work fine when writing the numpy struct version.
I'm not quite sure how to handle this off the top of my head. We probably need to do something like check if the variable dtype is complex and if it matches the passed in data, and if not, fall back to doing something else. Either writing it as the original dtype, or converting the passed in data to
complex.