Skip to content

Commit

Permalink
Merge pull request #82 from jodreen/master
Browse files Browse the repository at this point in the history
Linear modeling and other tests
  • Loading branch information
AlonDaks committed Dec 14, 2015
2 parents e4496d7 + 4ad7b99 commit 158fa21
Show file tree
Hide file tree
Showing 5 changed files with 77 additions and 91 deletions.
24 changes: 13 additions & 11 deletions code/stat159lambda/linear_modeling/linear_modeling.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,14 @@ def __init__(self, subject, interest_col_str, data=None):
will be used.
"""
self.subject = subject
if interest_col_str == "int-ext":
self.interest_col_ind = 0
elif interest_col_str == "day-night":
self.interest_col_ind = 1
else:
raise ValueError("Incorrect interest column name: please use either 'int-ext' or 'day-night'")
self.interest_col_str = interest_col_str
if not data:
if data is None:
data_path = dp.get_smoothed_2d_path(self.subject, 4)
data = np.load(data_path)
data = data[:, NUM_OFFSET_VOLUMES:]
Expand All @@ -45,18 +51,11 @@ def get_design_matrix(self):
if self.design is None:
scene_path = dp.get_scene_csv()
ss = ssm.SceneSlicer(scene_path)
if self.interest_col_str == "int-ext":
interest_col_ind = 1
elif self.interest_col_str == "day-night":
interest_col_ind = 0
else:
print(
"Incorrect interest column name: please use either 'int-ext' or 'day-night'")
interest_col = ss.get_scene_slices()[interest_col_ind]
interest_col = ss.get_scene_slices()[self.interest_col_ind]
n_trs = self.data.shape[-1]
design = np.ones((n_trs, 3))
design[:, 1] = np.linspace(-1, 1, n_trs)
design[:, 2] = interest_col[NUM_OFFSET_VOLUMES:]
design[:, 2] = interest_col[NUM_OFFSET_VOLUMES:NUM_OFFSET_VOLUMES+n_trs]
self.design = design
return self.design

Expand Down Expand Up @@ -114,7 +113,10 @@ def t_stat(self):
df = X.shape[0] - npl.matrix_rank(X)
MRSS = RSS / df
SE = np.sqrt(MRSS * c.T.dot(npl.pinv(X.T.dot(X)).dot(c)))
SE[SE == 0] = np.amin(SE[SE != 0])
try:
SE[SE == 0] = np.amin(SE[SE != 0])
except ValueError:
pass
t = c.T.dot(beta) / SE
self.t_values = abs(t[0])
self.t_indices = np.array(self.t_values).argsort(
Expand Down
88 changes: 49 additions & 39 deletions code/stat159lambda/linear_modeling/tests/test_linear_modeling.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,54 +10,64 @@
import numpy as np
import matplotlib.pyplot as plt
import numpy.linalg as npl
import unittest
from stat159lambda.linear_modeling import linear_modeling as lm
from numpy.testing import assert_equal, assert_almost_equal
from numpy.testing import assert_equal, assert_almost_equal, assert_array_equal
from stat159lambda.config import REPO_HOME_PATH, NUM_OFFSET_VOLUMES

try:
from mock import patch
except:
from unittest.mock import patch

# def setup_test():
# data = np.array([[1, 0, 7, 8, 0], [1, 0, 4, 10, 4], [3, 7, 10, 1, 12
# ], [3, 7, 10, 1, 12],
# [3, 7, 10, 1, 12], [3, 0, 7, 4, 12], [3, 0, 7, 4, 12]])
# ve = lm.VoxelExtractor(0, 'day-night', data=data)
# return ve

class LinearModeling(unittest.TestCase):
def setup_data(self):
data = np.array([[1, 2, 7, 8, 2], [1, 2, 4, 12, 4], [3, 7, 12, 1, 12
], [3, 7, 12, 1, 12],
[3, 7, 12, 1, 12], [3, 2, 7, 4, 12], [3, 2, 7, 4, 12]])
return data

# def test_get_betas_Y():
# ve = setup_test()
# actual = linear_modeling.get_betas_Y(X, data)[0]
# expected = np.array([[-0.85496183, -0.11450382, -0.01526718],
# [6.91603053, 2.90839695, 6.58778626]])
# assert_almost_equal(expected, actual)
# actual = linear_modeling.get_betas_Y(X, data)[1]
# expected = np.array([[1, 1, 3], [0, 0, 7], [7, 4, 9], [0, 4, 7]])
# assert_almost_equal(expected, actual)
def setup_test(self):
ve = lm.VoxelExtractor(0, 'day-night', data=self.setup_data())
return ve

@patch.object(np, 'load')
def test_init_none_data(self, mock_np_load):
data = self.setup_data()
mock_np_load.return_value = data
ve = lm.VoxelExtractor(0, 'int-ext')
assert_array_equal(ve.data, data[:, NUM_OFFSET_VOLUMES:])

# def test_get_betas_4d():
# actual = linear_modeling.get_betas_4d(
# linear_modeling.get_betas_Y(X, data)[0], data)
# expected = np.array([[[-0.85496183, 6.91603053], [-0.11450382, 2.90839695],
# [-0.01526718, 6.58778626]]])
# assert_almost_equal(expected, actual)
def test_incorrect_col_name(self):
self.assertRaises(ValueError, lm.VoxelExtractor, 0, 'night-day', data=self.setup_data())

def test_get_design_matrix(self):
ve = self.setup_test()
ve.get_design_matrix()
assert ve.design.shape[0] == ve.data.shape[1]
assert ve.design.shape[1] == 3

# def test_t_stat():
# actual = linear_modeling.t_stat(
# linear_modeling.get_betas_Y(X, data)[1], X, [0, 1])
# expected = np.array([2.7475368, 1.04410995, 1.90484058])
# assert_almost_equal(expected, actual)
@patch.object(plt, 'imshow')
def test_plot_design_matrix(self, mock_imshow):
ve = self.setup_test()
ve.plot_design_matrix()
assert_array_equal(mock_imshow.call_args[0][0], ve.design)

def test_get_betas_Y(self):
ve = self.setup_test()
ve.get_betas_Y()
assert ve.B is not None

# def test_get_top_32():
# a = np.array([6, 4, 1, 2, 8, 8, 1, 9, 5, 2, 1, 9, 5, 4, 3, 6, 5, 3, 5, 8])
# assert_equal(linear_modeling.get_top_32(a, .2), [11, 7, 19, 4])
# actual = linear_modeling.get_top_32(
# linear_modeling.t_stat(
# linear_modeling.get_betas_Y(X, data)[1], X, [0, 1]), .5)
# expected = np.array([0, 2])
# assert_almost_equal(actual, expected)
def test_t_stat(self):
ve = self.setup_test()
ve.t_stat()
assert ve.t_indices is not None
assert ve.t_values is not None
assert ve.t_indices.shape[0] == ve.data.shape[0]


# def test_get_index_4d():
# actual = linear_modeling.get_index_4d([0, 2], data)
# assert_equal(list(actual), [(0, 0), (0, 2)])
@patch.object(plt, 'plot')
def test_plot_single_voxel(self, mock_plot):
ve = self.setup_test()
ve.plot_single_voxel(0)
assert_array_equal(mock_plot.call_args[0][0], np.array([1, 2, 7, 8, 2]))
7 changes: 5 additions & 2 deletions code/stat159lambda/preprocess/tests/test_preprocess.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from __future__ import absolute_import
from stat159lambda.preprocess import preprocess
from stat159lambda.config import REPO_HOME_PATH
from stat159lambda.config import REPO_HOME_PATH, SUBJECTS
from stat159lambda.utils import data_path as dp
import numpy as np
import matplotlib
Expand Down Expand Up @@ -47,7 +47,10 @@ def test_reshape_smoothed_to_2d(self, mock_smooth, mock_np):
def test_get_affine(self, mock_raw, mock_np_save, mock_np_load):
mock_raw.return_value = '{0}/testing/test_raw.nii'.format(REPO_HOME_PATH)
preprocess.get_affine()
assert mock_np_save.call_args[0][0] == '{0}/data/affine.npy'.format(REPO_HOME_PATH)
if mock_np_load.call_args:
assert mock_np_load.call_args[0][0] == '{0}/data/affine.npy'.format(REPO_HOME_PATH)
else:
assert mock_np_save.call_args[0][0] == '{0}/data/affine.npy'.format(REPO_HOME_PATH)

@patch.object(preprocess, 'apply_gaussian_smooth')
@patch.object(np, 'load')
Expand Down
11 changes: 8 additions & 3 deletions code/stat159lambda/utils/tests/test_scene_slicer.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from __future__ import absolute_import, division, print_function
from stat159lambda.utils import scene_slicer
from stat159lambda.config import NUM_VOLUMES
from stat159lambda.config import NUM_VOLUMES, NUM_OFFSET_VOLUMES
import os
import nibabel as nib
import csv
Expand All @@ -25,7 +25,7 @@ def teardown_test():
def test_constants():
assert scene_slicer.INTEGER_LABELS == {'day-night': {'DAY': 0,
'NIGHT': 1,
'DAWN': 2},
'DAWN': 0},
'int-ext': {'INT': 0,
'EXT': 1}}
assert scene_slicer.TUNING_SECONDS_OFFSET == 17
Expand All @@ -42,14 +42,15 @@ def test_scene_slicer_init():
def test_get_scene_slices():
ss = setup_test()
scene_slices = ss.get_scene_slices()
day_night_labels = 9*[None] + 11*[0] + 11*[1] + 15*[0] + 4*[1]
day_night_labels = 9*[None] + 11*[0] + 11*[1] + 15*[0] + 4*[1]
int_ext_labels = 9*[None] + 11*[1] + 11*[0] + 15*[1] + 4*[0]
assert scene_slices[0][:50] == day_night_labels
assert scene_slices[1][:50] == int_ext_labels
assert len(scene_slices[0]) == NUM_VOLUMES
assert len(scene_slices[1]) == NUM_VOLUMES
teardown_test()


def test_get_labels_by_slice():
ss = setup_test()
assert (None, None) == ss.get_labels_by_slice(0)
Expand All @@ -59,3 +60,7 @@ def test_get_labels_by_slice():
teardown_test()


def test_get_clean_slice_mask():
ss = setup_test()
mask = ss.get_clean_slice_mask()
assert len(mask) == NUM_VOLUMES - NUM_OFFSET_VOLUMES
38 changes: 2 additions & 36 deletions data/tests/test_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,46 +10,12 @@ def test_check_hashes():
temp.write(b'Some data')
temp.flush()
fname = temp.name
d = [(fname, '5b82f8bf4df2bfb0e66ccaa7306fd024')]
d = {fname: '5b82f8bf4df2bfb0e66ccaa7306fd024'}
assert data.check_hashes(d)
d = [(fname, '4b82f8bf4df2bfb0e66ccaa7306fd024')]
d = {fname: '4b82f8bf4df2bfb0e66ccaa7306fd024'}
assert not data.check_hashes(d)


def test_get_hash_values():
data_paths = {
"subjects": [
{
"runs": [
{
"linear": {
"path": "test/file/path/example.file1",
"hash": "test-hash-value1"
},
"rcds": {
"path": "data/raw/sub001/task001_run001/bold_dico_dico_rcds_nl.nii"
}
},
{
"linear": {
"path": "test/file/path/example.file2",
"hash": "test-hash-value2"
},
"rcds": {
"path": "data/raw/sub001/task001_run001/bold_dico_dico_rcds_nl.nii"
}
}
]
}
]
}

assert data.get_hash_values(data_paths) == [
('test/file/path/example.file1', 'test-hash-value1'),
('test/file/path/example.file2', 'test-hash-value2')
]


def test_main():
data_path = '{0}/data/data.py'.format(REPO_HOME_PATH)
main_module = imp.load_source('__main__', data_path)
Expand Down

0 comments on commit 158fa21

Please sign in to comment.