Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add get_channel_names to niscope API #1957

Merged
merged 9 commits into from
May 2, 2023
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ All notable changes to this project will be documented in this file.
* #### Removed
* ### `niscope` (NI-SCOPE)
* #### Added
* `get_channel_names()`
* #### Changed
* #### Removed
* ### `niswitch` (NI-SWITCH)
Expand Down
39 changes: 39 additions & 0 deletions docs/niscope/class.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1894,6 +1894,45 @@ fetch_measurement_stats



get_channel_names
-----------------

.. py:currentmodule:: niscope.Session

.. py:method:: get_channel_names(indices)

Returns a list of channel names for given channel indices.





:param indices:


Index list for the channels in the session. Valid values are from zero to the total number of channels in the session minus one. The index string can be one of the following formats:

- A comma-separated list—for example, "0,2,3,1"
- A range using a hyphen—for example, "0-3"
- A range using a colon—for example, "0:3 "

You can combine comma-separated lists and ranges that use a hyphen or colon. Both out-of-order and repeated indices are supported ("2,3,0," "1,2,2,3"). White space characters, including spaces, tabs, feeds, and carriage returns, are allowed between characters. Ranges can be incrementing or decrementing.




:type indices: basic sequence types or str or int

:rtype: list of str
:return:


The channel name(s) at the specified indices.





get_equalization_filter_coefficients
------------------------------------

Expand Down
7 changes: 7 additions & 0 deletions generated/niscope/niscope/_grpc_stub_interpreter.py
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,13 @@ def get_attribute_vi_string(self, channel_list, attribute_id): # noqa: N802
)
return response.value

def get_channel_names(self, indices): # noqa: N802
response = self._invoke(
self._client.GetChannelNameFromString,
grpc_types.GetChannelNameFromStringRequest(vi=self._vi, index=indices),
)
return response.name

