Back to the main page.

Bug 520 - Neighbourselection crashes when providing a layout and no neighbourdist

Status CLOSED FIXED
Reported 2011-03-04 10:03:00 +0100
Modified 2011-07-13 14:46:43 +0200
Product: FieldTrip
Component: core
Version: unspecified
Hardware: PC
Operating System: Windows
Importance: P1 normal
Assigned to: Jörn M. Horschig
URL:
Tags:
Depends on:
Blocks:
See also:

Jörn M. Horschig - 2011-03-04 10:03:34 +0100

cfg.neighbourdist is only set if 'sens' has a unit field. At least when using cfg.layout='EEG1010.lay', this is not the case. Here, cfg.neighbourdist is kept empty and then compneighbstructfromgradelec crashes. Two ways to fix this: 1) Throw an error in line 106 (at the moment, there is an empty else-clause) 2) Come with a good way to estimate the neighbour dist from the unit-sphere (as the EEG1010 layout is a unit-sphere). Here, I see two ways: - Take the same ratio as 4cm is to a real head (that would be around 0.1) - Calculate the neighbourdistance using the average channel distance, maybe also take the total number of channels into account Just in case that cfg.layout should not be used with neighbourselection, then the documentation needs an update, preferably in the non-parametric statistics tutorial.


Jan-Mathijs Schoffelen - 2011-03-08 08:46:33 +0100

I think this can easily be solved by forcing sens to have a unit-field. This can be achieved with the function ft_convert_units. I believe that if the function is called as: sens=ft_convert_units(sens), it guesses the units based on the geometry. So a call to ft_convert_units somewhere should do the trick. Isn't there a key-value pair 'hasunit' in ft_checkdata; this would even be cleaner, thus ft_checkdata(sens, 'hasunits', 'yes') or so. Jorn could you have a look at this? Thanks


Jörn M. Horschig - 2011-03-09 10:16:44 +0100

