33import datetime as dt
44import sys
55import warnings
6- from collections .abc import Sequence
6+ from collections .abc import Mapping , Sequence
77from typing import Any , Generic , SupportsIndex , TypeVar , Union , cast , overload
88
99import hightime as ht
1717 CHANNEL_NAME ,
1818 UNIT_DESCRIPTION ,
1919 ExtendedPropertyDictionary ,
20+ ExtendedPropertyValue ,
2021)
2122from nitypes .waveform ._scaling import NO_SCALING , ScaleMode
2223from nitypes .waveform ._timing import BaseTiming , PrecisionTiming , Timing , convert_timing
@@ -83,6 +84,9 @@ def from_array_1d(
8384 copy : bool = ...,
8485 start_index : SupportsIndex | None = ...,
8586 sample_count : SupportsIndex | None = ...,
87+ extended_properties : Mapping [str , ExtendedPropertyValue ] | None = ...,
88+ timing : Timing | PrecisionTiming | None = ...,
89+ scale_mode : ScaleMode | None = ...,
8690 ) -> AnalogWaveform [_ScalarType ]: ...
8791
8892 @overload
@@ -94,6 +98,9 @@ def from_array_1d(
9498 copy : bool = ...,
9599 start_index : SupportsIndex | None = ...,
96100 sample_count : SupportsIndex | None = ...,
101+ extended_properties : Mapping [str , ExtendedPropertyValue ] | None = ...,
102+ timing : Timing | PrecisionTiming | None = ...,
103+ scale_mode : ScaleMode | None = ...,
97104 ) -> AnalogWaveform [_ScalarType ]: ...
98105
99106 @overload
@@ -105,6 +112,9 @@ def from_array_1d(
105112 copy : bool = ...,
106113 start_index : SupportsIndex | None = ...,
107114 sample_count : SupportsIndex | None = ...,
115+ extended_properties : Mapping [str , ExtendedPropertyValue ] | None = ...,
116+ timing : Timing | PrecisionTiming | None = ...,
117+ scale_mode : ScaleMode | None = ...,
108118 ) -> AnalogWaveform [Any ]: ...
109119
110120 @staticmethod
@@ -115,6 +125,9 @@ def from_array_1d(
115125 copy : bool = True ,
116126 start_index : SupportsIndex | None = 0 ,
117127 sample_count : SupportsIndex | None = None ,
128+ extended_properties : Mapping [str , ExtendedPropertyValue ] | None = None ,
129+ timing : Timing | PrecisionTiming | None = None ,
130+ scale_mode : ScaleMode | None = None ,
118131 ) -> AnalogWaveform [_ScalarType ]:
119132 """Construct an analog waveform from a one-dimensional array or sequence.
120133
@@ -125,6 +138,9 @@ def from_array_1d(
125138 copy: Specifies whether to copy the array or save a reference to it.
126139 start_index: The sample index at which the analog waveform data begins.
127140 sample_count: The number of samples in the analog waveform.
141+ extended_properties: The extended properties of the analog waveform.
142+ timing: The timing information of the analog waveform.
143+ scale_mode: The scale mode of the analog waveform.
128144
129145 Returns:
130146 An analog waveform containing the specified data.
@@ -143,9 +159,12 @@ def from_array_1d(
143159 raise invalid_arg_type ("input array" , "one-dimensional array or sequence" , array )
144160
145161 return AnalogWaveform (
146- _data = np .asarray (array , dtype , copy = copy ),
162+ raw_data = np .asarray (array , dtype , copy = copy ),
147163 start_index = start_index ,
148164 sample_count = sample_count ,
165+ extended_properties = extended_properties ,
166+ timing = timing ,
167+ scale_mode = scale_mode ,
149168 )
150169
151170 @overload
@@ -157,6 +176,9 @@ def from_array_2d(
157176 copy : bool = ...,
158177 start_index : SupportsIndex | None = ...,
159178 sample_count : SupportsIndex | None = ...,
179+ extended_properties : Mapping [str , ExtendedPropertyValue ] | None = ...,
180+ timing : Timing | PrecisionTiming | None = ...,
181+ scale_mode : ScaleMode | None = ...,
160182 ) -> list [AnalogWaveform [_ScalarType ]]: ...
161183
162184 @overload
@@ -168,6 +190,9 @@ def from_array_2d(
168190 copy : bool = ...,
169191 start_index : SupportsIndex | None = ...,
170192 sample_count : SupportsIndex | None = ...,
193+ extended_properties : Mapping [str , ExtendedPropertyValue ] | None = ...,
194+ timing : Timing | PrecisionTiming | None = ...,
195+ scale_mode : ScaleMode | None = ...,
171196 ) -> list [AnalogWaveform [_ScalarType ]]: ...
172197
173198 @overload
@@ -179,6 +204,9 @@ def from_array_2d(
179204 copy : bool = ...,
180205 start_index : SupportsIndex | None = ...,
181206 sample_count : SupportsIndex | None = ...,
207+ extended_properties : Mapping [str , ExtendedPropertyValue ] | None = ...,
208+ timing : Timing | PrecisionTiming | None = ...,
209+ scale_mode : ScaleMode | None = ...,
182210 ) -> list [AnalogWaveform [Any ]]: ...
183211
184212 @staticmethod
@@ -189,6 +217,9 @@ def from_array_2d(
189217 copy : bool = True ,
190218 start_index : SupportsIndex | None = 0 ,
191219 sample_count : SupportsIndex | None = None ,
220+ extended_properties : Mapping [str , ExtendedPropertyValue ] | None = None ,
221+ timing : Timing | PrecisionTiming | None = None ,
222+ scale_mode : ScaleMode | None = None ,
192223 ) -> list [AnalogWaveform [_ScalarType ]]:
193224 """Construct a list of analog waveforms from a two-dimensional array or nested sequence.
194225
@@ -199,9 +230,16 @@ def from_array_2d(
199230 copy: Specifies whether to copy the array or save a reference to it.
200231 start_index: The sample index at which the analog waveform data begins.
201232 sample_count: The number of samples in the analog waveform.
233+ extended_properties: The extended properties of the analog waveform.
234+ timing: The timing information of the analog waveform.
235+ scale_mode: The scale mode of the analog waveform.
202236
203237 Returns:
204238 A list containing an analog waveform for each row of the specified data.
239+
240+ When constructing multiple analog waveforms, the same extended properties, timing
241+ information, and scale mode are applied to all analog waveforms. Consider assigning
242+ these properties after construction.
205243 """
206244 if isinstance (array , np .ndarray ):
207245 if array .ndim != 2 :
@@ -218,9 +256,12 @@ def from_array_2d(
218256
219257 return [
220258 AnalogWaveform (
221- _data = np .asarray (array [i ], dtype , copy = copy ),
259+ raw_data = np .asarray (array [i ], dtype , copy = copy ),
222260 start_index = start_index ,
223261 sample_count = sample_count ,
262+ extended_properties = extended_properties ,
263+ timing = timing ,
264+ scale_mode = scale_mode ,
224265 )
225266 for i in range (len (array ))
226267 ]
@@ -251,9 +292,12 @@ def __init__( # noqa: D107 - Missing docstring in __init__ (auto-generated noqa
251292 sample_count : SupportsIndex | None = ...,
252293 dtype : None = ...,
253294 * ,
295+ raw_data : None = ...,
254296 start_index : SupportsIndex | None = ...,
255297 capacity : SupportsIndex | None = ...,
256- _data : None = ...,
298+ extended_properties : Mapping [str , ExtendedPropertyValue ] | None = ...,
299+ timing : Timing | PrecisionTiming | None = ...,
300+ scale_mode : ScaleMode | None = ...,
257301 ) -> None : ...
258302
259303 @overload
@@ -262,9 +306,12 @@ def __init__( # noqa: D107 - Missing docstring in __init__ (auto-generated noqa
262306 sample_count : SupportsIndex | None = ...,
263307 dtype : type [_ScalarType_co ] | np .dtype [_ScalarType_co ] = ...,
264308 * ,
309+ raw_data : None = ...,
265310 start_index : SupportsIndex | None = ...,
266311 capacity : SupportsIndex | None = ...,
267- _data : None = ...,
312+ extended_properties : Mapping [str , ExtendedPropertyValue ] | None = ...,
313+ timing : Timing | PrecisionTiming | None = ...,
314+ scale_mode : ScaleMode | None = ...,
268315 ) -> None : ...
269316
270317 @overload
@@ -273,9 +320,12 @@ def __init__( # noqa: D107 - Missing docstring in __init__ (auto-generated noqa
273320 sample_count : SupportsIndex | None = ...,
274321 dtype : None = ...,
275322 * ,
323+ raw_data : npt .NDArray [_ScalarType_co ] | None = ...,
276324 start_index : SupportsIndex | None = ...,
277325 capacity : SupportsIndex | None = ...,
278- _data : npt .NDArray [_ScalarType_co ] | None = ...,
326+ extended_properties : Mapping [str , ExtendedPropertyValue ] | None = ...,
327+ timing : Timing | PrecisionTiming | None = ...,
328+ scale_mode : ScaleMode | None = ...,
279329 ) -> None : ...
280330
281331 @overload
@@ -284,45 +334,71 @@ def __init__( # noqa: D107 - Missing docstring in __init__ (auto-generated noqa
284334 sample_count : SupportsIndex | None = ...,
285335 dtype : npt .DTypeLike = ...,
286336 * ,
337+ raw_data : npt .NDArray [Any ] | None = ...,
287338 start_index : SupportsIndex | None = ...,
288339 capacity : SupportsIndex | None = ...,
289- _data : npt .NDArray [Any ] | None = ...,
340+ extended_properties : Mapping [str , ExtendedPropertyValue ] | None = ...,
341+ timing : Timing | PrecisionTiming | None = ...,
342+ scale_mode : ScaleMode | None = ...,
290343 ) -> None : ...
291344
292345 def __init__ (
293346 self ,
294347 sample_count : SupportsIndex | None = None ,
295348 dtype : npt .DTypeLike = None ,
296349 * ,
350+ raw_data : npt .NDArray [_ScalarType_co ] | None = None ,
297351 start_index : SupportsIndex | None = None ,
298352 capacity : SupportsIndex | None = None ,
299- _data : npt .NDArray [_ScalarType_co ] | None = None ,
353+ extended_properties : Mapping [str , ExtendedPropertyValue ] | None = None ,
354+ timing : Timing | PrecisionTiming | None = None ,
355+ scale_mode : ScaleMode | None = None ,
300356 ) -> None :
301357 """Construct an analog waveform.
302358
303359 Args:
304360 sample_count: The number of samples in the analog waveform.
305361 dtype: The NumPy data type for the analog waveform data. If not specified, the data
306362 type defaults to np.float64.
363+ raw_data: A NumPy ndarray to use for sample storage. The analog waveform takes ownership
364+ of this array. If not specified, an ndarray is created based on the specified dtype,
365+ start index, sample count, and capacity.
307366 start_index: The sample index at which the analog waveform data begins.
308367 sample_count: The number of samples in the analog waveform.
309368 capacity: The number of samples to allocate. Pre-allocating a larger buffer optimizes
310369 appending samples to the waveform.
370+ extended_properties: The extended properties of the analog waveform.
371+ timing: The timing information of the analog waveform.
372+ scale_mode: The scale mode of the analog waveform.
311373
312374 Returns:
313375 An analog waveform.
314-
315- Arguments that are prefixed with an underscore are internal implementation details and are
316- subject to change.
317376 """
318- if _data is None :
377+ if raw_data is None :
319378 self ._init_with_new_array (
320379 sample_count , dtype , start_index = start_index , capacity = capacity
321380 )
322- else :
381+ elif isinstance ( raw_data , np . ndarray ) :
323382 self ._init_with_provided_array (
324- _data , dtype , start_index = start_index , sample_count = sample_count , capacity = capacity
383+ raw_data ,
384+ dtype ,
385+ start_index = start_index ,
386+ sample_count = sample_count ,
387+ capacity = capacity ,
325388 )
389+ else :
390+ raise invalid_arg_type ("raw data" , "NumPy ndarray" , raw_data )
391+
392+ self ._extended_properties = ExtendedPropertyDictionary (extended_properties )
393+
394+ if timing is None :
395+ timing = Timing .empty
396+ self ._timing = timing
397+ self ._converted_timing_cache = {}
398+
399+ if scale_mode is None :
400+ scale_mode = NO_SCALING
401+ self ._scale_mode = scale_mode
326402
327403 def _init_with_new_array (
328404 self ,
@@ -357,10 +433,6 @@ def _init_with_new_array(
357433 self ._data = np .zeros (capacity , dtype )
358434 self ._start_index = start_index
359435 self ._sample_count = sample_count
360- self ._extended_properties = ExtendedPropertyDictionary ()
361- self ._timing = Timing .empty
362- self ._converted_timing_cache = {}
363- self ._scale_mode = NO_SCALING
364436
365437 def _init_with_provided_array (
366438 self ,
@@ -414,10 +486,6 @@ def _init_with_provided_array(
414486 self ._data = data
415487 self ._start_index = start_index
416488 self ._sample_count = sample_count
417- self ._extended_properties = ExtendedPropertyDictionary ()
418- self ._timing = Timing .empty
419- self ._converted_timing_cache = {}
420- self ._scale_mode = NO_SCALING
421489
422490 @property
423491 def raw_data (self ) -> npt .NDArray [_ScalarType_co ]:
@@ -784,3 +852,32 @@ def _increase_capacity(self, amount: int) -> None:
784852 new_capacity = self ._start_index + self ._sample_count + amount
785853 if new_capacity > self .capacity :
786854 self .capacity = new_capacity
855+
856+ def __eq__ (self , value : object , / ) -> bool :
857+ """Return self==value."""
858+ if not isinstance (value , self .__class__ ):
859+ return NotImplemented
860+ return (
861+ self .dtype == value .dtype
862+ and np .array_equal (self .raw_data , value .raw_data )
863+ and self ._extended_properties == value ._extended_properties
864+ and self ._timing == value ._timing
865+ and self ._scale_mode == value ._scale_mode
866+ )
867+
868+ def __repr__ (self ) -> str :
869+ """Return repr(self)."""
870+ args = [f"{ self ._sample_count } " ]
871+ if self .dtype != np .float64 :
872+ args .append (f"{ self .dtype .name } " )
873+ # start_index and capacity are not shown because they are allocation details. raw_data hides
874+ # the unused data before start_index and after start_index+sample_count.
875+ if self ._sample_count > 0 :
876+ args .append (f"raw_data={ self .raw_data !r} " )
877+ if self ._extended_properties :
878+ args .append (f"extended_properties={ self ._extended_properties ._properties !r} " )
879+ if self ._timing is not Timing .empty and self ._timing is not PrecisionTiming .empty :
880+ args .append (f"timing={ self ._timing !r} " )
881+ if self ._scale_mode is not NO_SCALING :
882+ args .append (f"scale_mode={ self ._scale_mode } " )
883+ return f"{ self .__class__ .__module__ } .{ self .__class__ .__name__ } ({ ', ' .join (args )} )"
0 commit comments