def get_equalization_filter_coefficients(self, channel, number_of_coefficients): # noqa: N802
response = self._invoke(
self._client.GetEqualizationFilterCoefficients,
Expand Down
9 changes: 9 additions & 0 deletions generated/niscope/niscope/_library.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ def __init__(self, ctypes_library):
self.niScope_GetAttributeViInt64_cfunc = None
self.niScope_GetAttributeViReal64_cfunc = None
self.niScope_GetAttributeViString_cfunc = None
self.niScope_GetChannelNameFromString_cfunc = None
self.niScope_GetEqualizationFilterCoefficients_cfunc = None
self.niScope_GetError_cfunc = None
self.niScope_ImportAttributeConfigurationBuffer_cfunc = None
Expand Down Expand Up @@ -396,6 +397,14 @@ def niScope_GetAttributeViString(self, vi, channel_list, attribute_id, buf_size,
self.niScope_GetAttributeViString_cfunc.restype = ViStatus # noqa: F405
return self.niScope_GetAttributeViString_cfunc(vi, channel_list, attribute_id, buf_size, value)

def niScope_GetChannelNameFromString(self, vi, indices, name_buffer_size, names): # noqa: N802
with self._func_lock:
if self.niScope_GetChannelNameFromString_cfunc is None:
self.niScope_GetChannelNameFromString_cfunc = self._get_library_function('niScope_GetChannelNameFromString')
self.niScope_GetChannelNameFromString_cfunc.argtypes = [ViSession, ctypes.POINTER(ViChar), ViInt32, ctypes.POINTER(ViChar)] # noqa: F405
self.niScope_GetChannelNameFromString_cfunc.restype = ViStatus # noqa: F405
return self.niScope_GetChannelNameFromString_cfunc(vi, indices, name_buffer_size, names)

def niScope_GetEqualizationFilterCoefficients(self, vi, channel, number_of_coefficients, coefficients): # noqa: N802
with self._func_lock:
if self.niScope_GetEqualizationFilterCoefficients_cfunc is None:
Expand Down
13 changes: 13 additions & 0 deletions generated/niscope/niscope/_library_interpreter.py
Original file line number Diff line number Diff line change
Expand Up @@ -486,6 +486,19 @@ def get_attribute_vi_string(self, channel_list, attribute_id): # noqa: N802
errors.handle_error(self, error_code, ignore_warnings=False, is_error_handling=False)
return value_ctype.value.decode(self._encoding)

def get_channel_names(self, indices): # noqa: N802
vi_ctype = _visatype.ViSession(self._vi) # case S110
indices_ctype = ctypes.create_string_buffer(indices.encode(self._encoding)) # case C020
name_buffer_size_ctype = _visatype.ViInt32() # case S170
names_ctype = None # case C050
error_code = self._library.niScope_GetChannelNameFromString(vi_ctype, indices_ctype, name_buffer_size_ctype, names_ctype)
errors.handle_error(self, error_code, ignore_warnings=True, is_error_handling=False)
name_buffer_size_ctype = _visatype.ViInt32(error_code) # case S180
names_ctype = (_visatype.ViChar * name_buffer_size_ctype.value)() # case C060
error_code = self._library.niScope_GetChannelNameFromString(vi_ctype, indices_ctype, name_buffer_size_ctype, names_ctype)
errors.handle_error(self, error_code, ignore_warnings=False, is_error_handling=False)
return names_ctype.value.decode(self._encoding)

def get_equalization_filter_coefficients(self, channel, number_of_coefficients): # noqa: N802
vi_ctype = _visatype.ViSession(self._vi) # case S110
channel_ctype = ctypes.create_string_buffer(channel.encode(self._encoding)) # case C010
Expand Down
24 changes: 24 additions & 0 deletions generated/niscope/niscope/session.py
Original file line number Diff line number Diff line change
Expand Up @@ -3420,6 +3420,30 @@ def _get_attribute_vi_string(self, attribute_id):
value = self._interpreter.get_attribute_vi_string(self._repeated_capability, attribute_id)
return value

@ivi_synchronized
def get_channel_names(self, indices):
r'''get_channel_names

Returns a list of channel names for given channel indices.

Args:
indices (basic sequence types or str or int): Index list for the channels in the session. Valid values are from zero to the total number of channels in the session minus one. The index string can be one of the following formats:

- A comma-separated list—for example, "0,2,3,1"
- A range using a hyphen—for example, "0-3"
- A range using a colon—for example, "0:3 "

You can combine comma-separated lists and ranges that use a hyphen or colon. Both out-of-order and repeated indices are supported ("2,3,0," "1,2,2,3"). White space characters, including spaces, tabs, feeds, and carriage returns, are allowed between characters. Ranges can be incrementing or decrementing.


Returns:
names (list of str): The channel name(s) at the specified indices.

'''
indices = _converters.convert_repeated_capabilities_without_prefix(indices)
names = self._interpreter.get_channel_names(indices)
return _converters.convert_comma_separated_string_to_list(names)

@ivi_synchronized
def _get_equalization_filter_coefficients(self, number_of_coefficients):
r'''_get_equalization_filter_coefficients
Expand Down
16 changes: 16 additions & 0 deletions generated/niscope/niscope/unit_tests/_mock_helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,9 @@ def __init__(self):
self._defaults['GetAttributeViString'] = {}
self._defaults['GetAttributeViString']['return'] = 0
self._defaults['GetAttributeViString']['value'] = None
self._defaults['GetChannelNameFromString'] = {}
self._defaults['GetChannelNameFromString']['return'] = 0
self._defaults['GetChannelNameFromString']['name'] = None
self._defaults['GetEqualizationFilterCoefficients'] = {}
self._defaults['GetEqualizationFilterCoefficients']['return'] = 0
self._defaults['GetEqualizationFilterCoefficients']['coefficients'] = None
Expand Down Expand Up @@ -623,6 +626,17 @@ def niScope_GetAttributeViString(self, vi, channel_list, attribute_id, buf_size,
value.value = self._defaults['GetAttributeViString']['value'].encode('ascii')
return self._defaults['GetAttributeViString']['return']

def niScope_GetChannelNameFromString(self, vi, indices, name_buffer_size, names): # noqa: N802
if self._defaults['GetChannelNameFromString']['return'] != 0:
return self._defaults['GetChannelNameFromString']['return']
# names
if self._defaults['GetChannelNameFromString']['name'] is None:
raise MockFunctionCallError("niScope_GetChannelNameFromString", param='name')
if name_buffer_size.value == 0:
return len(self._defaults['GetChannelNameFromString']['name'])
names.value = self._defaults['GetChannelNameFromString']['name'].encode('ascii')
return self._defaults['GetChannelNameFromString']['return']

def niScope_GetEqualizationFilterCoefficients(self, vi, channel, number_of_coefficients, coefficients): # noqa: N802
if self._defaults['GetEqualizationFilterCoefficients']['return'] != 0:
return self._defaults['GetEqualizationFilterCoefficients']['return']
Expand Down Expand Up @@ -898,6 +912,8 @@ def set_side_effects_and_return_values(self, mock_library):
mock_library.niScope_GetAttributeViReal64.return_value = 0
mock_library.niScope_GetAttributeViString.side_effect = MockFunctionCallError("niScope_GetAttributeViString")
mock_library.niScope_GetAttributeViString.return_value = 0
mock_library.niScope_GetChannelNameFromString.side_effect = MockFunctionCallError("niScope_GetChannelNameFromString")
mock_library.niScope_GetChannelNameFromString.return_value = 0
mock_library.niScope_GetEqualizationFilterCoefficients.side_effect = MockFunctionCallError("niScope_GetEqualizationFilterCoefficients")
mock_library.niScope_GetEqualizationFilterCoefficients.return_value = 0
mock_library.niScope_GetError.side_effect = MockFunctionCallError("niScope_GetError")
Expand Down
58 changes: 57 additions & 1 deletion src/niscope/metadata/functions_addon.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,63 @@
]
}
}

functions_additional_get_channel_name = {
'GetChannelNameFromString': {
'documentation': {
'description': 'Returns a list of channel names for given channel indices.\n'
},
'included_in_proto': True,
'parameters': [
{
'direction': 'in',
'documentation': {
'description': '\nThe instrument handle you obtain from niScope_init that identifies a\nparticular instrument session.\n'
},
'name': 'vi',
'type': 'ViSession'
},
{
'direction': 'in',
'documentation': {
'description': 'Index list for the channels in the session. Valid values are from zero to the total number of channels in the session minus one. The index string can be one of the following formats:\n\n- A comma-separated list—for example, "0,2,3,1"\n- A range using a hyphen—for example, "0-3"\n- A range using a colon—for example, "0:3 "\n\nYou can combine comma-separated lists and ranges that use a hyphen or colon. Both out-of-order and repeated indices are supported ("2,3,0," "1,2,2,3"). White space characters, including spaces, tabs, feeds, and carriage returns, are allowed between characters. Ranges can be incrementing or decrementing.\n'
},
'grpc_name': 'index',
'name': 'index',
'python_api_converter_name': 'convert_repeated_capabilities_without_prefix',
'python_name': 'indices',
'type': 'ViConstString',
'type_in_documentation': 'basic sequence types or str or int',
},
{
'direction': 'in',
'documentation': {
'description': 'The number of elements in the ViChar array you specify for name.\n'
},
'name': 'nameBufferSize',
'type': 'ViInt32'
},
{
'direction': 'out',
'documentation': {
'description': 'The channel name(s) at the specified indices.\n'
},
'grpc_name': 'name',
'name': 'name',
'python_api_converter_name': 'convert_comma_separated_string_to_list',
'python_name': 'names',
'size': {
'mechanism': 'ivi-dance',
'value': 'nameBufferSize'
},
'type': 'ViChar[]',
'type_in_documentation': 'list of str',
}
],
'python_name': 'get_channel_names',
'render_in_session_base': True,
ni-jfitzger marked this conversation as resolved.
Show resolved Hide resolved
'returns': 'ViStatus'
}
}
functions_additional_fetch_array_measurement = {
'FancyFetchArrayMeasurement': {
'codegen_method': 'python-only',
Expand Down
12 changes: 12 additions & 0 deletions src/niscope/system_tests/test_system_niscope.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,11 @@ def multi_instrument_session(self, session_creation_kwargs):
with niscope.Session(','.join(instruments), False, True, 'Simulate=1, DriverSetup=Model:5164; BoardType:PXIe', **session_creation_kwargs) as simulated_session:
yield simulated_session

@pytest.fixture(scope='function')
def multi_instrument_session_5171(self, session_creation_kwargs): # High channel-count session for get_channel_names testing
with niscope.Session(','.join(instruments), False, True, 'Simulate=1, DriverSetup=Model:5171R (8CH); BoardType:PXIe', **session_creation_kwargs) as simulated_session:
yield simulated_session

@pytest.fixture(scope='function')
def session_5124(self, session_creation_kwargs):
with daqmx_sim_5124_lock:
Expand All @@ -72,6 +77,13 @@ def test_vi_string_attribute(self, multi_instrument_session):
assert trigger_source == multi_instrument_session.acq_arm_source

# Basic usability tests
def test_get_channel_names(self, multi_instrument_session_5171):
ni-jfitzger marked this conversation as resolved.
Show resolved Hide resolved
expected_string = [f'{instruments[0]}/{x}' for x in range(8)] + [f'{instruments[1]}/{x}' for x in range(4)]
# Sanity test few different types of input. No need for test to be exhaustive
# since all the various types are covered by converter unit tests.
channel_indices = ['0-1, 2, 3:4', 5, (6, 7), range(8, 10), slice(10, 12)]
assert multi_instrument_session_5171.get_channel_names(indices=channel_indices) == expected_string

def test_read(self, multi_instrument_session):
test_voltage = 1.0
test_record_length = 2000
Expand Down