@@ -1599,6 +1599,8 @@ def get_fselection_numpy(self, key: list | np.ndarray) -> np.ndarray:
15991599 return out .reshape (out_shape ) # should have filled in correct order, just need to reshape
16001600
16011601 # Default when there are booleans
1602+ # TODO: for boolean indexing could be optimised by avoiding
1603+ # calculating out_shape prior to loop and keeping track on-the-fly (like in LazyExpr machinery)
16021604 return self ._get_set_findex_default (_slice , out_shape )
16031605
16041606 def _get_set_findex_default (self , _slice , out_shape = None , updater = None ):
@@ -1718,36 +1720,36 @@ def __getitem__( # noqa: C901
17181720 expr = blosc2 .LazyExpr ._new_expr (key , self .fields , guess = False )
17191721 return expr .where (self )
17201722
1721- # key not iterable
1722- key = key [()] if isinstance (key , NDArray ) else key
1723+ key = key [()] if isinstance (key , NDArray ) else key # key not iterable
17231724 key = tuple (k [()] if isinstance (k , NDArray ) else k for k in key ) if isinstance (key , tuple ) else key
17241725
17251726 # decompress NDArrays
17261727 key_ , mask = process_key (key , self .shape ) # internally handles key an integer
17271728 key = key [()] if hasattr (key , "shape" ) and key .shape == () else key # convert to scalar
1729+
17281730 # fancy indexing
17291731 if isinstance (key_ , (list , np .ndarray )) or builtins .any (
17301732 isinstance (k , (list , np .ndarray )) for k in key_
17311733 ):
1732- # check scalar booleans, which add 1 dim to beginning but which cause problems for ndindex.as_subindex
1734+ # check scalar booleans, which add 1 dim to beginning
17331735 if np .issubdtype (type (key ), bool ) and np .isscalar (key ):
17341736 if key :
17351737 _slice = ndindex .ndindex (()).expand (self .shape ) # just get whole array
17361738 out_shape = _slice .newshape (self .shape )
17371739 return np .expand_dims (self ._get_set_findex_default (_slice , out_shape = out_shape ), 0 )
17381740 else : # do nothing
17391741 return np .empty ((0 ,) + self .shape , dtype = self .dtype )
1740- elif hasattr (key , "dtype" ) and np .issubdtype (key .dtype , np .bool_ ): # check ORIGINAL key
1741- # This can be interpreted as a boolean expression
1742- # elif key.shape == self.shape: # This is faster than the fancy indexing path
1743- # expr = blosc2.lazyexpr(f"(key)")
1744- # The next should be a bit faster
1745- expr = blosc2 .LazyExpr ._new_expr ("key" , {"key" : key }, guess = False )
1742+ elif (
1743+ hasattr (key , "dtype" ) and np .issubdtype (key .dtype , np .bool_ ) and key .shape == self .shape
1744+ ): # check ORIGINAL key
1745+ # This can be interpreted as a boolean expression but only for key shape same as self shape
1746+ expr = blosc2 .LazyExpr ._new_expr ("key" , {"key" : key }, guess = False ).where (self )
17461747 # Decorate with where and force a getitem operation to return actual values.
17471748 # This behavior is consistent with NumPy, although different from e.g. ['expr']
17481749 # which returns a lazy expression.
1749- return expr .where (self )[:]
1750- return self .get_fselection_numpy (key_ ) # fancy index
1750+ # This is faster than the fancy indexing path
1751+ return expr [:]
1752+ return self .get_fselection_numpy (key ) # fancy index default, can be quite slow
17511753
17521754 start , stop , step , none_mask = get_ndarray_start_stop (self .ndim , key_ , self .shape )
17531755 for i , s in enumerate (step ): # (start, stop, -1) => stop < start
@@ -4096,7 +4098,7 @@ def save(array: NDArray, urlpath: str, contiguous=True, **kwargs: Any) -> None:
40964098 array .save (urlpath , contiguous , ** kwargs )
40974099
40984100
4099- def asarray (array : Sequence | np .ndarray | blosc2 .C2Array | NDArray , copy = True , ** kwargs : Any ) -> NDArray : # noqa: C901
4101+ def asarray (array : Sequence | np .ndarray | blosc2 .C2Array | NDArray , copy = True , ** kwargs : Any ) -> NDArray :
41004102 """Convert the `array` to an `NDArray`.
41014103
41024104 Parameters
@@ -4159,10 +4161,7 @@ def asarray(array: Sequence | np.ndarray | blosc2.C2Array | NDArray, copy=True,
41594161 # A getitem operation should be enough to get a numpy array
41604162 array = array [()]
41614163
4162- if dtype != array .dtype :
4163- array = array .astype (dtype = dtype , casting = casting )
4164- if not array .flags .contiguous :
4165- array = np .ascontiguousarray (array )
4164+ array = np .require (array , dtype = dtype , requirements = "C" ) # require contiguous array
41664165
41674166 return blosc2_ext .asarray (array , chunks , blocks , ** kwargs )
41684167
@@ -4182,7 +4181,7 @@ def asarray(array: Sequence | np.ndarray | blosc2.C2Array | NDArray, copy=True,
41824181 for i , (c , s ) in enumerate (zip (coords , chunks , strict = True ))
41834182 )
41844183 # Ensure the array slice is contiguous and of correct dtype
4185- array_slice = np .ascontiguousarray (array [slice_ ], dtype = dtype )
4184+ array_slice = np .require (array [slice_ ], dtype = dtype , requirements = "C" )
41864185 if behaved :
41874186 # The whole chunk is to be updated, so this fastpath is safe
41884187 ndarr .schunk .update_data (nchunk , array_slice , copy = False )
0 commit comments