Beispiel #1
0
    def setup_class(cls):
        """
        Called once for all tests for Pipelines.
        Sets rounding_precision, and does a one-time load
        of dynamic and static trial data as dictionaries from
        SampleData/Sample_2/.
        """
        cls.rounding_precision = 8
        cwd = os.getcwd()
        if(cwd.split(os.sep)[-1]=="pyCGM_Single"):
            parent = os.path.dirname(cwd)
            os.chdir(parent)
        cls.cwd = os.getcwd()

        cur_dir = cls.cwd
        dynamic_trial, static_trial,_,_,_ = getfilenames(3)
        dynamic_trial = os.path.join(cur_dir, dynamic_trial)
        static_trial = os.path.join(cur_dir, static_trial)
        motionData = loadData(dynamic_trial)
        staticData = loadData(static_trial)
        cls.data_original = dataAsDict(motionData, npArray=True)
        cls.static_original = dataAsDict(staticData, npArray=True)
        for frame in motionData:
            frame['SACR'] = pelvisJointCenter(frame)[2]
        cls.data_with_sacrum_original = dataAsDict(motionData, npArray=True)
        Pipelines.clearMarker(motionData, 'LFHD')
        cls.data_with_sacrum_clear_marker = dataAsDict(motionData, npArray=True)
Beispiel #2
0
 def test_transform_from_mov_exceptions(self,key,clust,last_time,i):
     """
     We test exceptions raised when there are not enough usable markers,
     the frame number is out of range, and the marker name does not exist.
     """
     data = self.data
     with pytest.raises(Exception):
         Pipelines.transform_from_mov(data,key,clust,last_time,i)
Beispiel #3
0
 def test_segmentFinder_exceptions(self,key,target_dict,segment_dict,j,missings):
     """
     We test the exception that is raised when the marker name does not
     exist.
     """
     data = self.data
     with pytest.raises(Exception):
         Pipelines.segmentFinder(key,data,target_dict,segment_dict,j,missings)
Beispiel #4
0
 def test_butterFilter_exceptions(self, data, cutoff, Fs):
     """
     We test exceptions raised when the length of the input data is too short, 
     when the cutoff frequency value is negative, zero, or too large, 
     and when the sampling frequency value is negative, zero, or too small.
     """
     with pytest.raises(Exception):
         Pipelines.butterFilter(data, cutoff, Fs)
Beispiel #5
0
 def test_transform_from_static_exceptions(self, key, useables, s):
     """
     We test exceptions raised when there are not enough usable markers,
     the frame number is out of range, or the marker name does not exist.
     """
     data = self.data 
     static = self.static
     with pytest.raises(Exception):
         Pipelines.transform_from_static(data,static,key,useables,s)
Beispiel #6
0
 def test_filt_exceptions(self, data, cutoff, Fs):
     """
     We test exceptions raised when the arrays in data are not of the same
     shape, when the length of data is too short, when the cutoff frequency 
     value is negative, zero, or too large, when the sampling frequency 
     value is negative, zero, or too small, and when data is not a numpy array.
     """
     with pytest.raises(Exception):
         Pipelines.filt(data, cutoff, Fs)
Beispiel #7
0
 def test_rigid_fill_exceptions(self):
     """
     We test the exception raised when the marker SACR does not
     exist in Data.
     """
     #Test that the marker SACR must exist:
     with pytest.raises(Exception):
         data = self.data
         static = self.static
         Pipelines.rigid_fill(data, static)
Beispiel #8
0
 def test_prep_accuracy(self, trajs, expected_result):
     """
     This function tests Pipelines.prep(trajs), where trajs
     is a dictionary containing numpy arrays.
     """
     result = Pipelines.prep(trajs)
     np.testing.assert_equal(result, expected_result)
Beispiel #9
0
    def test_clearMarker_accuracy(self, data, name, expected_result):
        """
        This function tests Pipelines.clearMarker(data, name), where
        data is an array of dictionary of markers lists and name is the 
        name of a marker to clear.

        We test cases where the values in data are lists and numpy arrays.
        We test the case where the marker name is not a key in data.
        """
        result = Pipelines.clearMarker(data, name)
        np.testing.assert_equal(result, expected_result)
Beispiel #10
0
    def test_filtering_accuracy(self, Data, expected_result):
        """
        This function tests Pipelines.filtering(Data), where
        Data is a dictionary of marker lists. Pipelines.filtering() calls
        Pipelines.filt(), and uses the same fourth-order Butterworth
        filter constructed in Pipelines.butterFilter().

        We test cases where inputs are numpy arrays of positive and 
        negative floats and ints.
        """
        result = Pipelines.filtering(Data)
        for key in Data:
            np.testing.assert_almost_equal(result[key], expected_result[key], self.rounding_precision)