I fixed it for now, using the following approach: 1) I use checkdata to force a unit-field into the sens-structure 2) I added an if-clause that covers 'dm' as a unit, taking 0.4 as the default value (given that 4cm and 40mm is default as well) 3) Throwing an error if the unit type is not 'dm', 'cm' or 'mm' I still have a problem with this. ft_checkdata estimates the sensor units to be 'dm' in case I provide an EEG-layout. Since the points of the sensor are actually all in the range between [-0.5; 0.5], a default of 0.4 would be a lot (meaning e.g. that Fpz is a neighbour Cz as well as 31 other channels: K>> neighbours{2} ans = label: 'Fpz' neighblabel: {32x1 cell} So, before I commit this, any suggestions? I think a fix of ft_convert_units or on ft_estimate_units would be appropriate


Jörn M. Horschig - 2011-03-09 11:13:42 +0100

Update: Implement neighbourselection using triangulation as an alternative method Convert connectivity matrix to neighbour-label-structure


Jörn M. Horschig - 2011-03-23 10:36:44 +0100

MATLAB has a built-in function that calculates triangulation (DelaunayTri). I could use this to compute the triangular neighbours. This function, however, is object-oriented, which would diminish backwards compatibility. I could either write the (Delaunay) triangulation myself or search for an already open-source matlab function or ignore backward compatibility issues and use the built-in function. The built-in MATLAB DelaunayTri uses an open library: http://www.cgal.org/ We could maybe add a function out of this library and mex it Need feedback on this :)


Jan-Mathijs Schoffelen - 2011-03-24 23:53:58 +0100

Probably that is an overkill. Did you look at fieldtrip/private/projecttri?


Jörn M. Horschig - 2011-03-25 10:01:02 +0100

The problem is that projecttri has two methods, one is using some convexhull approach, the other is using Delaunay (so the object-oriented approach). While the latter one constitutes the problems already described, the first one does not make a triangulation that we want it to be like. Apart from that, projecttri projects the input points to a 2D plane, which is not necessary (anymore?) because Delaunay can handle 3D input as well (at least the OO function can do so)


Jan-Mathijs Schoffelen - 2011-03-25 13:30:37 +0100

is the delaunay method in projecttri object oriented? As far as I know this function far predates the support of objects by matlab


Jörn M. Horschig - 2011-03-25 15:42:44 +0100

projecttri calls the function 'delaunay' which again calls 'DelaunayTri'. DelaunayTri is the OO-function. If it precedes the OO matlab times then it might be that 'delaunay' is working differently for newer versions? I would need an old Matlab version to check this, or I could just use that function then without checking for backward compatibility


Jörn M. Horschig - 2011-03-31 14:58:36 +0200

Created attachment 36 size of channels ~ # neighbours The file shows a comparison between the current 'distance' metric for determinic neighbouring channels and a triangulation approach, based on the EEG1010 layout. The size of the channels is proportional to the number of neighbours(^2). Red lines connect neighbours.


Jörn M. Horschig - 2011-03-31 15:01:10 +0200

In the FT meeting, Robert confirmed that the delaunay function precedes OO Matlab, so I'll use that, however I need to make sure that it can only handle 2D cases (recently, it can handle 3D cases, but backwardscompatibility is the key phrase again). Further, I would need a way to validate the method a bit better, so he explained that Hanneke plotting the size of the channel proportional to the number of neighbours, so I quickly wrote a script doing that as well. I'll keep testing with other layouts and datafiles to see whether the triangulation works as expected.


Jörn M. Horschig - 2011-04-01 17:36:09 +0200

beautiful results now - I'll do some more sanity checks and will present that on the next FT meeting. two more things, maybe also for discussion next wednesday: - do you think there would be a need to actually announce this as a change in order to let ppl know that this might(?) improve statistical testing (as the choice of neighbours makes more sense this way) - what about the megplanar stuff? neighbours are calculated like using a distance threshold - do you actually want the algorithms to work differently?


Jan-Mathijs Schoffelen - 2011-04-01 18:32:08 +0200

@announcement: probably announcing is OK, but we have to see whether the statistics improve. I don't see a straightforward way to test this by the way. @megplanar: have to think about this. I guess a distance criterion makes sense here, because the computation of the spatial derivative should anyhow take the distance into account, as well was the relative location.


Jörn M. Horschig - 2011-04-07 17:17:30 +0200

Created attachment 38 Matlab figure of the three triangulation approach Dear Robert & JM, I thought about improving the triangulation neighbourselection according to what we discussed. After thinking about more complicated approaches, I thought I'd try the simple thing that immediately popped to my mind, but sounded too simple to actually work. In the current version, I calculate three triangulations: First, the normal triangulation, second a triangulation with all x-coordinates halfed, third a triangulation with all y-coordinates halfed. Surprisingly, this works extremely well. I attached a .fig of the 2D EEG1010 layout. This also works for 3D head models, though looks weird for not symmetrically distributed sensors (like in the Yokogawa system) - but not in particular faulty. The triangulation method does, however, not work properly for the bti248 system (that means, independently of applying this trick, a triangulation results in one sensor getting far more neighbours than all other sensors) Actually, you can test it yourself, as I uploaded the file(s): ft_neighbourplot - to be used similar as ft_neighbourselection (see also help ft_neighbourplot) ft_neighbourselection - now can handle a cfg.method field. default value: 'dist' corresponds to the old way of selecting neighbour (distance thresholding). 'tri' or 'triangulation' uses the newly implemented triangulation approach. Easiest way to see how it works and to compare, just call it this way: ft_neighbourplot([], data); cfg = []; cfg.method = 'tri'; ft_neighbourplot(cfg, data) btw: all this text, because I am on vacation from Saturday on. Anyway, I tested the function thoroughly! See Bug 570 for situations where this method fails!


Jörn M. Horschig - 2011-04-29 13:19:56 +0200

I tested the triangulation neighbourselection way on the tutorial data (I got no other reliable data to compare with). For the TFR statistics (CTF151 data), the 'triangulation' method either finds similar cluster, or no significant in contrast to the traditional 'distance' measure. I tracked this down, and it seems to be because the number of neighbours is actually bigger in the triangulation approach, and they seem to be not symmetrical, i.e. channels in the left hemisphere have more neighbours than for the channels on the right hemisphere. I guess this is due to the 2D projection of the 3D gradiometer structure. The CTF 151 neighbourplot looks messy to me using triangulation but pretty nice using the distance method. So for now, my conclusion seems to be that the user should compare the two methods and decide for the more appropriate (e.g. triangulation for 2D layout, distance for CTF). Should I try to improve the triangulation method or keep it thought it works suboptimally in some cases?


Robert Oostenveld - 2011-05-04 13:54:14 +0200

todo: make templates and documentation


Jörn M. Horschig - 2011-05-18 11:11:25 +0200

Created attachment 53 Current neighbours using triangulation - what neighbours to add for templatE? I attached a pic of ft_neighbourplot for CTF275 neighbours - in the upcoming meeting I intend to ask what additional neighbours to define, and to ask on what criteria neighbours should be defined.


Jörn M. Horschig - 2011-07-07 11:32:37 +0200

nneighbourselection does not crash anymore due to the given reason - will create a new bug about neighbourstructure templates


Robert Oostenveld - 2011-07-13 14:46:43 +0200

changed the status for a whole bunch of resolved bugs to CLOSED