@@ -40,20 +40,19 @@ class Array(LGDOCollection):
4040
4141 def __init__ (
4242 self ,
43- nda : np .ndarray = None ,
43+ nda : np .ndarray | ak . Array | None = None ,
4444 shape : tuple [int , ...] = (),
45- dtype : np .dtype = None ,
45+ dtype : np .dtype | None = None ,
4646 fill_val : float | int | None = None ,
4747 attrs : dict [str , Any ] | None = None ,
4848 ) -> None :
4949 """
5050 Parameters
5151 ----------
5252 nda
53- An :class:`numpy.ndarray` to be used for this object's internal
54- array. Note: the array is used directly, not copied. If not
55- supplied, internal memory is newly allocated based on the shape and
56- dtype arguments.
53+ An :class:`numpy.ndarray` or :class:`ak.Array` to be used for this
54+ object's internal array. If the Awkward array carries a ``units``
55+ parameter, it will forwarded as LGDO attribute.
5756 shape
5857 A numpy-format shape specification for shape of the internal
5958 ndarray. Required if `nda` is ``None``, otherwise unused.
@@ -65,7 +64,21 @@ def __init__(
6564 the array is allocated with all elements set to the corresponding
6665 fill value. If `nda` is not ``None``, this parameter is ignored.
6766 attrs
68- A set of user attributes to be carried along with this LGDO.
67+ A set of user attributes to be carried along with this LGDO. These
68+ attributes have always precedence over all the others (e.g. those
69+ carried by `nda`).
70+
71+ Warning
72+ -------
73+ This constructor has partial units support. It supports fishing `units`
74+ from Awkward Array parameters but not (yet) from e.g. NumPy+Pint
75+ arrays. In any case, the user can always attach units later by
76+ modifying the dictionary held by :attr:`attrs`.
77+
78+ Note
79+ ----
80+ The array is used directly, not copied. If not supplied, internal
81+ memory is newly allocated based on the shape and dtype arguments.
6982 """
7083 if nda is None :
7184 if fill_val is None :
@@ -75,6 +88,26 @@ def __init__(
7588 else :
7689 nda = np .full (shape , fill_val , dtype = dtype )
7790
91+ elif isinstance (nda , ak .Array ):
92+ # units: we don't just forward all ak parameters, there might be
93+ # some weird thing in there
94+ units = ak .parameters (nda ).get ("units" , None )
95+ if units is not None :
96+ if attrs is None :
97+ attrs = {}
98+
99+ # give precedence to the user units
100+ attrs = {"units" : units } | attrs
101+
102+ if nda .type .content .parameters .get ("__array__" ) == "string" :
103+ # Variable length strings aren't quite up to snuff yet, so pad the
104+ # fixed-width string length in case we want to update the array
105+ # TODO: numpy 2.2.5 fixes this; but it required python v3.10 or higher
106+ s_len = np .max (ak .num (nda ))
107+ nda = np .array (nda , dtype = f"<U{ s_len * 2 } " )
108+ else :
109+ nda = ak .to_numpy (nda ) # this is zero-copy
110+
78111 elif isinstance (nda , Array ):
79112 nda = nda .nda
80113
0 commit comments