Beispiel #11
0
    def test_filt_accuracy(self, data, cutoff, Fs, expected_result):
        """
        This function tests Pipelines.filt(data, cutoff, Fs),
        where data is a 2darray of numbers to filter, cutoff is the cutoff
        frequency to filter, and Fs is the sampling frequency of the data.

        Pipelines.filt() uses the same fourth-order Butterworth filter constructed
        in Pipelines.butterFilter().

        We test cases where inputs are lists of positive and negative floats 
        and ints.
        """
        result = Pipelines.filt(data, cutoff, Fs)
        np.testing.assert_almost_equal(result, expected_result, self.rounding_precision)
Beispiel #12
0
    def test_butterFilter_accuracy(self, data, cutoff, Fs, expected_result):
        """
        This function tests Pipelines.butterFilter(data, cutoff, Fs),
        where data is an array of numbers to filter, cutoff is the cutoff
        frequency to filter, and Fs is the sampling frequency of the data.

        Pipelines.butterFilter applies a fourth-order low-pass Butterworth filter
        that is constructed using the scipy functions butter() and filtfilt().

        For each case, we test that the Butterworth filter is applied correctly
        by testing its output is accurate in cases where inputs are positive and negative 
        floats and integers. We test cases where inputs are lists and numpy arrays.
        """
        #Call butterFilter() with parametrized values
        result = Pipelines.butterFilter(data, cutoff, Fs)
        np.testing.assert_almost_equal(result, expected_result, self.rounding_precision)
Beispiel #13
0
    def test_segmentFinder_accuracy(self,key,target_dict,segment_dict,j,missings,expected_result):
        """
        This function tests Pipelines.segmentFinder(key,data,target_dict,segment_dict,j,missings),
        where data is an array of dictionaries of marker data,
        key is the name of the missing marker to find the segment for,
        target_dict is a dictionary of marker to segment,
        segment_dict is a dictionary of segments to marker names,
        j is the frame number the marker is missing for, 
        and missings is a dictionary indicating other missing markers.

        We test to ensure that missing markers are not used to reconstruct
        other missing markers. 
        """
        data = self.data
        result = Pipelines.segmentFinder(key,data,target_dict,segment_dict,j,missings)
        assert result == expected_result
Beispiel #14
0
    def test_transform_from_mov_SampleData(self,key,clust,last_time,i,expected_result):
        """
        This function tests Pipelines.transform_from_mov(data,key,clust,last_time,i),
        where data is an array of dictionaries of marker data,
        key is the name of the missing marker to perform gap filling for,
        clust is a list of markers in the same cluster as key,
        last_time is the last frame the the missing marker was visible, and
        i is the frame number the marker is missing for.

        We use files from SampleData/Sample_2/ for testing.
        We test for 6 missing frames from the loaded data.
        """
        data = self.data
        data[key][i] = np.array([np.nan, np.nan, np.nan])
        result = Pipelines.transform_from_mov(data,key,clust,last_time,i)
        np.testing.assert_almost_equal(result, expected_result, self.rounding_precision)
Beispiel #15
0
    def test_transform_from_static_SampleData(self, key, useables, s, expected_result):
        """
        This function tests Pipelines.transform_from_static(data,static,key,useables,s),
        where data is an array of dictionaries of marker data,
        static is an array of static marker data, key is the name of the
        missing marker to perform gap filling for,
        useables is a list of markers in the same cluster as key,
        and s is the frame number that the marker data is missing for.

        We use files from SampleData/Sample_2/ for testing.
        We test for 6 missing frames from the loaded data.
        """
        data = self.data
        static = self.static
        #Clear given key and frame to test gap filling
        data[key][s] = np.array([np.nan, np.nan, np.nan])
        result = Pipelines.transform_from_static(data,static,key,useables,s)
        np.testing.assert_almost_equal(result, expected_result, self.rounding_precision)
Beispiel #16
0
    def test_transform_from_static(self):
        """
        This function tests Pipelines.transform_from_static().

        Pipelines.transform_from_static() uses a transformation that is stored between a 4 marker cluster.  
        It requires an inverse transformation matrix to be stored between the 
        combination of 3 marker groupings, with the 4th marker stored in relation to that frame. 
        
        Pipelines.transform_from_static() takes in as input the missing marker, and uses static data to 
        create an inverse transformation matrix, multiplying the new frame by the stored 
        inverse transform to get the missing marker position.

        We test that Pipelines.transform_from_mov() is accurate by creating four markers
        in a square in static data, and adding one to all but one of their x-coordinates
        for motion data.

        We ensure that the correct position is reconstructed from the static 
        data.
        """
        #Define the four markers, A, B, C, D, as the four corners of a square.
        static = {
            'A': np.array([[1, 1, 0]]),
            'B': np.array([[-1, 1, 0]]),
            'C': np.array([[1, -1, 0]]),
            'D': np.array([[-1, -1, 0]])
        }

        #Use the three markers, B, C, D to reconstruct the position of A
        useables = ['B', 'C', 'D']

        #Add one to all of the x-coordinates of B, C, D
        data = {
            'B': np.array([[0, 1, 0]]),
            'C': np.array([[2, -1, 0]]),
            'D': np.array([[0, -1, 0]])
        }

        #We expect that A is at [2, 1, 0]
        expected = np.array([2, 1, 0])
        result = Pipelines.transform_from_static(data, static, 'A', useables, 0)
        np.testing.assert_equal(result, expected)
