From f33da305ad3ad501e939d7438257809082499d29 Mon Sep 17 00:00:00 2001 From: Stephen Thompson Date: Wed, 27 Sep 2023 10:23:51 +0100 Subject: [PATCH 1/9] Issue #78 added new class to mocks to enable better get frame --- tests/polaris_mocks.py | 46 ++++++++++++++----- ...st_sksurgerynditracker_mockndi_getframe.py | 15 +++--- 2 files changed, 43 insertions(+), 18 deletions(-) diff --git a/tests/polaris_mocks.py b/tests/polaris_mocks.py index 4c007f6..250d324 100644 --- a/tests/polaris_mocks.py +++ b/tests/polaris_mocks.py @@ -2,6 +2,7 @@ """scikit-surgerynditracker mocks for polaris""" +from numpy import array, concatenate import ndicapy SETTINGS_POLARIS = { @@ -60,15 +61,36 @@ def mockndiVER(_device, _other_arg): #pylint:disable=invalid-name """Mock of ndiVER""" return 'Mock for Testing' -def mockndiGetBXFrame(_device, _port_handle): #pylint:disable=invalid-name - """Mock of ndiGetBXFrame""" - bx_frame_count = 0 - return bx_frame_count - -def mockndiGetBXTransform(_device, _port_handle): #pylint:disable=invalid-name - """Mock of ndiGetBXTransform""" - return [0,0,0,0,0,0,0,0] - -def mockndiGetBXTransformMissing(_device, _port_handle): #pylint:disable=invalid-name - """Mock of ndiGetBXTransform""" - return "MISSING" +class MockBXFrameSource(): + """ + A class to handle mocking of calls to get + frame. Enables us to increment the frame number and return + changing values + """ + def __init__(self): + self.bx_frame_count = 0 + self.rotation = array([0, 0, 0, 0]) + self.position = array([0, 0, 0]) + self.velocity = array([10, -20, 5]) + self.quality = array([1]) + + def mockndiGetBXFrame(self, _device, _port_handle): #pylint:disable=invalid-name + """Mock of ndiGetBXFrame""" + self.bx_frame_count += 1 + + return self.bx_frame_count + + def mockndiGetBXTransform(self, _device, _port_handle): #pylint:disable=invalid-name + """ + Mock of ndiGetBXTransform. To enable a simple test of tracking + smoothing translate the mock object between frames. Full testing of + the averaging code is in the base class + sksurgerycore.tests.algorithms + """ + assert self.bx_frame_count > 0 + + return concatenate((self.rotation, self.position, self.quality)) + + def mockndiGetBXTransformMissing(self, _device, _port_handle): #pylint:disable=invalid-name + """Mock of ndiGetBXTransform""" + return "MISSING" diff --git a/tests/test_sksurgerynditracker_mockndi_getframe.py b/tests/test_sksurgerynditracker_mockndi_getframe.py index 950c22f..518faa9 100644 --- a/tests/test_sksurgerynditracker_mockndi_getframe.py +++ b/tests/test_sksurgerynditracker_mockndi_getframe.py @@ -6,8 +6,8 @@ from tests.polaris_mocks import SETTINGS_POLARIS, mockndiProbe, \ mockndiOpen, mockndiGetError, mockComports, \ mockndiGetPHSRNumberOfHandles, mockndiGetPHRQHandle, \ - mockndiGetPHSRHandle, mockndiVER, mockndiGetBXFrame, \ - mockndiGetBXTransform, mockndiGetBXTransformMissing + mockndiGetPHSRHandle, mockndiVER, \ + MockBXFrameSource def test_getframe_polaris_mock(mocker): """ @@ -15,6 +15,7 @@ def test_getframe_polaris_mock(mocker): reqs: 03, 04 """ tracker = None + bxsource = MockBXFrameSource() mocker.patch('serial.tools.list_ports.comports', mockComports) mocker.patch('ndicapy.ndiProbe', mockndiProbe) mocker.patch('ndicapy.ndiOpen', mockndiOpen) @@ -27,8 +28,8 @@ def test_getframe_polaris_mock(mocker): mocker.patch('ndicapy.ndiPVWRFromFile') mocker.patch('ndicapy.ndiGetPHSRHandle', mockndiGetPHSRHandle) mocker.patch('ndicapy.ndiVER', mockndiVER) - mocker.patch('ndicapy.ndiGetBXFrame', mockndiGetBXFrame) - mocker.patch('ndicapy.ndiGetBXTransform', mockndiGetBXTransform) + mocker.patch('ndicapy.ndiGetBXFrame', bxsource.mockndiGetBXFrame) + mocker.patch('ndicapy.ndiGetBXTransform', bxsource.mockndiGetBXTransform) tracker = NDITracker(SETTINGS_POLARIS) tracker.get_frame() @@ -41,6 +42,7 @@ def test_getframe_missing(mocker): reqs: 03, 04 """ tracker = None + bxsource = MockBXFrameSource() mocker.patch('serial.tools.list_ports.comports', mockComports) mocker.patch('ndicapy.ndiProbe', mockndiProbe) mocker.patch('ndicapy.ndiOpen', mockndiOpen) @@ -53,8 +55,9 @@ def test_getframe_missing(mocker): mocker.patch('ndicapy.ndiPVWRFromFile') mocker.patch('ndicapy.ndiGetPHSRHandle', mockndiGetPHSRHandle) mocker.patch('ndicapy.ndiVER', mockndiVER) - mocker.patch('ndicapy.ndiGetBXFrame', mockndiGetBXFrame) - mocker.patch('ndicapy.ndiGetBXTransform', mockndiGetBXTransformMissing) + mocker.patch('ndicapy.ndiGetBXFrame', bxsource.mockndiGetBXFrame) + mocker.patch('ndicapy.ndiGetBXTransform', + bxsource.mockndiGetBXTransformMissing) tracker = NDITracker(SETTINGS_POLARIS) tracker.get_frame() From 8cbeb6e3b0cdc7a592a73f8cad3b806614dc203a Mon Sep 17 00:00:00 2001 From: Stephen Thompson Date: Wed, 27 Sep 2023 13:55:56 +0100 Subject: [PATCH 2/9] Issue #78 created mock device to keep track of number of tools --- tests/polaris_mocks.py | 20 +++++++++++++++---- ...st_sksurgerynditracker_mockndi_getframe.py | 14 +++++++------ ...est_sksurgerynditracker_mockndi_polaris.py | 11 +++++----- 3 files changed, 30 insertions(+), 15 deletions(-) diff --git a/tests/polaris_mocks.py b/tests/polaris_mocks.py index 250d324..ddbb4b7 100644 --- a/tests/polaris_mocks.py +++ b/tests/polaris_mocks.py @@ -49,10 +49,6 @@ def mockndiGetPHSRNumberOfHandles(_device): #pylint:disable=invalid-name """Mock of ndiGetPHSRNumberOfHandles""" return 4 -def mockndiGetPHRQHandle(_device): #pylint:disable=invalid-name - """Mock of ndiGetPHRQHandle""" - return int(0) - def mockndiGetPHSRHandle(_device, index): #pylint:disable=invalid-name """Mock of ndiGetPHSRHandle""" return int(index) @@ -61,6 +57,22 @@ def mockndiVER(_device, _other_arg): #pylint:disable=invalid-name """Mock of ndiVER""" return 'Mock for Testing' +class MockNDIDevice(): + """ + A mock NDI device, enables us to keep track of how many tools we've added + """ + def __init__(self): + self.attached_tools = 0 + + def mockndiCommand(self, _device, command): #pylint:disable=invalid-name + """Mock a general command, strings over serial""" + if command == "PHRQ:*********1****": + self.attached_tools += 1 + + def mockndiGetPHRQHandle(self, _device): #pylint:disable=invalid-name + """Mock of ndiGetPHRQHandle""" + return int(self.attached_tools - 1) + class MockBXFrameSource(): """ A class to handle mocking of calls to get diff --git a/tests/test_sksurgerynditracker_mockndi_getframe.py b/tests/test_sksurgerynditracker_mockndi_getframe.py index 518faa9..03ea24f 100644 --- a/tests/test_sksurgerynditracker_mockndi_getframe.py +++ b/tests/test_sksurgerynditracker_mockndi_getframe.py @@ -5,9 +5,9 @@ from tests.polaris_mocks import SETTINGS_POLARIS, mockndiProbe, \ mockndiOpen, mockndiGetError, mockComports, \ - mockndiGetPHSRNumberOfHandles, mockndiGetPHRQHandle, \ + mockndiGetPHSRNumberOfHandles, \ mockndiGetPHSRHandle, mockndiVER, \ - MockBXFrameSource + MockNDIDevice, MockBXFrameSource def test_getframe_polaris_mock(mocker): """ @@ -16,15 +16,16 @@ def test_getframe_polaris_mock(mocker): """ tracker = None bxsource = MockBXFrameSource() + ndidevice = MockNDIDevice() mocker.patch('serial.tools.list_ports.comports', mockComports) mocker.patch('ndicapy.ndiProbe', mockndiProbe) mocker.patch('ndicapy.ndiOpen', mockndiOpen) - mocker.patch('ndicapy.ndiCommand') + mocker.patch('ndicapy.ndiCommand', ndidevice.mockndiCommand) mocker.patch('ndicapy.ndiGetError', mockndiGetError) mocker.patch('ndicapy.ndiClose') mocker.patch('ndicapy.ndiGetPHSRNumberOfHandles', mockndiGetPHSRNumberOfHandles) - mocker.patch('ndicapy.ndiGetPHRQHandle', mockndiGetPHRQHandle) + mocker.patch('ndicapy.ndiGetPHRQHandle', ndidevice.mockndiGetPHRQHandle) mocker.patch('ndicapy.ndiPVWRFromFile') mocker.patch('ndicapy.ndiGetPHSRHandle', mockndiGetPHSRHandle) mocker.patch('ndicapy.ndiVER', mockndiVER) @@ -43,15 +44,16 @@ def test_getframe_missing(mocker): """ tracker = None bxsource = MockBXFrameSource() + ndidevice = MockNDIDevice() mocker.patch('serial.tools.list_ports.comports', mockComports) mocker.patch('ndicapy.ndiProbe', mockndiProbe) mocker.patch('ndicapy.ndiOpen', mockndiOpen) - mocker.patch('ndicapy.ndiCommand') + mocker.patch('ndicapy.ndiCommand', ndidevice.mockndiCommand) mocker.patch('ndicapy.ndiGetError', mockndiGetError) mocker.patch('ndicapy.ndiClose') mocker.patch('ndicapy.ndiGetPHSRNumberOfHandles', mockndiGetPHSRNumberOfHandles) - mocker.patch('ndicapy.ndiGetPHRQHandle', mockndiGetPHRQHandle) + mocker.patch('ndicapy.ndiGetPHRQHandle', ndidevice.mockndiGetPHRQHandle) mocker.patch('ndicapy.ndiPVWRFromFile') mocker.patch('ndicapy.ndiGetPHSRHandle', mockndiGetPHSRHandle) mocker.patch('ndicapy.ndiVER', mockndiVER) diff --git a/tests/test_sksurgerynditracker_mockndi_polaris.py b/tests/test_sksurgerynditracker_mockndi_polaris.py index df8ab34..03c2022 100644 --- a/tests/test_sksurgerynditracker_mockndi_polaris.py +++ b/tests/test_sksurgerynditracker_mockndi_polaris.py @@ -8,8 +8,8 @@ from tests.polaris_mocks import SETTINGS_POLARIS, mockndiProbe, \ mockndiOpen, mockndiOpen_fail, mockndiGetError, mockComports, \ - mockndiGetPHSRNumberOfHandles, mockndiGetPHRQHandle, \ - mockndiGetPHSRHandle, mockndiVER + mockndiGetPHSRNumberOfHandles, \ + mockndiGetPHSRHandle, mockndiVER, MockNDIDevice def test_connect_polaris_mock(mocker): """ @@ -17,15 +17,16 @@ def test_connect_polaris_mock(mocker): reqs: 03, 04 """ tracker = None + ndidevice = MockNDIDevice() mocker.patch('serial.tools.list_ports.comports', mockComports) mocker.patch('ndicapy.ndiProbe', mockndiProbe) mocker.patch('ndicapy.ndiOpen', mockndiOpen) - mocker.patch('ndicapy.ndiCommand') + mocker.patch('ndicapy.ndiCommand', ndidevice.mockndiCommand) mocker.patch('ndicapy.ndiGetError', mockndiGetError) mocker.patch('ndicapy.ndiClose') mocker.patch('ndicapy.ndiGetPHSRNumberOfHandles', mockndiGetPHSRNumberOfHandles) - mocker.patch('ndicapy.ndiGetPHRQHandle', mockndiGetPHRQHandle) + mocker.patch('ndicapy.ndiGetPHRQHandle', ndidevice.mockndiGetPHRQHandle) mocker.patch('ndicapy.ndiPVWRFromFile') mocker.patch('ndicapy.ndiGetPHSRHandle', mockndiGetPHSRHandle) mocker.patch('ndicapy.ndiVER', mockndiVER) @@ -45,7 +46,7 @@ def test_connect_polaris_mock(mocker): assert spy.call_args_list[9] == call(True, 'PHSR:01') assert spy.call_args_list[10] == call(True, 'PHSR:02') assert spy.call_args_list[11] == call(True, 'PINIT:00') - assert spy.call_args_list[12] == call(True, 'PINIT:00') + assert spy.call_args_list[12] == call(True, 'PINIT:01') assert spy.call_args_list[13] == call(True, 'PHSR:03') assert spy.call_args_list[14] == call(True, 'PENA:00D') assert spy.call_args_list[15] == call(True, 'PENA:01D') From 44bd71d783482b0cc2e43294d75063b33039a312 Mon Sep 17 00:00:00 2001 From: Stephen Thompson Date: Wed, 27 Sep 2023 15:25:02 +0100 Subject: [PATCH 3/9] Issue #78 get some output from get frame --- tests/test_sksurgerynditracker_mockndi_getframe.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tests/test_sksurgerynditracker_mockndi_getframe.py b/tests/test_sksurgerynditracker_mockndi_getframe.py index 03ea24f..4ba98ea 100644 --- a/tests/test_sksurgerynditracker_mockndi_getframe.py +++ b/tests/test_sksurgerynditracker_mockndi_getframe.py @@ -62,6 +62,10 @@ def test_getframe_missing(mocker): bxsource.mockndiGetBXTransformMissing) tracker = NDITracker(SETTINGS_POLARIS) - tracker.get_frame() + (port_handles, time_stamps, frame_numbers, tracking, + tracking_quality ) = tracker.get_frame() + print (port_handles) + print (time_stamps) + print (frame_numbers) del tracker From 08f16777ce14748f6ddf5579f7eae6d7d653f6ec Mon Sep 17 00:00:00 2001 From: Stephen Thompson Date: Wed, 27 Sep 2023 15:47:13 +0100 Subject: [PATCH 4/9] Issue #78 get_frame should return either a string or a tuple --- tests/polaris_mocks.py | 6 ++++-- tests/test_sksurgerynditracker_mockndi_getframe.py | 4 ++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/tests/polaris_mocks.py b/tests/polaris_mocks.py index ddbb4b7..8d904fa 100644 --- a/tests/polaris_mocks.py +++ b/tests/polaris_mocks.py @@ -100,8 +100,10 @@ def mockndiGetBXTransform(self, _device, _port_handle): #pylint:disable=invalid- sksurgerycore.tests.algorithms """ assert self.bx_frame_count > 0 - - return concatenate((self.rotation, self.position, self.quality)) + #the base ndicapi library uses Py_BuildValue to return the transform + #as a tuple of double float values, so let's make sure we're als + #returning a tuple + return tuple(concatenate((self.rotation, self.position, self.quality))) def mockndiGetBXTransformMissing(self, _device, _port_handle): #pylint:disable=invalid-name """Mock of ndiGetBXTransform""" diff --git a/tests/test_sksurgerynditracker_mockndi_getframe.py b/tests/test_sksurgerynditracker_mockndi_getframe.py index 4ba98ea..1b0504c 100644 --- a/tests/test_sksurgerynditracker_mockndi_getframe.py +++ b/tests/test_sksurgerynditracker_mockndi_getframe.py @@ -62,8 +62,8 @@ def test_getframe_missing(mocker): bxsource.mockndiGetBXTransformMissing) tracker = NDITracker(SETTINGS_POLARIS) - (port_handles, time_stamps, frame_numbers, tracking, - tracking_quality ) = tracker.get_frame() + (port_handles, time_stamps, frame_numbers, _tracking, + _tracking_quality ) = tracker.get_frame() print (port_handles) print (time_stamps) print (frame_numbers) From 55defcd13ce2215875dd3557f6cdf929efe6e73f Mon Sep 17 00:00:00 2001 From: Stephen Thompson Date: Wed, 27 Sep 2023 16:43:33 +0100 Subject: [PATCH 5/9] Issue #78 put getPHSR handles in class so it returns the right number of values, updated mock polaris to suit --- tests/polaris_mocks.py | 9 +++--- ...st_sksurgerynditracker_mockndi_getframe.py | 5 ++- ...est_sksurgerynditracker_mockndi_polaris.py | 31 +++++++++---------- 3 files changed, 22 insertions(+), 23 deletions(-) diff --git a/tests/polaris_mocks.py b/tests/polaris_mocks.py index 8d904fa..ccaad8d 100644 --- a/tests/polaris_mocks.py +++ b/tests/polaris_mocks.py @@ -45,10 +45,6 @@ def mockComports(): #pylint:disable=invalid-name mock_ports[5].device = 'good port' return mock_ports -def mockndiGetPHSRNumberOfHandles(_device): #pylint:disable=invalid-name - """Mock of ndiGetPHSRNumberOfHandles""" - return 4 - def mockndiGetPHSRHandle(_device, index): #pylint:disable=invalid-name """Mock of ndiGetPHSRHandle""" return int(index) @@ -73,6 +69,11 @@ def mockndiGetPHRQHandle(self, _device): #pylint:disable=invalid-name """Mock of ndiGetPHRQHandle""" return int(self.attached_tools - 1) + def mockndiGetPHSRNumberOfHandles(self, _device): #pylint:disable=invalid-name + """Mock of ndiGetPHSRNumberOfHandles""" + return self.attached_tools + + class MockBXFrameSource(): """ A class to handle mocking of calls to get diff --git a/tests/test_sksurgerynditracker_mockndi_getframe.py b/tests/test_sksurgerynditracker_mockndi_getframe.py index 1b0504c..beff8ef 100644 --- a/tests/test_sksurgerynditracker_mockndi_getframe.py +++ b/tests/test_sksurgerynditracker_mockndi_getframe.py @@ -5,7 +5,6 @@ from tests.polaris_mocks import SETTINGS_POLARIS, mockndiProbe, \ mockndiOpen, mockndiGetError, mockComports, \ - mockndiGetPHSRNumberOfHandles, \ mockndiGetPHSRHandle, mockndiVER, \ MockNDIDevice, MockBXFrameSource @@ -24,7 +23,7 @@ def test_getframe_polaris_mock(mocker): mocker.patch('ndicapy.ndiGetError', mockndiGetError) mocker.patch('ndicapy.ndiClose') mocker.patch('ndicapy.ndiGetPHSRNumberOfHandles', - mockndiGetPHSRNumberOfHandles) + ndidevice.mockndiGetPHSRNumberOfHandles) mocker.patch('ndicapy.ndiGetPHRQHandle', ndidevice.mockndiGetPHRQHandle) mocker.patch('ndicapy.ndiPVWRFromFile') mocker.patch('ndicapy.ndiGetPHSRHandle', mockndiGetPHSRHandle) @@ -52,7 +51,7 @@ def test_getframe_missing(mocker): mocker.patch('ndicapy.ndiGetError', mockndiGetError) mocker.patch('ndicapy.ndiClose') mocker.patch('ndicapy.ndiGetPHSRNumberOfHandles', - mockndiGetPHSRNumberOfHandles) + ndidevice.mockndiGetPHSRNumberOfHandles) mocker.patch('ndicapy.ndiGetPHRQHandle', ndidevice.mockndiGetPHRQHandle) mocker.patch('ndicapy.ndiPVWRFromFile') mocker.patch('ndicapy.ndiGetPHSRHandle', mockndiGetPHSRHandle) diff --git a/tests/test_sksurgerynditracker_mockndi_polaris.py b/tests/test_sksurgerynditracker_mockndi_polaris.py index 03c2022..2a90be0 100644 --- a/tests/test_sksurgerynditracker_mockndi_polaris.py +++ b/tests/test_sksurgerynditracker_mockndi_polaris.py @@ -8,7 +8,6 @@ from tests.polaris_mocks import SETTINGS_POLARIS, mockndiProbe, \ mockndiOpen, mockndiOpen_fail, mockndiGetError, mockComports, \ - mockndiGetPHSRNumberOfHandles, \ mockndiGetPHSRHandle, mockndiVER, MockNDIDevice def test_connect_polaris_mock(mocker): @@ -18,6 +17,8 @@ def test_connect_polaris_mock(mocker): """ tracker = None ndidevice = MockNDIDevice() + #add a couple of extra tools to increase test coverage + ndidevice.attached_tools = 2 mocker.patch('serial.tools.list_ports.comports', mockComports) mocker.patch('ndicapy.ndiProbe', mockndiProbe) mocker.patch('ndicapy.ndiOpen', mockndiOpen) @@ -25,7 +26,7 @@ def test_connect_polaris_mock(mocker): mocker.patch('ndicapy.ndiGetError', mockndiGetError) mocker.patch('ndicapy.ndiClose') mocker.patch('ndicapy.ndiGetPHSRNumberOfHandles', - mockndiGetPHSRNumberOfHandles) + ndidevice.mockndiGetPHSRNumberOfHandles) mocker.patch('ndicapy.ndiGetPHRQHandle', ndidevice.mockndiGetPHRQHandle) mocker.patch('ndicapy.ndiPVWRFromFile') mocker.patch('ndicapy.ndiGetPHSRHandle', mockndiGetPHSRHandle) @@ -33,25 +34,23 @@ def test_connect_polaris_mock(mocker): spy = mocker.spy(ndicapy, 'ndiCommand') tracker = NDITracker(SETTINGS_POLARIS) - assert spy.call_count == 18 + assert spy.call_count == 16 assert spy.call_args_list[0] == call(True, 'INIT:') assert spy.call_args_list[1] == call(True, 'COMM:50000') assert spy.call_args_list[2] == call(True, 'PHSR:01') assert spy.call_args_list[3] == call(True, 'PHF:00') assert spy.call_args_list[4] == call(True, 'PHF:01') - assert spy.call_args_list[5] == call(True, 'PHF:02') - assert spy.call_args_list[6] == call(True, 'PHF:03') - assert spy.call_args_list[7] == call(True, 'PHRQ:*********1****') - assert spy.call_args_list[8] == call(True, 'PHRQ:*********1****') - assert spy.call_args_list[9] == call(True, 'PHSR:01') - assert spy.call_args_list[10] == call(True, 'PHSR:02') - assert spy.call_args_list[11] == call(True, 'PINIT:00') - assert spy.call_args_list[12] == call(True, 'PINIT:01') - assert spy.call_args_list[13] == call(True, 'PHSR:03') - assert spy.call_args_list[14] == call(True, 'PENA:00D') - assert spy.call_args_list[15] == call(True, 'PENA:01D') - assert spy.call_args_list[16] == call(True, 'PENA:02D') - assert spy.call_args_list[17] == call(True, 'PENA:03D') + assert spy.call_args_list[5] == call(True, 'PHRQ:*********1****') + assert spy.call_args_list[6] == call(True, 'PHRQ:*********1****') + assert spy.call_args_list[7] == call(True, 'PHSR:01') + assert spy.call_args_list[8] == call(True, 'PHSR:02') + assert spy.call_args_list[9] == call(True, 'PINIT:02') + assert spy.call_args_list[10] == call(True, 'PINIT:03') + assert spy.call_args_list[11] == call(True, 'PHSR:03') + assert spy.call_args_list[12] == call(True, 'PENA:00D') + assert spy.call_args_list[13] == call(True, 'PENA:01D') + assert spy.call_args_list[14] == call(True, 'PENA:02D') + assert spy.call_args_list[15] == call(True, 'PENA:03D') del tracker def test_connect_polaris_mk_fserial(mocker): From 13aaeead4aee9c0743ab911c8b8439d76277e89a Mon Sep 17 00:00:00 2001 From: Stephen Thompson Date: Wed, 27 Sep 2023 17:24:05 +0100 Subject: [PATCH 6/9] Issue #78 implemnted return value tests for missing frame --- tests/polaris_mocks.py | 22 +++++++++++++++++-- ...st_sksurgerynditracker_mockndi_getframe.py | 20 ++++++++++++++--- 2 files changed, 37 insertions(+), 5 deletions(-) diff --git a/tests/polaris_mocks.py b/tests/polaris_mocks.py index ccaad8d..2e82c65 100644 --- a/tests/polaris_mocks.py +++ b/tests/polaris_mocks.py @@ -82,14 +82,32 @@ class MockBXFrameSource(): """ def __init__(self): self.bx_frame_count = 0 + self.bx_call_count = 0 self.rotation = array([0, 0, 0, 0]) self.position = array([0, 0, 0]) self.velocity = array([10, -20, 5]) self.quality = array([1]) + self.tracked_tools = 0 - def mockndiGetBXFrame(self, _device, _port_handle): #pylint:disable=invalid-name + def setdevice(self, ndidevice): + """ + We set an ndidevice so we know how many tracked objects to + return + """ + assert isinstance (ndidevice, MockNDIDevice) + self.tracked_tools = ndidevice.attached_tools + + def mockndiGetBXFrame(self, _device, port_handle): #pylint:disable=invalid-name """Mock of ndiGetBXFrame""" - self.bx_frame_count += 1 + self.bx_call_count += 1 + ph_int = int.from_bytes(port_handle, byteorder = 'little') + if ph_int == 0: + self.bx_frame_count += 1 + + assert ph_int < self.tracked_tools + if ph_int == self.tracked_tools - 1: + assert self.bx_call_count == self.bx_frame_count * \ + self.tracked_tools return self.bx_frame_count diff --git a/tests/test_sksurgerynditracker_mockndi_getframe.py b/tests/test_sksurgerynditracker_mockndi_getframe.py index beff8ef..cbb20fb 100644 --- a/tests/test_sksurgerynditracker_mockndi_getframe.py +++ b/tests/test_sksurgerynditracker_mockndi_getframe.py @@ -1,6 +1,8 @@ # coding=utf-8 """scikit-surgerynditracker tests using a mocked ndicapy""" + +import numpy as np from sksurgerynditracker.nditracker import NDITracker from tests.polaris_mocks import SETTINGS_POLARIS, mockndiProbe, \ @@ -32,6 +34,8 @@ def test_getframe_polaris_mock(mocker): mocker.patch('ndicapy.ndiGetBXTransform', bxsource.mockndiGetBXTransform) tracker = NDITracker(SETTINGS_POLARIS) + + bxsource.setdevice(ndidevice) tracker.get_frame() del tracker @@ -61,10 +65,20 @@ def test_getframe_missing(mocker): bxsource.mockndiGetBXTransformMissing) tracker = NDITracker(SETTINGS_POLARIS) - (port_handles, time_stamps, frame_numbers, _tracking, - _tracking_quality ) = tracker.get_frame() + + bxsource.setdevice(ndidevice) + (port_handles, time_stamps, frame_numbers, tracking, + tracking_quality ) = tracker.get_frame() + print (port_handles) - print (time_stamps) print (frame_numbers) + print (tracking) + print (tracking_quality) + + assert len(port_handles) == 2 + assert len(time_stamps) == 2 + assert frame_numbers.count(1) == 2 + assert np.all(np.isnan(tracking)) + assert np.all(np.isnan(tracking_quality)) del tracker From e3df8e88f4fa88fb4267d4ce80db330674fcf770 Mon Sep 17 00:00:00 2001 From: Stephen Thompson Date: Tue, 3 Oct 2023 10:14:01 +0100 Subject: [PATCH 7/9] Issue #78 added checks to return values on get frame --- ...st_sksurgerynditracker_mockndi_getframe.py | 42 ++++++++++++++++--- 1 file changed, 36 insertions(+), 6 deletions(-) diff --git a/tests/test_sksurgerynditracker_mockndi_getframe.py b/tests/test_sksurgerynditracker_mockndi_getframe.py index cbb20fb..546c0ac 100644 --- a/tests/test_sksurgerynditracker_mockndi_getframe.py +++ b/tests/test_sksurgerynditracker_mockndi_getframe.py @@ -36,7 +36,42 @@ def test_getframe_polaris_mock(mocker): tracker = NDITracker(SETTINGS_POLARIS) bxsource.setdevice(ndidevice) - tracker.get_frame() + + (port_handles, time_stamps, frame_numbers, tracking, + tracking_quality ) = tracker.get_frame() + + assert len(port_handles) == 2 + assert len(time_stamps) == 2 + assert frame_numbers.count(1) == 2 + expected_tracking_0 = np.array([[1.,0.,0.,10.], + [0.,1.,0.,-20.], + [0.,0.,1.,5.], + [0.,0.,0.,1.]]) + assert np.array_equal(expected_tracking_0, tracking[0]) + expected_tracking_1 = np.array([[1.,0.,0.,0.], + [0.,1.,0.,0.], + [0.,0.,1.,0.], + [0.,0.,0.,1.]]) + assert np.array_equal(expected_tracking_1, tracking[1]) + assert tracking_quality.count(1.) == 2 + + (port_handles, time_stamps, frame_numbers, tracking, + tracking_quality ) = tracker.get_frame() + + assert len(port_handles) == 2 + assert len(time_stamps) == 2 + assert frame_numbers.count(2) == 2 + expected_tracking_0 = np.array([[1.,0.,0.,20.], + [0.,1.,0.,-40.], + [0.,0.,1.,10.], + [0.,0.,0.,1.]]) + assert np.array_equal(expected_tracking_0, tracking[0]) + expected_tracking_1 = np.array([[1.,0.,0.,0.], + [0.,1.,0.,0.], + [0.,0.,1.,0.], + [0.,0.,0.,1.]]) + assert np.array_equal(expected_tracking_1, tracking[1]) + assert tracking_quality.count(1.) == 2 del tracker @@ -70,11 +105,6 @@ def test_getframe_missing(mocker): (port_handles, time_stamps, frame_numbers, tracking, tracking_quality ) = tracker.get_frame() - print (port_handles) - print (frame_numbers) - print (tracking) - print (tracking_quality) - assert len(port_handles) == 2 assert len(time_stamps) == 2 assert frame_numbers.count(1) == 2 From 7ccbb8f720cefc4c2785c20ec0cd11b66aa0b5ee Mon Sep 17 00:00:00 2001 From: Stephen Thompson Date: Tue, 3 Oct 2023 10:29:28 +0100 Subject: [PATCH 8/9] Issue #78 added useage note for quaternions in documentation --- sksurgerynditracker/nditracker.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sksurgerynditracker/nditracker.py b/sksurgerynditracker/nditracker.py index c7f3eae..8f9f490 100644 --- a/sksurgerynditracker/nditracker.py +++ b/sksurgerynditracker/nditracker.py @@ -116,6 +116,8 @@ def __init__(self, configuration): ports to probe: + use quaternions: + :raises Exception: IOError, KeyError, OSError """ self._device = None From 795350e690605749531423596047688b8030a8ac Mon Sep 17 00:00:00 2001 From: Stephen Thompson Date: Tue, 3 Oct 2023 10:30:29 +0100 Subject: [PATCH 9/9] Issue #78 added tests for get frame with quaternions --- tests/polaris_mocks.py | 34 ++++++++--- ...st_sksurgerynditracker_mockndi_getframe.py | 58 +++++++++++++++++-- 2 files changed, 78 insertions(+), 14 deletions(-) diff --git a/tests/polaris_mocks.py b/tests/polaris_mocks.py index 2e82c65..a92a04f 100644 --- a/tests/polaris_mocks.py +++ b/tests/polaris_mocks.py @@ -13,6 +13,15 @@ "data/8700339.rom"] } +SETTINGS_POLARIS_QUAT = { + "tracker type": "polaris", + "ports to probe": 20, + "romfiles" : [ + "data/something_else.rom", + "data/8700339.rom"], + "use quaternions": "true" + } + class MockPort: """A fake serial port for ndi""" device = 'bad port' @@ -83,10 +92,10 @@ class MockBXFrameSource(): def __init__(self): self.bx_frame_count = 0 self.bx_call_count = 0 - self.rotation = array([0, 0, 0, 0]) - self.position = array([0, 0, 0]) - self.velocity = array([10, -20, 5]) - self.quality = array([1]) + self.rotation = array([1., 0., 0., 0.]) + self.position = array([0., 0., 0.]) + self.velocity = array([10., -20., 5.]) + self.quality = array([1.]) self.tracked_tools = 0 def setdevice(self, ndidevice): @@ -111,18 +120,25 @@ def mockndiGetBXFrame(self, _device, port_handle): #pylint:disable=invalid-name return self.bx_frame_count - def mockndiGetBXTransform(self, _device, _port_handle): #pylint:disable=invalid-name + def mockndiGetBXTransform(self, _device, port_handle): #pylint:disable=invalid-name """ Mock of ndiGetBXTransform. To enable a simple test of tracking smoothing translate the mock object between frames. Full testing of the averaging code is in the base class sksurgerycore.tests.algorithms + The base ndicapi library uses Py_BuildValue to return the transform + as a tuple of double float values, so we also + return a tuple """ assert self.bx_frame_count > 0 - #the base ndicapi library uses Py_BuildValue to return the transform - #as a tuple of double float values, so let's make sure we're als - #returning a tuple - return tuple(concatenate((self.rotation, self.position, self.quality))) + ph_int = int.from_bytes(port_handle, byteorder = 'little') + if ph_int == 0: + self.position = self.velocity * self.bx_frame_count + return tuple(concatenate((self.rotation, self.position, + self.quality))) + + return tuple(concatenate((self.rotation, array([0, 0, 0]), + self.quality))) def mockndiGetBXTransformMissing(self, _device, _port_handle): #pylint:disable=invalid-name """Mock of ndiGetBXTransform""" diff --git a/tests/test_sksurgerynditracker_mockndi_getframe.py b/tests/test_sksurgerynditracker_mockndi_getframe.py index 546c0ac..3814057 100644 --- a/tests/test_sksurgerynditracker_mockndi_getframe.py +++ b/tests/test_sksurgerynditracker_mockndi_getframe.py @@ -5,7 +5,8 @@ import numpy as np from sksurgerynditracker.nditracker import NDITracker -from tests.polaris_mocks import SETTINGS_POLARIS, mockndiProbe, \ +from tests.polaris_mocks import SETTINGS_POLARIS, SETTINGS_POLARIS_QUAT, \ + mockndiProbe, \ mockndiOpen, mockndiGetError, mockComports, \ mockndiGetPHSRHandle, mockndiVER, \ MockNDIDevice, MockBXFrameSource @@ -66,10 +67,57 @@ def test_getframe_polaris_mock(mocker): [0.,0.,1.,10.], [0.,0.,0.,1.]]) assert np.array_equal(expected_tracking_0, tracking[0]) - expected_tracking_1 = np.array([[1.,0.,0.,0.], - [0.,1.,0.,0.], - [0.,0.,1.,0.], - [0.,0.,0.,1.]]) + assert np.array_equal(expected_tracking_1, tracking[1]) + assert tracking_quality.count(1.) == 2 + + del tracker + +def test_getframe_polaris_mock_quat(mocker): + """ + Checks that get frame works with quaternions + """ + tracker = None + bxsource = MockBXFrameSource() + ndidevice = MockNDIDevice() + mocker.patch('serial.tools.list_ports.comports', mockComports) + mocker.patch('ndicapy.ndiProbe', mockndiProbe) + mocker.patch('ndicapy.ndiOpen', mockndiOpen) + mocker.patch('ndicapy.ndiCommand', ndidevice.mockndiCommand) + mocker.patch('ndicapy.ndiGetError', mockndiGetError) + mocker.patch('ndicapy.ndiClose') + mocker.patch('ndicapy.ndiGetPHSRNumberOfHandles', + ndidevice.mockndiGetPHSRNumberOfHandles) + mocker.patch('ndicapy.ndiGetPHRQHandle', ndidevice.mockndiGetPHRQHandle) + mocker.patch('ndicapy.ndiPVWRFromFile') + mocker.patch('ndicapy.ndiGetPHSRHandle', mockndiGetPHSRHandle) + mocker.patch('ndicapy.ndiVER', mockndiVER) + mocker.patch('ndicapy.ndiGetBXFrame', bxsource.mockndiGetBXFrame) + mocker.patch('ndicapy.ndiGetBXTransform', bxsource.mockndiGetBXTransform) + + tracker = NDITracker(SETTINGS_POLARIS_QUAT) + + bxsource.setdevice(ndidevice) + + (port_handles, time_stamps, frame_numbers, tracking, + tracking_quality ) = tracker.get_frame() + + assert len(port_handles) == 2 + assert len(time_stamps) == 2 + assert frame_numbers.count(1) == 2 + expected_tracking_0 = np.array([[1.,0.,0.,0.,10.,-20,5.]]) + assert np.array_equal(expected_tracking_0, tracking[0]) + expected_tracking_1 = np.array([[1.,0.,0.,0.,0.,0.,0.]]) + assert np.array_equal(expected_tracking_1, tracking[1]) + assert tracking_quality.count(1.) == 2 + + (port_handles, time_stamps, frame_numbers, tracking, + tracking_quality ) = tracker.get_frame() + + assert len(port_handles) == 2 + assert len(time_stamps) == 2 + assert frame_numbers.count(2) == 2 + expected_tracking_0 = np.array([[1.,0.,0.,0.,20.,-40,10.]]) + assert np.array_equal(expected_tracking_0, tracking[0]) assert np.array_equal(expected_tracking_1, tracking[1]) assert tracking_quality.count(1.) == 2