Repository: mne-tools/mne-python

Issue:
BUG: Over decimation because of units issue
Hi all,
I'm loading in raw files from KIT system at NYU using `mne.io.read_raw_kit()` and found that the digitized head shape in `raw.info['dig']` was only producing 9 points (the 3 anatomical markers, five fiducials and 1 lone head-shape pt). This didn't use to be a problem so I tried loading old data which had worked fine before and now they have the same problem. The issue seems to be that units for the KIT head shape were changed from mm to m in `_read_dig_points()` in the meas_info.py file. This is fine unless you're like me and always have way too many points forcing automatic decimation in `_set_dig_kit()` in kit.py. That call looks like this:

```python
if n_pts > KIT.DIG_POINTS:
        hsp = _decimate_points(hsp, res=5)
```

I think the fix is that the 5 should be 0.005 now that we are in meters. Otherwise you have voxels with side-length of 5 meters which may be a bit of an over decimation. This fixes my issue at least. I am happy to make the PR but wanted to make sure that's not going to effect anything else that I'm not foreseeing. 
What do you guys think?
@teonbrooks @christianbrodbeck 


Discussion:
Sounds reasonable to me


Resolving patch:
diff --git a/mne/io/kit/kit.py b/mne/io/kit/kit.py
--- a/mne/io/kit/kit.py
+++ b/mne/io/kit/kit.py
@@ -477,7 +477,7 @@ def _set_dig_kit(mrk, elp, hsp):
     """Add landmark points and head shape data to the KIT instance.
 
     Digitizer data (elp and hsp) are represented in [mm] in the Polhemus
-    ALS coordinate system.
+    ALS coordinate system. This is converted to [m].
 
     Parameters
     ----------
@@ -504,7 +504,7 @@ def _set_dig_kit(mrk, elp, hsp):
         hsp = _read_dig_points(hsp)
     n_pts = len(hsp)
     if n_pts > KIT.DIG_POINTS:
-        hsp = _decimate_points(hsp, res=5)
+        hsp = _decimate_points(hsp, res=0.005)
         n_new = len(hsp)
         warn("The selected head shape contained {n_in} points, which is "
              "more than recommended ({n_rec}), and was automatically "
@@ -804,6 +804,11 @@ def read_raw_kit(input_fname, mrk=None, elp=None, hsp=None, stim='>',
     raw : Instance of RawKIT
         A Raw object containing KIT data.
 
+    Notes
+    -----
+    If mrk, hsp or elp are array_like inputs, then the numbers in xyz
+    coordinates should be in units of meters.
+
     See Also
     --------
     mne.io.Raw : Documentation of attribute and methods.


Test patch:
diff --git a/mne/io/kit/tests/test_kit.py b/mne/io/kit/tests/test_kit.py
--- a/mne/io/kit/tests/test_kit.py
+++ b/mne/io/kit/tests/test_kit.py
@@ -9,18 +9,20 @@
 import inspect
 import numpy as np
 from numpy.testing import assert_array_almost_equal, assert_array_equal
-from nose.tools import assert_equal, assert_raises, assert_true
+from nose.tools import (assert_equal, assert_almost_equal, assert_raises,
+                        assert_true)
 from scipy import linalg
 import scipy.io
 
 from mne import pick_types, Epochs, find_events, read_events
 from mne.transforms import apply_trans
 from mne.tests.common import assert_dig_allclose
-from mne.utils import run_tests_if_main
+from mne.utils import run_tests_if_main, _TempDir
 from mne.io import read_raw_fif, read_raw_kit, read_epochs_kit
 from mne.io.kit.coreg import read_sns
 from mne.io.kit.constants import KIT, KIT_CONSTANTS, KIT_NY, KIT_UMD_2014
 from mne.io.tests.test_raw import _test_raw_reader
+from mne.surface import _get_ico_surface
 
 FILE = inspect.getfile(inspect.currentframe())
 parent_dir = op.dirname(op.abspath(FILE))
@@ -36,6 +38,8 @@
 hsp_txt_path = op.join(data_dir, 'test_hsp.txt')
 elp_path = op.join(data_dir, 'test.elp')
 hsp_path = op.join(data_dir, 'test.hsp')
+# this is a fake headshape made up of a unit sphere to test decimation
+sphere_hsp_txt_path = op.join(data_dir, 'test_sphere_hsp.txt')
 
 
 def test_data():
@@ -185,4 +189,32 @@ def test_hsp_elp():
     assert_array_almost_equal(pts_elp_in_dev, pts_txt_in_dev, decimal=5)
 
 
+def test_decimate():
+    """Test decimation of digitizer headshapes with too many points. """
+    # load headshape and convert to meters
+    hsp_mm = _get_ico_surface(5)['rr'] * 100
+    hsp_m = hsp_mm / 1000.
+
+    # save headshape to a file in mm in temporary directory
+    tempdir = _TempDir()
+    sphere_hsp_path = op.join(tempdir, 'test_sphere.txt')
+    np.savetxt(sphere_hsp_path, hsp_mm)
+
+    # read in raw data using spherical hsp, and extract new hsp
+    raw = read_raw_kit(sqd_path, mrk_path, elp_txt_path, sphere_hsp_path)
+    # collect headshape from raw (should now be in m)
+    hsp_dec = np.array([dig['r'] for dig in raw.info['dig']])[8:]
+
+    # with 10242 points and _decimate_points set to resolution of 5 mm, hsp_dec
+    # should be a bit over 5000 points. If not, something is wrong or
+    # decimation resolution has been purposefully changed
+    assert_true(len(hsp_dec) > 5000)
+
+    # should have similar size, distance from center
+    dist = np.sqrt(np.sum((hsp_m - np.mean(hsp_m, axis=0))**2, axis=1))
+    dist_dec = np.sqrt(np.sum((hsp_dec - np.mean(hsp_dec, axis=0))**2, axis=1))
+    hsp_rad = np.mean(dist)
+    hsp_dec_rad = np.mean(dist_dec)
+    assert_almost_equal(hsp_rad, hsp_dec_rad, places=3)
+
 run_tests_if_main()