Skip to content

Commit 97dc7b8

Browse files
authored
Including Common changes for Multidimensional array (#2120)
* Including Common changes for 3d numpy * Updating comments and multidimension * Updating the test case name * Updated the api names and test cases * Updated code review comments. * consistency in description of arb waveform
1 parent 456b9b7 commit 97dc7b8

File tree

15 files changed

+250
-8
lines changed

15 files changed

+250
-8
lines changed

build/helper/metadata_add_all.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,12 @@ def _add_complex_type(parameter):
132132
parameter['complex_type'] = None
133133

134134

135+
def _add_array_dimension(parameter):
136+
'''Adds a array_dimension parameter to the metadata for multi dimensional arrays'''
137+
if 'array_dimension' not in parameter:
138+
parameter['array_dimension'] = 1
139+
140+
135141
def _add_numpy_info(parameter, parameters, config):
136142
'''Adds the following numpy-related information:
137143
@@ -457,6 +463,7 @@ def add_all_function_metadata(functions, config):
457463
_add_ctypes_variable_name(p)
458464
_add_ctypes_type(p, config)
459465
_add_complex_type(p)
466+
_add_array_dimension(p)
460467
_add_numpy_info(p, functions[f]['parameters'], config)
461468
_add_default_value_name(p)
462469
_add_default_value_name_for_docs(p, config['module_name'])

build/templates/_library_interpreter.py.mako

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,12 @@ def _get_ctypes_pointer_for_buffer(value=None, library_type=None, size=None):
5353
% if are_complex_parameters_used:
5454
if library_type in (_complextype.NIComplexI16, _complextype.NIComplexNumberF32, _complextype.NIComplexNumber):
5555
complex_dtype = numpy.dtype(library_type)
56-
structured_array = value.view(complex_dtype)
57-
return structured_array.ctypes.data_as(ctypes.POINTER(library_type))
56+
if value.ndim > 1:
57+
# we create a flattened view of the multi-dimensional numpy array
58+
restructured_array_view = value.ravel().view(complex_dtype)
59+
else:
60+
restructured_array_view = value.view(complex_dtype)
61+
return restructured_array_view.ctypes.data_as(ctypes.POINTER(library_type))
5862
else:
5963
return numpy.ctypeslib.as_ctypes(value)
6064
% else:

build/templates/session.py/numpy_write_method.py.mako

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@
3030
raise TypeError('${parameter['python_name']} must be in C-order')
3131
if ${parameter['python_name']}.dtype is not numpy.dtype('${parameter['numpy_type']}'):
3232
raise TypeError('${parameter['python_name']} must be numpy.ndarray of dtype=${parameter['numpy_type']}, is ' + str(${parameter['python_name']}.dtype))
33+
if ${parameter['python_name']}.ndim != ${parameter['array_dimension']}:
34+
raise TypeError('${parameter['python_name']} must be numpy.ndarray of dimension=${parameter['array_dimension']}, is ' + str(${parameter['python_name']}.ndim))
3335
% endfor
3436
% for p in helper.filter_parameters(parameters, helper.ParameterUsageOptions.INTERPRETER_METHOD_CALL):
3537
% if 'python_api_converter_name' in p:

build/unit_tests/test_metadata_add_all.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,7 @@ def _compare_dicts(actual, expected):
260260
'use_in_python_api': True,
261261
'python_name_or_default_for_init': 'vi',
262262
'complex_type': None,
263+
'array_dimension': 1,
263264
},
264265
{
265266
'ctypes_method_call_snippet': 'name_ctype',
@@ -294,6 +295,7 @@ def _compare_dicts(actual, expected):
294295
'use_in_python_api': True,
295296
'python_name_or_default_for_init': 'name',
296297
'complex_type': None,
298+
'array_dimension': 1,
297299
},
298300
{
299301
'ctypes_method_call_snippet': 'pin_data_buffer_size_ctype',
@@ -331,6 +333,7 @@ def _compare_dicts(actual, expected):
331333
'use_in_python_api': False,
332334
'python_name_or_default_for_init': 'pin_data_buffer_size',
333335
'complex_type': None,
336+
'array_dimension': 1,
334337
},
335338
{
336339
'ctypes_method_call_snippet': 'python_code_input_ctype',
@@ -368,6 +371,7 @@ def _compare_dicts(actual, expected):
368371
'use_in_python_api': True,
369372
'python_name_or_default_for_init': 'python_code_input',
370373
'complex_type': None,
374+
'array_dimension': 1,
371375
},
372376
{
373377
'ctypes_method_call_snippet': 'None if actual_num_pin_data_ctype is None else (ctypes.pointer(actual_num_pin_data_ctype))',
@@ -405,6 +409,7 @@ def _compare_dicts(actual, expected):
405409
'use_in_python_api': False,
406410
'python_name_or_default_for_init': 'actual_num_pin_data',
407411
'complex_type': None,
412+
'array_dimension': 1,
408413
},
409414
{
410415
'ctypes_method_call_snippet': 'expected_pin_states_ctype',
@@ -444,6 +449,7 @@ def _compare_dicts(actual, expected):
444449
'use_in_python_api': True,
445450
'python_name_or_default_for_init': 'expected_pin_states',
446451
'complex_type': None,
452+
'array_dimension': 1,
447453
},
448454
{
449455
'ctypes_method_call_snippet': 'custom_type_input_ctype',
@@ -481,6 +487,7 @@ def _compare_dicts(actual, expected):
481487
'use_in_python_api': True,
482488
'python_name_or_default_for_init': 'custom_type_input',
483489
'complex_type': None,
490+
'array_dimension': 1,
484491
},
485492
{
486493
'ctypes_method_call_snippet': 'None if custom_type_output_ctype is None else (ctypes.pointer(custom_type_output_ctype))',
@@ -518,6 +525,7 @@ def _compare_dicts(actual, expected):
518525
'use_in_python_api': True,
519526
'python_name_or_default_for_init': 'custom_type_output',
520527
'complex_type': None,
528+
'array_dimension': 1,
521529
},
522530
{
523531
'ctypes_method_call_snippet': 'custom_type_without_struct_prefix_input_ctype',
@@ -555,6 +563,7 @@ def _compare_dicts(actual, expected):
555563
'use_in_python_api': True,
556564
'python_name_or_default_for_init': 'custom_type_without_struct_prefix_input',
557565
'complex_type': None,
566+
'array_dimension': 1,
558567
},
559568
{
560569
'ctypes_method_call_snippet': 'None if custom_type_without_struct_prefix_output_ctype is None else (ctypes.pointer(custom_type_without_struct_prefix_output_ctype))',
@@ -592,6 +601,7 @@ def _compare_dicts(actual, expected):
592601
'use_in_python_api': True,
593602
'python_name_or_default_for_init': 'custom_type_without_struct_prefix_output',
594603
'complex_type': None,
604+
'array_dimension': 1,
595605
},
596606
],
597607
'python_name': 'make_a_foo',
@@ -640,6 +650,7 @@ def _compare_dicts(actual, expected):
640650
'use_in_python_api': True,
641651
'python_name_or_default_for_init': 'vi',
642652
'complex_type': None,
653+
'array_dimension': 1,
643654
},
644655
{
645656
'ctypes_method_call_snippet': 'status_ctype',
@@ -677,6 +688,7 @@ def _compare_dicts(actual, expected):
677688
'use_in_python_api': True,
678689
'python_name_or_default_for_init': 'status',
679690
'complex_type': None,
691+
'array_dimension': 1,
680692
},
681693
{
682694
'ctypes_method_call_snippet': 'data_buffer_size_ctype',
@@ -714,6 +726,7 @@ def _compare_dicts(actual, expected):
714726
'use_in_python_api': False,
715727
'python_name_or_default_for_init': 'data_buffer_size',
716728
'complex_type': None,
729+
'array_dimension': 1,
717730
},
718731
{
719732
'ctypes_method_call_snippet': 'data_ctype',
@@ -752,6 +765,7 @@ def _compare_dicts(actual, expected):
752765
'use_in_python_api': True,
753766
'python_name_or_default_for_init': 'data',
754767
'complex_type': None,
768+
'array_dimension': 1,
755769
},
756770
],
757771
'documentation': {

generated/nifake/nifake/_grpc_stub_interpreter.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,9 @@ def fetch_waveform(self, number_of_samples): # noqa: N802
144144
def fetch_waveform_into(self, number_of_samples): # noqa: N802
145145
raise NotImplementedError('numpy-specific methods are not supported over gRPC')
146146

147+
def function_with_3d_numpy_array_of_numpy_complex128_input_parameter(self, multidimensional_array): # noqa: N802
148+
raise NotImplementedError('numpy-specific methods are not supported over gRPC')
149+
147150
def function_with_intflag_parameter(self, flag): # noqa: N802
148151
self._invoke(
149152
self._client.FunctionWithIntflagParameter,

generated/nifake/nifake/_library.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ def __init__(self, ctypes_library):
3636
self.niFake_EnumInputFunctionWithDefaults_cfunc = None
3737
self.niFake_ExportAttributeConfigurationBuffer_cfunc = None
3838
self.niFake_FetchWaveform_cfunc = None
39+
self.niFake_FunctionWith3dNumpyArrayOfNumpyComplex128InputParameter_cfunc = None
3940
self.niFake_FunctionWithIntflagParameter_cfunc = None
4041
self.niFake_FunctionWithRepeatedCapabilityType_cfunc = None
4142
self.niFake_GetABoolean_cfunc = None
@@ -188,6 +189,14 @@ def niFake_FetchWaveform(self, vi, number_of_samples, waveform_data, actual_numb
188189
self.niFake_FetchWaveform_cfunc.restype = ViStatus # noqa: F405
189190
return self.niFake_FetchWaveform_cfunc(vi, number_of_samples, waveform_data, actual_number_of_samples)
190191

192+
def niFake_FunctionWith3dNumpyArrayOfNumpyComplex128InputParameter(self, vi, multidimensional_array): # noqa: N802
193+
with self._func_lock:
194+
if self.niFake_FunctionWith3dNumpyArrayOfNumpyComplex128InputParameter_cfunc is None:
195+
self.niFake_FunctionWith3dNumpyArrayOfNumpyComplex128InputParameter_cfunc = self._get_library_function('niFake_FunctionWith3dNumpyArrayOfNumpyComplex128InputParameter')
196+
self.niFake_FunctionWith3dNumpyArrayOfNumpyComplex128InputParameter_cfunc.argtypes = [ViSession, ctypes.POINTER(NIComplexNumber)] # noqa: F405
197+
self.niFake_FunctionWith3dNumpyArrayOfNumpyComplex128InputParameter_cfunc.restype = ViStatus # noqa: F405
198+
return self.niFake_FunctionWith3dNumpyArrayOfNumpyComplex128InputParameter_cfunc(vi, multidimensional_array)
199+
191200
def niFake_FunctionWithIntflagParameter(self, vi, flag): # noqa: N802
192201
with self._func_lock:
193202
if self.niFake_FunctionWithIntflagParameter_cfunc is None:

generated/nifake/nifake/_library_interpreter.py

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,12 @@ def _get_ctypes_pointer_for_buffer(value=None, library_type=None, size=None):
3232
import numpy
3333
if library_type in (_complextype.NIComplexI16, _complextype.NIComplexNumberF32, _complextype.NIComplexNumber):
3434
complex_dtype = numpy.dtype(library_type)
35-
structured_array = value.view(complex_dtype)
36-
return structured_array.ctypes.data_as(ctypes.POINTER(library_type))
35+
if value.ndim > 1:
36+
# we create a flattened view of the multi-dimensional numpy array
37+
restructured_array_view = value.ravel().view(complex_dtype)
38+
else:
39+
restructured_array_view = value.view(complex_dtype)
40+
return restructured_array_view.ctypes.data_as(ctypes.POINTER(library_type))
3741
else:
3842
return numpy.ctypeslib.as_ctypes(value)
3943
elif isinstance(value, bytes):
@@ -218,6 +222,13 @@ def fetch_waveform_into(self, waveform_data): # noqa: N802
218222
errors.handle_error(self, error_code, ignore_warnings=False, is_error_handling=False)
219223
return
220224

225+
def function_with_3d_numpy_array_of_numpy_complex128_input_parameter(self, multidimensional_array): # noqa: N802
226+
vi_ctype = _visatype.ViSession(self._vi) # case S110
227+
multidimensional_array_ctype = _get_ctypes_pointer_for_buffer(value=multidimensional_array, library_type=_complextype.NIComplexNumber) # case B510
228+
error_code = self._library.niFake_FunctionWith3dNumpyArrayOfNumpyComplex128InputParameter(vi_ctype, multidimensional_array_ctype)
229+
errors.handle_error(self, error_code, ignore_warnings=False, is_error_handling=False)
230+
return
231+
221232
def function_with_intflag_parameter(self, flag): # noqa: N802
222233
vi_ctype = _visatype.ViSession(self._vi) # case S110
223234
flag_ctype = _visatype.ViUInt64(flag.value) # case S130

generated/nifake/nifake/session.py

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -945,6 +945,27 @@ def fetch_waveform_into(self, waveform_data):
945945
raise TypeError('waveform_data must be numpy.ndarray of dtype=float64, is ' + str(waveform_data.dtype))
946946
self._interpreter.fetch_waveform_into(waveform_data)
947947

948+
def function_with_3d_numpy_array_of_numpy_complex128_input_parameter(self, multidimensional_array):
949+
r'''function_with_3d_numpy_array_of_numpy_complex128_input_parameter
950+
951+
Method that takes a 3D numpy array of numpy complex128 as an input parameter.
952+
953+
Args:
954+
multidimensional_array (numpy.array(dtype=numpy.complex128)): Specifies the 3D array of numpy complex numbers to write.
955+
956+
'''
957+
import numpy
958+
959+
if type(multidimensional_array) is not numpy.ndarray:
960+
raise TypeError('multidimensional_array must be {0}, is {1}'.format(numpy.ndarray, type(multidimensional_array)))
961+
if numpy.isfortran(multidimensional_array) is True:
962+
raise TypeError('multidimensional_array must be in C-order')
963+
if multidimensional_array.dtype is not numpy.dtype('complex128'):
964+
raise TypeError('multidimensional_array must be numpy.ndarray of dtype=complex128, is ' + str(multidimensional_array.dtype))
965+
if multidimensional_array.ndim != 3:
966+
raise TypeError('multidimensional_array must be numpy.ndarray of dimension=3, is ' + str(multidimensional_array.ndim))
967+
self._interpreter.function_with_3d_numpy_array_of_numpy_complex128_input_parameter(multidimensional_array)
968+
948969
@ivi_synchronized
949970
def function_with_intflag_parameter(self, flag):
950971
r'''function_with_intflag_parameter
@@ -1682,13 +1703,15 @@ def write_waveform_numpy(self, waveform):
16821703
raise TypeError('waveform must be in C-order')
16831704
if waveform.dtype is not numpy.dtype('float64'):
16841705
raise TypeError('waveform must be numpy.ndarray of dtype=float64, is ' + str(waveform.dtype))
1706+
if waveform.ndim != 1:
1707+
raise TypeError('waveform must be numpy.ndarray of dimension=1, is ' + str(waveform.ndim))
16851708
self._interpreter.write_waveform_numpy(waveform)
16861709

16871710
@ivi_synchronized
16881711
def write_waveform_numpy_complex128(self, waveform_data_array):
16891712
r'''write_waveform_numpy_complex128
16901713
1691-
A method that writes a waveform of numpy complex128 numbers
1714+
A method that writes a waveform of numpy complex128 numbers.
16921715
16931716
Args:
16941717
waveform_data_array (numpy.array(dtype=numpy.complex128)): Specifies the array of data to load into the waveform. Array should be numberOfSamples big.
@@ -1702,6 +1725,8 @@ def write_waveform_numpy_complex128(self, waveform_data_array):
17021725
raise TypeError('waveform_data_array must be in C-order')
17031726
if waveform_data_array.dtype is not numpy.dtype('complex128'):
17041727
raise TypeError('waveform_data_array must be numpy.ndarray of dtype=complex128, is ' + str(waveform_data_array.dtype))
1728+
if waveform_data_array.ndim != 1:
1729+
raise TypeError('waveform_data_array must be numpy.ndarray of dimension=1, is ' + str(waveform_data_array.ndim))
17051730
self._interpreter.write_waveform_numpy_complex128(waveform_data_array)
17061731

17071732
@ivi_synchronized
@@ -1722,6 +1747,8 @@ def write_waveform_numpy_complex64(self, waveform_data_array):
17221747
raise TypeError('waveform_data_array must be in C-order')
17231748
if waveform_data_array.dtype is not numpy.dtype('complex64'):
17241749
raise TypeError('waveform_data_array must be numpy.ndarray of dtype=complex64, is ' + str(waveform_data_array.dtype))
1750+
if waveform_data_array.ndim != 1:
1751+
raise TypeError('waveform_data_array must be numpy.ndarray of dimension=1, is ' + str(waveform_data_array.ndim))
17251752
self._interpreter.write_waveform_numpy_complex64(waveform_data_array)
17261753

17271754
@ivi_synchronized
@@ -1742,6 +1769,8 @@ def write_waveform_numpy_complex_interleaved_i16(self, waveform_data_array):
17421769
raise TypeError('waveform_data_array must be in C-order')
17431770
if waveform_data_array.dtype is not numpy.dtype('int16'):
17441771
raise TypeError('waveform_data_array must be numpy.ndarray of dtype=int16, is ' + str(waveform_data_array.dtype))
1772+
if waveform_data_array.ndim != 1:
1773+
raise TypeError('waveform_data_array must be numpy.ndarray of dimension=1, is ' + str(waveform_data_array.ndim))
17451774
self._interpreter.write_waveform_numpy_complex_interleaved_i16(waveform_data_array)
17461775

17471776
def _close(self):

generated/nifake/nifake/unit_tests/_mock_helper.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ def __init__(self):
4242
self._defaults['FetchWaveform']['return'] = 0
4343
self._defaults['FetchWaveform']['waveformData'] = None
4444
self._defaults['FetchWaveform']['actualNumberOfSamples'] = None
45+
self._defaults['FunctionWith3dNumpyArrayOfNumpyComplex128InputParameter'] = {}
46+
self._defaults['FunctionWith3dNumpyArrayOfNumpyComplex128InputParameter']['return'] = 0
4547
self._defaults['FunctionWithIntflagParameter'] = {}
4648
self._defaults['FunctionWithIntflagParameter']['return'] = 0
4749
self._defaults['FunctionWithRepeatedCapabilityType'] = {}
@@ -339,6 +341,11 @@ def niFake_FetchWaveform(self, vi, number_of_samples, waveform_data, actual_numb
339341
actual_number_of_samples.contents.value = self._defaults['FetchWaveform']['actualNumberOfSamples']
340342
return self._defaults['FetchWaveform']['return']
341343

344+
def niFake_FunctionWith3dNumpyArrayOfNumpyComplex128InputParameter(self, vi, multidimensional_array): # noqa: N802
345+
if self._defaults['FunctionWith3dNumpyArrayOfNumpyComplex128InputParameter']['return'] != 0:
346+
return self._defaults['FunctionWith3dNumpyArrayOfNumpyComplex128InputParameter']['return']
347+
return self._defaults['FunctionWith3dNumpyArrayOfNumpyComplex128InputParameter']['return']
348+
342349
def niFake_FunctionWithIntflagParameter(self, vi, flag): # noqa: N802
343350
if self._defaults['FunctionWithIntflagParameter']['return'] != 0:
344351
return self._defaults['FunctionWithIntflagParameter']['return']
@@ -1043,6 +1050,8 @@ def set_side_effects_and_return_values(self, mock_library):
10431050
mock_library.niFake_ExportAttributeConfigurationBuffer.return_value = 0
10441051
mock_library.niFake_FetchWaveform.side_effect = MockFunctionCallError("niFake_FetchWaveform")
10451052
mock_library.niFake_FetchWaveform.return_value = 0
1053+
mock_library.niFake_FunctionWith3dNumpyArrayOfNumpyComplex128InputParameter.side_effect = MockFunctionCallError("niFake_FunctionWith3dNumpyArrayOfNumpyComplex128InputParameter")
1054+
mock_library.niFake_FunctionWith3dNumpyArrayOfNumpyComplex128InputParameter.return_value = 0
10461055
mock_library.niFake_FunctionWithIntflagParameter.side_effect = MockFunctionCallError("niFake_FunctionWithIntflagParameter")
10471056
mock_library.niFake_FunctionWithIntflagParameter.return_value = 0
10481057
mock_library.niFake_FunctionWithRepeatedCapabilityType.side_effect = MockFunctionCallError("niFake_FunctionWithRepeatedCapabilityType")

0 commit comments

Comments
 (0)