Beispiel #17
0
    def test_transform_from_mov(self):
        """
        This function tests Pipelines.transform_from_mov().

        Pipelines.transform_from_mov() uses a transformation that is stored between a 4 marker cluster.  
        It requires an inverse transformation matrix to be stored between the 
        combination of 3 marker groupings, with the 4th marker stored in relation to that frame. 
        
        Pipelines.transform_from_mov() takes in as input the missing marker, and uses previous frames of motion data to 
        create an inverse transformation matrix, multiplying the new frame by the stored 
        inverse transform to get the missing marker position.

        We test that Pipelines.transform_from_mov() is accurate by creating four markers
        in a square at frame zero, and adding one to all but one of their x-coordinates
        in frame 1.

        We ensure that the correct position is reconstructed from the previous frame 
        data, and that the fourth marker is in the correct position after
        the transform.
        """
        #Define the four markers, A, B, C, D, as the four corners of a square in frame 0.
        #Add one to the x-coordinate of all markers but A in frame 1.
        data = {
            'A': np.array([[1, 1, 0], [np.nan, np.nan, np.nan]]),
            'B': np.array([[-1, 1, 0], [0, 1, 0]]),
            'C': np.array([[1, -1, 0], [2, -1, 0]]),
            'D': np.array([[-1, -1, 0], [0, -1, 0]])
        }
        #Use the three markers, B, C, D to reconstruct the position of A
        clust = ['B', 'C', 'D']
        #Last frame in which all four markers were visible
        last_time = 0
        #Frame for which a marker is missing data
        i = 1

        #We expect that A is at [2, 1, 0]
        expected = np.array([2, 1, 0])
        result = Pipelines.transform_from_mov(data, 'A', clust, last_time, i)
        np.testing.assert_equal(result, expected)
Beispiel #18
0
    def test_rigid_fill_transform_from_static(self):
        """
        This function tests Pipelines.rigid_fill(Data, static),
        where Data is an array of dictionaries of marker data,
        and static is an array of dictionaries of static trial data.

        Pipelines.rigid_fill() fills gaps for frames with missing data using
        the transform functions Pipelines.transform_from_static and
        Pipelines.transform_from_mov.

        Pipelines.rigid_fill() determines whether to call transform_from_static
        or transform_from_mov by determining if there is a previous frame where
        all markers in the cluster of the missing marker exist, and can be used
        to create an inverse transformation matrix to determine
        the position of the missing marker in the current frame. If there is,
        transform_from_mov is used. Otherwise, transform_from_static, which uses
        static data to reconstruct missing markers, is used.
        
        This function tests that rigid_fill will properly call transform_from_static
        by using Pipelines.clearMarker() to clear the value of a given key at all
        frames. Since there are no other frames to reconstruct the inverse transform
        off of, we expect the function to use transform_from_static.
        """

        #The sacrum marker must exist in data to use rigid_fill
        #Use data with the LFHD marker cleared from every frame
        data = self.data_with_sacrum_clear_marker 
        static = self.static

        #Return value from transform_from_static is mocked 
        mock_return_val = np.array([1, 2, 3])
        with mock.patch.object(Pipelines, 'transform_from_static', return_value=mock_return_val) as mock_transform_from_static:
            #Call Pipelines.rigid_fill with the mocked transform_from_static
            rigid_fill_data = Pipelines.rigid_fill(data, static)
            mock_transform_from_static.assert_called()

        result = rigid_fill_data['LFHD'][10]
        np.testing.assert_almost_equal(result, np.array([1, 2, 3]), self.rounding_precision)
Beispiel #19
0
    def test_rigid_fill_transform_from_mov(self):
        """        
        This function tests that Pipelines.rigid_fill() will properly call transform_from_mov
        by clearing the value of a marker at only one frame. We expect transform_from_mov
        to be called in this case since there are previous markers to create the
        inverse transform matrix from.
        """

        #Use data with all markers
        data = self.data_with_sacrum
        static = self.static
        #Clear marker LFHD from frame 10
        data['LFHD'][10] = np.array([np.nan, np.nan, np.nan])

        #Return value from transform_from_mov is mocked 
        mock_return_val = np.array([1, 2, 3])
        with mock.patch.object(Pipelines, 'transform_from_mov', return_value=mock_return_val) as mock_transform_from_mov:
            #Call Pipelines.rigid_fill with the mocked transform_from_static
            rigid_fill_data = Pipelines.rigid_fill(data, static)
            mock_transform_from_mov.assert_called()

        result = rigid_fill_data['LFHD'][10]
        np.testing.assert_almost_equal(result, np.array([1, 2, 3]), self.rounding_precision)
Beispiel #20
0
 def test_prep_exceptions(self, trajs):
     with pytest.raises(Exception):
         Pipelines.prep(trajs)
Beispiel #21
0
 def test_filtering_exceptions(self, Data):
     with pytest.raises(Exception):
         Pipelines.filtering(Data)