diff --git a/README_EEGLAB_PLUGIN.txt b/README_EEGLAB_PLUGIN.txt new file mode 100644 index 0000000..21a3469 --- /dev/null +++ b/README_EEGLAB_PLUGIN.txt @@ -0,0 +1,14 @@ +To make these function work under the EEGLAB interface +you must uncompress the ctf folder in the plugin directory +of EEGLAB. Type + + cd eeglab4.311/plugins + cvs -z3 -d:pserver:anonymous@cvs.sourceforge.net:/cvsroot/eeg checkout ctf + + [use "move" instead of "mv" under windows] + +What these commands do is that they download all the files into +a folder named ctf under the plugin sub-directory of your version of +EEGLAB. + +Arnaud Delorme, July 9, 2004 diff --git a/bigeeglabscriptsf.m b/bigeeglabscriptsf.m new file mode 100644 index 0000000..90d0c98 --- /dev/null +++ b/bigeeglabscriptsf.m @@ -0,0 +1,32 @@ +clear all; + +folder='sampledataset.ds'; + +[data]=readepochs(folder); +%wind = [-.1 .15]; +%[data]=readepochs(folder,'markers',{'click'},'window',wind); +%[data]=readepochs(folder,'window',wind,'trials',[1:10],'megsens',[2:7]); +if ~exist('wind','var') + wind = data.setup.start_sec; +end +dat=permute(data.epochs{1},[2,1,3]); +size(dat) +[ALLEEG EEG CURRENTSET ALLCOM] = eeglab; + +EEG = pop_importdata( 'nbchan', size(dat,1), 'dataformat', 'array', 'data', 'dat', ... + 'pnts', size(dat,2), 'srate', data.setup.sample_rate, 'xmin', wind(1)); + +[ALLEEG EEG CURRENTSET] = pop_newset(ALLEEG, EEG, CURRENTSET, 'setname','test'); +eeglab redraw; + +for i=1:size(dat,1) + EEG.chanlocs(i).labels = char(data.sensor.label(i)); + EEG.chanlocs(i).X = data.sensor.location(1,i); + EEG.chanlocs(i).Y = data.sensor.location(2,i); + EEG.chanlocs(i).Z = data.sensor.location(3,i); +end +EEG.chanlocs = pop_chanedit(EEG.chanlocs, 'convert', 'cart2topo', 'convert', 'cart2sph'); + +[ALLEEG EEG] = eeg_store(ALLEEG, EEG, CURRENTSET); + +eeglab redraw; diff --git a/crosshair.m b/crosshair.m new file mode 100644 index 0000000..b31ddc6 --- /dev/null +++ b/crosshair.m @@ -0,0 +1,952 @@ +function [Xpoint,Ypoint,XYhist] = crosshair(action); +% CROSSHAIR: A gui interface for reading (x,y) values from a plot. +% +% [Xpoint,Ypoint,XYhist] = crosshair(action); +% +% A set of mouse driven crosshairs is placed on the current axes, +% and displays the current (x,y) values of the line plot. There is an +% option to provide data specific values or interpolated values. The +% resolution of the data specific values depends on both the data +% resolution and the GUI interface (mainly mouse movement resolution). +% The interpolated values appear to provide a more continuous function, +% however they too depend on the GUI interface resolution. There are +% no options for extrapolation. +% +% For multiple traces, plots with the same length(xdata) are +% tracked. Each mouse click returns Xpoint,Ypoint values and selecting +% 'done' will remove the GUI and restore the mouse buttons to previous +% values. Selecting 'exit' will remove the GUI and close the figure. +% +% In this version (Dec 2002), there are new options to define functions +% of X/Y and monitor their results. There is also a new STORE button +% that creates and updates an XYhist struct in the base workspace, which +% contains value labels and values. This version has better controls +% of X/Y movements, including better interpolation movement options. +% This version attempts to respond correctly to keyboard entries also. +% +% Some further help is given in the tool tips of the GUI. +% +% Note: crosshair always updates the Xpoint,Ypoint in the base +% workspace. Here is an example of how to get return values within +% a script/function after pressing the exit button of crosshair: +% function [X,Y] = crosshair_returnXY +% x = [1:10]; y(1,:) = sin(x); y(2,:) = cos(x); +% figure; plot(x,y); crosshair; +% uiwait +% X = evalin('base','Xpoint'); +% Y = evalin('base','Ypoint'); +% return +% Copy this text to a function .m file and then call it from the +% base workspace with [X,Y] = crosshair_returnXY +% +% Useage: x = [1:10]; y(1,:) = sin(x); y(2,:) = cos(x); x2 = x.^2; +% figure; plot(x2,y); crosshair +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +% Copyright (C) 2002 Darren L. Weber +% +% This program is free software; you can redistribute it and/or +% modify it under the terms of the GNU General Public License +% as published by the Free Software Foundation; either version 2 +% of the License, or (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program; if not, write to the Free Software +% Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +% History: 03/96, Richard G. Cobb +% 08/01, Darren.Weber@flinders.edu.au +% replaced obsolete 'table1' with 'interp1'; fixed bug +% with number of 'traces'; rationalized calculations into +% a common subfunction for x,y point calc in 'down','up', +% & 'move' button functions; added option to turn on/off +% interpolation and the exit button; simplified updates +% to graphics using global GUI handle structure. +% 11/01, Darren.Weber@flinders.edu.au +% added tooltips for several GUI handles +% added multiple interpolation methods +% added GUI for data matrix indices (given no interpolation) +% added option to select trace nearest to mouse click point +% reversed order of lines in data matrix to be consistent +% with the value returned from the nearest trace subfunction +% create crosshair lines after finding all plot lines to +% avoid confusing them with the plot lines +% 01/02, Darren.Weber@flinders.edu.au +% should now work across multiple plot figures, given +% that all gui handles and data are now stored in the +% plot figure 'userdata' handle. +% added functionality to move smoothly from interpolation +% back to the delimited data via the "next/previous" +% buttons. +% 06/02, Darren.Weber@flinders.edu.au +% learned how to get values back to a script/function with +% evalin command and updated help above. +% 12/02, Darren.Weber@flinders.edu.au +% added Store uicontrol and associated XYhist variable +% updates in base workspace to provide storage of +% consecutive XY values (thanks to C.A.Swenne@lumc.nl & +% H.van_de_Vooren@lumc.nl for their suggestion/assistance). +% added keyboard controls to left/right arrow and return. +% added prev/next X interpolation interval. +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + + +if ~exist('action','var') + action = 'init'; +elseif isempty(action) + action = 'init'; +end + +XHR_HANDLES = get(gcbf,'userdata'); + + +% Check for specific keys and assign reasonable actions +if strcmp(action, 'keypress'), + + CC = get(XHR_HANDLES.gui,'CurrentCharacter'); + cc = double(CC); + if cc, + switch cc, + case 27, action = 'done'; % ESC + case 28, action = 'prevx'; % left + case 29, action = 'nextx'; % right + case 30, action = 'ygt'; % up + case 31, action = 'ylt'; % down + case 13, action = 'store'; % return/enter + otherwise, action = 'up'; % all other keys + end + end +end + +action = lower(action); + +switch action, + +case 'init', + + % Paint GUI + XHR_HANDLES = INIT; + + % Update and return values + XHR_HANDLES = updateDATA(XHR_HANDLES); + Xpoint = get(XHR_HANDLES.xvalue,'Value'); + Ypoint = get(XHR_HANDLES.yvalue,'Value'); + %updateXYhistory(Xpoint,Ypoint); + +% Mouse Click Down +case 'down', + + set(XHR_HANDLES.gui,'WindowButtonMotionFcn','crosshair(''move'');'); + set(XHR_HANDLES.gui,'WindowButtonUpFcn','[Xpoint,Ypoint] = crosshair(''up'');'); + + XHR_HANDLES = updateDATA(XHR_HANDLES); + Xpoint = get(XHR_HANDLES.xvalue,'Value'); + Ypoint = get(XHR_HANDLES.yvalue,'Value'); + %updateXYhistory(Xpoint,Ypoint); + +% Mouse Drag Motion +case 'move', + + XHR_HANDLES = updateDATA(XHR_HANDLES); + Xpoint = get(XHR_HANDLES.xvalue,'Value'); + Ypoint = get(XHR_HANDLES.yvalue,'Value'); + %updateXYhistory(Xpoint,Ypoint); + +% Mouse Click Up +case 'up', + + set(XHR_HANDLES.gui,'WindowButtonMotionFcn',' '); + set(XHR_HANDLES.gui,'WindowButtonUpFcn',' '); + + XHR_HANDLES = updateDATA(XHR_HANDLES); + Xpoint = get(XHR_HANDLES.xvalue,'Value'); + Ypoint = get(XHR_HANDLES.yvalue,'Value'); + %updateXYhistory(Xpoint,Ypoint); + +% Next or Previous X point +case {'nextx','prevx','changex','nexty','prevy','changey','ylt','ygt'}, % Change X/Y + + XHR_HANDLES = moveXY(XHR_HANDLES,action); + Xpoint = get(XHR_HANDLES.xvalue,'Value'); + Ypoint = get(XHR_HANDLES.yvalue,'Value'); + %updateXYhistory(Xpoint,Ypoint); + +% Store XY values into a history array +case 'store', + + Xpoint = get(XHR_HANDLES.xvalue,'Value'); + Ypoint = get(XHR_HANDLES.yvalue,'Value'); + updateXYhistory(XHR_HANDLES); + +% Exit crosshairs GUI +case {'done','exit'}, + + XHR_HANDLES = get(gcbf,'userdata'); + + Xpoint = get(XHR_HANDLES.xvalue,'Value'); + Ypoint = get(XHR_HANDLES.yvalue,'Value'); + %updateXYhistory(Xpoint,Ypoint); + + handles = fieldnames(XHR_HANDLES); + for i=1:length(handles), + switch handles{i}, + case {'axis','datalines','gui'}, + otherwise, + h = getfield(XHR_HANDLES,handles{i}); + if ishandle(h), delete(h); end + end + end + + if strcmp(action,'exit'); + if ishandle(XHR_HANDLES.gui), + close(XHR_HANDLES.gui); + end + else + + set(XHR_HANDLES.gui,'WindowButtonUpFcn',''); + set(XHR_HANDLES.gui,'WindowButtonMotionFcn',''); + set(XHR_HANDLES.gui,'WindowButtonDownFcn',XHR_HANDLES.button); + + refresh(XHR_HANDLES.gui); + end + + clear XHR_HANDLES; + return; + +end + +set(gcf,'userdata',XHR_HANDLES); +if ishandle(XHR_HANDLES.gui), + figure(XHR_HANDLES.gui); +end + +return; + + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function updateXYhistory(H), + + Ch = get(H.yindex,'Value'); + X = get(H.xvalue,'Value'); + Y = get(H.yvalue,'Value'); + fX = get(H.fxvalue,'Value'); + fY = get(H.fyvalue,'Value'); + + fXeq = get(H.fxeq,'String'); + fYeq = get(H.fyeq,'String'); + + XY.labels = {'Channel','X','Y',['f(x) = ',fXeq],['f(y) = ',fYeq]}; + XY.data = [Ch,X,Y,fX,fY]; + + if evalin('base','exist(''XYhist'',''var'');'), + XYhist = evalin('base','XYhist'); + % get the current history set + set = getfield(XYhist,['set',num2str(XYhist.set)]); + if isequal(set.labels,XY.labels), + set.data(end+1,:) = XY.data; + XYhist = setfield(XYhist,['set',num2str(XYhist.set)],set); + assignin('base','XYhist',XYhist); + else + fprintf('\nWarning: creating new set of XYhist in base workspace.\n\n'); + XYhist.set = XYhist.set + 1; + XYhist = setfield(XYhist,['set',num2str(XYhist.set)],XY); + assignin('base','XYhist',XYhist); + end + else + XYhist.set = 1; + XYhist.set1 = XY; + assignin('base','XYhist',XYhist); + end + +return + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [H] = moveXY(H,move) + + interp = get(H.interp,'Value'); + xinterp = get(H.xinterp,'Value'); + + if (xinterp > 0) & (interp > 1), + + % Use incremental interpolation of x values + switch move, + case 'nexty', H.data.yindex = H.data.yindex + 1; + case 'prevy', H.data.yindex = H.data.yindex - 1; + case 'ygt', + ydata = interpYall(H); + [ysort,yi] = sort(ydata); + currYI = find(ysort > H.data.ypoint); + if min(currYI), + H.data.yindex = yi(min(currYI)); + end + case 'ylt', + ydata = interpYall(H); + [ysort,yi] = sort(ydata); + currYI = find(ysort < H.data.ypoint); + if max(currYI), + H.data.yindex = yi(max(currYI)); + end + case 'nextx', + H.data.xpoint = H.data.xpoint + xinterp; + case 'prevx', + H.data.xpoint = H.data.xpoint - xinterp; + end + H = checkdatarange(H); + H = interpY(H); + updateGUI(H); + return + end + + + % No interpolation of x values... + + if (interp > 1) + xdata = H.data.xdata(:,H.data.yindex); + [H.data.xindex] = NearestXYArrayPoint( xdata, H.data.xpoint, move ); + end + + switch move, + case 'nextx', + % Increase current xindex by one + if(interp == 1), H.data.xindex = H.data.xindex + 1; end + case 'prevx', + % Decrease current xindex by one + if(interp == 1), H.data.xindex = H.data.xindex - 1; end + case 'nexty', H.data.yindex = H.data.yindex + 1; + case 'prevy', H.data.yindex = H.data.yindex - 1; + case 'ygt', + ydata = H.data.ydata(H.data.xindex,:); + [ysort,yi] = sort(ydata); + currYI = find(ysort == H.data.ypoint); + if currYI < length(yi), + H.data.yindex = yi(currYI+1); + end + case 'ylt', + ydata = H.data.ydata(H.data.xindex,:); + [ysort,yi] = sort(ydata); + currYI = find(ysort == H.data.ypoint); + if currYI > 1, + H.data.yindex = yi(currYI-1); + end + otherwise + end + + H = checkdatarange(H); + + % Get x/y value at new x/y index + H.data.xpoint = H.data.xdata(H.data.xindex,H.data.yindex); + H.data.ypoint = H.data.ydata(H.data.xindex,H.data.yindex); + + set(H.interp,'Value',1); + H = updateGUI(H); + +return + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [ H ] = checkdatarange(H), + + % Ensure that x/y index is within data range + s = size(H.data.xdata,1); + if( H.data.xindex < 1 ), + H.data.xindex = 1; + elseif( H.data.xindex >= s ), + H.data.xindex = s; + end + s = size(H.data.ydata,2); + if( H.data.yindex < 1 ), + H.data.yindex = 1; + elseif( H.data.yindex >= s ), + H.data.yindex = s; + end + +return + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [ H ] = updateDATA( H ) + + % Only update if mouse pointer is in the + % axis limits + set(H.gui,'units','normalized'); + axpos = get(H.axis,'position'); + figcp = get(H.gui,'Currentpoint'); + axlim = axpos(1) + axpos(3); + aylim = axpos(2) + axpos(4); + if or(figcp(1) > (axlim+.01), figcp(1) < (axpos(1)-.01)), + return; + elseif or(figcp(2) > (aylim+.01), figcp(2) < (axpos(2)-.01)), + return; + end + + CurrentPoint = get(H.axis,'Currentpoint'); + H.data.xpoint = CurrentPoint(1,1); + H.data.ypoint = CurrentPoint(1,2); + + doNearTrace = get(H.traceNearest,'Value'); + + if (doNearTrace > 0) + + % Get new yindex for nearest trace + [ H.data.xpoint, ... + H.data.xindex, ... + H.data.ypoint, ... + H.data.yindex ] = NearestXYMatrixPoint( H.data.xdata,... + H.data.ydata,... + H.data.xpoint,... + H.data.ypoint); + else + H.data.yindex = get(H.trace,'Value'); + end + + CurrentPoint = get(H.axis,'Currentpoint'); + H.data.xpoint = CurrentPoint(1,1); + H.data.ypoint = CurrentPoint(1,2); + + H = interpY(H); + H = updateGUI(H); + +return + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [ H ] = updateGUI( H ) + + InterpMethod = get(H.interp,'Value'); + if (InterpMethod > 1) + % There is no specific matrix x-index for + % an interpolated point, but the nearest xindex + % is always returned from the interp function below + % so that next/prev move function works correctly + set(H.xindex,'String','interp'); + else + set(H.xindex,'String',num2str(H.data.xindex)); + end + set(H.xindex,'Value',H.data.xindex); + + tracestr = sprintf('%d',H.data.yindex); + set(H.yindex,'String',tracestr,'Value',uint16(H.data.yindex)); + set(H.trace,'Value',uint16(H.data.yindex)); + + % Create the crosshair lines on the figure, crossing at the x,y point + x_rng = get(H.axis,'Xlim'); + y_rng = get(H.axis,'Ylim'); + set(H.xline,'Xdata',[H.data.xpoint H.data.xpoint],'Ydata',y_rng); + set(H.yline,'Ydata',[H.data.ypoint H.data.ypoint],'Xdata',x_rng); + + % Update the x,y values displayed for the x,y point + xstring = sprintf('%g',H.data.xpoint); + ystring = sprintf('%g',H.data.ypoint); + set(H.xvalue,'String',xstring,'Value',H.data.xpoint); + set(H.yvalue,'String',ystring,'Value',H.data.ypoint); + + % Calculate the f(x) function + fyeq = get(H.fyeq,'string'); + fyval = eval(strrep(fyeq,'y',ystring)); + fystr = sprintf('%g',fyval); + set(H.fyvalue,'String',fystr,'Value',fyval); + + % Calculate the f(y) function + fxeq = get(H.fxeq,'string'); + fxval = eval(strrep(fxeq,'x',xstring)); + fxstr = sprintf('%g',fxval); + set(H.fxvalue,'String',fxstr,'Value',fxval); + +return + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [ H ] = interpY( H ) + + % In this function, xdata & ydata are arrays, not matrices + xdata = H.data.xdata(:,H.data.yindex); + ydata = H.data.ydata(:,H.data.yindex); + + if H.data.xpoint >= max(xdata) + H.data.xpoint = max(xdata); + H.data.xindex = find(xdata == max(xdata)); + H.data.ypoint = ydata(H.data.xindex); + return; + elseif H.data.xpoint <= min(xdata) + H.data.xpoint = min(xdata); + H.data.xindex = find(xdata == min(xdata)); + H.data.ypoint = ydata(H.data.xindex); + return; + end + + % 'none|nearest|linear|spline|cubic' + interp = get(H.interp,'Value'); + + switch interp + case 1 + % Given that xdata & ydata are the same length arrays, + % we can find the ypoint given the nearest xpoint. + [H.data.xindex, H.data.xpoint] = NearestXYArrayPoint( xdata, H.data.xpoint ); + H.data.ypoint = ydata(H.data.xindex); + case 2 + H.data.ypoint = interp1( xdata, ydata, H.data.xpoint, 'nearest' ); + case 3 + H.data.ypoint = interp1( xdata, ydata, H.data.xpoint, 'linear' ); + case 4 + H.data.ypoint = interp1( xdata, ydata, H.data.xpoint, 'spline' ); + case 5 + H.data.ypoint = interp1( xdata, ydata, H.data.xpoint, 'cubic' ); + otherwise + %use default (linear in matlabR12) + H.data.ypoint = interp1( xdata, ydata, H.data.xpoint ); + end + +return + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [ Yall ] = interpYall( H ) + + xdata = H.data.xdata(:,H.data.yindex); + Yall = H.data.ydata; + + if H.data.xpoint >= max(xdata), + H.data.xpoint = max(xdata); + H.data.xindex = find(xdata == max(xdata)); + Yall = ydata(:,H.data.xindex); + return; + elseif H.data.xpoint <= min(xdata), + H.data.xpoint = min(xdata); + H.data.xindex = find(xdata == min(xdata)); + Yall = ydata(:,H.data.xindex); + return; + end + + % 'none|nearest|linear|spline|cubic' + interp = get(H.interp,'Value'); + + switch interp, + case 1 + % do nothing in this case + case 2 + Yall = interp1( xdata, Yall, H.data.xpoint, 'nearest' ); + case 3 + Yall = interp1( xdata, Yall, H.data.xpoint, 'linear' ); + case 4 + Yall = interp1( xdata, Yall, H.data.xpoint, 'spline' ); + case 5 + Yall = interp1( xdata, Yall, H.data.xpoint, 'cubic' ); + otherwise + %use default (linear in matlabR12) + Yall = interp1( xdata, Yall, H.data.xpoint ); + end + +return + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [ index, point ] = NearestXYArrayPoint( data_array, point, type ) + + if ~exist('type','var') type = ''; end + + % In this function, input data_array is an array, not a matrix. + % This function returns the data point in the array + % that has the closest value to the value given (point). In + % the context of 'crosshair' the point is a mouse position. + + if point >= max(data_array) + point = max(data_array); + index = find(data_array == point); + return; + elseif point <= min(data_array) + point = min(data_array); + index = find(data_array == point); + return; + end + + data_sorted = sort(data_array); + + greater = find(data_sorted > point); + greater_index = greater(1); + + lesser = find(data_sorted < point); + lesser_index = lesser(length(lesser)); + + greater_dif = data_sorted(greater_index) - point; + lesser_dif = point - data_sorted(lesser_index); + + if strcmp(type,'nextx'), + index = greater_index; + elseif strcmp(type,'prevx'), + index = lesser_index; + else + if (greater_dif < lesser_dif) + index = find(data_array == data_sorted(greater_index)); + else + index = find(data_array == data_sorted(lesser_index)); + end + end + point = data_array(index); + +return + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [ xpoint, xindex, ypoint, yindex ] = NearestXYMatrixPoint( Xdata, Ydata, xpoint, ypoint ) + + % In this function, Xdata & Ydata are matrices of the same dimensions. + % This function attempts to find the nearest values in Xdata & Ydata + % to the mouse position (xpoint, ypoint). + + % It is assumed that Xdata has identical columns, so we only really + % need the first column to find the nearest value to xpoint. + + [ xindex, xpoint ] = NearestXYArrayPoint( Xdata(:,1), xpoint ); + + % Now, given the xpoint, we can select just that row of the + % Ydata matrix corresponding to the xpoint. + ydata = Ydata(xindex,:); + + % The ydata array is searched in same manner as the xdata + % array for the nearest value. + [ yindex, ypoint ] = NearestXYArrayPoint( ydata, ypoint ); + +return + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [H] = INIT + + H.gui = gcf; % Get current figure handles + H.axis = gca; % Get current axis handles + + H.axis = gca; % Get current axis handles + H.ylim = get(H.axis,'ylim'); + + % store current button fcn + H.button = get(H.gui,'WindowButtonDownFcn'); + % set XHR button down fcn + set(H.gui,'WindowButtonDownFcn','crosshair(''down'');'); + set(H.gui,'KeyPressFcn','crosshair(''keypress'');'); + + % Match background figure colour + bgcolor = get(H.gui,'Color'); + % Try to adapt the foreground colour a little + black = find(bgcolor <= .6); + fgcolor = [0 0 0]; %black text + if length(black)>2, fgcolor = [1 1 1]; end + + + Font.FontName = 'Helvetica'; + Font.FontUnits = 'Pixels'; + Font.FontSize = 10; + Font.FontWeight = 'normal'; + Font.FontAngle = 'normal'; + + H.yflip = uicontrol(H.gui,'Style','pushbutton','Units','Normalized',Font,... + 'Position',[.00 .70 .08 .05],... + 'Tag','YFLIP',... + 'TooltipString','Flip Y Axis', ... + 'String','Flip',... + 'Callback',strcat('XHR = get(gcbf,''userdata'');',... + 'ydir = get(XHR.axis,''YDir'');',... + 'if isequal(ydir,''normal''),',... + ' set(XHR.axis,''YDir'',''reverse'');',... + 'else,',... + ' set(XHR.axis,''YDir'',''normal'');',... + 'end;',... + 'set(gcbf,''userdata'',XHR); figure(XHR.gui); clear XHR;')); + + H.yreset = uicontrol(H.gui,'Style','pushbutton','Units','Normalized',Font,... + 'Position',[.00 .65 .08 .05],... + 'Tag','YRESET',... + 'TooltipString','Reset Axis Limits', ... + 'String','Reset',... + 'Callback',strcat('XHR = get(gcbf,''userdata'');',... + 'XHR.ylim = get(XHR.axis,''ylim'');',... + 'set(XHR.ymin,''string'',sprintf(''%g'',XHR.ylim(1)));',... + 'set(XHR.ymax,''string'',sprintf(''%g'',XHR.ylim(2)));',... + 'set(gcbf,''userdata'',XHR); figure(XHR.gui); clear XHR;')); + + H.ymin = uicontrol(H.gui,'Style','edit','Units','Normalized',Font,... + 'Position',[.00 .60 .08 .05],... + 'HorizontalAlign','left',... + 'Tag','YMIN',... + 'TooltipString','Set Y min', ... + 'String',sprintf('%g',H.ylim(1)),... + 'Callback',strcat('XHR = get(gcbf,''userdata'');',... + 'ymin = str2num(get(XHR.ymin,''string''));',... + 'XHR.ylim(1) = ymin;',... + 'set(XHR.axis,''ylim'',XHR.ylim);',... + 'set(XHR.ymin,''string'',sprintf(''%g'',XHR.ylim(1)));',... + 'set(gcbf,''userdata'',XHR); figure(XHR.gui); clear XHR ymin;')); + + H.ymax = uicontrol(H.gui,'Style','edit','Units','Normalized',Font,... + 'Position',[.00 .55 .08 .05],... + 'HorizontalAlign','left',... + 'Tag','YMAX',... + 'TooltipString','Set Y max', ... + 'String',sprintf('%g',H.ylim(2)),... + 'Callback',strcat('XHR = get(gcbf,''userdata'');',... + 'ymax = str2num(get(XHR.ymax,''string''));',... + 'XHR.ylim(2) = ymax;',... + 'set(XHR.axis,''ylim'',XHR.ylim);',... + 'set(XHR.ymax,''string'',sprintf(''%g'',XHR.ylim(2)));',... + 'set(gcbf,''userdata'',XHR); figure(XHR.gui); clear XHR ymax;')); + + H.grid = uicontrol(H.gui,'Style','checkbox','Units','Normalized',Font,... + 'Position',[.00 .50 .08 .05],... + 'BackgroundColor',bgcolor,'ForegroundColor',fgcolor,... + 'Tag','GRID',... + 'TooltipString','Toggle plot grid on/off.', ... + 'String','grid',... + 'Callback',strcat('XHR = get(gcbf,''userdata'');',... + 'grid(XHR.axis);',... + 'set(gcbf,''userdata'',XHR); figure(XHR.gui); clear XHR;')); + + H.xvalue = uicontrol(H.gui,'Style','edit','Units','Normalized',Font,... + 'Position',[.13 .95 .15 .05],... + 'BackGroundColor',[ 0 .9 0],'ForeGroundColor',[ 0 0 0],... + 'Tag','XVALUE',... + 'TooltipString','X value (Read Only)',... + 'String',' '); + H.yvalue = uicontrol(H.gui,'Style','edit','Units','Normalized',Font,... + 'Position',[.28 .95 .15 .05],... + 'BackGroundColor',[ 0 0 .9],'ForeGroundColor',[ 1 1 1],... + 'Tag','YVALUE',... + 'TooltipString','Y value (Read Only)',... + 'String',' '); + + + H.fxeq = uicontrol('Style','edit','Units','Normalized',... + 'Position',[.45 .95 .10 .05],... + 'Tag','FXDEFINE',... + 'TooltipString','Define f(x) equation here',... + 'BackGroundColor',[ 0 .9 0],... + 'ForeGroundColor',[ 0 0 0],'String','x'); + H.fxvalue = uicontrol('Style','edit','Units','Normalized',... + 'Position',[.55 .95 .15 .05],... + 'Tag','FYVALUE',... + 'TooltipString','f(x) result',... + 'BackGroundColor',[ 0 .9 0],... + 'ForeGroundColor',[ 0 0 0],'String',' '); + + H.fyeq = uicontrol('Style','edit','Units','Normalized',... + 'Position',[.70 .95 .10 .05],... + 'Tag','FYDEFINE',... + 'TooltipString','Define f(y) equation here',... + 'BackGroundColor',[ 0 0 .9],... + 'ForeGroundColor',[ 1 1 1],'String','y'); + H.fyvalue = uicontrol('Style','edit','Units','Normalized',... + 'Position',[.80 .95 .15 .05],... + 'Tag','FYVALUE',... + 'TooltipString','f(y) result',... + 'BackGroundColor',[ 0 0 .9],... + 'ForeGroundColor',[ 1 1 1],'String',' '); + + H.yindex = uicontrol('Style','edit','Units','Normalized',Font,... + 'Position',[.92 .87 .08 .05],... + 'BackGroundColor',[ 0 0 .9],'ForeGroundColor',[ 1 1 1],... + 'Tag','YINDEX',... + 'TooltipString','Enter Y index into plot data matrix. Same as trace number.',... + 'String','1',... + 'Value',1,... + 'Callback',strcat('H = get(gcbf,''userdata'');',... + 'yi = str2num(get(H.yindex,''String''));',... + 'H.data.yindex = yi;',... + 'set(H.gui,''userdata'',H); clear H yi; ',... + '[Xpoint,Ypoint] = crosshair(''changey'');')); + H.yprev = uicontrol('Style','Push','Units','Normalized',Font,... + 'Position',[.92 .82 .04 .05],... + 'String','<',... + 'Tag','YPREV',... + 'TooltipString','Goto Previous Y Index (channel).',... + 'CallBack','[Xpoint,Ypoint] = crosshair(''prevy'');'); + H.ynext = uicontrol('Style','Push','Units','Normalized',Font,... + 'Position',[.96 .82 .04 .05],... + 'String','>',... + 'Tag','YNEXT',... + 'TooltipString','Goto Next Y Index (channel).',... + 'CallBack','[Xpoint,Ypoint] = crosshair(''nexty'');'); + H.yLT = uicontrol('Style','Push','Units','Normalized',Font,... + 'Position',[.92 .77 .04 .05],... + 'String','LT',... + 'Tag','YLT',... + 'TooltipString','Goto next Y Less Than current Y.',... + 'CallBack','[Xpoint,Ypoint] = crosshair(''yLT'');'); + H.yGT = uicontrol('Style','Push','Units','Normalized',Font,... + 'Position',[.96 .77 .04 .05],... + 'String','GT',... + 'Tag','YGT',... + 'TooltipString','Goto next Y Greater Than current Y.',... + 'CallBack','[Xpoint,Ypoint] = crosshair(''yGT'');'); + + H.xindex = uicontrol('Style','edit','Units','Normalized',Font,... + 'Position',[.92 .70 .08 .05],... + 'BackGroundColor',[ 0 .9 0],'ForeGroundColor',[ 0 0 0],... + 'Tag','XINDEX',... + 'TooltipString','Enter X index into plot data matrix. Only available for interpolation = ''none''.',... + 'String','1',... + 'Value',1,... + 'Callback',strcat('XHR = get(gcbf,''userdata'');',... + 'xi = str2num(get(XHR.xindex,''String''));',... + 'XHR.data.xindex = xi;',... + 'set(XHR.xinterp,''value'',0); ',... + 'set(XHR.xinterp,''string'',''0''); ',... + 'set(XHR.interp, ''value'',1); ',... + 'set(XHR.gui,''userdata'',XHR); clear XHR; ',... + '[Xpoint,Ypoint] = crosshair(''changex'');')); + H.xprev = uicontrol('Style','Push','Units','Normalized',Font,... + 'Position',[.92 .65 .04 .05],... + 'String','<',... + 'Tag','XPREV',... + 'TooltipString','Goto Previous X Index (no interpolation).',... + 'CallBack','[Xpoint,Ypoint] = crosshair(''prevx'');'); + H.xnext = uicontrol('Style','Push','Units','Normalized',Font,... + 'Position',[.96 .65 .04 .05],... + 'String','>',... + 'Tag','XNEXT',... + 'TooltipString','Goto Next X Index (no interpolation).',... + 'CallBack','[Xpoint,Ypoint] = crosshair(''nextx'');'); + + H.xinterp = uicontrol('Style','Edit','Units','Normalized',... + 'Position',[.92 .60 .08 .05],... + 'String','0',... + 'Value',0,.... + 'Tag','XINTERP',... + 'TooltipString','Interpolation X increment (zero = nearest X).',... + 'Callback',strcat('XHR = get(gcf,''userdata''); ',... + 'xint = str2num(get(XHR.xinterp,''string'')); ',... + 'set(XHR.xinterp,''value'',xint); figure(XHR.gui); clear XHR; ')); + + interpstr = 'none|nearest|linear|spline|cubic'; + H.interp = uicontrol('Style','popup','Units','Normalized',Font,... + 'Position',[.92 .55 .08 .05],... + 'Tag','INTERP',... + 'TooltipString','INTERP1 methods (none = raw values).', ... + 'String',interpstr,... + 'Callback',strcat('XHR = get(gcbf,''userdata'');',... + 'xint = get(XHR.xinterp,''Value''); ',... + 'if xint == 0, ',... + ' xint = 0.5; ',... + ' set(XHR.xinterp,''value'',xint); ',... + ' set(XHR.xinterp,''string'',num2str(xint)); ',... + ' set(XHR.xindex, ''string'',''interp''); ',... + 'end; ',... + 'set(XHR.gui,''userdata'',XHR); figure(XHR.gui); clear XHR; ')); + + H.store = uicontrol('Style','Push','Units','Normalized',... + 'Position',[.92 .40 .08 .05],... + 'String','Store',... + 'Tag','STORE',... + 'TooltipString','Store current Channel & XY values into base XYhist array.', ... + 'CallBack','crosshair(''store'');'); + + H.done = uicontrol('Style','Push','Units','Normalized',... + 'Position',[.80 .00 .10 .05],... + 'BackgroundColor',[.8 .5 0],... + 'ForegroundColor',[1 1 1],... + 'FontWeight','bold',... + 'String','Done',... + 'Tag','DONE',... + 'TooltipString','Close crosshair', ... + 'CallBack','crosshair(''done'');'); + H.exit = uicontrol('Style','Push','Units','Normalized',... + 'Position',[.90 .00 .10 .05],... + 'BackgroundColor',[.8 0 0],... + 'ForegroundColor',[1 1 1],... + 'FontWeight','bold',... + 'String','Exit',... + 'Tag','EXIT',... + 'TooltipString','Close crosshair and Figure', ... + 'CallBack','crosshair(''exit'');'); + + %%%%%%%%%%%%%%%%%%%%%%%%% + % Get Line Data from Plot + + % Lines are referenced as axis children, among other + % axis children; so first get all axis children + sibs = get(H.axis,'Children'); + + % Now search axis children for any line types. + % Because the columns of the y data matrix in a plot + % command seem to be reversed in the axis children, + % count down from max sibs to the first sib. + lines = 0; + H.data.xdata = []; + H.data.ydata = []; + H.data.xpoint = []; + H.data.ypoint = []; + H.data.xindex = 1; + H.data.yindex = 1; + i = max(size(sibs)); + while i >= 1 + if strcmp(get(sibs(i),'Type'),'line') + + % OK, found a line among the axis children. + lines = lines + 1; + + % put line data into a column of DATA.xdata|DATA.ydata + H.data.xdata(:,lines) = get(sibs(i),'XData').'; + H.data.ydata(:,lines) = get(sibs(i),'YData').'; + end + i = i - 1; + end + + % 'traces' string variable must be in ascending order + traces = ''; + i = 1; + while i <= lines; + if i < lines + tracelabel = sprintf('Column %4d|',i); + else + tracelabel = sprintf('Column %4d',i); + end + traces = strcat(traces,tracelabel); + i = i + 1; + end + + % If more than one line, provide GUI for line selection + + % Switch off||on Trace Selection GUI + Vis = 'Off'; + if lines > 1, + Vis = 'On'; + elseif lines == 0 + error('No lines found in the current plot window\n'); + end + + % Create Trace Index GUI + H.traceLabel = uicontrol('Style','Edit', 'Units','Normalized',... + 'Position',[.00 .00 .15 .05],... + 'Tag','TRACELABEL',... + 'Visible',Vis,'String','Select Trace :',... + 'TooltipString','Select trace to follow with crosshairs.'); + H.trace = uicontrol('Style','Popup','Units','Normalized',... + 'Position',[.15 .00 .20 .05],... + 'Tag','TRACESWITCH',... + 'BackGroundColor','w','String',traces,... + 'Visible',Vis,... + 'CallBack','crosshair(''up'');'); + H.traceNearest = uicontrol('Style','checkbox', 'Units','Normalized',... + 'Position',[.36 .00 .19 .05],... + 'BackgroundColor',bgcolor,'ForegroundColor',fgcolor,... + 'Tag','TRACENEAREST',... + 'Visible',Vis,'String','Nearest Trace','Value',1,... + 'TooltipString','Trace nearest to mouse click; switch off to keep trace constant.'); + + + % Set X,Y cross hair lines + % Do this after finding all the line axis children + % to avoid confusing these lines with those of the + % plot itself (counted above). + x_rng = get(H.axis,'Xlim'); + y_rng = get(H.axis,'Ylim'); + H.xline = line(x_rng,[y_rng(1) y_rng(1)]); + H.yline = line(x_rng,[y_rng(1) y_rng(1)]); + set(H.xline,'Color','r','EraseMode','xor','Tag','XLINE'); + set(H.yline,'Color','r','EraseMode','xor','Tag','YLINE'); + +return diff --git a/crosshair_subplots.m b/crosshair_subplots.m new file mode 100644 index 0000000..6e7e57d --- /dev/null +++ b/crosshair_subplots.m @@ -0,0 +1,1128 @@ +function [Xpoint,Ypoint,XYhist] = crosshair_subplots(action); +% CROSSHAIR: A gui interface for reading (x,y) values from a plot. +% +% [Xpoint,Ypoint,XYhist] = crosshair_subplots(action); +% +% A set of mouse driven crosshairs is placed on the current axes, +% and displays the current (x,y) values of the line plot. There is an +% option to provide data specific values or interpolated values. The +% resolution of the data specific values depends on both the data +% resolution and the GUI interface (mainly mouse movement resolution). +% The interpolated values appear to provide a more continuous function, +% however they too depend on the GUI interface resolution. There are +% no options for extrapolation. +% +% For multiple traces, plots with the same length(xdata) are +% tracked. Each mouse click returns Xpoint,Ypoint values and selecting +% 'done' will remove the GUI and restore the mouse buttons to previous +% values. Selecting 'exit' will remove the GUI and close the figure. +% +% In this version (Dec 2002), the crosshairs can track multiple subplots +% and there are new options to define functions of X/Y and monitor +% their results. There is also a new STORE button that creates and +% updates an XYhist struct in the base workspace, which contains value +% labels and values. This version has better controls of X/Y movements, +% including better interpolation movement options. This version attempts +% to respond correctly to keyboard entries, including TAB between subplots, +% RETURN to 'save', ESC for 'done' and all the arrow keys to move the +% crosshairs. +% +% Some further help is given in the tool tips of the GUI. +% +% Note: crosshair should always update the Xpoint,Ypoint in the base +% workspace. Here is an example of how to get return values within +% a script/function after pressing the exit button of crosshair: +% function [X,Y] = crosshair_returnXY +% x = [1:10]; y(1,:) = sin(x); y(2,:) = cos(x); +% figure; plot(x,y); crosshair; +% uiwait +% X = evalin('base','Xpoint'); +% Y = evalin('base','Ypoint'); +% return +% Copy this text to a function .m file and then call it from the +% base workspace with [X,Y] = crosshair_returnXY +% +% Useage: wt=0:0.01:2.5*pi; +% t=wt; +% subplot(2,1,1),plot(t,1.0*sin(wt),t,1.0*sin(wt-110/180*pi),t,1.0*sin(wt-250/180*pi)); +% subplot(2,1,2), plot(t,sin(2*wt)); +% crosshair_subplots; +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +% Copyright (C) 2002 Darren L. Weber +% +% This program is free software; you can redistribute it and/or +% modify it under the terms of the GNU General Public License +% as published by the Free Software Foundation; either version 2 +% of the License, or (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program; if not, write to the Free Software +% Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +% History: 03/96, Richard G. Cobb +% 08/01, Darren.Weber@flinders.edu.au +% replaced obsolete 'table1' with 'interp1'; fixed bug +% with number of 'traces'; rationalized calculations into +% a common subfunction for x,y point calc in 'down','up', +% & 'move' button functions; added option to turn on/off +% interpolation and the exit button; simplified updates +% to graphics using global GUI handle structure. +% 11/01, Darren.Weber@flinders.edu.au +% added tooltips for several GUI handles +% added multiple interpolation methods +% added GUI for data matrix indices (given no interpolation) +% added option to select trace nearest to mouse click point +% reversed order of lines in data matrix to be consistent +% with the value returned from the nearest trace subfunction +% create crosshair lines after finding all plot lines to +% avoid confusing them with the plot lines +% 01/02, Darren.Weber@flinders.edu.au +% should now work across multiple plot figures, given +% that all gui handles and data are now stored in the +% plot figure 'userdata' handle. +% added functionality to move smoothly from interpolation +% back to the delimited data via the "next/previous" +% buttons. +% 06/02, Darren.Weber@flinders.edu.au +% learned how to get values back to a script/function with +% evalin command and updated help above. +% 12/02, Darren.Weber@flinders.edu.au +% added Store uicontrol and associated XYhist variable +% updates in base workspace to provide storage of +% consecutive XY values (thanks to C.A.Swenne@lumc.nl & +% H.van_de_Vooren@lumc.nl for their suggestion/assistance). +% added keyboard controls to left/right arrow and return. +% added prev/next X interpolation interval. +% added handling of subplots in crosshair_subplots version. +% 06/05, suggestion not implemented yet: +% I often use 2 or more vertically arranged sublots with the same x coordinates. +% Would it be possible to adapt your function to have vertical cursor displayed +% on each sublots with the same x coordinates? Of course y information would be +% written only for one sublot at a time(the selected one)! +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +if ~exist('action','var') + action = 'init'; +elseif isempty(action) + action = 'init'; +end + +XHR_HANDLES = get(gcf,'userdata'); + +if gca & ~isempty(XHR_HANDLES), + if ~isequal(gca,XHR_HANDLES.axis), + % Ensure we have the right axis data + XHR_HANDLES.axis = gca; + XHR_HANDLES.data = get_data; + end +end + + +% Check for specific keys and assign reasonable actions +if strcmp(action, 'keypress'), + + CC = get(XHR_HANDLES.gui,'CurrentCharacter'); + cc = double(CC); + if cc, + switch cc, + case 9, action = 'axes'; % TAB, switch axes, if possible + case 27, action = 'done'; % ESC + case 28, action = 'prevx'; % left + case 29, action = 'nextx'; % right + case 30, action = 'ygt'; % up + case 31, action = 'ylt'; % down + case 13, action = 'store'; % return/enter + otherwise, action = 'up'; % all other keys + end + end +end + + +action = lower(action); + +switch action, + +case 'init', + + % Paint GUI + XHR_HANDLES = INIT; + + % Update and return values + XHR_HANDLES = updateDATA(XHR_HANDLES); + Xpoint = get(XHR_HANDLES.xvalue,'Value'); + Ypoint = get(XHR_HANDLES.yvalue,'Value'); + %updateXYhistory(Xpoint,Ypoint); + +case 'axes', + + % TAB between axes in subplots of a figure + ax = findobj(gcf,'type','axes'); + if length(ax) > 1, + nax = find(ax == gca); + if nax < length(ax), + axes(ax(nax+1)); + else + axes(ax(1)); + end + end + XHR_HANDLES.axis = gca; + XHR_HANDLES.data = get_data; + XHR_HANDLES = updateGUI(XHR_HANDLES); + Xpoint = get(XHR_HANDLES.xvalue,'Value'); + Ypoint = get(XHR_HANDLES.yvalue,'Value'); + +% Mouse Click Down +case 'down', + + set(XHR_HANDLES.gui,'WindowButtonMotionFcn','crosshair_subplots(''move'');'); + set(XHR_HANDLES.gui,'WindowButtonUpFcn','[Xpoint,Ypoint] = crosshair_subplots(''up'');'); + + XHR_HANDLES = updateDATA(XHR_HANDLES); + Xpoint = get(XHR_HANDLES.xvalue,'Value'); + Ypoint = get(XHR_HANDLES.yvalue,'Value'); + %updateXYhistory(Xpoint,Ypoint); + +% Mouse Drag Motion +case 'move', + + XHR_HANDLES = updateDATA(XHR_HANDLES); + Xpoint = get(XHR_HANDLES.xvalue,'Value'); + Ypoint = get(XHR_HANDLES.yvalue,'Value'); + %updateXYhistory(Xpoint,Ypoint); + +% Mouse Click Up +case 'up', + + set(XHR_HANDLES.gui,'WindowButtonMotionFcn',' '); + set(XHR_HANDLES.gui,'WindowButtonUpFcn',' '); + + XHR_HANDLES = updateDATA(XHR_HANDLES); + Xpoint = get(XHR_HANDLES.xvalue,'Value'); + Ypoint = get(XHR_HANDLES.yvalue,'Value'); + %updateXYhistory(Xpoint,Ypoint); + +% Next or Previous X point +case {'nextx','prevx','changex','nexty','prevy','changey','ylt','ygt'}, % Change X/Y + + XHR_HANDLES = moveXY(XHR_HANDLES,action); + Xpoint = get(XHR_HANDLES.xvalue,'Value'); + Ypoint = get(XHR_HANDLES.yvalue,'Value'); + %updateXYhistory(Xpoint,Ypoint); + +% Store XY values into a history array +case 'store', + + Xpoint = get(XHR_HANDLES.xvalue,'Value'); + Ypoint = get(XHR_HANDLES.yvalue,'Value'); + updateXYhistory(XHR_HANDLES); + +% Exit crosshairs GUI +case {'done','exit'}, + + Xpoint = get(XHR_HANDLES.xvalue,'Value'); + Ypoint = get(XHR_HANDLES.yvalue,'Value'); + %updateXYhistory(Xpoint,Ypoint); + + handles = fieldnames(XHR_HANDLES); + for i=1:length(handles), + switch handles{i}, + case {'axis','datalines','gui'}, + otherwise, + h = getfield(XHR_HANDLES,handles{i}); + if ishandle(h), delete(h); end + end + end + + if strcmp(action,'exit'); + if ishandle(XHR_HANDLES.gui), + close(XHR_HANDLES.gui); + end + else + + lines = findobj(gcf,'tag','XHR_XLINE'); + for l = 1:length(lines), + line = lines(l); + if ishandle(line), delete(line); end + end + lines = findobj(gcf,'tag','XHR_YLINE'); + for l = 1:length(lines), + line = lines(l); + if ishandle(line), delete(line); end + end + + set(XHR_HANDLES.gui,'WindowButtonUpFcn',''); + set(XHR_HANDLES.gui,'WindowButtonMotionFcn',''); + set(XHR_HANDLES.gui,'WindowButtonDownFcn',' '); + + refresh(XHR_HANDLES.gui); + end + + clear XHR_HANDLES; + return; + +end + +if ishandle(XHR_HANDLES.axis), + set(XHR_HANDLES.axis,'userdata',XHR_HANDLES.data); +end + +if ishandle(XHR_HANDLES.gui), + set(XHR_HANDLES.gui,'userdata',XHR_HANDLES); + figure(XHR_HANDLES.gui); +end + +return; + + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function updateXYhistory(H), + + Ch = get(H.yindex,'Value'); + X = get(H.xvalue,'Value'); + Y = get(H.yvalue,'Value'); + fX = get(H.fxvalue,'Value'); + fY = get(H.fyvalue,'Value'); + + fXeq = get(H.fxeq,'String'); + fYeq = get(H.fyeq,'String'); + + XY.labels = {'Channel','X','Y',['f(x) = ',fXeq],['f(y) = ',fYeq]}; + XY.data = [Ch,X,Y,fX,fY]; + + if evalin('base','exist(''XYhist'',''var'');'), + XYhist = evalin('base','XYhist'); + % get the current history set + set = getfield(XYhist,['set',num2str(XYhist.set)]); + if isequal(set.labels,XY.labels), + set.data(end+1,:) = XY.data; + XYhist = setfield(XYhist,['set',num2str(XYhist.set)],set); + assignin('base','XYhist',XYhist); + else + fprintf('\nWarning: creating new set of XYhist in base workspace.\n\n'); + XYhist.set = XYhist.set + 1; + XYhist = setfield(XYhist,['set',num2str(XYhist.set)],XY); + assignin('base','XYhist',XYhist); + end + else + XYhist.set = 1; + XYhist.set1 = XY; + assignin('base','XYhist',XYhist); + end + +return + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [H] = moveXY(H,move) + + interp = get(H.interp,'Value'); + xinterp = get(H.xinterp,'Value'); + + if (xinterp > 0) & (interp > 1), + + % Use incremental interpolation of x values + switch move, + case 'nexty', H.data.yindex = H.data.yindex + 1; + case 'prevy', H.data.yindex = H.data.yindex - 1; + case 'ygt', + ydata = interpYall(H); + [ysort,yi] = sort(ydata); + currYI = find(ysort > H.data.ypoint); + if min(currYI), + H.data.yindex = yi(min(currYI)); + end + case 'ylt', + ydata = interpYall(H); + [ysort,yi] = sort(ydata); + currYI = find(ysort < H.data.ypoint); + if max(currYI), + H.data.yindex = yi(max(currYI)); + end + case 'nextx', + H.data.xpoint = H.data.xpoint + xinterp; + case 'prevx', + H.data.xpoint = H.data.xpoint - xinterp; + end + H = checkdatarange(H); + H = interpY(H); + updateGUI(H); + return + end + + + % No interpolation of x values... + + if (interp > 1) + xdata = H.data.xdata(:,H.data.yindex); + [H.data.xindex] = NearestXYArrayPoint( xdata, H.data.xpoint, move ); + end + + switch move, + case 'nextx', + % Increase current xindex by one + if(interp == 1), H.data.xindex = H.data.xindex + 1; end + case 'prevx', + % Decrease current xindex by one + if(interp == 1), H.data.xindex = H.data.xindex - 1; end + case 'nexty', H.data.yindex = H.data.yindex + 1; + case 'prevy', H.data.yindex = H.data.yindex - 1; + case 'ygt', + ydata = H.data.ydata(H.data.xindex,:); + [ysort,yi] = sort(ydata); + currYI = find(ysort == H.data.ypoint); + if currYI < length(yi), + H.data.yindex = yi(currYI+1); + end + case 'ylt', + ydata = H.data.ydata(H.data.xindex,:); + [ysort,yi] = sort(ydata); + currYI = find(ysort == H.data.ypoint); + if currYI > 1, + H.data.yindex = yi(currYI-1); + end + otherwise + end + + H = checkdatarange(H); + + % Get x/y value at new x/y index + H.data.xpoint = H.data.xdata(H.data.xindex,H.data.yindex); + H.data.ypoint = H.data.ydata(H.data.xindex,H.data.yindex); + + set(H.interp,'Value',1); + H = updateGUI(H); + +return + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [ H ] = checkdatarange(H), + + % Ensure that x/y index is within data range + s = size(H.data.xdata,1); + if( H.data.xindex < 1 ), + H.data.xindex = 1; + elseif( H.data.xindex >= s ), + H.data.xindex = s; + end + s = size(H.data.ydata,2); + if( H.data.yindex < 1 ), + H.data.yindex = 1; + elseif( H.data.yindex >= s ), + H.data.yindex = s; + end + +return + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [ H ] = updateDATA( H ) + + % Only update if mouse pointer is in the + % axis limits + set(H.gui,'units','normalized'); + axpos = get(H.axis,'position'); + figcp = get(H.gui,'Currentpoint'); + axlim = axpos(1) + axpos(3); + aylim = axpos(2) + axpos(4); + if or(figcp(1) > (axlim+.01), figcp(1) < (axpos(1)-.01)), + return; + elseif or(figcp(2) > (aylim+.01), figcp(2) < (axpos(2)-.01)), + return; + end + + CurrentPoint = get(H.axis,'Currentpoint'); + H.data.xpoint = CurrentPoint(1,1); + H.data.ypoint = CurrentPoint(1,2); + + if get(H.traceNearest,'Value'), + + % Get new yindex for nearest trace + [ H.data.xpoint, ... + H.data.xindex, ... + H.data.ypoint, ... + H.data.yindex ] = NearestXYMatrixPoint( H.data.xdata,... + H.data.ydata,... + H.data.xpoint,... + H.data.ypoint); + end + + CurrentPoint = get(H.axis,'Currentpoint'); + H.data.xpoint = CurrentPoint(1,1); + H.data.ypoint = CurrentPoint(1,2); + + H = interpY(H); + H = updateGUI(H); + +return + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [ H ] = updateGUI( H ) + + InterpMethod = get(H.interp,'Value'); + if (InterpMethod > 1) + % There is no specific matrix x-index for + % an interpolated point, but the nearest xindex + % is always returned from the interp function below + % so that next/prev move function works correctly + set(H.xindex,'String','interp'); + else + set(H.xindex,'String',num2str(H.data.xindex)); + end + set(H.xindex,'Value',H.data.xindex); + + tracestr = sprintf('%d',H.data.yindex); + set(H.yindex,'String',tracestr,'Value',uint16(H.data.yindex)); + %set(H.trace,'Value',uint16(H.data.yindex)); + + % Create the crosshair lines on the figure, crossing at the x,y point + x_rng = get(H.axis,'Xlim'); + y_rng = get(H.axis,'Ylim'); + set(H.data.xline,'Xdata',[H.data.xpoint H.data.xpoint],'Ydata',y_rng); + set(H.data.yline,'Ydata',[H.data.ypoint H.data.ypoint],'Xdata',x_rng); + + % Update the x,y values displayed for the x,y point + xstring = sprintf('%g',H.data.xpoint); + ystring = sprintf('%g',H.data.ypoint); + set(H.xvalue,'String',xstring,'Value',H.data.xpoint); + set(H.yvalue,'String',ystring,'Value',H.data.ypoint); + + % Calculate the f(x) function + fyeq = get(H.fyeq,'string'); + fyval = eval(strrep(fyeq,'y',ystring)); + fystr = sprintf('%g',fyval); + set(H.fyvalue,'String',fystr,'Value',fyval); + + % Calculate the f(y) function + fxeq = get(H.fxeq,'string'); + fxval = eval(strrep(fxeq,'x',xstring)); + fxstr = sprintf('%g',fxval); + set(H.fxvalue,'String',fxstr,'Value',fxval); + +return + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [ H ] = interpY( H ) + + % In this function, xdata & ydata are arrays, not matrices + xdata = H.data.xdata(:,H.data.yindex); + ydata = H.data.ydata(:,H.data.yindex); + + if H.data.xpoint >= max(xdata) + H.data.xpoint = max(xdata); + H.data.xindex = find(xdata == max(xdata)); + H.data.ypoint = ydata(H.data.xindex); + return; + elseif H.data.xpoint <= min(xdata) + H.data.xpoint = min(xdata); + H.data.xindex = find(xdata == min(xdata)); + H.data.ypoint = ydata(H.data.xindex); + return; + end + + % 'none|nearest|linear|spline|cubic' + interp = get(H.interp,'Value'); + + switch interp + case 1 + % Given that xdata & ydata are the same length arrays, + % we can find the ypoint given the nearest xpoint. + [H.data.xindex, H.data.xpoint] = NearestXYArrayPoint( xdata, H.data.xpoint ); + H.data.ypoint = ydata(H.data.xindex); + case 2 + H.data.ypoint = interp1( xdata, ydata, H.data.xpoint, 'nearest' ); + case 3 + H.data.ypoint = interp1( xdata, ydata, H.data.xpoint, 'linear' ); + case 4 + H.data.ypoint = interp1( xdata, ydata, H.data.xpoint, 'spline' ); + case 5 + H.data.ypoint = interp1( xdata, ydata, H.data.xpoint, 'cubic' ); + otherwise + %use default (linear in matlabR12) + H.data.ypoint = interp1( xdata, ydata, H.data.xpoint ); + end + +return + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [ Yall ] = interpYall( H ) + + xdata = H.data.xdata(:,H.data.yindex); + Yall = H.data.ydata; + + if H.data.xpoint >= max(xdata), + H.data.xpoint = max(xdata); + H.data.xindex = find(xdata == max(xdata)); + Yall = ydata(:,H.data.xindex); + return; + elseif H.data.xpoint <= min(xdata), + H.data.xpoint = min(xdata); + H.data.xindex = find(xdata == min(xdata)); + Yall = ydata(:,H.data.xindex); + return; + end + + % 'none|nearest|linear|spline|cubic' + interp = get(H.interp,'Value'); + + switch interp, + case 1 + % do nothing in this case + case 2 + Yall = interp1( xdata, Yall, H.data.xpoint, 'nearest' ); + case 3 + Yall = interp1( xdata, Yall, H.data.xpoint, 'linear' ); + case 4 + Yall = interp1( xdata, Yall, H.data.xpoint, 'spline' ); + case 5 + Yall = interp1( xdata, Yall, H.data.xpoint, 'cubic' ); + otherwise + %use default (linear in matlabR12) + Yall = interp1( xdata, Yall, H.data.xpoint ); + end + +return + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [ index, point ] = NearestXYArrayPoint( data_array, point, type ) + + if ~exist('type','var') type = ''; end + + % In this function, input data_array is an array, not a matrix. + % This function returns the data point in the array + % that has the closest value to the value given (point). In + % the context of 'crosshair' the point is a mouse position. + + if point >= max(data_array) + point = max(data_array); + index = find(data_array == point); + return; + elseif point <= min(data_array) + point = min(data_array); + index = find(data_array == point); + return; + end + + data_sorted = sort(data_array); + + greater = find(data_sorted > point); + greater_index = greater(1); + + lesser = find(data_sorted < point); + lesser_index = lesser(length(lesser)); + + greater_dif = data_sorted(greater_index) - point; + lesser_dif = point - data_sorted(lesser_index); + + if strcmp(type,'nextx'), + index = greater_index; + elseif strcmp(type,'prevx'), + index = lesser_index; + else + if (greater_dif < lesser_dif) + index = find(data_array == data_sorted(greater_index)); + else + index = find(data_array == data_sorted(lesser_index)); + end + end + point = data_array(index); + +return + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [ xpoint, xindex, ypoint, yindex ] = NearestXYMatrixPoint( Xdata, Ydata, xpoint, ypoint ) + + % In this function, Xdata & Ydata are matrices of the same dimensions. + % This function attempts to find the nearest values in Xdata & Ydata + % to the mouse position (xpoint, ypoint). + + % It is assumed that Xdata has identical columns, so we only really + % need the first column to find the nearest value to xpoint. + + [ xindex, xpoint ] = NearestXYArrayPoint( Xdata(:,1), xpoint ); + + % Now, given the xpoint, we can select just that row of the + % Ydata matrix corresponding to the xpoint. + ydata = Ydata(xindex,:); + + % The ydata array is searched in same manner as the xdata + % array for the nearest value. + [ yindex, ypoint ] = NearestXYArrayPoint( ydata, ypoint ); + +return + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [ data ] = get_data, + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % Get Line Data from Current Axes + + if gca, + + % see if we have stored any data in userdata already + data = get(gca,'userdata'); + + if isfield(data,'lineobj'), + if data.lineobj, + return; + end + end + + data.ylim = get(gca,'ylim'); + + % Get all the line objects from the current axis + data.lineobj = findobj(gca,'Type','line'); + + if data.lineobj, + + data.lines = length(data.lineobj); + data.xdata = []; + data.ydata = []; + data.xpoint = []; + data.ypoint = []; + data.xindex = 1; + data.yindex = 1; + for i = data.lines:-1:1, + + % put line data into a columns of data + data.xdata(:,i) = get(data.lineobj(i),'XData').'; + data.ydata(:,i) = get(data.lineobj(i),'YData').'; + end + + % Set X,Y cross hair lines + % Do this after finding all the line axis children + % to avoid confusing these lines with those of the + % plot itself (counted above). + x_rng = get(gca,'Xlim'); + y_rng = get(gca,'Ylim'); + data.xline = line(x_rng,[y_rng(1) y_rng(1)]); + data.yline = line(x_rng,[y_rng(1) y_rng(1)]); + set(data.xline,'Color','r','EraseMode','xor','tag','XHR_XLINE'); + set(data.yline,'Color','r','EraseMode','xor','tag','XHR_YLINE'); + + set(gca,'userdata',data); + + else + fprintf('No lines in current axes\n'); + end + + end + +return + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [H] = INIT + + H.gui = gcf; % Get current figure handles + H.axis = gca; % Get current axis handles + + H.data = get_data; + + % store current button fcn + H.button = get(H.gui,'WindowButtonDownFcn'); + % set XHR button down fcn + set(H.gui,'WindowButtonDownFcn','crosshair_subplots(''down'');'); + set(H.gui,'KeyPressFcn','crosshair_subplots(''keypress'');'); + + % Match background figure colour + bgcolor = get(H.gui,'Color'); + % Try to adapt the foreground colour a little + black = find(bgcolor <= .6); + fgcolor = [0 0 0]; %black text + if length(black)>2, fgcolor = [1 1 1]; end + + + Font.FontName = 'Helvetica'; + Font.FontUnits = 'Pixels'; + Font.FontSize = 10; + Font.FontWeight = 'normal'; + Font.FontAngle = 'normal'; + + + if findobj(gcf,'tag','XHR_YFLIP'), + H.yflip = findobj(gcf,'tag','XHR_YFLIP'); + else + H.yflip = uicontrol(H.gui,'tag','XHR_YFLIP','Style','pushbutton',... + 'Units','Normalized',Font,... + 'Position',[.00 .95 .08 .05],... + 'TooltipString','Flip Y Axis', ... + 'String','Flip',... + 'Callback',strcat('XHR = get(gcf,''userdata'');',... + 'ydir = get(XHR.axis,''YDir'');',... + 'if isequal(ydir,''normal''),',... + ' set(XHR.axis,''YDir'',''reverse'');',... + 'else,',... + ' set(XHR.axis,''YDir'',''normal'');',... + 'end;',... + 'set(XHR.gui,''userdata'',XHR); figure(XHR.gui); clear XHR;')); + end + + if findobj(gcf,'tag','XHR_YRESET'), + H.yreset = findobj(gcf,'tag','XHR_YRESET'); + else + H.yreset = uicontrol(H.gui,'tag','XHR_YRESET','Style','pushbutton',... + 'Units','Normalized',Font,... + 'Position',[.00 .90 .08 .05],... + 'TooltipString','Reset Axis Limits', ... + 'String','Reset',... + 'Callback',strcat('XHR = get(gcf,''userdata'');',... + 'XHR.data.ylim = get(XHR.axis,''ylim'');',... + 'set(XHR.ymin,''string'',sprintf(''%g'',XHR.data.ylim(1)));',... + 'set(XHR.ymax,''string'',sprintf(''%g'',XHR.data.ylim(2)));',... + 'set(XHR.gui,''userdata'',XHR); figure(XHR.gui); clear XHR;')); + end + + if findobj(gcf,'tag','XHR_YMIN'), + H.ymin = findobj(gcf,'tag','XHR_YMIN'); + else + H.ymin = uicontrol(H.gui,'tag','XHR_YMIN','Style','edit',... + 'Units','Normalized',Font,... + 'Position',[.00 .85 .08 .05],... + 'HorizontalAlign','left',... + 'TooltipString','Set Y min', ... + 'String',sprintf('%g',H.data.ylim(1)),... + 'Callback',strcat('XHR = get(gcf,''userdata'');',... + 'ymin = str2num(get(XHR.ymin,''string''));',... + 'XHR.data.ylim(1) = ymin;',... + 'set(XHR.axis,''ylim'',XHR.data.ylim);',... + 'set(XHR.ymin,''string'',sprintf(''%g'',XHR.data.ylim(1)));',... + 'set(XHR.gui,''userdata'',XHR); figure(XHR.gui); clear XHR ymin;')); + end + + if findobj(gcf,'tag','XHR_YMAX'), + H.ymax = findobj(gcf,'tag','XHR_YMAX'); + else + H.ymax = uicontrol(H.gui,'tag','XHR_YMAX','Style','edit',... + 'Units','Normalized',Font,... + 'Position',[.00 .80 .08 .05],... + 'HorizontalAlign','left',... + 'TooltipString','Set Y max', ... + 'String',sprintf('%g',H.data.ylim(2)),... + 'Callback',strcat('XHR = get(gcf,''userdata'');',... + 'ymax = str2num(get(XHR.ymax,''string''));',... + 'XHR.data.ylim(2) = ymax;',... + 'set(XHR.axis,''ylim'',XHR.data.ylim);',... + 'set(XHR.ymax,''string'',sprintf(''%g'',XHR.data.ylim(2)));',... + 'set(XHR.gui,''userdata'',XHR); figure(XHR.gui); clear XHR ymax;')); + end + + if findobj(gcf,'tag','XHR_GRID'), + H.grid = findobj(gcf,'tag','XHR_GRID'); + else + H.grid = uicontrol(H.gui,'tag','XHR_GRID','Style','checkbox',... + 'Units','Normalized',Font,... + 'Position',[.00 .75 .08 .05],... + 'BackgroundColor',bgcolor,'ForegroundColor',fgcolor,... + 'TooltipString','Toggle plot grid on/off.', ... + 'String','grid',... + 'Callback',strcat('XHR = get(gcf,''userdata'');',... + 'grid(XHR.axis);',... + 'set(XHR.gui,''userdata'',XHR); figure(XHR.gui); clear XHR;')); + end + + if findobj(gcf,'tag','XHR_XVALUE'), + H.xvalue = findobj(gcf,'tag','XHR_XVALUE'); + else + H.xvalue = uicontrol(H.gui,'tag','XHR_XVALUE','Style','edit',... + 'Units','Normalized',Font,... + 'Position',[.13 .95 .15 .05],... + 'BackGroundColor',[ 0 .9 0],'ForeGroundColor',[ 0 0 0],... + 'TooltipString','X value (Read Only)',... + 'String',' '); + end + + if findobj(gcf,'tag','XHR_YVALUE'), + H.yvalue = findobj(gcf,'tag','XHR_YVALUE'); + else + H.yvalue = uicontrol(H.gui,'tag','XHR_YVALUE','Style','edit',... + 'Units','Normalized',Font,... + 'Position',[.28 .95 .15 .05],... + 'BackGroundColor',[ 0 0 .9],'ForeGroundColor',[ 1 1 1],... + 'TooltipString','Y value (Read Only)',... + 'String',' '); + end + + if findobj(gcf,'tag','XHR_FXEQ'), + H.fxeq = findobj(gcf,'tag','XHR_FXEQ'); + else + H.fxeq = uicontrol(H.gui,'tag','XHR_FXEQ','Style','edit',... + 'Units','Normalized',... + 'Position',[.45 .95 .10 .05],... + 'TooltipString','Define f(x) equation here',... + 'BackGroundColor',[ 0 .9 0],... + 'ForeGroundColor',[ 0 0 0],'String','x'); + end + + if findobj(gcf,'tag','XHR_FXVALUE'), + H.fxvalue = findobj(gcf,'tag','XHR_FXVALUE'); + else + H.fxvalue = uicontrol(H.gui,'tag','XHR_FXVALUE','Style','edit',... + 'Units','Normalized',... + 'Position',[.55 .95 .15 .05],... + 'TooltipString','f(x) result',... + 'BackGroundColor',[ 0 .9 0],... + 'ForeGroundColor',[ 0 0 0],'String',' '); + end + + if findobj(gcf,'tag','XHR_FYEQ'), + H.fyeq = findobj(gcf,'tag','XHR_FYEQ'); + else + H.fyeq = uicontrol(H.gui,'tag','XHR_FYEQ','Style','edit',... + 'Units','Normalized',... + 'Position',[.70 .95 .10 .05],... + 'TooltipString','Define f(y) equation here',... + 'BackGroundColor',[ 0 0 .9],... + 'ForeGroundColor',[ 1 1 1],'String','y'); + end + + if findobj(gcf,'tag','XHR_FYVALUE'), + H.fyvalue = findobj(gcf,'tag','XHR_FYVALUE'); + else + H.fyvalue = uicontrol(H.gui,'tag','XHR_FYVALUE','Style','edit',... + 'Units','Normalized',... + 'Position',[.80 .95 .15 .05],... + 'TooltipString','f(y) result',... + 'BackGroundColor',[ 0 0 .9],... + 'ForeGroundColor',[ 1 1 1],'String',' '); + end + + if findobj(gcf,'tag','XHR_YINDEX'), + H.yindex = findobj(gcf,'tag','XHR_YINDEX'); + else + H.yindex = uicontrol(H.gui,'tag','XHR_YINDEX','Style','edit',... + 'Units','Normalized',Font,... + 'Position',[.92 .87 .08 .05],... + 'BackGroundColor',[ 0 0 .9],'ForeGroundColor',[ 1 1 1],... + 'TooltipString','Enter Y index into plot data matrix. Same as trace number.',... + 'String','1','Value',1,... + 'Callback',strcat('XHR = get(gcf,''userdata'');',... + 'yi = str2num(get(XHR.yindex,''String''));',... + 'XHR.data.yindex = yi;',... + 'set(XHR.gui,''userdata'',XHR); clear XHR yi; ',... + '[Xpoint,Ypoint] = crosshair_subplots(''changey'');')); + end + + if findobj(gcf,'tag','XHR_YPREV'), + H.yprev = findobj(gcf,'tag','XHR_YPREV'); + else + H.yprev = uicontrol(H.gui,'tag','XHR_YPREV','Style','Push',... + 'Units','Normalized',Font,... + 'Position',[.92 .82 .04 .05],... + 'String','<',... + 'TooltipString','Goto Previous Y Index (channel).',... + 'CallBack','[Xpoint,Ypoint] = crosshair_subplots(''prevy'');'); + end + + if findobj(gcf,'tag','XHR_YNEXT'), + H.ynext = findobj(gcf,'tag','XHR_YNEXT'); + else + H.ynext = uicontrol(H.gui,'tag','XHR_YNEXT','Style','Push',... + 'Units','Normalized',Font,... + 'Position',[.96 .82 .04 .05],... + 'String','>',... + 'TooltipString','Goto Next Y Index (channel).',... + 'CallBack','[Xpoint,Ypoint] = crosshair_subplots(''nexty'');'); + end + + if findobj(gcf,'tag','XHR_YLT'), + H.yLT = findobj(gcf,'tag','XHR_YLT'); + else + H.yLT = uicontrol(H.gui,'tag','XHR_YLT','Style','Push',... + 'Units','Normalized',Font,... + 'Position',[.92 .77 .04 .05],... + 'String','LT',... + 'TooltipString','Goto next Y Less Than current Y.',... + 'CallBack','[Xpoint,Ypoint] = crosshair_subplots(''yLT'');'); + end + + if findobj(gcf,'tag','XHR_YGT'), + H.yGT = findobj(gcf,'tag','XHR_YGT'); + else + H.yGT = uicontrol(H.gui,'tag','XHR_YGT','Style','Push',... + 'Units','Normalized',Font,... + 'Position',[.96 .77 .04 .05],... + 'String','GT',... + 'TooltipString','Goto next Y Greater Than current Y.',... + 'CallBack','[Xpoint,Ypoint] = crosshair_subplots(''yGT'');'); + end + + if findobj(gcf,'tag','XHR_XINDEX'), + H.xindex = findobj(gcf,'tag','XHR_XINDEX'); + else + H.xindex = uicontrol(H.gui,'tag','XHR_XINDEX','Style','edit',... + 'Units','Normalized',Font,... + 'Position',[.92 .70 .08 .05],... + 'BackGroundColor',[ 0 .9 0],'ForeGroundColor',[ 0 0 0],... + 'TooltipString','Enter X index into plot data matrix. Only available for interpolation = ''none''.',... + 'String','1','Value',1,... + 'Callback',strcat('XHR = get(gcf,''userdata'');',... + 'xi = str2num(get(XHR.xindex,''String''));',... + 'XHR.data.xindex = xi;',... + 'set(XHR.xinterp,''value'',0); ',... + 'set(XHR.xinterp,''string'',''0''); ',... + 'set(XHR.interp, ''value'',1); ',... + 'set(XHR.gui,''userdata'',XHR); clear XHR; ',... + '[Xpoint,Ypoint] = crosshair_subplots(''changex'');')); + end + + if findobj(gcf,'tag','XHR_XPREV'), + H.xprev = findobj(gcf,'tag','XHR_XPREV'); + else + H.xprev = uicontrol(H.gui,'tag','XHR_XPREV','Style','Push',... + 'Units','Normalized',Font,... + 'Position',[.92 .65 .04 .05],... + 'String','<',... + 'TooltipString','Goto Previous X Index (no interpolation).',... + 'CallBack','[Xpoint,Ypoint] = crosshair_subplots(''prevx'');'); + end + + if findobj(gcf,'tag','XHR_XNEXT'), + H.xnext = findobj(gcf,'tag','XHR_XNEXT'); + else + H.xnext = uicontrol(H.gui,'tag','XHR_XNEXT','Style','Push',... + 'Units','Normalized',Font,... + 'Position',[.96 .65 .04 .05],... + 'String','>',... + 'TooltipString','Goto Next X Index (no interpolation).',... + 'CallBack','[Xpoint,Ypoint] = crosshair_subplots(''nextx'');'); + end + + if findobj(gcf,'tag','XHR_XINTERP'), + H.xinterp = findobj(gcf,'tag','XHR_XINTERP'); + else + H.xinterp = uicontrol(H.gui,'tag','XHR_XINTERP','Style','Edit',... + 'Units','Normalized',... + 'Position',[.92 .60 .08 .05],... + 'String','0','Value',0,... + 'TooltipString','Interpolation X increment (zero = nearest X).',... + 'Callback',strcat('XHR = get(gcf,''userdata''); ',... + 'xint = str2num(get(XHR.xinterp,''string'')); ',... + 'set(XHR.xinterp,''value'',xint); ',... + 'set(XHR.gui,''userdata'',XHR); figure(XHR.gui); clear XHR; ')); + end + + if findobj(gcf,'tag','XHR_INTERP'), + H.interp = findobj(gcf,'tag','XHR_INTERP'); + else + interpstr = 'none|nearest|linear|spline|cubic'; + H.interp = uicontrol(H.gui,'tag','XHR_INTERP','Style','popup',... + 'Units','Normalized',Font,... + 'Position',[.92 .55 .08 .05],... + 'TooltipString','INTERP1 methods (none = raw values).', ... + 'String',interpstr,... + 'Callback',strcat('XHR = get(gcf,''userdata'');',... + 'xint = get(XHR.xinterp,''Value''); ',... + 'if xint == 0, ',... + ' xint = 0.5; ',... + ' set(XHR.xinterp,''value'',xint); ',... + ' set(XHR.xinterp,''string'',num2str(xint)); ',... + ' set(XHR.xindex, ''string'',''interp''); ',... + 'end; ',... + 'set(XHR.gui,''userdata'',XHR); figure(XHR.gui); clear XHR; ')); + end + + if findobj(gcf,'tag','XHR_STORE'), + H.store = findobj(gcf,'tag','XHR_STORE'); + else + H.store = uicontrol(H.gui,'tag','XHR_STORE','Style','Push',... + 'Units','Normalized',... + 'Position',[.92 .40 .08 .05],... + 'String','Store',... + 'TooltipString','Store current Channel & XY values into base XYhist array.', ... + 'CallBack','crosshair_subplots(''store'');'); + end + + if findobj(gcf,'tag','XHR_DONE'), + H.done = findobj(gcf,'tag','XHR_DONE'); + else + H.done = uicontrol(H.gui,'tag','XHR_DONE','Style','Push',... + 'Units','Normalized',... + 'Position',[.80 .00 .10 .05],... + 'BackgroundColor',[.8 .5 0],... + 'ForegroundColor',[1 1 1],... + 'FontWeight','bold',... + 'String','Done',... + 'TooltipString','Close crosshair', ... + 'CallBack','crosshair_subplots(''done'');'); + end + + if findobj(gcf,'tag','XHR_EXIT'), + H.exit = findobj(gcf,'tag','XHR_EXIT'); + else + H.exit = uicontrol(H.gui,'tag','XHR_EXIT','Style','Push',... + 'Units','Normalized',... + 'Position',[.90 .00 .10 .05],... + 'BackgroundColor',[.8 0 0],... + 'ForegroundColor',[1 1 1],... + 'FontWeight','bold',... + 'String','Exit',... + 'TooltipString','Close crosshair and Figure', ... + 'CallBack','crosshair_subplots(''exit'');'); + end + + if findobj(gcf,'tag','XHR_TRACENEAREST'), + H.traceNearest = findobj(gcf,'tag','XHR_TRACENEAREST'); + else + H.traceNearest = uicontrol(H.gui,'tag','XHR_TRACENEAREST','Style','checkbox',... + 'Units','Normalized',... + 'Position',[.60 .00 .19 .05],... + 'BackgroundColor',bgcolor,'ForegroundColor',fgcolor,... + 'String','Nearest Trace','Value',1,... + 'TooltipString','Trace nearest to mouse click; switch off to keep trace constant.'); + end + +% % Switch off||on Trace Selection GUI +% Vis = 'Off'; +% if H.data.lines > 1, +% Vis = 'On'; +% elseif H.data.lines == 0 +% error('No lines found in the current axes (gca)\n'); +% end +% +% % 'traces' string variable must be in ascending order +% traces = ''; +% i = 1; +% while i <= lines; +% if i < lines +% tracelabel = sprintf('Column %4d|',i); +% else +% tracelabel = sprintf('Column %4d',i); +% end +% traces = strcat(traces,tracelabel); +% i = i + 1; +% end +% +% % If more than one line, provide GUI for line selection +% +% +% if findobj(gcf,'tag','XHR_TRACESWITCH'), +% H.trace = findobj(gcf,'tag','XHR_TRACESWITCH'); +% set(H.trace,'String',traces); +% else +% H.trace = uicontrol(H.gui,'tag','XHR_TRACESWITCH','Style','Popup',... +% 'Units','Normalized',... +% 'Position',[.15 .00 .20 .05],... +% 'BackGroundColor','w','String',traces,... +% 'TooltipString','Select trace to follow with crosshairs.',... +% 'Visible',Vis,... +% 'CallBack','crosshair_subplots(''up'');'); +% end + + + set(H.axis,'userdata',H.data); + set(H.gui,'userdata',H); + +return diff --git a/ctf2eeglab.m b/ctf2eeglab.m new file mode 100644 index 0000000..3d62d0c --- /dev/null +++ b/ctf2eeglab.m @@ -0,0 +1,133 @@ + +% ctf2eeglab - script to convert and save ctf .ds into eeglab .set data +% +% ctf2eeglab +% +% The script uses a ctf struct in the matlab workspace or a GUI prompt to +% load a CTF .ds folder, then converts the ctf data into an EEGLAB EEG +% struct, saving the resulting dataset into an EEEGLAB .set file, located +% in the same path as the ctf .ds folder. The GUI prompt for the CTF .ds +% folder also provides access to definition of the channels, time and +% trials to load. +% + +% $Revision: 1.1 $ $Date: 2009-01-30 03:49:26 $ + +% Licence: GNU GPL, no express or implied warranties +% Modified: 01/2004, Darren.Weber_at_radiology.ucsf.edu +% - developed in collaboration with Fredrick Carver of +% the NIH, USA. +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +ver = '$Revision: 1.1 $'; +fprintf('\nCTF2EEGLAB [v %s]\n\n',ver(11:15)); +clear ver + +switch exist('eeglab'), + case 2, + fprintf('...found eeglab to be a function that exists\n'); + case 7, + fprintf('...found eeglab to be a directory that exists\n'); + otherwise, + error('eeglab does not exist'); +end + +% only prompt for ctf data if it does not already exist in the matlab +% workspace +if exist('ctf') ~= 1, + + fprintf('...no ''ctf'' struct in workspace\n'); + [ctf,FIG] = ctf_read_gui; + uiwait(FIG); clear FIG; +end +if ~isfield(ctf,'data'), + fprintf('...no ctf.data field in workspace\n'); + [ctf,FIG] = ctf_read_gui; + uiwait(FIG); clear FIG; +end +if isempty(ctf.data), + fprintf('...ctf.data field is empty\n'); + [ctf,FIG] = ctf_read_gui; + uiwait(FIG); clear FIG; +end + +% check if the data is averaged +if ctf.setup.number_trials_averaged > 0, + warning('this .ds folder is averaged'); +end + +% check if the data is greater than 500 Mb +data_size = ctf.setup.number_samples * ctf.setup.number_channels * ctf.setup.number_trials; +data_bytes = data_size * 8; +if data_bytes > 5e9, warning('data is greater than 500 Mb'); end +clear data_size data_bytes; + +% rearrange the trials into a 3D data matrix +% ctf.data is a 3D matrix with samples X channels X trials, +% whereas EEGLAB is a 3D matrix with channels X samples X trials +clear data +data = zeros( size(ctf.data,2), size(ctf.data,1), size(ctf.data,3) ); +for i = 1:size(ctf.data,3), + data(:,:,i) = ctf.data(:,:,i)'; +end + + +% Startup EEGLAB +[ALLEEG EEG CURRENTSET ALLCOM] = eeglab; + +% import the data into the EEGLAB EEG struct + +[DSpath,DSfile,DSext] = fileparts(ctf.folder); + +EEG.setname = DSfile; +EEG.filename = [DSfile,'.set']; +EEG.filepath = [DSpath,filesep]; +EEG.pnts = ctf.setup.number_samples; +EEG.nbchan = ctf.setup.number_channels; +EEG.trials = ctf.setup.number_trials; +EEG.srate = ctf.setup.sample_rate; +EEG.xmin = ctf.setup.start_sec; +EEG.xmax = ctf.setup.end_sec; +EEG.data = data; +EEG.icawinv = []; +EEG.icasphere = []; +EEG.icaweights = []; +EEG.icaact = []; +EEG.event = []; +EEG.epoch = []; +EEG.comments = ctf.setup.run_description'; +EEG.ref = 'common'; + +for i=1:ctf.setup.number_channels, + EEG.chanlocs(i).labels = ctf.sensor.label{i}; + EEG.chanlocs(i).X = ctf.sensor.location(1,i); + EEG.chanlocs(i).Y = ctf.sensor.location(2,i); + EEG.chanlocs(i).Z = ctf.sensor.location(3,i); +end +EEG.chanlocs = pop_chanedit(EEG.chanlocs, 'convert', 'cart2topo', 'convert', 'cart2sph'); + +% now clear the workspace of the input data +clear ctf data +clear DSpath DSfile DSext i + +if ~exist('saveSet','var'), saveSet = 1; end + +if saveSet, + + [ALLEEG EEG CURRENTSET] = pop_newset(ALLEEG, EEG, CURRENTSET,... + 'setname', EEG.setname,... + 'comments', EEG.comments,... + 'overwrite','on',... + 'save', [EEG.filepath,filesep,EEG.filename]); + +else + + [ALLEEG EEG CURRENTSET] = pop_newset(ALLEEG, EEG, CURRENTSET,... + 'setname', EEG.setname,... + 'comments', EEG.comments,... + 'overwrite','on'); + +end + +eeglab redraw; +pack diff --git a/ctf2eeglab_gui.m b/ctf2eeglab_gui.m new file mode 100644 index 0000000..d3e2923 --- /dev/null +++ b/ctf2eeglab_gui.m @@ -0,0 +1,85 @@ +%GUI script for reading ctf data into eeglab. +%to run type ctf2eeglab on the command line. + +clear all; +folder = uigetdir('*.ds','Data Set Finder'); +[ctf2] = ctf_read_res4(folder,1); +sensors = {'meg','eeg','ref','vc'}; +sensloc = 'ctf2.sensor.index'; +sensorlen = '1:'; +num2str(length(ctf2.sensor.index.meg_sens)); + +k = menu('Choose the channels you would like to use:','MEG','EEG','Reference','Virtual'); +sensloc = strcat(sensloc,sensors(k)); +sensorlen = strcat(sensorlen, num2str(length(eval(sensloc{1})))); +prompt = {'Enter Sensor Numbers to Read (ie 2:7 or 1 3 7 23 65)'}; +title = 'Input for Sensor Range (Default is all sensors)'; +lines = 1; +def = {sensorlen}; +sensnum = inputdlg(prompt,title,lines,def); +for i = str2num(sensnum{1}); + if ~ismember(str2num(def{1}),i) + errordlg('There is no such sensor','Sensor Range Error') + exit(1); + end +end + +trialnums = '1:'; +trialnums = strcat(trialnums, num2str(ctf2.setup.number_trials)); +prompt2 = {'Enter the trials you would like to use(ie 1:3 or 2 4 5):'}; +def2 = {trialnums}; +trials = inputdlg(prompt2, 'Input for trial range', 1,def2); +for i = str2num(trials{1}) + if ~ismember(str2num(def2{1}),i) + errordlg('Trial not in dataset','Trial Error') + exit(1); + end +end +button = questdlg('Would you like to use markers?','Use Markers?','Yes','No','Yes'); +if strcmp(button,'Yes') + [marker_info] = readmarkerfile(folder); + markers = marker_info.marker_names; + m = menu('Please choose which marker you would like to use', markers); +end +prompt = {'Enter the start time (sec):', 'Enter the end time:'}; +title = 'Time Window'; +lines = 1; +def = {'0', '.15'}; +def(1) = {num2str(ctf2.setup.start_sec)}; +def(2) = {num2str(ctf2.setup.end_sec)}; +markeranswer = inputdlg(prompt,title,lines,def); +wind = [0 0]; +wind(1) = str2num(markeranswer{1}); +wind(2) = str2num(markeranswer{2}); + +if strcmp(button,'Yes') + [data]=readepochs(folder,'marker_info',marker_info,'ctf',ctf2,sensors{k}, str2num(sensnum{1}),'trials',str2num(trials{1}), 'markers',markers(m),'window', wind); +else + [data]=readepochs(folder,'ctf',ctf2,sensors{k}, str2num(sensnum{1}),'trials',str2num(trials{1}), 'window', wind); +end + + +%wind = [-.1 .15]; +%[data]=readepochs(folder,'markers',{'click'},'window',wind); +%[data]=readepochs(folder,'window',wind,'trials',[1:10],'megsens',[2:7]); + +dat=permute(data.epochs{1},[2,1,3]); +size(dat) +[ALLEEG EEG CURRENTSET ALLCOM] = eeglab; + +EEG = pop_importdata( 'nbchan', size(dat,1), 'dataformat', 'array', 'data', 'dat', 'pnts', size(dat,2), 'srate', data.setup.sample_rate, 'xmin', wind(1)); +[ALLEEG EEG CURRENTSET] = pop_newset(ALLEEG, EEG, CURRENTSET, 'setname',data.setup.subject); +eeglab redraw; + +for i=1:size(dat,1) + if ~isempty(data.sensor.location) + EEG.chanlocs(i).labels=char(data.sensor.label(i)); + EEG.chanlocs(i).X=data.sensor.location(1,i); + EEG.chanlocs(i).Y=data.sensor.location(2,i); + EEG.chanlocs(i).Z=data.sensor.location(3,i); + end +end +EEG.chanlocs=pop_chanedit(EEG.chanlocs, 'convert', 'cart2topo', 'convert', 'cart2sph'); +[ALLEEG EEG] = eeg_store(ALLEEG, EEG, CURRENTSET); +eeglab redraw; +clear dat data ctf2 marker_info markers sensors; diff --git a/ctf_avw2mri.m b/ctf_avw2mri.m new file mode 100644 index 0000000..f5f4f2f --- /dev/null +++ b/ctf_avw2mri.m @@ -0,0 +1,109 @@ +function mri = ctf_avw2mri(avw) + +% mri = ctf_avw2mri(avw) +% +% The purpose of this function is to convert an Analyze volume into a CTF +% .mri volume. It currently requires that the Analyze volume is +% 256x256x256, 1x1x1 mm voxels. The avw_read function can +% handle various Analyze orientations, so this function assumes that the +% avw.img volume has axial unflipped orientation (it always is when +% returned by avw_read, regardless of the format in the .img file). The +% returned mri struct in the matlab workspace can be saved using +% ctf_write_mri. +% +% This function depends on the avw* functions availabe in the mri_toolbox +% at http://eeg.sf.net/. In particular, the avw_read and associated +% functions for reading an Analyze volume into a matlab avw struct, used as +% input to this function. +% +% <>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> % +% < > % +% < DISCLAIMER: > % +% < > % +% < THIS PROGRAM IS INTENDED FOR RESEARCH PURPOSES ONLY. > % +% < THIS PROGRAM IS IN NO WAY INTENDED FOR CLINICAL OR > % +% < OFFICIAL USE. > % +% < > % +% <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<> % +% + +% $Revision: 1.1 $ $Date: 2009-01-30 03:49:26 $ + +% Copyright (C) 2003 Darren L. Weber +% +% This program is free software; you can redistribute it and/or +% modify it under the terms of the GNU General Public License +% as published by the Free Software Foundation; either version 2 +% of the License, or (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program; if not, write to the Free Software +% Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +% History: 08/2003, Darren.Weber_at_radiology.ucsf.edu +% - adapted from an appendex to CTF document +% MRIConverter.pdf, which is copied at the end of this +% function. +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +mri = ctf_mri_make; + +mri.file = [avw.fileprefix,'.mri']; + + +ver = '[$Revision: 1.1 $]'; +fprintf('\nCTF_AVW2MRI [v%s]\n',ver(12:16)); tic; + + +% these checks for the volume dims/pixel size could be replaced with an +% interpolation function that could take any Analyze volume and convert it +% to 256x256x256, 1x1x1 mm +if avw.hdr.dime.dim(2) ~= 256, + error('avw.hdr.dime.dim(2) ~= 256'); +end +if avw.hdr.dime.dim(3) ~= 256, + error('avw.hdr.dime.dim(3) ~= 256'); +end +if avw.hdr.dime.dim(4) ~= 256, + error('avw.hdr.dime.dim(4) ~= 256'); +end + +if avw.hdr.dime.pixdim(2) ~= 1, + error('avw.hdr.dime.dim(2) ~= 256'); +end +if avw.hdr.dime.pixdim(3) ~= 1, + error('avw.hdr.dime.dim(3) ~= 256'); +end +if avw.hdr.dime.pixdim(4) ~= 1, + error('avw.hdr.dime.dim(4) ~= 256'); +end + + +% mri.hdr.dataSize = 1 or 2 (bytes), 8 or 16 bits +if avw.hdr.dime.bitpix == 8, + mri.hdr.dataSize = 1; + mri.hdr.clippingRange = 255; +else + mri.hdr.dataSize = 2; + mri.hdr.clippingRange = 65536; +end + +% This next step should always work correctly, given that avw_read always +% converts any Analyze orientation into axial unflipped in the matlab +% workspace variable avw.img; the axial unflipped orientation is +% (+X left, +Y anterior, +Z superior); the ctf orientation is +% (+X right, +Y posterior, +Z inferior), the complete opposite. +temp = flipdim(avw.img,1); +temp = flipdim(temp,2); +temp = flipdim(temp,3); +mri.img = temp; + +t=toc; fprintf('...done (%5.2f sec).\n\n',t); + +return diff --git a/ctf_baseline.m b/ctf_baseline.m new file mode 100644 index 0000000..33fdf2f --- /dev/null +++ b/ctf_baseline.m @@ -0,0 +1,39 @@ +function [ ctf ] = ctf_baseline(ctf) + +% ctf_baseline - remove mean of pretrigger period from all ctf.data +% +% [ ctf ] = ctf_baseline(ctf) +% + + +% $Revision: 1.1 $ $Date: 2009-01-30 03:49:26 $ + +% Copyright (C) 2004 Darren L. Weber +% +% This program is free software; you can redistribute it and/or +% modify it under the terms of the GNU General Public License +% as published by the Free Software Foundation; either version 2 +% of the License, or (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program; if not, write to the Free Software +% Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +% Created: 01/2004, copyright 2004 Darren.Weber_at_radiology.ucsf.edu +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +for epoch = 1:size(ctf.data,3), + + pretrigger_mean = mean(ctf.data(1:ctf.setup.pretrigger_samples,:,epoch)); + + pretrigger_mean = repmat(pretrigger_mean,ctf.setup.number_samples,1); + + ctf.data(:,:,epoch) = ctf.data(:,:,epoch) - pretrigger_mean; + +end diff --git a/ctf_channel2eeglab.m b/ctf_channel2eeglab.m new file mode 100644 index 0000000..a86b54e --- /dev/null +++ b/ctf_channel2eeglab.m @@ -0,0 +1,25 @@ +indir = '/data/dnl4/ctf_data/hin/cuebase/'; +outdir = '/home/awu9/eeglab_tutorial/'; +outputFile = 'data.mat'; +outputCHANFile = 'CHAN.xyz'; +CHAN1020 = {'Fp1','Fpz','Fp2','AF7','AFz','AF8','F9','F7','F5','F3','Fz','F2','F4','F6','F8','F10','FT9','FT7','FC5','FC3','FC1','FCz','FC2','FC4','FC6','FT8','FT10','T9','T7','C5','C3','C1','Cz','C2','C4','C6','T8','T10','TP7','CP5','CP3','CP1','CPz','CP2','CP4','CP6','TP8','P9','P7','P5','P3','P1','Pz','P2','P4','P6','P8','P8','P10','PO9','PO7','POz','PO8','PO10','O1','Oz','O2'}; + +cd(indir) + + + +ctf = ctf_read; + +CHAN = ctf_channel_select1020(ctf,CHAN1020); +CHANXYZ = ctf.sensor.location(:,CHAN); + +fid = fopen([outdir outputCHANFile],'w'); +for i = 1:length(CHAN1020); + fprintf(fid,'%d\t%g\t%g\t%g\t%s\n',i,CHANXYZ(1,i),CHANXYZ(2,i),CHANXYZ(3,i),CHAN1020{i}); +end + +eegdata = ctf.data(:,CHAN,1); +eegdata = eegdata'; + +save([outdir outputFile],'eegdata'); + diff --git a/ctf_channel_bad.m b/ctf_channel_bad.m new file mode 100644 index 0000000..36a8fcd --- /dev/null +++ b/ctf_channel_bad.m @@ -0,0 +1,55 @@ +function [CHAN] = ctf_channel_bad(ctf,CHAN,BAD) + +% ctf_channel_bad - remove bad channels +% +% [CHAN] = ctf_channel_bad(ctf) +% +% CHAN is an index of good channels +% +% <>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +% < > +% < DISCLAIMER: > +% < > +% < THIS PROGRAM IS INTENDED FOR RESEARCH PURPOSES ONLY. > +% < THIS PROGRAM IS IN NO WAY INTENDED FOR CLINICAL OR > +% < OFFICIAL USE. > +% < > +% <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<> +% + + +% $Revision: 1.1 $ $Date: 2009-01-30 03:49:26 $ + +% Copyright (C) 2005 Darren L. Weber +% +% This program is free software; you can redistribute it and/or +% modify it under the terms of the GNU General Public License +% as published by the Free Software Foundation; either version 2 +% of the License, or (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program; if not, write to the Free Software +% Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +% Modified: 02/2004, Darren.Weber_at_radiology.ucsf.edu +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +ver = '$Revision: 1.1 $ $Date: 2009-01-30 03:49:26 $'; +fprintf('\nCTF_CHANNEL_BAD [v %s]\n',ver(11:15)); + +% remove bad channels +fprintf('...removing bad channels\n'); +ctf = ctf_read_badchannels([],ctf); +badChanNames = ctf.sensor.bad; +chanNames = ctf.sensor.label(CHAN); +[newChanNames,index] = setdiff(chanNames,badChanNames); +index = sort(index); % to undo the sorting of setdiff +CHAN = CHAN(index); + +return diff --git a/ctf_channel_metrics.m b/ctf_channel_metrics.m new file mode 100644 index 0000000..a9eeb6d --- /dev/null +++ b/ctf_channel_metrics.m @@ -0,0 +1,112 @@ +function [stats] = ctf_channel_metrics(ctf) + +% ctf_channel_metrics - CTF channel geometry +% +% [stats] = ctf_channel_metrics(ctf) +% +% stats output contains measures of gradiometer separation and +% inter-gradiometer distances. +% +% <>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +% < > +% < DISCLAIMER: > +% < > +% < THIS PROGRAM IS INTENDED FOR RESEARCH PURPOSES ONLY. > +% < THIS PROGRAM IS IN NO WAY INTENDED FOR CLINICAL OR > +% < OFFICIAL USE. > +% < > +% <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<> +% + + +% $Revision: 1.1 $ $Date: 2009-01-30 03:49:26 $ + +% Copyright (C) 2005 Darren L. Weber +% +% This program is free software; you can redistribute it and/or +% modify it under the terms of the GNU General Public License +% as published by the Free Software Foundation; either version 2 +% of the License, or (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program; if not, write to the Free Software +% Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +% Created: 08/2005, Darren.Weber_at_radiology.ucsf.edu +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +ver = '$Revision: 1.1 $ $Date: 2009-01-30 03:49:26 $'; +fprintf('\nCTF_CHANNEL_METRICS [v %s]\n',ver(11:15)); + +meg_sens = ctf_channel_select(ctf,'meg'); + +coil_inner = zeros(length(meg_sens), 3); +coil_outer = coil_inner; +coilOrient_inner = coil_inner; +coilOrient_outer = coil_inner; + +for i = 1:length(meg_sens), + + index = meg_sens(i); + coil_i = ctf.sensor.info(index).hcoil(1).position; + coil_i = [ coil_i.x; coil_i.y; coil_i.z ]; + coil_o = ctf.sensor.info(index).hcoil(2).position; + coil_o = [ coil_o.x; coil_o.y; coil_o.z ]; + coil_inner(i,:) = coil_i'; + coil_outer(i,:) = coil_o'; + + coilOrient_i = ctf.sensor.info(index).hcoil(1).orient; + coilOrient_i = [ coilOrient_i.x; coilOrient_i.y; coilOrient_i.z ]; + coilOrient_o = ctf.sensor.info(index).hcoil(2).orient; + coilOrient_o = [ coilOrient_o.x; coilOrient_o.y; coilOrient_o.z ]; + coilOrient_inner(i,:) = coilOrient_i'; + coilOrient_outer(i,:) = coilOrient_o'; + +end + +surf_inner.vertices = coil_inner; +surf_inner.faces = convhulln(coil_inner); + +surf_outer.vertices = coil_outer; +surf_outer.faces = convhulln(coil_outer); + +figure; hold on +patch('faces',surf_inner.faces,'vertices',surf_inner.vertices,... + 'facecolor',[0.9 0.5 0.5],'edgecolor','none',... + 'facealpha',0.8); +patch('faces',surf_outer.faces,'vertices',surf_outer.vertices,... + 'facecolor',[0.5 0.5 0.9],'edgecolor','none',... + 'facealpha',0.2); +legend('inner','outer') +scatter3(coil_inner(:,1), coil_inner(:,2), coil_inner(:,3), 10, 'r', 'filled') +scatter3(coil_outer(:,1), coil_outer(:,2), coil_outer(:,3), 10, 'b', 'filled') + +X = coil_outer(:,1); +Y = coil_outer(:,2); +Z = coil_outer(:,3); +U = coilOrient_outer(:,1); +V = coilOrient_outer(:,2); +W = coilOrient_outer(:,3); +quiver3(X, Y, Z, U, V, W, 0) + +set(gca,'DataAspectRatio',[1,1,1]); +rotate3d on + +coil_separation = coil_outer - coil_inner; +coil_distance = zeros(length(coil_separation),1); +for i = 1:length(coil_separation), + coil_distance(i) = norm(coil_separation(i,:)); +end + +stats.coil_distance = coil_distance; +stats.mean = mean(coil_distance); +stats.std = std(coil_distance); + +return diff --git a/ctf_channel_plot.m b/ctf_channel_plot.m new file mode 100644 index 0000000..736dfac --- /dev/null +++ b/ctf_channel_plot.m @@ -0,0 +1,152 @@ +function [Handles] = ctf_channel_plot(ctf,surf,CHAN,Handles) + +% ctf_channel_plot - plot ctf.sensor data +% +% [Handles] = ctf_channel_plot(ctf [,surf][,CHAN][,H]) +% +% ctf - a struct returned by ctf_read +% surf - a surface tesselation struct, surf.vertices and surf.faces; +% the default is to create a convex hull of the sensor locations +% CHAN - see ctf_channel_select for options (default, CHAN = 'meg') +% +% Handles - handles struct, eg: +% H.Hf - figure handle to plot into (default, H.Hf = figure;) +% H.Hs - sensor handles +% H.Hp - patch handles +% H.Hl - light handles +% +% All inputs, except ctf, are optional. An empty input [] will be replaced +% with the default. +% +% <>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +% < > +% < DISCLAIMER: > +% < > +% < THIS PROGRAM IS INTENDED FOR RESEARCH PURPOSES ONLY. > +% < THIS PROGRAM IS IN NO WAY INTENDED FOR CLINICAL OR > +% < OFFICIAL USE. > +% < > +% <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<> +% + +% $Revision: 1.1 $ $Date: 2009-01-30 03:49:26 $ + +% Copyright (C) 2004 Darren L. Weber +% +% This program is free software; you can redistribute it and/or +% modify it under the terms of the GNU General Public License +% as published by the Free Software Foundation; either version 2 +% of the License, or (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program; if not, write to the Free Software +% Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +% Modified: 05/2004, Darren.Weber_at_radiology.ucsf.edu +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +if ~exist('ctf','var'), error('no ctf input'); end +if isempty(ctf), error('no ctf input'); end + +% check the figure handle for initialization +if ~exist('Handles','var'), + Handles.Hf = figure; + colordef(Handles.Hf,'white') +end +if isempty(Handles), + Handles.Hf = figure; + colordef(Handles.Hf,'white') +end +if ~isfield(Handles,'Hf'), + Handles.Hf = figure; + colordef(Handles.Hf,'white') +end +if isempty(Handles.Hf), + Handles.Hf = figure; + colordef(Handles.Hf,'white') +end + +% check other fields of the Handles +if ~isfield(Handles,'Hp'), Handles.Hp = {}; end +if ~isfield(Handles,'Hs'), Handles.Hs = {}; end +if ~isfield(Handles,'Hl'), Handles.Hl = []; end + +usesurf = 1; % assume input surf +if ~exist('surf','var'), usesurf = 0; end +if isempty(surf), usesurf = 0; end + +if ~exist('CHAN','var'), CHAN = 'meg'; end +if CHAN, + % Get the channel indices to plot + [CHAN,type] = ctf_channel_select(ctf,CHAN); + sensors.vertices = zeros(length(CHAN),3); + for i = 1:length(CHAN), + sensors.vertices(i,:) = ctf.sensor.info(CHAN(i)).location(:,1)'; + end +end + +ver = '$Revision: 1.1 $ $Date: 2009-01-30 03:49:26 $'; +fprintf('\nCTF_CHANNEL_PLOT [v %s]\n',ver(11:15)); + +figure(Handles.Hf); hold on +set(Handles.Hf,'Renderer','OpenGL') + +if CHAN, + % plot the sensor cloud + Handles.Hs{end+1} = scatter3(sensors.vertices(:,1),... + sensors.vertices(:,2),... + sensors.vertices(:,3),... + 50,'bo','filled'); +end + +if ~usesurf, + % nothing provided, assume we want + % to create a convex hull of the sensors + surf.vertices = sensors.vertices; + surf.faces = convhulln(surf.vertices); +end +Nvert = length(surf.vertices); + +% assume surface is a skin color +skinRGB = [1, 0.85, 0.75]; +vertexColors = ones(Nvert,1) * skinRGB; + +% plot the surface patch (eg, sensors or scalp) +Handles.Hp{end+1} = patch('faces',surf.faces,'vertices',surf.vertices,... + 'facecolor','interp',... + 'FaceVertexCData', vertexColors,... + 'edgecolor', 'none',... + 'facealpha',0.5); + +% view parameters +view([40,20]) +daspect([1 1 1]) +axis equal +axis tight +grid on + +lighting phong +material dull + +% only add a light if it doesn't exist already +if ~isfield(Handles,'Hl'), + Handles.Hl = camlight; +elseif isempty(Handles.Hl), + Handles.Hl = camlight; +end + +% The CTF MEG Head Coordinate System is +% +X anterior, +Y left, +Z superior +xlabel('x (cm)') +ylabel('y (cm)') +zlabel('z (cm)') + +rotate3d on + +return diff --git a/ctf_channel_select.m b/ctf_channel_select.m new file mode 100644 index 0000000..215d3f0 --- /dev/null +++ b/ctf_channel_select.m @@ -0,0 +1,167 @@ +function [CHAN,type] = ctf_channel_select(ctf,CHAN) + +% ctf_channel_select - select channels using character codes +% +% [CHAN,type] = ctf_channel_select(ctf,CHAN) +% +% where CHAN input is an array of channel numbers or a string that +% corresponds to a channel set below (these channel sets are defined by +% ctf_channel_sets): +% +% 'all', CHAN = [1:ctf.setup.number_channels]; % default +% 'ref', CHAN = ctf.sensor.index.meg_ref; +% 'meg', CHAN = ctf.sensor.index.meg_sens; +% 'eeg', CHAN = ctf.sensor.index.eeg_sens; +% 'other', CHAN = ctf.sensor.index.other; +% {'megeeg','eegmeg'}, CHAN = [ ctf.sensor.index.eeg_sens ctf.sensor.index.meg_sens ]; +% 'lc', CHAN = ctf.sensor.index.meg_left_central; +% 'lf', CHAN = ctf.sensor.index.meg_left_frontal; +% 'lo', CHAN = ctf.sensor.index.meg_left_occipital; +% 'lp', CHAN = ctf.sensor.index.meg_left_parietal; +% 'lt', CHAN = ctf.sensor.index.meg_left_temporal; +% 'rc', CHAN = ctf.sensor.index.meg_right_central; +% 'rf', CHAN = ctf.sensor.index.meg_right_frontal; +% 'ro', CHAN = ctf.sensor.index.meg_right_occipital; +% 'rp', CHAN = ctf.sensor.index.meg_right_parietal; +% 'rt', CHAN = ctf.sensor.index.meg_right_temporal; +% 'mc', CHAN = ctf.sensor.index.meg_mid_central; +% 'mf', CHAN = ctf.sensor.index.meg_mid_frontal; +% 'mo', CHAN = ctf.sensor.index.meg_mid_occipital; +% 'mp', CHAN = ctf.sensor.index.meg_mid_parietal; +% 'l', CHAN = ctf.sensor.index.meg_left; +% 'r', CHAN = ctf.sensor.index.meg_right; +% 'c', CHAN = ctf.sensor.index.meg_central; +% 'f', CHAN = ctf.sensor.index.meg_frontal; +% 'o', CHAN = ctf.sensor.index.meg_occipital; +% 'p', CHAN = ctf.sensor.index.meg_parietal; +% 't', CHAN = ctf.sensor.index.meg_temporal; +% +% CHAN output is a numeric array of channel indices +% type output is the string type of the channel indices +% +% <>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +% < > +% < DISCLAIMER: > +% < > +% < THIS PROGRAM IS INTENDED FOR RESEARCH PURPOSES ONLY. > +% < THIS PROGRAM IS IN NO WAY INTENDED FOR CLINICAL OR > +% < OFFICIAL USE. > +% < > +% <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<> +% + + +% $Revision: 1.1 $ $Date: 2009-01-30 03:49:26 $ + +% Copyright (C) 2004 Darren L. Weber +% +% This program is free software; you can redistribute it and/or +% modify it under the terms of the GNU General Public License +% as published by the Free Software Foundation; either version 2 +% of the License, or (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program; if not, write to the Free Software +% Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +% Modified: 02/2004, Darren.Weber_at_radiology.ucsf.edu +% 02/2005, removed unique(CHAN) +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +ver = '$Revision: 1.1 $ $Date: 2009-01-30 03:49:26 $'; +fprintf('\nCTF_CHANNEL_SELECT [v %s]\n',ver(11:15)); + + +if ~exist('CHAN','var'), CHAN = 'all'; end +if ~exist('BAD','var'), BAD = 1; end + +if ischar(CHAN), + fprintf('...selecting %s channels\n', CHAN); +else + fprintf('...selecting %d channels\n', length(CHAN)); +end + +type = num2str(lower(CHAN)); + +switch type, + case 'ref', + CHAN = ctf.sensor.index.meg_ref; + case 'meg', + CHAN = ctf.sensor.index.meg_sens; + case 'eeg', + CHAN = ctf.sensor.index.eeg_sens; + case 'other', + CHAN = ctf.sensor.index.other; + case {'megeeg','eegmeg'}, + CHAN = [ ctf.sensor.index.eeg_sens ctf.sensor.index.meg_sens ]; + case 'all', + CHAN = [1:ctf.setup.number_channels]; + case 'lc', + CHAN = ctf.sensor.index.meg_left_central; + case 'lf', + CHAN = ctf.sensor.index.meg_left_frontal; + case 'lo', + CHAN = ctf.sensor.index.meg_left_occipital; + case 'lp', + CHAN = ctf.sensor.index.meg_left_parietal; + case 'lt', + CHAN = ctf.sensor.index.meg_left_temporal; + case 'rc', + CHAN = ctf.sensor.index.meg_right_central; + case 'rf', + CHAN = ctf.sensor.index.meg_right_frontal; + case 'ro', + CHAN = ctf.sensor.index.meg_right_occipital; + case 'rp', + CHAN = ctf.sensor.index.meg_right_parietal; + case 'rt', + CHAN = ctf.sensor.index.meg_right_temporal; + case 'mc', + CHAN = ctf.sensor.index.meg_mid_central; + case 'mf', + CHAN = ctf.sensor.index.meg_mid_frontal; + case 'mo', + CHAN = ctf.sensor.index.meg_mid_occipital; + case 'mp', + CHAN = ctf.sensor.index.meg_mid_parietal; + case 'l', + CHAN = ctf.sensor.index.meg_left; + case 'r', + CHAN = ctf.sensor.index.meg_right; + case 'c', + CHAN = ctf.sensor.index.meg_central; + case 'f', + CHAN = ctf.sensor.index.meg_frontal; + case 'o', + CHAN = ctf.sensor.index.meg_occipital; + case 'p', + CHAN = ctf.sensor.index.meg_parietal; + case 't', + CHAN = ctf.sensor.index.meg_temporal; + otherwise + type = 'numeric'; + % assume the input is an array of channel numbers +end + +%CHAN = unique(CHAN); + + +% remove bad channels +% if BAD, +% fprintf('...removing bad channels\n'); +% ctf = ctf_read_badchannels([],ctf); +% badChanNames = ctf.sensor.bad; +% chanNames = ctf.sensor.label(CHAN); +% [newChanNames,index] = setdiff(chanNames,badChanNames); +% index = sort(index); % to undo the sorting of setdiff +% CHAN = CHAN(index); +% end + + +return diff --git a/ctf_channel_select1020.m b/ctf_channel_select1020.m new file mode 100644 index 0000000..773990f --- /dev/null +++ b/ctf_channel_select1020.m @@ -0,0 +1,125 @@ +function [CHAN,ctf] = ctf_channel_select1020(ctf,CHAN,mod,plot) + +% ctf_channel_select1020 - select CTF channels closest to 10-20 locations +% +% [CHAN,ctf] = ctf_channel_select1020(ctf,CHAN,mod,plot) +% +% where CHAN input is a cell array of channel names from the International +% 10-20 nomenclature for EEG electrode placement. The default is a basic +% 19 channel layout. For a full list of 10-20 electrode names, see the +% elec_1020all_cart function, which is based on: +% +% Oostenveld, R. & Praamstra, P. (2001). The five percent electrode system +% for high-resolution EEG and ERP measurements. Clinical Neurophysiology, +% 112:713-719. +% +% Of course, the MEG sensors are not placed on head locations that move +% with the subject, as an EEG electrode will, so this function is an +% idealization. This function fits the EEG/MEG sensors to a unit sphere +% and then finds the channels nearest the 10-20 locations requested. The +% 10-20 locations are stored in the text file "elec_1020all_cart.txt" in +% this ctf toolbox. +% +% CHAN output is a numeric array of channel indices +% ctf output is modified to select only the 1020 channels if the mod input +% variable is 1. +% +% <>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +% < > +% < DISCLAIMER: > +% < > +% < THIS PROGRAM IS INTENDED FOR RESEARCH PURPOSES ONLY. > +% < THIS PROGRAM IS IN NO WAY INTENDED FOR CLINICAL OR > +% < OFFICIAL USE. > +% < > +% <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<> +% + + +% $Revision: 1.1 $ $Date: 2009-01-30 03:49:26 $ + +% Copyright (C) 2005 Darren L. Weber +% +% This program is free software; you can redistribute it and/or +% modify it under the terms of the GNU General Public License +% as published by the Free Software Foundation; either version 2 +% of the License, or (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program; if not, write to the Free Software +% Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +% Modified: 02/2004, Darren.Weber_at_radiology.ucsf.edu +% 03/2005, Darren.Weber_at_radiology.ucsf.edu +% added mod option, removed type return value +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +ver = '$Revision: 1.1 $ $Date: 2009-01-30 03:49:26 $'; +fprintf('\nCTF_CHANNEL_SELECT1020 [v %s]\n',ver(11:15)); + +if ~exist('CHAN','var'), CHAN = []; end +if isempty(CHAN), + % select 19 locations of 10-20 channel set + CHAN = {'Fp1','Fp2',... + 'F7','F3','Fz','F4','F8',... + 'T7','C3','Cz','C4','T8',... + 'P7','P3','Pz','P4','P8',... + 'O1','O2'}; +end + +if ~exist('mod','var'), mod = 0; end +if isempty(mod), mod = 0; end +if ~exist('plot','var'), plot = 0; end +if isempty(plot), plot = 0; end + +% get the 1020 data +[CHAN1020,XYZ1020] = elec_1020select(CHAN); + +% translate the CTF sensors into a unit sphere, +% assuming the origin is at (0,0,0) +sens = ctf.sensor.location'; +distance = sqrt( sens(:,1).^2 + sens(:,2).^2 + sens(:,3).^2 ); +distance = repmat(distance,1,3); +sens_unit = sens ./ distance; +clear distance + +% K = DSEARCHN(X,T,XI) returns the indices K of the closest points in X for +% each point in XI. X is an m-by-n matrix representing m points in n-D +% space. XI is a p-by-n matrix, representing p points in n-D space. + +CHAN = dsearchn(sens_unit,XYZ1020); +%[sortedCHAN,i] = unique(CHAN); + + +if plot + figure; hold on + % plot all meg sensors + scatter3( sens_unit(:,1), sens_unit(:,2), sens_unit(:,3), 'k'); + % plot the 10-20 locations required + H1 = scatter3( XYZ1020(:,1), XYZ1020(:,2), XYZ1020(:,3), 'r','filled'); + % plot the matching MEG locations to these 10-20 locations + H2 = scatter3( sens_unit(CHAN,1), sens_unit(CHAN,2), sens_unit(CHAN,3), 'b','filled'); + legend([H1(1),H2(1)],'10-20','MEG'); + view(2); rotate3d +end + +if mod, + % Edit ctf to reflect only these channels + ctf.setup.number_channels = length(CHAN1020); + ctf.data = ctf.data(:,CHAN,:); + ctf.sensor.location = ctf.sensor.location(:,CHAN); + ctf.sensor.orientation = ctf.sensor.orientation(:,CHAN); + label = cell(1,length(CHAN1020)); + for i = 1:length(CHAN1020) + label{i} = [ctf.sensor.label{CHAN(i)} '_' CHAN1020{i}]; + end + ctf.sensor.label = label; +end + +return diff --git a/ctf_channel_sets.m b/ctf_channel_sets.m new file mode 100644 index 0000000..b31ba77 --- /dev/null +++ b/ctf_channel_sets.m @@ -0,0 +1,230 @@ +function [ctf] = ctf_channel_sets(ctf); + +% ctf_channel_sets - Define CTF MEG sensor regions +% +% ctf = ctf_channel_sets(ctf) +% +% This function parses the resource information in ctf.sensor, +% which is returned from ctf_read_res4 +% +% INPUTS +% +% ctf - the struct created by ctf_read_res4 +% +% OUTPUTS +% +% ctf.sensor.index - various regional sensor indices +% +% <>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +% < > +% < DISCLAIMER: > +% < > +% < THIS PROGRAM IS INTENDED FOR RESEARCH PURPOSES ONLY. > +% < THIS PROGRAM IS IN NO WAY INTENDED FOR CLINICAL OR > +% < OFFICIAL USE. > +% < > +% <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<> +% + +% $Revision: 1.1 $ $Date: 2009-01-30 03:49:26 $ + +% Copyright (C) 2004 Darren L. Weber +% +% This program is free software; you can redistribute it and/or +% modify it under the terms of the GNU General Public License +% as published by the Free Software Foundation; either version 2 +% of the License, or (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program; if not, write to the Free Software +% Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +% Modified: 02/2004, Darren.Weber_at_radiology.ucsf.edu +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%ver = '$Revision: 1.1 $'; +%fprintf('\nCTF_CHANNEL_SETS [v %s]\n',ver(11:15)); tic; + +if ~exist('ctf','var'), + ctf = ctf_folder; +end + +if ~isfield(ctf,'setup'), + ctf = ctf_read_res4(ctf.folder); +end + +%------------------------------------------------------------- +% Find channel types and define channel sets, see the +% System Administrators .pdf, 'Channel Sets Configuration' + +%types = unique([ctf.sensor.info.index]) +% 0 1 5 9 11 17 +%for typeValue = types, +% index = find([ctf.sensor.info.index] == typeValue); +% labels = ctf.sensor.info(index).label; +%end + + + +% ctf.SensorNames = {... +% 'Ref Magnetometer',... % Sensor Type Index of 0 +% 'Ref Gradiometer' ,... % Index of 1 +% '' ,... % 2 +% '' ,... % 3 +% '' ,... % 4 +% 'MEG Sensor',... % 5 +% '' ,... % 6 +% '',... % 7 +% '',... % 8 +% 'EEG Sensor',... % 9 +% 'ADC Input Current',...% 10 ADC Input Current (Amps) +% 'Stimulation input',...% 11 +% 'Video Time',... % 12 +% '',... % 13 +% '',... % 14 +% 'SAM Sensor',... % 15 +% 'Virtual Channel',... % 16 +% 'System Clock',... % 17 System Time Ref +% 'ADC Input Voltage',...% 18 ADC Input Voltage (Volts) +% }; + + + +% find the indices of the MEG reference sensors + +ctf.sensor.type.meg_ref = [0 1]; +ctf.sensor.type.refMagnetometers = 0; % include B* +ctf.sensor.type.refGradiometers = 1; % include G*,P*,Q*,R* + +magref = find([ctf.sensor.info.index] == 0); +gradref = find([ctf.sensor.info.index] == 1); + +ctf.sensor.index.meg_ref_mag = magref; +ctf.sensor.index.meg_ref_grad = gradref; +ctf.sensor.index.meg_ref = [magref,gradref]; + + +% find the indices of the MEG head sensors + +ctf.sensor.type.meg_sens = 5; % include B* +ctf.sensor.index.meg_sens = find([ctf.sensor.info.index] == 5); + + +% find the indices of the EEG head sensors + +ctf.sensor.type.eeg_sens = 9; % include EEG* +ctf.sensor.index.eeg_sens = find([ctf.sensor.info.index] == 9); + + +% find the indices of the ADC channels + +ctf.sensor.type.adc = 10; +ctf.sensor.index.adc = find([ctf.sensor.info.index] == 10); + + +% find the indices of the STIM channels + +ctf.sensor.type.stim_ref = 11; +ctf.sensor.index.stim_ref = find([ctf.sensor.info.index] == 11); + + +% find the indices of the STIM channels + +ctf.sensor.type.video_time = 12; +ctf.sensor.index.video_time = find([ctf.sensor.info.index] == 12); + + +% find the indices of the SAM channels (Synthetic Aperture Magnetometry) + +ctf.sensor.type.sam = 15; +ctf.sensor.index.sam = find([ctf.sensor.info.index] == 15); + + +% find the indices of the virtual channels + +ctf.sensor.type.virtual_channels = 16; +ctf.sensor.index.virtual_channels = find([ctf.sensor.info.index] == 16); + + +% find the indices of the system clock + +ctf.sensor.type.sclk_ref = 17; % include SCLK* +ctf.sensor.index.sclk_ref = find([ctf.sensor.info.index] == 17); + + +% combine eeg and meg channels + +ctf.sensor.index.all_sens = [ ctf.sensor.index.meg_sens, ctf.sensor.index.eeg_sens ]; + +all = [ ctf.sensor.index.all_sens, ctf.sensor.index.meg_ref, ... + ctf.sensor.index.stim_ref, ctf.sensor.index.sclk_ref ]; + +ctf.sensor.index.other = setdiff([1:ctf.setup.number_channels],all); + + +% define regions of MEG sensors +labels = {ctf.sensor.info.label}; +ctf.sensor.index.meg_left_central = strmatch('MLC',labels)'; +ctf.sensor.index.meg_left_frontal = strmatch('MLF',labels)'; +ctf.sensor.index.meg_left_parietal = strmatch('MLP',labels)'; +ctf.sensor.index.meg_left_occipital = strmatch('MLO',labels)'; +ctf.sensor.index.meg_left_parietal = strmatch('MLP',labels)'; +ctf.sensor.index.meg_left_temporal = strmatch('MLT',labels)'; +ctf.sensor.index.meg_right_central = strmatch('MRC',labels)'; +ctf.sensor.index.meg_right_frontal = strmatch('MRF',labels)'; +ctf.sensor.index.meg_right_occipital = strmatch('MRO',labels)'; +ctf.sensor.index.meg_right_parietal = strmatch('MRP',labels)'; +ctf.sensor.index.meg_right_temporal = strmatch('MRT',labels)'; +ctf.sensor.index.meg_mid_central = strmatch('MZC',labels)'; +ctf.sensor.index.meg_mid_frontal = strmatch('MZF',labels)'; +ctf.sensor.index.meg_mid_occipital = strmatch('MZO',labels)'; +ctf.sensor.index.meg_mid_parietal = strmatch('MZP',labels)'; + +ctf.sensor.index.meg_left = [ ... + ctf.sensor.index.meg_left_central, ... + ctf.sensor.index.meg_left_frontal, ... + ctf.sensor.index.meg_left_occipital, ... + ctf.sensor.index.meg_left_parietal, ... + ctf.sensor.index.meg_left_temporal ]; + +ctf.sensor.index.meg_right = [ ... + ctf.sensor.index.meg_right_central, ... + ctf.sensor.index.meg_right_frontal, ... + ctf.sensor.index.meg_right_occipital, ... + ctf.sensor.index.meg_right_parietal, ... + ctf.sensor.index.meg_right_temporal ]; + +ctf.sensor.index.meg_central = [ ... + ctf.sensor.index.meg_left_central, ... + ctf.sensor.index.meg_right_central, ... + ctf.sensor.index.meg_mid_central ]; + +ctf.sensor.index.meg_frontal = [ ... + ctf.sensor.index.meg_left_frontal, ... + ctf.sensor.index.meg_right_frontal, ... + ctf.sensor.index.meg_mid_frontal ]; + +ctf.sensor.index.meg_occipital = [ ... + ctf.sensor.index.meg_left_occipital, ... + ctf.sensor.index.meg_right_occipital, ... + ctf.sensor.index.meg_mid_occipital ]; + +ctf.sensor.index.meg_parietal = [ ... + ctf.sensor.index.meg_left_parietal, ... + ctf.sensor.index.meg_right_parietal, ... + ctf.sensor.index.meg_mid_parietal ]; + +ctf.sensor.index.meg_temporal = [ ... + ctf.sensor.index.meg_left_temporal, ... + ctf.sensor.index.meg_right_temporal ]; + + +%t = toc; fprintf('...done (%6.2f sec)\n\n',t); + +return diff --git a/ctf_channel_unit.m b/ctf_channel_unit.m new file mode 100644 index 0000000..29b13a7 --- /dev/null +++ b/ctf_channel_unit.m @@ -0,0 +1,56 @@ +function [sens_unit] = ctf_channel_unit(ctf) + +% ctf_channel_unit - project CTF channel locations onto a unit sphere +% +% [sens_unit] = ctf_channel_unit(ctf) +% +% sens_unit output is a projection of all the CTF sensor locations onto a +% unit sphere, assuming the origin is at (0,0,0). The output vector is Nx3 +% Cartesian coordinates. +% +% <>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +% < > +% < DISCLAIMER: > +% < > +% < THIS PROGRAM IS INTENDED FOR RESEARCH PURPOSES ONLY. > +% < THIS PROGRAM IS IN NO WAY INTENDED FOR CLINICAL OR > +% < OFFICIAL USE. > +% < > +% <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<> +% + + +% $Revision: 1.1 $ $Date: 2009-01-30 03:49:26 $ + +% Copyright (C) 2005 Darren L. Weber +% +% This program is free software; you can redistribute it and/or +% modify it under the terms of the GNU General Public License +% as published by the Free Software Foundation; either version 2 +% of the License, or (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program; if not, write to the Free Software +% Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +% Modified: 01/2005, Darren.Weber_at_radiology.ucsf.edu +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +ver = '$Revision: 1.1 $ $Date: 2009-01-30 03:49:26 $'; +fprintf('\nCTF_CHANNEL_UNIT [v %s]\n',ver(11:15)); + +% translate the CTF sensors into a unit sphere, +% assuming the origin is at (0,0,0) +sens = ctf.sensor.location'; +distance = sqrt( sens(:,1).^2 + sens(:,2).^2 + sens(:,3).^2 ); +distance = repmat(distance,1,3); +sens_unit = sens ./ distance; + +return diff --git a/ctf_check_eog.m b/ctf_check_eog.m new file mode 100644 index 0000000..cb43006 --- /dev/null +++ b/ctf_check_eog.m @@ -0,0 +1,205 @@ + +ctf = ctf_read_res4('/data/meg/WA_singleTrials/WA_HiN_alltrials_1250msec.ds') +ctf = ctf_read_markerfile([],ctf) +ctf.class = ctf_read_classfile(ctf) + +% ----------------------------- +% This section is based on prior knowledge of the artifact names used to +% identify VEOG and HEOG artifacts during ctf preprocessing + +classNames = {ctf.class.data(:).name}; +EYEBLINKaIndex = strmatch('EYEBLINKa',classNames); +EYEBLINKaTrials = ctf.class.data(EYEBLINKaIndex).trials; + +EYEBLINKdIndex = strmatch('EYEBLINKd',classNames); +EYEBLINKdTrials = ctf.class.data(EYEBLINKdIndex).trials; + +EYEMVMTaIndex = strmatch('EYEMVMTa',classNames); +EYEMVMTaTrials = ctf.class.data(EYEMVMTaIndex).trials; + +EYEMVMTdIndex = strmatch('EYEMVMTd',classNames); +EYEMVMTdTrials = ctf.class.data(EYEMVMTdIndex).trials; + +% find all unique artifact trials +EYEBLINKTrials = unique([EYEBLINKaTrials, EYEBLINKdTrials]); +EYEMVMTTrials = unique([EYEMVMTaTrials, EYEMVMTdTrials]); +EOGBADTrials = unique([EYEBLINKaTrials, EYEBLINKdTrials,... + EYEMVMTaTrials, EYEMVMTdTrials]); + +allTrials = 1:ctf.setup.number_trials; + +thresholdDetect.veog.amp = 50e-6; % 50 uV +thresholdDetect.veog.der = 25e-3; % 25 mV/sec +thresholdDetect.heog.amp = 25e-6; % 25 uV +thresholdDetect.heog.der = 25e-3; % 25 mV/sec + +% ------------------------------ + +cd(ctf.folder) + +% ----------------------------- +% This section here is based on prior extraction of the STIM, EEG121 and +% EEG122 channels, it could be replaced with the ctf_read_meg4 function +% to do this directly + +stimeegFile = fullfile(ctf.folder,'WA_HiN_alltrials_1250msec_stimeeg.mat'); +stimeegData = load(stimeegFile); +ctf.data = stimeegData.data; +ctf.sensor.label = stimeegData.labels +% ----------------------------- + +stim = strmatch('STIM',ctf.sensor.label); +veog = strmatch('EEG121',ctf.sensor.label); +heog = strmatch('EEG122',ctf.sensor.label); + +blPoints = ctf.setup.pretrigger_samples; +timeSec = ctf.setup.time_sec; +epochs = size(ctf.data,3); + + +% For continuous data, use arbitrary epoch lengths for viewing +%i = 1; +%epochs(i,:) = 1:10000; +%timeSec = epochs(i,:) * ctf.setup.sample_sec; +%while (i * 10000) < size(ctf.data,1), +% epochs(i,:) = (i * 10000) + epochs(1,:); +% i = i + 1; +%end + +fig = figure; + +for e = allTrials, + + set(fig,'Name',sprintf('Trial %04d',e)) + + veogData = ctf.data(:,veog,e); + heogData = ctf.data(:,heog,e); + + veogBaseline = mean(veogData(1:blPoints)); + heogBaseline = mean(heogData(1:blPoints)); + + veogDataBaselined = veogData - veogBaseline; + heogDataBaselined = heogData - heogBaseline; + + %plot(timeSec,[veogDataBaselined,heogDataBaselined]); + %legend('VEOG','HEOG') + + % EEG differential must be normalized by the sample rate (sec) + veogDataDiff = [0; diff(veogDataBaselined)] / ctf.setup.sample_sec; + heogDataDiff = [0; diff(heogDataBaselined)] / ctf.setup.sample_sec; + + % check if this is an artifact trial + EYEBLINKaTrial = find(EYEBLINKaTrials == e); + EYEBLINKdTrial = find(EYEBLINKdTrials == e); + EYEMVMTaTrial = find(EYEMVMTaTrials == e); + EYEMVMTdTrial = find(EYEMVMTdTrials == e); + + % ------------------------------- + % VEOG check + + + + % amplitude threshold + t = thresholdDetect.veog.amp; % 80 uV + % detect values above threshold + eyeblinkA = find(abs(veogDataBaselined) > t); + eyeblinkWave = veogDataBaselined * 0; + eyeblinkWave(eyeblinkA) = max(abs(veogDataBaselined)); + + veogAxisAmp = subplot(2,2,1); + plot(timeSec, [veogDataBaselined, eyeblinkWave]); hold on + legend('VEOG', 'VEOG Blink (Amp)') + plot(timeSec, [veogData*0, (veogData*0)+t, (veogData*0)-t],'k:'); hold off + ylabel('Volt') + xlabel('Time (sec)') + set(veogAxisAmp,'XLim',[ctf.setup.start_sec, ctf.setup.end_sec]); + ampLimit = thresholdDetect.veog.amp + (thresholdDetect.veog.amp * 0.5); + set(veogAxisAmp,'YLim',[-ampLimit, ampLimit]) + set(veogAxisAmp,'YTick',-ampLimit:10e-6:ampLimit) + if EYEBLINKaTrial, + set(veogAxisAmp,'color',[1 0.75 0.75]) + else + set(veogAxisAmp,'color',[1 1 1]) + end + + + + % detect derivatives above 20 mV/sec + t = thresholdDetect.veog.der; + eyeblinkD = find(abs(veogDataDiff) > t); + eyeblinkWave = veogDataDiff * 0; + eyeblinkWave(eyeblinkD) = max(abs(veogDataDiff)); + + veogAxisDer = subplot(2,2,3); + plot(timeSec,[veogDataDiff, eyeblinkWave]); hold on + legend('diff(VEOG)/sec', 'VEOG Blink (Der)') + plot(timeSec, [veogData*0, (veogData*0)+t, (veogData*0)-t],'k:'); hold off + ylabel('Volt / sec') + xlabel('Time (sec)') + set(veogAxisDer,'XLim',[ctf.setup.start_sec, ctf.setup.end_sec]); + ampLimit = thresholdDetect.veog.der + (thresholdDetect.veog.der * 0.5); + set(veogAxisDer,'YLim',[-ampLimit, ampLimit]) + %set(veogAxisDer,'YTick',-ampLimit:10e-6:ampLimit) + if EYEBLINKdTrial, + set(veogAxisDer,'color',[1 0.75 0.75]) + else + set(veogAxisDer,'color',[1 1 1]) + end + + % ------------------------------- + % HEOG check + + + + % amplitude threshold + t = thresholdDetect.heog.amp; + % detect values above threshold + eyeMoveA = find(abs(heogDataBaselined) > t); + eyeMoveWave = heogDataBaselined * 0; + eyeMoveWave(eyeMoveA) = max(abs(heogDataBaselined)); + + heogAxisAmp = subplot(2,2,2); + plot(timeSec, [heogDataBaselined, eyeMoveWave]); hold on + legend('HEOG', 'HEOG Move (Amp)') + plot(timeSec, [heogData*0, (heogData*0)+t, (heogData*0)-t],'k:'); hold off + ylabel('Volt') + xlabel('Time (sec)') + set(heogAxisAmp,'XLim',[ctf.setup.start_sec, ctf.setup.end_sec]); + ampLimit = thresholdDetect.heog.amp + (thresholdDetect.heog.amp * 0.5); + set(heogAxisAmp,'YLim',[-ampLimit, ampLimit]) + set(heogAxisAmp,'YTick',-ampLimit:10e-6:ampLimit) + if EYEMVMTaTrial, + set(heogAxisAmp,'color',[1 0.75 0.75]) + else + set(heogAxisAmp,'color',[1 1 1]) + end + + + + % HEOG movements may accelerate at about 20 mV/sec + t = thresholdDetect.heog.der; + eyeMoveD = find(abs(heogDataDiff) > t); + eyeMoveWave = heogDataDiff * 0; + eyeMoveWave(eyeMoveD) = max(abs(heogDataDiff)); + + heogAxisDer = subplot(2,2,4); + plot(timeSec, [heogDataDiff, eyeMoveWave]); hold on + legend('diff(HEOG)/sec', 'HEOG Move (Der)') + plot(timeSec, [heogData*0, (heogData*0)+t, (heogData*0)-t],'k:'); hold off + ylabel('Volt / sec') + xlabel('Time (sec)') + set(heogAxisDer,'XLim',[ctf.setup.start_sec, ctf.setup.end_sec]); + ampLimit = thresholdDetect.heog.der + (thresholdDetect.heog.der * 0.5); + set(heogAxisDer,'YLim',[-ampLimit, ampLimit]) + %set(heogAxisDer,'YTick',-ampLimit:10e-6:ampLimit) + if EYEMVMTdTrial, + set(heogAxisDer,'color',[1 0.75 0.75]) + else + set(heogAxisDer,'color',[1 1 1]) + end + + pause(10) + +end + +return diff --git a/ctf_eeglab_jtfa_script.m b/ctf_eeglab_jtfa_script.m new file mode 100644 index 0000000..36a9818 --- /dev/null +++ b/ctf_eeglab_jtfa_script.m @@ -0,0 +1,100 @@ +% ctfcomp +% EEGLAB script for joint time-frequency analysis for MEG data +% Saves single-channel ERP and JTF +% Saves all outputs in .mat file +% Thomas Ferree @ UCSF +% Revised 1/28/2004 + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +clear; + + + + +% toggle saving eeglab .set, 0 = no, 1 = yes +saveSet = 0; + +% set machine: 1 = TiBoard, 2 = Glutamate/Acetylcholine/Brainmap +machine = 2 ; + +% user-defined paths +if machine == 1 + pathdata = '/Users/tferree/Documents/Data/Attention/HighN/'; + pathersp = '/Users/tferree/Documents/Research/Attention/Temp/'; + pathfigs = '/Users/tferree/Documents/Research/Attention/Temp/'; +else + addpath /netopt/lib/matlab/eeglab/ -end; + addpath /home/tferree/Attention/HighN/ctf2eeglab/ -end; + pathdata = '/home/cdale/HighN/HM_epoch/processed/'; + pathersp = '/home/tferree/Attention/HighN/Temp/'; + pathfigs = '/home/tferree/Attention/HighN/Temp/'; +end + +% call Darren's scripts +ctffolder = [pathdata 'HM_DNL_20040126_HiN_CueLValNT-fEOG.ds']; +ctfchannels = 'meg'; +ctftime = 'all'; +%ctftrials = [1:5:100]; +ctftrials = 'all'; +ctf = ctf_read(ctffolder,ctfchannels,ctftime,ctftrials); +ctf2eeglab; + +% define JTFA parameters +winsize = 128; +padratio = 2; % frequency resolution +bootalpha = 0.05; % already two-tailed +bootnaccu = 200; % 200-20000 + +% scale data upward to order unity +EEG.data = EEG.data * 10^12; + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +% loop on channels +Nchan = EEG.nbchan; +for ichan = 1:Nchan + + % channel string for saving figures to files with sequential file names + if ichan < 10 + chanstring = ['00' num2str(ichan)]; + end + if ichan > 9 & chan < 100 + chanstring = ['0' num2str(ichan)]; + end + if ichan > 99 + chanstring = num2str(ichan); + end + + % make single-channel ERP image + h1 = figure(1000+ichan); + avewidth = 1; + decimate = 1; + pop_erpimage(EEG,1, [ichan],[],['Channel ' num2str(ichan)],avewidth,decimate,{},[],'' ,'erp','cbar'); + saveas(h1,[pathfigs 'ERP_Ch' chanstring '.jpg'],'jpg'); + close(h1); + + % make single-channel JTF image + h2 = figure(2000+ichan); + [ersp,itc,powbase,times,freqs,erspboot,itcboot]=pop_timef( EEG, 1, ichan, [-1200 2000], 0 ,'type', 'phasecoher', 'title',['Channel ' num2str(ichan)],'padratio', padratio, 'plotphase', 'off','winsize',winsize,'alpha',bootalpha,'naccu',bootnaccu,'baseline',-1200); + saveas(h2,[pathfigs 'JTF_Ch' chanstring '.jpg'],'jpg'); + close(h2); + + % store all timef results in 'all' array, referring to all channels + allersp(:,:,ichan) = ersp; + allitc(:,:,ichan) = itc; + allpowbase(:,:,ichan) = powbase; + alltimes(:,:,ichan) = times; + allfreqs(:,:,ichan) = freqs; + allerspboot(:,:,ichan) = erspboot; + allitcboot(:,:,ichan) = itcboot; + +end % end loop over channels + +% save results to file - avoiding overwrite with 'old' designation +%if exist([pathersp 'ERSP.mat']) +% mv [pathersp 'ERSP.mat'] [pathersp 'ERSP_old.mat']; +%end +folderpath = [pathersp 'ERSP.mat']; +save(folderpath,'allersp','allitc','allpowbase','alltimes','allfreqs','allerspboot','allitcboot'); + diff --git a/ctf_eog.m b/ctf_eog.m new file mode 100644 index 0000000..9163046 --- /dev/null +++ b/ctf_eog.m @@ -0,0 +1,565 @@ +function [ctf,GUI] = ctf_eog(command); + +% ctf_eog - GUI interface to check EOG data in a CTF .ds folder +% +% [ctf,FIG] = ctf_eog( [command] ); +% +% eg, +% ctf = ctf_eog; +% +% <>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> % +% < > % +% < DISCLAIMER: > % +% < > % +% < THIS PROGRAM IS INTENDED FOR RESEARCH PURPOSES ONLY. > % +% < THIS PROGRAM IS IN NO WAY INTENDED FOR CLINICAL OR > % +% < OFFICIAL USE. > % +% < > % +% <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<> % +% + + +% $Revision: 1.1 $ $Date: 2009-01-30 03:49:26 $ + +% Copyright (C) 2006 Darren L. Weber +% +% This program is free software; you can redistribute it and/or +% modify it under the terms of the GNU General Public License +% as published by the Free Software Foundation; either version 2 +% of the License, or (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program; if not, write to the Free Software +% Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +% Created: 01/2006, Darren.Weber_at_radiology.ucsf.edu +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + + +if ~exist('command','var'), command = 'init'; end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Paint the GUI +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +switch command, + + case 'init', + + [ctf,GUI] = INIT; + + case 'update', + + CTFeog = get(gcbf,'Userdata'); + + ctf = CTFeog.ctf; + + CTFeog.CHANNELS = 1:ctf.setup.number_channels; + CTFeog.TIME = ctf.setup.time_sec; + CTFeog.TRIALS = 1:ctf.setup.number_trials; + + set(gcbf,'Userdata',CTFeog); + + + case 'return', + + CTFeog = get(gcbf,'Userdata'); + + ctf = CTFeog.ctf; + + close gcbf; + + case 'plot', + + fprintf('\nCTF_EOG: Plot not implemented yet.\n'); + + case 'save', + + fprintf('\nCTF_EOG: Save not implemented yet.\n'); + + otherwise, + + CTFeog = get(gcbf,'Userdata'); + GUI.parent = CTFeog.parent; + gui_updateparent(GUI); + close gcbf; + +end + +return + + + + + + +% ------------------------------------------- + +fig = figure; + +for e = allTrials, + + set(fig,'Name',sprintf('Trial %04d',e)) + + veogData = ctf.data(:,veog,e); + heogData = ctf.data(:,heog,e); + + veogBaseline = mean(veogData(1:blPoints)); + heogBaseline = mean(heogData(1:blPoints)); + + veogDataBaselined = veogData - veogBaseline; + heogDataBaselined = heogData - heogBaseline; + + %plot(timeSec,[veogDataBaselined,heogDataBaselined]); + %legend('VEOG','HEOG') + + % EEG differential must be normalized by the sample rate (sec) + veogDataDiff = [0; diff(veogDataBaselined)] / ctf.setup.sample_sec; + heogDataDiff = [0; diff(heogDataBaselined)] / ctf.setup.sample_sec; + + % check if this is an artifact trial + EYEBLINKaTrial = find(EYEBLINKaTrials == e); + EYEBLINKdTrial = find(EYEBLINKdTrials == e); + EYEMVMTaTrial = find(EYEMVMTaTrials == e); + EYEMVMTdTrial = find(EYEMVMTdTrials == e); + + % ------------------------------- + % VEOG check + + + + % amplitude threshold + t = thresholdDetect.veog.amp; % 80 uV + % detect values above threshold + eyeblinkA = find(abs(veogDataBaselined) > t); + eyeblinkWave = veogDataBaselined * 0; + eyeblinkWave(eyeblinkA) = max(abs(veogDataBaselined)); + + veogAxisAmp = subplot(2,2,1); + plot(timeSec, [veogDataBaselined, eyeblinkWave]); hold on + legend('VEOG', 'VEOG Blink (Amp)') + plot(timeSec, [veogData*0, (veogData*0)+t, (veogData*0)-t],'k:'); hold off + ylabel('Volt') + xlabel('Time (sec)') + set(veogAxisAmp,'XLim',[ctf.setup.start_sec, ctf.setup.end_sec]); + ampLimit = thresholdDetect.veog.amp + (thresholdDetect.veog.amp * 0.5); + set(veogAxisAmp,'YLim',[-ampLimit, ampLimit]) + set(veogAxisAmp,'YTick',-ampLimit:10e-6:ampLimit) + if EYEBLINKaTrial, + set(veogAxisAmp,'color',[1 0.75 0.75]) + else + set(veogAxisAmp,'color',[1 1 1]) + end + + + + % detect derivatives above 20 mV/sec + t = thresholdDetect.veog.der; + eyeblinkD = find(abs(veogDataDiff) > t); + eyeblinkWave = veogDataDiff * 0; + eyeblinkWave(eyeblinkD) = max(abs(veogDataDiff)); + + veogAxisDer = subplot(2,2,3); + plot(timeSec,[veogDataDiff, eyeblinkWave]); hold on + legend('diff(VEOG)/sec', 'VEOG Blink (Der)') + plot(timeSec, [veogData*0, (veogData*0)+t, (veogData*0)-t],'k:'); hold off + ylabel('Volt / sec') + xlabel('Time (sec)') + set(veogAxisDer,'XLim',[ctf.setup.start_sec, ctf.setup.end_sec]); + ampLimit = thresholdDetect.veog.der + (thresholdDetect.veog.der * 0.5); + set(veogAxisDer,'YLim',[-ampLimit, ampLimit]) + %set(veogAxisDer,'YTick',-ampLimit:10e-6:ampLimit) + if EYEBLINKdTrial, + set(veogAxisDer,'color',[1 0.75 0.75]) + else + set(veogAxisDer,'color',[1 1 1]) + end + + % ------------------------------- + % HEOG check + + + + % amplitude threshold + t = thresholdDetect.heog.amp; + % detect values above threshold + eyeMoveA = find(abs(heogDataBaselined) > t); + eyeMoveWave = heogDataBaselined * 0; + eyeMoveWave(eyeMoveA) = max(abs(heogDataBaselined)); + + heogAxisAmp = subplot(2,2,2); + plot(timeSec, [heogDataBaselined, eyeMoveWave]); hold on + legend('HEOG', 'HEOG Move (Amp)') + plot(timeSec, [heogData*0, (heogData*0)+t, (heogData*0)-t],'k:'); hold off + ylabel('Volt') + xlabel('Time (sec)') + set(heogAxisAmp,'XLim',[ctf.setup.start_sec, ctf.setup.end_sec]); + ampLimit = thresholdDetect.heog.amp + (thresholdDetect.heog.amp * 0.5); + set(heogAxisAmp,'YLim',[-ampLimit, ampLimit]) + set(heogAxisAmp,'YTick',-ampLimit:10e-6:ampLimit) + if EYEMVMTaTrial, + set(heogAxisAmp,'color',[1 0.75 0.75]) + else + set(heogAxisAmp,'color',[1 1 1]) + end + + + + % HEOG movements may accelerate at about 20 mV/sec + t = thresholdDetect.heog.der; + eyeMoveD = find(abs(heogDataDiff) > t); + eyeMoveWave = heogDataDiff * 0; + eyeMoveWave(eyeMoveD) = max(abs(heogDataDiff)); + + heogAxisDer = subplot(2,2,4); + plot(timeSec, [heogDataDiff, eyeMoveWave]); hold on + legend('diff(HEOG)/sec', 'HEOG Move (Der)') + plot(timeSec, [heogData*0, (heogData*0)+t, (heogData*0)-t],'k:'); hold off + ylabel('Volt / sec') + xlabel('Time (sec)') + set(heogAxisDer,'XLim',[ctf.setup.start_sec, ctf.setup.end_sec]); + ampLimit = thresholdDetect.heog.der + (thresholdDetect.heog.der * 0.5); + set(heogAxisDer,'YLim',[-ampLimit, ampLimit]) + %set(heogAxisDer,'YTick',-ampLimit:10e-6:ampLimit) + if EYEMVMTdTrial, + set(heogAxisDer,'color',[1 0.75 0.75]) + else + set(heogAxisDer,'color',[1 1 1]) + end + + pause(10) + +end + +return + + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [ctf,GUI] = INIT +% GUI General Parameters + + ctf = ctf_folder; + ctf = ctf_read_res4(ctf.folder); + + + thresholdDetect.veog.amp = 50e-6; % 50 uV + thresholdDetect.veog.der = 25e-3; % 25 mV/sec + thresholdDetect.heog.amp = 25e-6; % 25 uV + thresholdDetect.heog.der = 25e-3; % 25 mV/sec + + + + CTFeog.CHANNELS = 1:ctf.setup.number_channels; + CTFeog.TIME = ctf.setup.time_sec; + CTFeog.TRIALS = 1:ctf.setup.number_trials; + + GUIwidth = 800; + GUIheight = 600; + + ver = '$Revision: 1.1 $'; + name = sprintf('CTF EOG [v %s]\n',ver(11:15)); + + GUI = figure('Name',name,'Tag','CTF_EOG',... + 'NumberTitle','off',... + 'MenuBar','none','Position',[1 1 GUIwidth GUIheight]); + movegui(GUI,'center'); + + %Font.FontName = 'Helvetica'; + Font.FontUnits = 'Pixels'; + Font.FontSize = 12; + Font.FontWeight = 'normal'; + Font.FontAngle = 'normal'; + + boxdepth = 0.15; + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % CTF Data Selection and Parameters + + Font.FontWeight = 'bold'; + + % BROWSE for a .ds folder + browsecommand = strcat('CTFeog = get(gcbf,''Userdata'');',... + 'ctf = CTFeog.ctf; ',... + 'ctf = ctf_folder([],ctf); ',... + 'ctf = ctf_read_res4(ctf.folder); ',... + 'CTFeog.ctf = ctf; ',... + 'set(CTFeog.handles.EctfFolder,''String'',ctf.folder); ',... + 'set(gcbf,''Userdata'',CTFeog);',... + 'clear CTFeog; ctf = ctf_read_gui(''update'');'); + G.BctfFile = uicontrol('Parent',GUI,'Style','pushbutton','Units','Normalized',Font, ... + 'Position',[.01 .80 .17 boxdepth], 'String','CTF Folder (*.ds)',... + 'BackgroundColor',[0.8 0.8 0.0], 'ForegroundColor', [1 1 1], ... + 'HorizontalAlignment', 'center', ... + 'TooltipString','Browse for CTF folder', ... + 'Callback', browsecommand ); + + Font.FontWeight = 'normal'; + + % EDIT the .ds folder name + editcommand = strcat('CTFeog = get(gcbf,''Userdata'');',... + 'CTFeog.ctf.folder = get(CTFeog.handles.EctfFolder,''String''); ',... + 'ctf = CTFeog.ctf; ',... + 'ctf = ctf_folder(ctf.folder,ctf); ',... + 'ctf = ctf_read_res4(ctf.folder); ',... + 'CTFeog.ctf = ctf; ',... + 'set(CTFeog.handles.EctfFolder,''String'',ctf.folder); ',... + 'set(gcbf,''Userdata'',CTFeog);',... + 'clear CTFeog; ctf = ctf_read_gui(''update'');'); + G.EctfFolder = uicontrol('Parent',GUI,'Style','edit','Units','Normalized',Font, ... + 'Position',[.20 .80 .75 boxdepth], 'String',ctf.folder,... + 'Callback', editcommand ); + + + + %--------------------------------------------------------------- + % Channels + height = 0.6; + + G.Title_channels = uicontrol('Parent',GUI,'Style','text','Units','Normalized',Font, ... + 'Position',[.01 height .17 boxdepth],'HorizontalAlignment', 'center','String','Channels:'); + + % Channel types + CTFeog.channeltypes = {'all', 'eeg', 'meg', 'ref', 'other', '[array]'}; + channelpopup = strcat('CTFeog = get(gcbf,''Userdata'');',... + 'channelvalue = get(CTFeog.handles.PctfCHANNELS,''Value''); ',... + 'channeltype = CTFeog.channeltypes{channelvalue}; ',... + 'switch channeltype, ',... + ' case ''all'', CTFeog.CHANNELS = 1:CTFeog.ctf.setup.number_channels; ',... + ' case ''eeg'', CTFeog.CHANNELS = CTFeog.ctf.sensor.index.eeg; ',... + ' case ''meg'', CTFeog.CHANNELS = CTFeog.ctf.sensor.index.meg; ',... + ' case ''ref'', CTFeog.CHANNELS = CTFeog.ctf.sensor.index.ref; ',... + ' case ''other'', CTFeog.CHANNELS = CTFeog.ctf.sensor.index.other; ',... + ' otherwise, CTFeog.CHANNELS = []; ',... + 'end; ',... + 'set(CTFeog.handles.EctfCHANNELS,''Value'',CTFeog.CHANNELS); ',... + 'set(CTFeog.handles.EctfCHANNELS,''string'',num2str(CTFeog.CHANNELS)); ',... + 'set(gcbf,''Userdata'',CTFeog);',... + 'clear CTFeog channelvalue channeltype;'); + G.PctfCHANNELS = uicontrol('Parent',GUI,'Style','popup','Units','Normalized',Font, ... + 'Position',[.20 height .20 boxdepth], ... + 'String',CTFeog.channeltypes,... + 'Value',1, ... + 'TooltipString','Channel selection - enter values for [array]', ... + 'Callback', channelpopup ); + + % Channels array + channelarray = strcat('CTFeog = get(gcbf,''Userdata'');',... + 'CTFeog.CHANNELS = str2num(get(CTFeog.handles.EctfCHANNELS,''String'')); ',... + 'set(CTFeog.handles.EctfCHANNELS,''Value'',CTFeog.CHANNELS); ',... + 'set(gcbf,''Userdata'',CTFeog); clear CTFeog;'); + G.EctfCHANNELS = uicontrol('Parent',GUI,'Style','edit','Units','Normalized',Font, ... + 'Position',[.40 height .50 boxdepth], ... + 'String',num2str(CTFeog.CHANNELS),'Value',CTFeog.CHANNELS,... + 'TooltipString','Channels array - enter values for [array] selection', ... + 'Callback', channelarray ); + G.EctfCHANNELSCLEAR = uicontrol('Parent',GUI,'Style','pushbutton','Units','Normalized',Font, ... + 'Position',[.90 height .05 boxdepth], ... + 'String','Clear',... + 'TooltipString','Clear channels array', ... + 'Callback', strcat('CTFeog = get(gcbf,''Userdata'');',... + 'CTFeog.CHANNELS = []; ',... + 'set(CTFeog.handles.EctfCHANNELS,''String'',''''); ',... + 'set(CTFeog.handles.EctfCHANNELS,''Value'',CTFeog.CHANNELS); ',... + 'set(gcbf,''Userdata'',CTFeog); clear CTFeog;') ); + + + + + %--------------------------------------------------------------- + % Time + height = 0.4; + + G.Title_channels = uicontrol('Parent',GUI,'Style','text','Units','Normalized',Font, ... + 'Position',[.01 height .17 boxdepth],'HorizontalAlignment', 'center','String','Time (sec):'); + + % Time array + start = sprintf('%6.5f', CTFeog.TIME(1)); + step = sprintf('%6.5f',[CTFeog.TIME(2) - CTFeog.TIME(1)]); + stop = sprintf('%6.5f', CTFeog.TIME(end)); + timestring = [start,':',step,':',stop]; + + G.TctfTIME = uicontrol('Parent',GUI,'Style','text','Units','Normalized',Font, ... + 'Position',[.20 height .20 boxdepth],'HorizontalAlignment', 'center',... + 'TooltipString','Time array (sec)', ... + 'String',timestring); + + + timearray = strcat('CTFeog = get(gcbf,''Userdata'');',... + 'CTFeog.TIME = str2num(get(CTFeog.handles.EctfTIME,''String''))''; ',... + 'set(CTFeog.handles.EctfTIME,''Value'',CTFeog.TIME); ',... + 'set(gcbf,''Userdata'',CTFeog); clear CTFeog;'); + G.EctfTIME = uicontrol('Parent',GUI,'Style','edit','Units','Normalized',Font, ... + 'Position',[.40 height .50 boxdepth], ... + 'String',num2str(CTFeog.TIME'),'Value',CTFeog.TIME,... + 'TooltipString','Time array (sec)', ... + 'Callback', timearray ); +G.EctfTIMECLEAR = uicontrol('Parent',GUI,'Style','pushbutton','Units','Normalized',Font, ... + 'Position',[.90 height .05 boxdepth], ... + 'String','Clear',... + 'TooltipString','Clear time array', ... + 'Callback', strcat('CTFeog = get(gcbf,''Userdata'');',... + 'CTFeog.TIME = []; ',... + 'set(CTFeog.handles.EctfTIME,''String'',''''); ',... + 'set(CTFeog.handles.EctfTIME,''Value'',CTFeog.TIME); ',... + 'set(gcbf,''Userdata'',CTFeog); clear CTFeog;') ); + + + +%--------------------------------------------------------------- +% Trials +height = 0.2; + +G.Title_trials = uicontrol('Parent',GUI,'Style','text','Units','Normalized',Font, ... + 'Position',[.01 height .17 boxdepth],'HorizontalAlignment', 'center','String','Trials:'); + +start = num2str(CTFeog.TRIALS(1)); +stop = num2str(CTFeog.TRIALS(end)); +trialstring = [start,':',stop]; + +G.TctfTRIALS = uicontrol('Parent',GUI,'Style','text','Units','Normalized',Font, ... + 'Position',[.20 height .20 boxdepth],'HorizontalAlignment', 'center',... + 'String',trialstring); + +% Trials array +trialsarray = strcat('CTFeog = get(gcbf,''Userdata'');',... + 'CTFeog.TRIALS = str2num(get(CTFeog.handles.EctfTRIALS,''String'')); ',... + 'set(CTFeog.handles.EctfTRIALS,''Value'',CTFeog.TRIALS); ',... + 'set(gcbf,''Userdata'',CTFeog); clear CTFeog;'); +G.EctfTRIALS = uicontrol('Parent',GUI,'Style','edit','Units','Normalized',Font, ... + 'Position',[.40 height .50 boxdepth], ... + 'String',num2str(CTFeog.TRIALS),'Value',CTFeog.TRIALS,... + 'TooltipString','Trials array', ... + 'Callback', trialsarray ); +G.EctfTRIALSCLEAR = uicontrol('Parent',GUI,'Style','pushbutton','Units','Normalized',Font, ... + 'Position',[.90 height .05 boxdepth], ... + 'String','Clear',... + 'TooltipString','Clear trials array', ... + 'Callback', strcat('CTFeog = get(gcbf,''Userdata'');',... + 'CTFeog.TRIALS = []; ',... + 'set(CTFeog.handles.EctfTRIALS,''String'',''''); ',... + 'set(CTFeog.handles.EctfTRIALS,''Value'',CTFeog.TRIALS); ',... + 'set(gcbf,''Userdata'',CTFeog); clear CTFeog;') ); + + +% % PLOT: Load & plot the data! +% G.Bplot = uicontrol('Parent',GUI,'Style','pushbutton','Units','Normalized', Font, ... +% 'Position',[.20 .01 .18 .2],... +% 'String','PLOT','BusyAction','queue',... +% 'TooltipString','Plot the EEG data and return p struct.',... +% 'BackgroundColor',[0.0 0.5 0.0],... +% 'ForegroundColor', [1 1 1], 'HorizontalAlignment', 'center',... +% 'Callback',strcat('CTFeog = get(gcbf,''Userdata'');',... +% 'p = ctf_read_gui(CTFeog.p,''plot'');',... +% 'clear CTFeog;')); +% +% % Save As +% G.Bsave = uicontrol('Parent',GUI,'Style','pushbutton','Units','Normalized', Font, ... +% 'Position',[.40 .01 .18 .2],'HorizontalAlignment', 'center',... +% 'String','SAVE AS','TooltipString','EEG File Conversion Tool (not implemented yet)',... +% 'BusyAction','queue',... +% 'Visible','off',... +% 'BackgroundColor',[0.0 0.0 0.75],... +% 'ForegroundColor', [1 1 1], 'HorizontalAlignment', 'center',... +% 'Callback',strcat('CTFeog = get(gcbf,''Userdata'');',... +% 'p = ctf_read_gui(CTFeog.p,''save'');',... +% 'clear CTFeog;')); + +Font.FontWeight = 'bold'; + +% Quit, return file parameters +G.Breturn = uicontrol('Parent',GUI,'Style','pushbutton','Units','Normalized', Font, ... + 'Position',[.70 .01 .10 boxdepth],... + 'String','RETURN','BusyAction','queue',... + 'TooltipString','Return p struct to workspace and parent GUI.',... + 'BackgroundColor',[0.0 0.75 0.0],... + 'ForegroundColor', [1 1 1], 'HorizontalAlignment', 'center',... + 'Callback','ctf = ctf_read_gui(''return'');' ); + +% Cancel +G.Bcancel = uicontrol('Parent',GUI,'Style','pushbutton','Units','Normalized', Font, ... + 'Position',[.85 .01 .10 boxdepth],... + 'String','CANCEL','BusyAction','queue',... + 'TooltipString','Close, do not read data.',... + 'BackgroundColor',[0.75 0.0 0.0],... + 'ForegroundColor', [1 1 1], 'HorizontalAlignment', 'center',... + 'Callback','close(gcbf);'); + +% Store userdata +CTFeog.gui = GUI; +CTFeog.handles = G; +CTFeog.ctf = ctf; +set(GUI,'Userdata',CTFeog); +set(GUI,'HandleVisibility','callback'); + +return + + + + + + + + +% --------------------------------------------------------- + +function classTrials = extract_classTrials(CTFeog), + + ctf = CTFeog.ctf; + + ctf.class = ctf_read_classfile(ctf); + + if ctf.class.number, + + classNames = {ctf.class.data(:).name}; + classTrials = cell(1,ctf.class.number); + for c = 1:ctf.class.number, + classTrials{c} = ctf.class.data(c).trials; + end + + % ------------------------------ + + cd(ctf.folder) + + % ----------------------------- + % This section here is based on prior extraction of the STIM, EEG121 and + % EEG122 channels, it could be replaced with the ctf_read_meg4 function + % to do this directly + + stimeegFile = fullfile(ctf.folder,'WA_HiN_alltrials_1250msec_stimeeg.mat'); + stimeegData = load(stimeegFile); + ctf.data = stimeegData.data; + ctf.sensor.label = stimeegData.labels + % ----------------------------- + + stim = strmatch('STIM',ctf.sensor.label); + veog = strmatch('EEG121',ctf.sensor.label); + heog = strmatch('EEG122',ctf.sensor.label); + + blPoints = ctf.setup.pretrigger_samples; + timeSec = ctf.setup.time_sec; + epochs = size(ctf.data,3); + + + end + + % For continuous data, use arbitrary epoch lengths for viewing + %i = 1; + %epochs(i,:) = 1:10000; + %timeSec = epochs(i,:) * ctf.setup.sample_sec; + %while (i * 10000) < size(ctf.data,1), + % epochs(i,:) = (i * 10000) + epochs(1,:); + % i = i + 1; + %end + + + return diff --git a/ctf_filter.m b/ctf_filter.m new file mode 100644 index 0000000..8e9258b --- /dev/null +++ b/ctf_filter.m @@ -0,0 +1,86 @@ +function ctf = ctf_filter(ctf,lcf,hcf,order); + +% ctf_filter - apply a butterworth polynomial filter +% +% Usage : ctf = ctf_filter(ctf,lcf,hcf,order); +% +% - input arguments +% ctf : meg data file returned by ctf_read +% lcf : low cutoff frequency (default 0.01) +% hcf : high cutoff frequency (default 40) +% order : butterworth polynomial order (default 2) +% +% - output argument +% ctf.data : filtered replacement of ctf.data +% +% This function calls the butter and filtfilt functions of the matlab +% signal processing toolbox. The filtfilt values are baselined with +% ctf_baseline, so the baseline offsets can be slightly different from the +% input ctf.data. +% + + +% $Revision: 1.1 $ $Date: 2009-01-30 03:49:27 $ + +% Copyright (C) 2004 Darren L. Weber +% +% This program is free software; you can redistribute it and/or +% modify it under the terms of the GNU General Public License +% as published by the Free Software Foundation; either version 2 +% of the License, or (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program; if not, write to the Free Software +% Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +% Created: 05/2004, copyright 2004 Darren.Weber_at_radiology.ucsf.edu +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + + +% low cutoff frequency (default 2) +if ~exist('lcf','var') || isempty(lcf), + lcf = 0.01; +end +% high cutoff frequency (default 20) +if ~exist('hcf','var') || isempty(hcf), + hcf = 40; +end +% butter filter order (default 2) +if ~exist('order','var') || isempty(order), + order = 2; +end + +sample_freq = ctf.setup.sample_rate; + +if hcf > (sample_freq/2), + warning('hcf > sample_freq/2, setting hcf = sample_freq/2'); + hcf = sample_freq / 2; +end +if lcf <= 0 || lcf > (sample_freq/2) || lcf >= hcf, + warning('lcf value is <=0 or >(sample_freq/2) or >=hcf, setting lcf = 2'); + lcf = 2; +end + + +% design the Butterworth filter +cf1 = lcf/(sample_freq/2); +cf2 = hcf/(sample_freq/2); +[B,A] = butter(order,[cf1 cf2]); + +% filter the data +% data should be N samples x M channels +for trial = 1:size(ctf.data,3) + data = ctf.data(:,:,trial); + ctf.data(:,:,trial) = filtfilt(B,A,data); +end + +% now rebaseline the filtered data +ctf = ctf_baseline(ctf); + +return diff --git a/ctf_folder.m b/ctf_folder.m new file mode 100644 index 0000000..33c3ee9 --- /dev/null +++ b/ctf_folder.m @@ -0,0 +1,106 @@ +function [ctf] = ctf_folder(folder,ctf); + +% ctf_folder - get and check CTF .ds folder name +% +% [ctf] = ctf_folder( [folder], [ctf] ); +% +% folder: The .ds directory of the dataset. It should be a complete path +% or given relative to the current working directory (given by pwd). The +% returned value will ensure the complete path is identified. If this +% argument is empty or not given, a graphical prompt for the folder +% appears. +% +% eg, +% ctf = ctf_folder; +% +% ctf.folder is returned (as a complete path). +% +% <>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> % +% < > % +% < DISCLAIMER: > % +% < > % +% < THIS PROGRAM IS INTENDED FOR RESEARCH PURPOSES ONLY. > % +% < THIS PROGRAM IS IN NO WAY INTENDED FOR CLINICAL OR > % +% < OFFICIAL USE. > % +% < > % +% <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<> % +% + + +% $Revision: 1.1 $ $Date: 2009-01-30 03:49:27 $ + +% Copyright (C) 2004 Darren L. Weber +% +% This program is free software; you can redistribute it and/or +% modify it under the terms of the GNU General Public License +% as published by the Free Software Foundation; either version 2 +% of the License, or (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program; if not, write to the Free Software +% Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +% Modified: 01/2004, Darren.Weber_at_radiology.ucsf.edu +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +if ~exist('folder','var'), folder = []; end +if ~exist('ctf','var'), ctf = []; end + +if isempty(folder), + if isfield(ctf,'folder'), + folder = ctf.folder; + else + folder = []; + end +end + +if exist(folder) ~= 7, + fprintf('...folder inputs are invalid\n'); + folder = getfolder; +end + +ctf.folder = folder; + +% ensure we get the folder path +current_dir = pwd; +cd(ctf.folder); +cd .. +folderPath = pwd; +cd(current_dir); + +% check whether the folder path is in the folder already +[path,file] = fileparts(ctf.folder); + +% if findstr(folderPath,ctf.folder), + % OK the path is already in the folder +% else +if isempty(path) + % Add the folderPath + ctf.folder = fullfile(folderPath,ctf.folder); +end + + +return + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function folder = getfolder, + +% This does not work on linux systems (only windows) +folder = uigetdir(pwd,'locate CTF .ds folder'); + +if ~folder, + % try to get it this way + [filename, folder, filterindex] = uigetfile('*.res4', 'Pick a .res4 file'); + if ~folder, + error('invalid folder'); + end +end + +return diff --git a/ctf_head2mri.m b/ctf_head2mri.m new file mode 100644 index 0000000..8c4d1d3 --- /dev/null +++ b/ctf_head2mri.m @@ -0,0 +1,187 @@ +function MRIVertices = ctf_head2mri(HeadVertices,mri) + +% ctf_head2mri - convert a CTF head into a voxel coordinate +% +% MRIVertices = ctf_mri2head(HeadVertices,mri) +% +% This function converts CTF head coordinates into the CTF MRI voxel +% coordinates. The input 'HeadVertices' are head space locations; they are +% Nx3 coordinates in the CTF head space (see below). The 'mri' input +% is a struct returned by ctf_read_mri, which contains the fiducials +% and a transformation matrix between head and MRI voxel coordinates. +% +% CTF MRI volumes are 256^3 voxels, 1mm^3 each. The volume index has +% an origin at the left, anterior, superior voxel, such that: +% +% Sag increases from left to right (+X Right) +% Cor increases from anterior to posterior (+Y Posterior) +% Axi increases from superior to inferior (+Z Inferior) +% +% The head space coordinates are defined in relation to the MRI fiducial +% locations (nasion, left preauricular and right preauricular). The origin +% lies half way between the left and right preauricular points and the +% coordinate axes are given as: +% +% +X is through the nasion, +% +Y is left +% +Z is superior +% +% CTF head coordinate axes are othogonalized by first taking the cross +% product of the +X and +Y vectors (from the origin through the nasion and +% left preauricular, respectively) to find the +Z vector. Then, the Y axis +% is orthogonalized to the X/Z plane using the cross product and right hand +% rule. Hence, +Y can be slightly offset from the left preauricular. +% + +% $Revision: 1.1 $ $Date: 2009-01-30 03:49:27 $ + +% Copyright (C) 2004 Darren L. Weber +% +% This program is free software; you can redistribute it and/or +% modify it under the terms of the GNU General Public License +% as published by the Free Software Foundation; either version 2 +% of the License, or (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program; if not, write to the Free Software +% Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +% History: 04/2004, Darren.Weber_at_radiology.ucsf.edu +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +fprintf('in development!'); return + + +ver = '$Revision: 1.1 $'; +fprintf('CTF_HEAD2MRI [v %s]\n',ver(11:15)); tic; + +%-------------------------------------------------------------------- +% Extract the coordinate transform matrices from the mri struct. These are +% designed to be left multiplied into the vertices (I don't like this +% because it means the column arrays need to be transposed below) +%T.ctfHEAD2MRI = mri.hdr.transformMatrixHead2MRI; +%T.ctfMRI2HEAD = mri.hdr.transformMatrixMRI2Head; + +% OK, so I got fed up with trying to figure out how to use these +% bloody matrices and decided to calculate them myself, so +% that the entries would work in a way that I can understand! +[trans,rot] = calc_tranfer_matrix(mri); + + +%-------------------------------------------------------------------- +fprintf('...converting from cm to mm\n'); +MRIVertices = HeadVertices * 10; + + +%-------------------------------------------------------------------- +% Pad out the HeadVertices to Nx4 matrix + +Nvertices = size(MRIVertices,1); + +right_column = ones( Nvertices, 1 ); + +MRIVertices = [ MRIVertices right_column ]; + +%-------------------------------------------------------------------- +% Convert CTF head space coordinates into voxel indices + +MRIVertices = (-1 * MRIVertices * trans) * rot; + +MRIVertices = MRIVertices(:,1:3); + + +t = toc; fprintf('...done (%6.2f sec).\n\n',t); + +return + + + + + + + +%------------------------------------------------------- +function [trans,rot] = calc_tranfer_matrix(mri) + +% these are the translations! +%ctf.mri.hdr.headOrigin_sagittal: 130 +%ctf.mri.hdr.headOrigin_coronal: 123 +%ctf.mri.hdr.headOrigin_axial: 152 + +% This is how they are calculated from the fiducials: + +nas(1) = mri.hdr.HeadModel_Info.Nasion_Sag; +nas(2) = mri.hdr.HeadModel_Info.Nasion_Cor; +nas(3) = mri.hdr.HeadModel_Info.Nasion_Axi; +lpa(1) = mri.hdr.HeadModel_Info.LeftEar_Sag; +lpa(2) = mri.hdr.HeadModel_Info.LeftEar_Cor; +lpa(3) = mri.hdr.HeadModel_Info.LeftEar_Axi; +rpa(1) = mri.hdr.HeadModel_Info.RightEar_Sag; +rpa(2) = mri.hdr.HeadModel_Info.RightEar_Cor; +rpa(3) = mri.hdr.HeadModel_Info.RightEar_Axi; + +headOffset_Sag = ( rpa(1) - lpa(1) ) / 2; +headOrigin_Sag = lpa(1) + headOffset_Sag; + +headOffset_Cor = ( rpa(2) - lpa(2) ) / 2; +headOrigin_Cor = lpa(2) + headOffset_Cor; + +headOffset_Axi = ( rpa(3) - lpa(3) ) / 2; +headOrigin_Axi = lpa(3) + headOffset_Axi; + +headOrigin = [headOrigin_Sag headOrigin_Cor headOrigin_Axi]; + +%-------------from here to... + +% calculate voxel space vectors, in slices +voxNASvector = nas - headOrigin; +voxLPAvector = lpa - headOrigin; +voxRPAvector = rpa - headOrigin; + +% calculate head space vectors, in mm +headNASvector = -1 * [ voxNASvector(2), voxNASvector(1), voxNASvector(3) ]; +headLPAvector = -1 * [ voxLPAvector(2), voxLPAvector(1), voxLPAvector(3) ]; +headRPAvector = -1 * [ voxRPAvector(2), voxRPAvector(1), voxRPAvector(3) ]; + +%-------------here; is encapsulated in trans: + +trans = eye(3); +trans(1,1) = 0; +trans(2,1) = 1; +trans(1,2) = 1; +trans(2,2) = 0; +trans(4,1:3) = -1 * [ headOrigin(2) headOrigin(1) headOrigin(3) ]; + +%headVector = -1 * ctfVox * trans; + + +% At this point, the voxel indices are now in the head space, in +% mm; however, the head space at this point is not orthogonal + +%--------------now the head space is orthogonalized + +headNASunit = headNASvector / norm(headNASvector); +headLPAunit = headLPAvector / norm(headLPAvector); +headRPAunit = headRPAvector / norm(headRPAvector); + +headVERTEXunit = cross( headNASunit, headLPAunit ); + +% revise the LPA unit vector, so it is orthogonal to Nasion +headLPAunit = cross( headVERTEXunit, headNASunit ); + +% CHECK, these dot products = 0 +%dot( headNASunit, headLPAunit ) +%dot( headNASunit, headVERTEXunit ) +%dot( headLPAunit, headVERTEXunit ) + +% Note that the LPA/RPA moves! This has the effect of +% rotating the coordinates in the XY plane. + +rot = [ headNASunit; headLPAunit; headVERTEXunit ]; + +return diff --git a/ctf_import2sync.m b/ctf_import2sync.m new file mode 100644 index 0000000..ba43dc2 --- /dev/null +++ b/ctf_import2sync.m @@ -0,0 +1,13 @@ +ds_path='/export/data/test_oscill/disc04_DiscAud_Passive_correct-fEOG.ds' +info = ds2brainstorm(ds_path,0,2); +no_channels = info.gSetUp.no_channels; +no_trials=info.gSetUp.no_trials; +no_samples = info.gSetUp.no_samples; +sample_rate=info.gSetUp.sample_rate; +preTrigPts = info.gSetUp.preTrigPts; +imegsens = info.imegsens; +ieegsens = info.ieegsens; +Time = [-preTrigPts no_samples-preTrigPts]/sample_rate; +%F=ds2brainstorm(ds_path,0,0,irefsens,[min(Time) max(Time)],1:10,2) + [Ftmp,Channel,imegsens,ieegsens,iothersens,irefsens,grad_order_no,no_trials,filter,Time, Comment] = ... + ds2brainstorm(ds_path,0,0,[],[],1,2); diff --git a/ctf_jtfa_comp.m b/ctf_jtfa_comp.m new file mode 100644 index 0000000..c7bd435 --- /dev/null +++ b/ctf_jtfa_comp.m @@ -0,0 +1,163 @@ +% ctfcomp +% EEGLAB script for joint time-frequency analysis for MEG data +% Reads one channel at a time to minimize memory requirements +% Saves all single-channel ERSP figures including ITC +% Saves all numerical results in .mat file +% Thomas Ferree @ UCSF +% Revised 2/16/2004 + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +clear; + +% set machine: 1 = TiBoard, 2 = Glutamate/Acetylcholine/Brainmap, Corby +machine = 3; + +% set CTF parameters +ctftrials = 'all'; +%ctftrials = [1:10]; +ctftime = 'all'; + +% set JTFA parameters +winsize = 128; % time window width (->256, Scott 4/21/2004) +padratio = 4; % frequency resolution (->2?, Scott 4/21/2004) +bootalpha = 0.05; % two-tailed p-value +bootnaccu = 2000; % 200-20000 + +% user-defined paths +if machine == 1 + pathdata = '/Users/tferree/Documents/Data/Attention/HighN/'; + pathtemp = '/Users/tferree/Documents/Research/Attention/HighN/Temp/'; +end +if machine >= 2 + addpath /home/tferree/EEGLAB42/; + addpath /home/tferree/Attention/HighN/ctf2eeglab/; + pathdata = '/home/cdale/HighN/'; +end +if machine == 2 + pathtemp = '/home/tferree/Attention/HighN/Temp/'; +elseif machine == 3 + pathtemp = '/home/cdale/Temp/'; +end + +% toggle saving eeglab .set, 0 = no, 1 = yes +saveSet = 0; + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%subject = 'HM' +%date = '20040126'; + +%subject = 'GN' +%date = '20040109'; + +subject = 'CJ' +date = '20040116'; + +% loop on cues +for icue = 1:2 + + % define cue condition + if icue == 1 + cue = 'CueL' + else icue == 2 + cue = 'CueR' + end + + % loop on channels + for ichan = 1:275 + + % initialize data vector + datavector = []; + ntrials = 0; + + % loop over four targets with correct response + one for concatination + for itarget = 1:4 + + % define target condition + if itarget == 1 + target = 'InvNT' + elseif itarget == 2 + target = 'InvTarg' + elseif itarget == 3 + target = 'ValNT' + elseif itarget == 4 + target = 'ValTarg' + else + error('Invalid index for target condition.') + end + + % create output folders + + if ~exist([pathtemp 'ERSP_' subject(1:2) '_' cue]) + mkdir(pathtemp,['ERSP_' subject(1:2) '_' cue]); + end + +% if ~exist([pathtemp subject(1:2) '_' cue filesep 'ERP']) +% mkdir(pathtemp, [subject(1:2) '_' cue filesep 'ERP']); +% end +% +% if ~exist([pathtemp subject(1:2) '_' cue filesep 'JTF']) +% mkdir(pathtemp, [subject(1:2) '_' cue filesep 'JTF']); +% end + + % load CTF data + ctffolder = [pathdata subject '_epoch' filesep 'processed' filesep subject '_DNL_' date '_HiN_' cue target '-fEOG.ds']; + ctf = ctf_read_res4(ctffolder); + ctfchannels = ctf.sensor.index.meg; + + ctf = ctf_read(ctffolder,ctfchannels(ichan),ctftime,ctftrials); + ctf2eeglab; + + % concatinate trials over target conditions + ntrials = ntrials + EEG.trials; + for trial = 1:EEG.trials + datavector = [datavector EEG.data(1,:,trial)]; + end + + end % end loop over targets + + % scale data upward to order unity + datavector = datavector * 10^12; + + % channel string for saving figures to files with sequential file names + if ichan < 10 + chanstring = ['00' num2str(ichan)]; + end + if ichan > 9 & ichan < 100 + chanstring = ['0' num2str(ichan)]; + end + if ichan > 99 + chanstring = num2str(ichan); + end + +% % make single-channel ERP image +% h1 = figure(1000+ichan); +% avewidth = 1; +% decimate = 1; +% pop_erpimage(EEG,1, [ichan],[],['Channel ' num2str(ichan)],avewidth,decimate,{},[],'' ,'erp','cbar','yerplabel','pT'); +% saveas(h1,[pathtemp subject '_' cue filesep 'Ch' chanstring '.jpg'],'jpg'); +% close(h1); + + % make single-channel JTF image + h2 = figure(2000+ichan); + %[ersp,itc,powbase,times,freqs,erspboot,itcboot] = pop_timef( EEG, 1, ichan, [-1200 2000], 0 ,'type', 'phasecoher','baseline',-300, 'title',['Channel ' num2str(ichan)],'padratio', padratio, 'plotphase', 'off','winsize',winsize,'alpha',bootalpha,'naccu',bootnaccu); + [ersp,itc,powbase,times,freqs,erspboot,itcboot] = timef(datavector, EEG.pnts, [-1200 2000], EEG.srate, 0,'type', 'phasecoher','baseline',-300, 'title',['Channel ' num2str(ichan)],'padratio', padratio, 'plotphase', 'off','winsize',winsize,'alpha',bootalpha,'naccu',bootnaccu); + saveas(h2,[pathtemp 'ERSP_' subject '_' cue filesep 'Ch' chanstring '.jpg'],'jpg'); + close(h2); + + % store all timef results in 'all' arrays, referring to all channels + allersp(:,:,ichan) = ersp; + allitc(:,:,ichan) = itc; + allpowbase(:,:,ichan) = powbase; + alltimes(:,:,ichan) = times; + allfreqs(:,:,ichan) = freqs; + allerspboot(:,:,ichan) = erspboot; + allitcboot(:,:,ichan) = itcboot; + + end % end loop over channels + + folderpath = [pathtemp 'ERSP_' subject '_' cue '.mat']; + save(folderpath,'allersp','allitc','allpowbase','alltimes','allfreqs','allerspboot','allitcboot','ntrials'); + +end % end loop over cues diff --git a/ctf_jtfa_script.m b/ctf_jtfa_script.m new file mode 100644 index 0000000..36a9818 --- /dev/null +++ b/ctf_jtfa_script.m @@ -0,0 +1,100 @@ +% ctfcomp +% EEGLAB script for joint time-frequency analysis for MEG data +% Saves single-channel ERP and JTF +% Saves all outputs in .mat file +% Thomas Ferree @ UCSF +% Revised 1/28/2004 + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +clear; + + + + +% toggle saving eeglab .set, 0 = no, 1 = yes +saveSet = 0; + +% set machine: 1 = TiBoard, 2 = Glutamate/Acetylcholine/Brainmap +machine = 2 ; + +% user-defined paths +if machine == 1 + pathdata = '/Users/tferree/Documents/Data/Attention/HighN/'; + pathersp = '/Users/tferree/Documents/Research/Attention/Temp/'; + pathfigs = '/Users/tferree/Documents/Research/Attention/Temp/'; +else + addpath /netopt/lib/matlab/eeglab/ -end; + addpath /home/tferree/Attention/HighN/ctf2eeglab/ -end; + pathdata = '/home/cdale/HighN/HM_epoch/processed/'; + pathersp = '/home/tferree/Attention/HighN/Temp/'; + pathfigs = '/home/tferree/Attention/HighN/Temp/'; +end + +% call Darren's scripts +ctffolder = [pathdata 'HM_DNL_20040126_HiN_CueLValNT-fEOG.ds']; +ctfchannels = 'meg'; +ctftime = 'all'; +%ctftrials = [1:5:100]; +ctftrials = 'all'; +ctf = ctf_read(ctffolder,ctfchannels,ctftime,ctftrials); +ctf2eeglab; + +% define JTFA parameters +winsize = 128; +padratio = 2; % frequency resolution +bootalpha = 0.05; % already two-tailed +bootnaccu = 200; % 200-20000 + +% scale data upward to order unity +EEG.data = EEG.data * 10^12; + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +% loop on channels +Nchan = EEG.nbchan; +for ichan = 1:Nchan + + % channel string for saving figures to files with sequential file names + if ichan < 10 + chanstring = ['00' num2str(ichan)]; + end + if ichan > 9 & chan < 100 + chanstring = ['0' num2str(ichan)]; + end + if ichan > 99 + chanstring = num2str(ichan); + end + + % make single-channel ERP image + h1 = figure(1000+ichan); + avewidth = 1; + decimate = 1; + pop_erpimage(EEG,1, [ichan],[],['Channel ' num2str(ichan)],avewidth,decimate,{},[],'' ,'erp','cbar'); + saveas(h1,[pathfigs 'ERP_Ch' chanstring '.jpg'],'jpg'); + close(h1); + + % make single-channel JTF image + h2 = figure(2000+ichan); + [ersp,itc,powbase,times,freqs,erspboot,itcboot]=pop_timef( EEG, 1, ichan, [-1200 2000], 0 ,'type', 'phasecoher', 'title',['Channel ' num2str(ichan)],'padratio', padratio, 'plotphase', 'off','winsize',winsize,'alpha',bootalpha,'naccu',bootnaccu,'baseline',-1200); + saveas(h2,[pathfigs 'JTF_Ch' chanstring '.jpg'],'jpg'); + close(h2); + + % store all timef results in 'all' array, referring to all channels + allersp(:,:,ichan) = ersp; + allitc(:,:,ichan) = itc; + allpowbase(:,:,ichan) = powbase; + alltimes(:,:,ichan) = times; + allfreqs(:,:,ichan) = freqs; + allerspboot(:,:,ichan) = erspboot; + allitcboot(:,:,ichan) = itcboot; + +end % end loop over channels + +% save results to file - avoiding overwrite with 'old' designation +%if exist([pathersp 'ERSP.mat']) +% mv [pathersp 'ERSP.mat'] [pathersp 'ERSP_old.mat']; +%end +folderpath = [pathersp 'ERSP.mat']; +save(folderpath,'allersp','allitc','allpowbase','alltimes','allfreqs','allerspboot','allitcboot'); + diff --git a/ctf_jtfa_topo.m b/ctf_jtfa_topo.m new file mode 100644 index 0000000..8eb5f82 --- /dev/null +++ b/ctf_jtfa_topo.m @@ -0,0 +1,78 @@ +% ctftopo +% EEGLAB script for plotting topo maps of CTF data +% Thomas Ferree @ UCSF +% Revised 2/17/2004 + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +clear; + +% toggle saving eeglab .set, 0 = no, 1 = yes +saveSet = 0; + +% set machine: 1 = TiBoard, 2 = Glutamate/Acetylcholine/Brainmap +machine = 2; + +% set input and output paths +if machine == 1 + pathdata = '/Users/tferree/Documents/Data/Attention/HighN/'; + pathersp = '/Users/tferree/Documents/Research/Attention/HighN/Numerical/'; + pathtemp = '/Users/tferree/Documents/Research/Attention/HighN/Temp/'; +else + addpath /home/tferree/EEGLAB42/; + addpath /home/tferree/Attention/HighN/ctf2eeglab/; + pathdata = '/home/cdale/HighN/'; + pathersp = '/home/tferree/Attention/HighN/Numerical/'; + pathtemp = '/home/tferree/Attention/HighN/Temp/'; +end + +% set subject and conditions + +%subject = 'HM' +%date = '20040126'; + +%subject = 'GN' +%date = '20040109'; + +subject = 'CJ' +date = '20040116'; + +cue = 'CueL' + +% load ERSP results +load([pathersp 'ERSP_' subject '_' cue '.mat']); + +% call Darren's scripts +%ctffolder = [pathdata subject '_DNL_' date '_HiN_' cue 'InvNT' '-fEOG.ds']; +ctffolder = [pathdata subject '_epoch' filesep 'processed' filesep subject '_DNL_' date '_HiN_' cue 'InvNT' '-fEOG.ds']; + +ctfchannels = 'meg'; +ctftime = 'all'; +ctftrials = [1]; +ctf = ctf_read(ctffolder,ctfchannels,ctftime,ctftrials); +ctf2eeglab; + +% make topo maps +freqs = allfreqs(1,:,1); +times = alltimes(1,:,1); +maxcolor = 5; + +for plottime = 0:100:1800 + + if plottime <= 9 + timestring = ['000' num2str(plottime)]; + elseif plottime >= 10 & plottime <= 99 + timestring = ['00' num2str(plottime)]; + elseif plottime >= 100 & plottime < 1000 + timestring = ['0' num2str(plottime)]; + else + timestring = num2str(plottime); + end + + timefreqlist = [plottime 5; plottime 7; plottime 9; plottime 11; plottime 13; plottime 15; plottime 17]; + h3 = figure; + tftopo(allersp,times,freqs,'mode','ave','signifs', allerspboot,'limits',[min(times) max(times) 1 20 -maxcolor, maxcolor],'vert',[0 1000],'chanlocs',EEG.chanlocs,'timefreqs',timefreqlist,'electrodes','off','maplimits',[-maxcolor,maxcolor]); + saveas(h3,[pathtemp 'Topo_' subject '_' cue '_' timestring 'msec.jpg'],'jpg'); + close(h3); + +end diff --git a/ctf_mri2avw.m b/ctf_mri2avw.m new file mode 100644 index 0000000..8134e0b --- /dev/null +++ b/ctf_mri2avw.m @@ -0,0 +1,82 @@ +function avw = ctf_mri2avw(mri) + +% avw = ctf_mri2avw(mri) +% +% The purpose of this function is to convert a CTF .mri volume into +% an Analyze volume. The returned avw struct can be saved using avw_write. +% +% This function depends on the avw* functions availabe in the mri_toolbox +% at http://eeg.sf.net/. +% +% <>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> % +% < > % +% < DISCLAIMER: > % +% < > % +% < THIS PROGRAM IS INTENDED FOR RESEARCH PURPOSES ONLY. > % +% < THIS PROGRAM IS IN NO WAY INTENDED FOR CLINICAL OR > % +% < OFFICIAL USE. > % +% < > % +% <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<> % +% + +% $Revision: 1.1 $ $Date: 2009-01-30 03:49:27 $ + +% Copyright (C) 2004 Darren L. Weber +% +% This program is free software; you can redistribute it and/or +% modify it under the terms of the GNU General Public License +% as published by the Free Software Foundation; either version 2 +% of the License, or (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program; if not, write to the Free Software +% Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +% History: 04/2004, Darren.Weber_at_radiology.ucsf.edu +% - adapted from an appendex to CTF document +% MRIConverter.pdf, which is copied at the end of this +% function. +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +avw = avw_hdr_make; + +avw.fileprefix = strrep(mri.file,'.mri',''); + +ver = '[$Revision: 1.1 $]'; +fprintf('\nCTF_MRI2AVW [v%s]\n',ver(12:16)); tic; + +% CTF .mri files are always 256x256x256 voxels, 1mm^3 +avw.hdr.dime.dim(2) = 256; +avw.hdr.dime.dim(3) = 256; +avw.hdr.dime.dim(4) = 256; +avw.hdr.dime.pixdim(2) = 1; +avw.hdr.dime.pixdim(3) = 1; +avw.hdr.dime.pixdim(4) = 1; + +% mri.hdr.dataSize = 1 or 2 (bytes), 8 or 16 bits +if mri.hdr.dataSize == 1, + avw.hdr.dime.bitpix = 8; + avw.hdr.dime.datatype = 2; +else + avw.hdr.dime.bitpix = 16; + avw.hdr.dime.datatype = 4; +end + +% This next step should always work correctly, given that avw structs +% are always axial unflipped in the matlab workspace; the axial +% unflipped orientation is +% (+X left, +Y anterior, +Z superior); the ctf orientation is +% (+X right, +Y posterior, +Z inferior), the complete opposite. +temp = flipdim(mri.img,1); +temp = flipdim(temp,2); +temp = flipdim(temp,3); +avw.img = temp; + +t=toc; fprintf('...done (%5.2f sec).\n\n',t); + +return diff --git a/ctf_mri2brainstorm.m b/ctf_mri2brainstorm.m new file mode 100644 index 0000000..8f66157 --- /dev/null +++ b/ctf_mri2brainstorm.m @@ -0,0 +1,109 @@ +function [Comment, Cube, PCS, Segment, Voxsize] = ctf_mri2brainstorm(mri) + +% ctf_mri2brainstorm - create subjectimage variables from ctf .mri file +% +% [Comment, Cube, PCS, Segment, Voxsize] = ctf_mri2brainstorm(mri) +% +% The purpose of this function is to convert a CTF .mri volume into +% brainstorm subjectimage variables. The returned variables can be saved +% into *_subjectimage.mat using the matlab save command. +% +% The mri struct input for this function is returned by ctf_read_mri. +% +% <>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> % +% < > % +% < DISCLAIMER: > % +% < > % +% < THIS PROGRAM IS INTENDED FOR RESEARCH PURPOSES ONLY. > % +% < THIS PROGRAM IS IN NO WAY INTENDED FOR CLINICAL OR > % +% < OFFICIAL USE. > % +% < > % +% <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<> % +% + +% $Revision: 1.1 $ $Date: 2009-01-30 03:49:27 $ + +% Copyright (C) 2004 Darren L. Weber +% +% This program is free software; you can redistribute it and/or +% modify it under the terms of the GNU General Public License +% as published by the Free Software Foundation; either version 2 +% of the License, or (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program; if not, write to the Free Software +% Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +% History: 05/2004, Darren.Weber_at_radiology.ucsf.edu +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +ver = '[$Revision: 1.1 $]'; +fprintf('\nCTF_MRI2BRAINSTORM [v%s]\n',ver(12:16)); tic; + + +Comment = 'CTF'; + +% CTF .mri files are always 256x256x256 voxels, 1mm^3 +Voxsize = [1 1 1]; + +% Initialize the Segment variable; As of 05/2004, the codes for this field +% are not clear to me. They are defined in David Shattuck's +% BrainSuite MRI processing software. +Segment = []; + +% the ctf mri.img orientation is +% +X right +% +Y posterior +% +Z inferior + +% the brainstorm Cube orientation is +% +X right +% +Y anterior +% +Z superior + +temp = mri.img; +temp = flipdim(temp,2); +Cube = flipdim(temp,3); + +% ----- +% Patient Coordinate System + +PCS.Comment = 'CTF'; + +PCS.R = zeros(3,3); % not clear how to get this +PCS.t = zeros(3,1); % not clear how to get this + +PCS.PCSFiducial = zeros(3,4); % not clear how to get this + +PCS.CubeFiducial = zeros(3,4); +PCS.CubeFiducial(1,1) = mri.hdr.HeadModel_Info.Nasion_Sag; +PCS.CubeFiducial(2,1) = 256 - mri.hdr.HeadModel_Info.Nasion_Cor; +PCS.CubeFiducial(3,1) = 256 - mri.hdr.HeadModel_Info.Nasion_Axi; + +PCS.CubeFiducial(1,2) = mri.hdr.HeadModel_Info.LeftEar_Sag; +PCS.CubeFiducial(2,2) = 256 - mri.hdr.HeadModel_Info.LeftEar_Cor; +PCS.CubeFiducial(3,2) = 256 - mri.hdr.HeadModel_Info.LeftEar_Axi; + +PCS.CubeFiducial(1,3) = mri.hdr.HeadModel_Info.RightEar_Sag; +PCS.CubeFiducial(2,3) = 256 - mri.hdr.HeadModel_Info.RightEar_Cor; +PCS.CubeFiducial(3,3) = 256 - mri.hdr.HeadModel_Info.RightEar_Axi; + +% set the origin at half way between the left and right ears +PCS.CubeFiducial(1,4) = PCS.CubeFiducial(1,3) - PCS.CubeFiducial(1,2); +PCS.CubeFiducial(2,4) = PCS.CubeFiducial(2,3) - PCS.CubeFiducial(2,2); +PCS.CubeFiducial(3,4) = PCS.CubeFiducial(3,2) + (PCS.CubeFiducial(3,3) - PCS.CubeFiducial(3,2)); + +PCS.FiducialName = {'NAS' 'LPA' 'RPA' 'Origin'}; + +PCS.PERM = [1 2 3]; % not sure what this is +PCS.FLP = [1 1 0]; % not sure what this is + +t=toc; fprintf('...done (%5.2f sec).\n\n',t); + +return diff --git a/ctf_mri2head.m b/ctf_mri2head.m new file mode 100644 index 0000000..fdcfdb8 --- /dev/null +++ b/ctf_mri2head.m @@ -0,0 +1,182 @@ +function HeadVertices = ctf_mri2head(MRIVertices,mri) + +% ctf_mri2head - convert a CTF voxel into a head coordinate +% +% HeadVertices = ctf_mri2head(MRIVertices,mri) +% +% This function converts CTF MRI voxel coordinates into the CTF head +% coordinates. The input 'MRIVertices' are MRI voxel locations; they are +% Nx3 voxel index (or slice) coordinates in the CTF MRI volume. The 'mri' +% input is a struct returned by ctf_read_mri, which contains the fiducials +% and a transformation matrix from MRI voxel coordinates into the head +% space coordinates. CTF MRI volumes are 256^3 voxels, 1mm^3 each. The +% volume index has an origin at the left, anterior, superior voxel, such +% that: +% +% Sag increases from left to right (+X Right) +% Cor increases from anterior to posterior (+Y Posterior) +% Axi increases from superior to inferior (+Z Inferior) +% +% The head space coordinates are defined in relation to the MRI fiducial +% locations (nasion, left preauricular and right preauricular). The origin +% lies half way between the left and right preauricular points and the +% coordinate axes are given as: +% +% +X is through the nasion, +% +Y is left +% +Z is superior +% +% CTF head coordinate axes are othogonalized by first taking the cross +% product of the +X and +Y vectors (from the origin through the nasion and +% left preauricular, respectively) to find the +Z vector. Then, the Y axis +% is orthogonalized to the X/Z plane using the cross product and right hand +% rule. Hence, +Y can be slightly offset from the left preauricular. +% + +% $Revision: 1.1 $ $Date: 2009-01-30 03:49:27 $ + +% Copyright (C) 2004 Darren L. Weber +% +% This program is free software; you can redistribute it and/or +% modify it under the terms of the GNU General Public License +% as published by the Free Software Foundation; either version 2 +% of the License, or (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program; if not, write to the Free Software +% Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +% History: 02/2004, Darren.Weber_at_radiology.ucsf.edu +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +ver = '$Revision: 1.1 $'; +fprintf('CTF_MRI2HEAD [v %s]\n',ver(11:15)); tic; + +%-------------------------------------------------------------------- +% Extract the coordinate transform matrices from the mri struct. These are +% designed to be left multiplied into the vertices (I don't like this +% because it means the column arrays need to be transposed below, but +% that's how it is!) +%T.ctfHEAD2MRI = mri.hdr.transformMatrixHead2MRI; +%T.ctfMRI2HEAD = mri.hdr.transformMatrixMRI2Head; + +% OK, so I got fed up with trying to figure out how to use these +% bloody matrices and decided to calculate them myself, so +% that the entries would work in a way that I can understand! +[trans,rot] = calc_tranfer_matrix(mri); + + +%-------------------------------------------------------------------- +% Pad out the MRIVertices to Nx4 matrix + +Nvertices = size(MRIVertices,1); + +right_column = ones( Nvertices, 1 ); + +MRIVertices = [ MRIVertices right_column ]; + +%-------------------------------------------------------------------- +% Convert CTF voxel indices into CTF head space coordinates + +HeadVertices = (-1 * MRIVertices * trans) * inv(rot); + +fprintf('...converting from mm to cm\n'); +HeadVertices = HeadVertices(:,1:3) / 10; + + +t = toc; fprintf('...done (%6.2f sec).\n\n',t); + +return + + + + + + + +%------------------------------------------------------- +function [trans,rot] = calc_tranfer_matrix(mri) + +% these are the translations! +%ctf.mri.hdr.headOrigin_sagittal: 130 +%ctf.mri.hdr.headOrigin_coronal: 123 +%ctf.mri.hdr.headOrigin_axial: 152 + +% This is how they are calculated from the fiducials: + +nas(1) = mri.hdr.HeadModel_Info.Nasion_Sag; +nas(2) = mri.hdr.HeadModel_Info.Nasion_Cor; +nas(3) = mri.hdr.HeadModel_Info.Nasion_Axi; +lpa(1) = mri.hdr.HeadModel_Info.LeftEar_Sag; +lpa(2) = mri.hdr.HeadModel_Info.LeftEar_Cor; +lpa(3) = mri.hdr.HeadModel_Info.LeftEar_Axi; +rpa(1) = mri.hdr.HeadModel_Info.RightEar_Sag; +rpa(2) = mri.hdr.HeadModel_Info.RightEar_Cor; +rpa(3) = mri.hdr.HeadModel_Info.RightEar_Axi; + +headOffset_Sag = ( rpa(1) - lpa(1) ) / 2; +headOrigin_Sag = lpa(1) + headOffset_Sag; + +headOffset_Cor = ( rpa(2) - lpa(2) ) / 2; +headOrigin_Cor = lpa(2) + headOffset_Cor; + +headOffset_Axi = ( rpa(3) - lpa(3) ) / 2; +headOrigin_Axi = lpa(3) + headOffset_Axi; + +headOrigin = [headOrigin_Sag headOrigin_Cor headOrigin_Axi]; + +%-------------from here to... + +% calculate voxel space vectors, in slices +voxNASvector = nas - headOrigin; +voxLPAvector = lpa - headOrigin; +voxRPAvector = rpa - headOrigin; + +% calculate head space vectors, in mm +headNASvector = -1 * [ voxNASvector(2), voxNASvector(1), voxNASvector(3) ]; +headLPAvector = -1 * [ voxLPAvector(2), voxLPAvector(1), voxLPAvector(3) ]; +headRPAvector = -1 * [ voxRPAvector(2), voxRPAvector(1), voxRPAvector(3) ]; + +%-------------here; is encapsulated in trans: + +trans = eye(3); +trans(1,1) = 0; +trans(2,1) = 1; +trans(1,2) = 1; +trans(2,2) = 0; +trans(4,1:3) = -1 * [ headOrigin(2) headOrigin(1) headOrigin(3) ]; + +%headVector = -1 * ctfVox * trans; + + +% At this point, the voxel indices are now in the head space, in +% mm; however, the head space at this point is not orthogonal + +%--------------now the head space is orthogonalized + +headNASunit = headNASvector / norm(headNASvector); +headLPAunit = headLPAvector / norm(headLPAvector); +headRPAunit = headRPAvector / norm(headRPAvector); + +headVERTEXunit = cross( headNASunit, headLPAunit ); + +% revise the LPA unit vector, so it is orthogonal to Nasion +headLPAunit = cross( headVERTEXunit, headNASunit ); + +% these dot products = 0 +%dot( headNASunit, headLPAunit ) +%dot( headNASunit, headVERTEXunit ) +%dot( headLPAunit, headVERTEXunit ) + +% Note that the LPA/RPA moves! This has the effect of +% rotating the coordinates in the XY plane. + +rot = [ headNASunit; headLPAunit; headVERTEXunit ]; + +return diff --git a/ctf_mri_make.m b/ctf_mri_make.m new file mode 100644 index 0000000..8962c9c --- /dev/null +++ b/ctf_mri_make.m @@ -0,0 +1,197 @@ +function mri = ctf_mri_make + +% ctf_mri_make - create a CTF mri struct with zero image +% +% mri = ctf_mri_make +% +% mri is a data struct similar to those returned from ctf_read_mri, +% although this one returns a zero matrix. +% +% see also: ctf_read_mri, ctf_write_mri +% +% <>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> % +% < > % +% < DISCLAIMER: > % +% < > % +% < THIS PROGRAM IS INTENDED FOR RESEARCH PURPOSES ONLY. > % +% < THIS PROGRAM IS IN NO WAY INTENDED FOR CLINICAL OR > % +% < OFFICIAL USE. > % +% < > % +% <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<> % +% + + + +% $Revision: 1.1 $ $Date: 2009-01-30 03:49:27 $ + +% Copyright (C) 2004 Darren L. Weber +% +% This program is free software; you can redistribute it and/or +% modify it under the terms of the GNU General Public License +% as published by the Free Software Foundation; either version 2 +% of the License, or (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program; if not, write to the Free Software +% Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +% History: 08/2003, Darren.Weber_at_radiology.ucsf.edu +% - adapted from an appendex to CTF document +% MRIConverter.pdf, which is copied at the end of this +% function. +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +ver = '[$Revision: 1.1 $]'; +fprintf('\nCTF_MRI_MAKE [v%s]\n',ver(12:16)); tic; + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% create the header +fprintf('...creating header\n'); +mri.hdr = Version_2_Header_make; + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% ensure the data is 16 bits (it can be 8 or 16) +mri.hdr.dataSize = 2; + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% create a zero image matrix, CTF mri files are always 256 x 256 x 256 +fprintf('...creating zero image\n'); + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% imageOrientation, 0 = left on left, 1 = left on right +mri.hdr.imageOrientation = 0; +fprintf('...creating sagittal slices in neurological orientation (left is on the left)\n'); +fprintf('...+X left to right, +Y anterior to posterior, +Z superior to inferior\n'); + + +mri.img = zeros(256,256,256); + +t=toc; fprintf('...done (%5.2f sec).\n\n',t); + +return + + + + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function Version_2_Header = Version_2_Header_make, + +Version_2_Header.identifierString = 'CTF_MRI_FORMAT VER 2.2 '; + + +Version_2_Header.imageSize = 256; % always = 256 +Version_2_Header.dataSize = 2; % 1 or 2 (bytes), 8 or 16 bits +Version_2_Header.clippingRange = 65536; % max. integer value of data +Version_2_Header.imageOrientation = 1; % eg., 0 = left on left, 1 = left on right + +% voxel dimensions in mm +Version_2_Header.mmPerPixel_sagittal = 1.0; +Version_2_Header.mmPerPixel_coronal = 1.0; +Version_2_Header.mmPerPixel_axial = 1.0; + +Version_2_Header.HeadModel_Info = headModel_make; % defined below... +Version_2_Header.Image_Info = imageInfo_make; % defined below... + +% voxel location of head origin +Version_2_Header.headOrigin_sagittal = 128; +Version_2_Header.headOrigin_coronal = 128; +Version_2_Header.headOrigin_axial = 128; + +% euler angles to align MR to head coordinate system (angles in degrees!) +% 1. rotate in coronal plane by this angle +% 2. rotate in sagittal plane by this angle +% 3. rotate in axial plane by this angle +Version_2_Header.rotate_coronal = 0; +Version_2_Header.rotate_sagittal = 0; +Version_2_Header.rotate_axial = 0; + +Version_2_Header.orthogonalFlag = 0; % if set then image is orthogonal +Version_2_Header.interpolatedFlag = 0; % if set than image was interpolated + +% original spacing between slices before interpolation to CTF format +Version_2_Header.originalSliceThickness = 0; + +% transformation matrix head->MRI [column][row] +Version_2_Header.transformMatrix = eye(4); + +return + + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function HeadModel_Info = headModel_make, + +% this function is called from Version_2_Header_make + +% fid. point coordinate (in voxels) +HeadModel_Info.Nasion_Sag = 0; % nasion - sagittal +HeadModel_Info.Nasion_Cor = 0; % nasion - coronal +HeadModel_Info.Nasion_Axi = 0; % nasion - axial +HeadModel_Info.LeftEar_Sag = 0; % left ear - sagittal +HeadModel_Info.LeftEar_Cor = 0; % left ear - coronal +HeadModel_Info.LeftEar_Axi = 0; % left ear - axial +HeadModel_Info.RightEar_Sag = 0; % right ear - sagittal +HeadModel_Info.RightEar_Cor = 0; % right ear - coronal +HeadModel_Info.RightEar_Axi = 0; % right ear - axial + +% fid. point coordinate (in voxels) +% HeadModel_Info.Nasion_Sag = 128; % nasion - sagittal +% HeadModel_Info.Nasion_Cor = 64; % nasion - coronal +% HeadModel_Info.Nasion_Axi = 128; % nasion - axial +% HeadModel_Info.LeftEar_Sag = 64; % left ear - sagittal +% HeadModel_Info.LeftEar_Cor = 128; % left ear - coronal +% HeadModel_Info.LeftEar_Axi = 128; % left ear - axial +% HeadModel_Info.RightEar_Sag = 192; % right ear - sagittal +% HeadModel_Info.RightEar_Cor = 128; % right ear - coronal +% HeadModel_Info.RightEar_Axi = 128; % right ear - axial + +% default sphere origin +HeadModel_Info.defaultSphereX = 0.0; % sphere origin x coordinate ( in mm ) +HeadModel_Info.defaultSphereY = 0.0; % sphere origin y coordinate ( in mm ) +HeadModel_Info.defaultSphereZ = 0.0; % sphere origin z coordinate ( in mm ) +HeadModel_Info.defaultSphereRadius = 75.0; % default sphere radius ( in mm ) + +return + + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function Image_Info = imageInfo_make, + +% this function is called from Version_2_Header_make + +Image_Info.modality = 0; % 0 = MRI, 1 = CT, 2 = PET, 3 = SPECT, 4 = OTHER +Image_Info.manufacturerName = char(repmat(double(' '),1,64)); +Image_Info.instituteName = char(repmat(double(' '),1,64)); +Image_Info.patientID = char(repmat(double(' '),1,32)); +Image_Info.dateAndTime = char(repmat(double(' '),1,32)); +Image_Info.scanType = char(repmat(double(' '),1,32)); +Image_Info.contrastAgent = char(repmat(double(' '),1,32)); +Image_Info.imagedNucleus = char(repmat(double(' '),1,32)); + +Image_Info.Frequency = 0; +Image_Info.FieldStrength = 0; +Image_Info.EchoTime = 0; +Image_Info.RepetitionTime = 0; +Image_Info.InversionTime = 0; +Image_Info.FlipAngle = 0; +Image_Info.NoExcitations = 0; +Image_Info.NoAcquisitions = 0; + +Image_Info.commentString = char(repmat(double(' '),1,256)); +Image_Info.forFutureUse = char(repmat(double(' '),1,64)); + +return diff --git a/ctf_plot.m b/ctf_plot.m new file mode 100644 index 0000000..f8ae4e9 --- /dev/null +++ b/ctf_plot.m @@ -0,0 +1,188 @@ +function ctf_plot(ctf,CHAN,TIME,TRIALS,Xhair) + +% ctf_plot - plot ctf.data +% +% ctf_plot(ctf,CHAN,TIME,TRIALS,Xhair) +% +% CHAN - see ctf_channel_select for options +% TIME - see ctf_read for options (given in msec) +% TRIALS - select 1 trial to plot (the default is trial = 1) +% +% Xhair - 1 to use the crosshair GUI features (default), 0 otherwise +% +% <>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +% < > +% < DISCLAIMER: > +% < > +% < THIS PROGRAM IS INTENDED FOR RESEARCH PURPOSES ONLY. > +% < THIS PROGRAM IS IN NO WAY INTENDED FOR CLINICAL OR > +% < OFFICIAL USE. > +% < > +% <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<> +% + +% $Revision: 1.1 $ $Date: 2009-01-30 03:49:27 $ + +% Copyright (C) 2004 Darren L. Weber +% +% This program is free software; you can redistribute it and/or +% modify it under the terms of the GNU General Public License +% as published by the Free Software Foundation; either version 2 +% of the License, or (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program; if not, write to the Free Software +% Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +% Modified: 02/2004, Darren.Weber_at_radiology.ucsf.edu +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + + +if ~exist('CHAN','var'), CHAN = 'all'; end +if ~exist('TIME','var'), TIME = 'all'; end +if ~exist('TRIALS','var'), TRIALS = 1; end +if ~exist('Xhair','var'), Xhair = 1; end + + +if isempty(CHAN), CHAN = 'all'; end +if isempty(TIME), TIME = 'all'; end +if isempty(TRIALS), TRIALS = 1; end +if isempty(Xhair), Xhair = 1; end + + +% This function calls ctf_channel_select +[CHAN,type] = ctf_channel_select(ctf,CHAN); + +switch num2str(TIME), + case 'all', + TIME = ctf.setup.time_msec; + TIME_index = 1:ctf.setup.number_samples; +otherwise + fprintf('...sorry, time restrictions not implemented correctly (03/2004)\n'); + TIME = ctf.setup.time_msec; + TIME_index = 1:ctf.setup.number_samples; + + + % % assume the input is a range of times in sec + % % check the range + % if TIME(1) > ctf.setup.time_msec(1), + % fprintf('...setting TIME(1) = ctf.setup.time_msec(1)\n'); + % TIME(1) = ctf.setup.time_msec(1); + % end + % if TIME(end) > ctf.setup.time_msec(end), + % fprintf('...setting TIME(end) = ctf.setup.time_msec(end)\n'); + % TIME(end) = ctf.setup.time_msec(end); + % end + % % now find the nearest indices into the samples matrix + % TIME_index = interp1(ctf.setup.time_msec,1:ctf.setup.number_samples,TIME,'nearest'); + % % now ensure that the TIME array is consistent with ctf.setup.time_sec + % TIME = ctf.setup.time_msec(TIME_index); +end +TIME = sort(TIME); + + +switch num2str(TRIALS), + case 'all', + TRIALS = 1:ctf.setup.number_trials; + otherwise + % assume the input is an array of trials +end +TRIALS = unique(sort(TRIALS)); + +% check the input data for more than 1 trial +trials = size(ctf.data,3); +if trials > 1, + fprintf('...plotting trial %d of %d trials in ctf.data\n',TRIALS,trials); + data = ctf.data(:,:,TRIALS); +else + data = ctf.data; +end + + +% now plot the data +switch type, + + case 'all', + + if isempty(ctf.sensor.index.meg_sens), + fprintf('...no meg sensors\n'); + else + figure('Name','MEG sensors'); + MEGCHAN = ctf_channel_select(ctf,'meg'); + plot(ctf.setup.time_msec(TIME_index),data(TIME_index,MEGCHAN)) + axis tight + if exist('crosshair') & Xhair, + crosshair; + end + end + + if isempty(ctf.sensor.index.eeg_sens), + fprintf('...no eeg sensors\n'); + else + figure('Name','EEG sensors'); + EEGCHAN = ctf_channel_select(ctf,'eeg'); + plot(ctf.setup.time_msec(TIME_index),data(TIME_index,EEGCHAN)) + axis tight + end + + + case 'meg', + + if isempty(CHAN), + fprintf('...no meg sensors\n'); + else + figure('Name','MEG sensors'); + plot(ctf.setup.time_msec(TIME_index),data(TIME_index,CHAN)) + axis tight + end + + case 'eeg', + + if isempty(CHAN), + fprintf('...no eeg sensors\n'); + else + figure('Name','EEG sensors'); + plot(ctf.setup.time_msec(TIME_index),data(TIME_index,CHAN)) + axis tight + end + + case 'ref', + + if isempty(CHAN), + fprintf('...no ref sensors\n'); + else + figure('Name','MEG REF sensors'); + plot(ctf.setup.time_msec(TIME_index),data(TIME_index,CHAN)) + axis tight + end + + case 'others', + + if isempty(CHAN), + fprintf('...no other sensors\n'); + else + figure('Name','Other sensors'); + plot(ctf.setup.time_msec(TIME_index),data(TIME_index,CHAN)) + axis tight + end + + otherwise + + figure; + plot(ctf.setup.time_msec(TIME_index),data(TIME_index,CHAN)) + axis tight + +end + +if exist('crosshair') & Xhair, + crosshair; +end + +return diff --git a/ctf_print_setup.m b/ctf_print_setup.m new file mode 100644 index 0000000..2f8c204 --- /dev/null +++ b/ctf_print_setup.m @@ -0,0 +1,81 @@ +function ctf_print_setup(ctf); + +% ctf_print_setup - print setup information to matlab command window +% +% ctf_print_setup(ctf) +% +% <>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +% < > +% < DISCLAIMER: > +% < > +% < THIS PROGRAM IS INTENDED FOR RESEARCH PURPOSES ONLY. > +% < THIS PROGRAM IS IN NO WAY INTENDED FOR CLINICAL OR > +% < OFFICIAL USE. > +% < > +% <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<> +% + +% $Revision: 1.1 $ $Date: 2009-01-30 03:49:27 $ + +% Copyright (C) 2004 Darren L. Weber +% +% This program is free software; you can redistribute it and/or +% modify it under the terms of the GNU General Public License +% as published by the Free Software Foundation; either version 2 +% of the License, or (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program; if not, write to the Free Software +% Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +% Modified: 02/2004, Darren.Weber_at_radiology.ucsf.edu +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +fprintf('...data format : %s\n',ctf.res4.header); +fprintf('...date collected : %s\n',ctf.setup.date); +fprintf('...time collected : %s\n',ctf.setup.time); +fprintf('...run name : %s\n',ctf.setup.run_name); +fprintf('...run title : %s\n',ctf.setup.run_title); +fprintf('...subject : %s\n',ctf.setup.subject); +fprintf('...run description : %s\n',ctf.setup.run_description); +fprintf('...operator : %s\n',ctf.setup.operator); +fprintf('...number of channels: %d\n',ctf.setup.number_channels); +fprintf('...number of samples : %d per trial\n',ctf.setup.number_samples); +fprintf('...sample rate : %g samples/sec\n',ctf.setup.sample_rate); +fprintf('...number of trials : %g trials (average of %g)\n',ctf.setup.number_trials,ctf.setup.number_trials_averaged); +fprintf('...duration : %g sec total\n',ctf.setup.duration_total); +fprintf('...duration : %g sec / trial\n',ctf.setup.duration_trial); +fprintf('...pretrigger points : %g samples\n',ctf.setup.pretrigger_samples); +fprintf('...pretrigger msec : %g msec\n',ctf.setup.pretrigger_msec); +fprintf('...sensor file name : %s\n',ctf.setup.sensor_file_name); +fprintf('...head zeroing : %s\n',ctf.setup.head_zero); +fprintf('...number of filters : %d\n',ctf.setup.number_filters); +for i = 1:ctf.setup.number_filters, + fprintf(' -Filter # \t%g\n',i) + fprintf(' -Frequency: \t%g Hz\n',ctf.setup.filters(i).freq) + fprintf(' -Class: \t%g\n',ctf.setup.filters(i).class) + fprintf(' -Type: \t%g\n',ctf.setup.filters(i).type) + if ~isempty(ctf.setup.filters(i).params) + fprintf(' -Parameter(s): \t%g\n',ctf.setup.filters(i).params) + end +end +%fprintf('\n'); + +return + + +% from ctf_read_res4 + +% for i = 1:ctf.setup.number_filters, +% ctf.setup.filters(i).freq = fread(fid,1,'double'); +% ctf.setup.filters(i).class = fread(fid,1,'int32'); +% ctf.setup.filters(i).type = fread(fid,1,'int32'); +% ctf.setup.filters(i).numparam = fread(fid,1,'int16'); +% ctf.setup.filters(i).params = fread(fid,ctf.setup.filters(i).numparam,'double'); +% end diff --git a/ctf_read.m b/ctf_read.m new file mode 100644 index 0000000..68cf769 --- /dev/null +++ b/ctf_read.m @@ -0,0 +1,135 @@ +function [ctf] = ctf_read(folder,CHAN,TIME,TRIALS,COEFS); + +% ctf_read - Read data from a CTF .ds folder +% +% [ctf] = ctf_read( [folder], [CHAN], [TIME], [TRIALS], [COEFS] ); +% +% eg, +% ctf = ctf_read; % inputs are all optional +% ctf = ctf_read('/data/directory/datasetname.ds'); +% ctf = ctf_read(folder,'meg','all','all'); +% +% ctf struct returned has fields: +% +% folder: full path to .ds folder +% res4: the .res4 file path and version +% setup: dataset header parameters +% sensor: sensor data, including type, position and orientation +% data: all of the data in a 3D matrix, with rows of samples, columns +% of channels and frames of epochs, so: +% data(1,:,:) is the first sample, for all channels and epochs +% data(:,1,:) is the first channel, for all samples and epochs +% data(:,:,1) is the first epoch, with all samples and channels +% +% This function calls, in this order: +% +% ctf_read_res4 - to read in header, gain/offset, and sensor information +% ctf_read_meg4 - to read in the data +% +% INPUTS--------------------------------------------------------------------- +% folder: The .ds directory of the dataset. If not given, a graphical +% prompt for the folder appears. +% +% CHAN: eg. [30:35] - an interval of the desired channels to be read. +% If CHAN = 'eeg', only eeg channels/sensors +% If CHAN = 'meg', only meg channels/sensors +% If CHAN = 'ref', only reference channels/sensors +% If CHAN = 'other' only the other channels/sensors +% If CHAN = 'megeeg', only meg and eeg channels/sensors +% see ctf_channel_select for all the sensor types +% +% TIME: eg. [0 5] - seconds 0 to 5, the time interval to read. +% If TIME = 'all', the entire duration of the trial(s) will +% be read (i.e. TIME = [1:ctf.setup.duration]). +% +% TRIALS: eg. TRIALS = n, the nth trial is read. +% eg. TRIALS = [3,5,8], trials 3, 5, and 8 are read such that, +% ctf.data{1} = data for trial 3, +% ctf.data{2} = data for trial 5, and +% ctf.data{3} = data for trial 8. +% eg. TRIALS = [3:7], trials 3 through 7 are read. +% eg. TRIALS = 'alltrials', the data for all of the trials are +% read (i.e. TRIALS = [1:ctf.setup.duration]). +% +% COEFS: an option to read the sensor coefficients, which give the +% weights for calculation of synthetic 2nd or 3rd order +% gradiometers. +% If coefs = 1, read the sensor coefficients +% If coefs = 0, do not read the sensor coefficients (default) +% +% Note on 2nd, 3rd Order Synthetic Gradients: +% It is important to know what data type is saved into an .meg4 file. In +% CTF's DataEditor program, if you go to, "Analyse -> Processing +% Parameters" you may see "Noise Reduction of Saved Data" -- this is the +% data that ctf_read will pull off the disk, regardless of what +% "Current Noise Reduction" says. However, you can use "Save As" (or +% the newDs command line tool) and it will apply the gradient correction +% setting when saving the new dataset. +% When using ctf_read, the values returned by +% ctf.sensor.info.grad_order_no will indicate whether or not the data +% is corrected: +% "0" means no correction, +% "2" means synthetic third order gradient correction. +% "3" means synthetic third order gradient correction. +% Currently, there is no way to apply or remove the corrections with +% ctf_read. +% +% <>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +% < > +% < DISCLAIMER: > +% < > +% < THIS PROGRAM IS INTENDED FOR RESEARCH PURPOSES ONLY. > +% < THIS PROGRAM IS IN NO WAY INTENDED FOR CLINICAL OR > +% < OFFICIAL USE. > +% < > +% <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<> +% + + + +% $Revision: 1.1 $ $Date: 2009-01-30 03:49:27 $ + +% Copyright (C) 2004 Darren L. Weber +% +% This program is free software; you can redistribute it and/or +% modify it under the terms of the GNU General Public License +% as published by the Free Software Foundation; either version 2 +% of the License, or (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program; if not, write to the Free Software +% Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +% Modified: 11/2003, Darren.Weber_at_radiology.ucsf.edu +% - modified from NIH code +% simply to allocate data into one large struct +% Modified: 06/2005, Darren.Weber_at_radiology.ucsf.edu +% - updated ctf struct information +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +if ~exist('folder','var'), + ctf = ctf_folder; +else + ctf = ctf_folder(folder); +end + +if ~exist('CHAN','var'), CHAN = 'all'; end +if ~exist('TIME','var'), TIME = 'all'; end +if ~exist('TRIALS','var'), TRIALS = 'all'; end +if ~exist('COEFS','var'), COEFS = 0; end + +if isempty(CHAN), CHAN = 'all'; end +if isempty(TIME), TIME = 'all'; end +if isempty(TRIALS), TRIALS = 'all'; end +if isempty(COEFS), COEFS = 0; end + +ctf = ctf_read_res4(ctf.folder,1,COEFS); + +ctf = ctf_read_meg4(ctf.folder,ctf,CHAN,TIME,TRIALS,COEFS); + +return diff --git a/ctf_read_badchannels.m b/ctf_read_badchannels.m new file mode 100644 index 0000000..1c55f97 --- /dev/null +++ b/ctf_read_badchannels.m @@ -0,0 +1,114 @@ +function [ctf] = ctf_read_badchannels(folder,ctf); + +% ctf_read_badchannels - read BadChannels file from a CTF .ds folder +% +% [ctf] = ctf_read_badchannels(folder,ctf) +% +% This function reads the BadChannels text file in a .ds folder. +% +% The BadChannels file is a text file that contains the channel names of +% any bad channels. The channel names are assumed to be listed in a single +% column, one channel per line. +% +% INPUTS +% +% If you do not wish to specify an input option, use [], but keep the order +% of the input options as above. Only specify as many input options as +% required. With no input options, the function will prompt for a folder +% and read the BadChannels file (if it exists). +% +% folder - the directory of the .ds data set to read. By +% default, a gui prompts for the folder. +% +% ctf - a struct with folder, setup, sensor and data fields. +% +% OUTPUTS +% +% ctf.sensor.bad - a string cell array of channel labels +% +% <>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> % +% < > % +% < DISCLAIMER: > % +% < > % +% < THIS PROGRAM IS INTENDED FOR RESEARCH PURPOSES ONLY. > % +% < THIS PROGRAM IS IN NO WAY INTENDED FOR CLINICAL OR > % +% < OFFICIAL USE. > % +% < > % +% <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<> % +% + + +% $Revision: 1.1 $ $Date: 2009-01-30 03:49:27 $ + +% Copyright (C) 2005 Darren L. Weber +% +% This program is free software; you can redistribute it and/or +% modify it under the terms of the GNU General Public License +% as published by the Free Software Foundation; either version 2 +% of the License, or (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program; if not, write to the Free Software +% Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +% Modified: 01/2005, Darren.Weber_at_radiology.ucsf.edu +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +%----------------------------------------------- +% ensure we have the folder + +if exist('folder','var'), + if exist('ctf','var'), + ctf = ctf_folder(folder,ctf); + else + ctf = ctf_folder(folder); + end +else + if exist('ctf','var'), + ctf = ctf_folder([],ctf); + else + ctf = ctf_folder; + end +end + + +%-------------------------------------------------------------- +ver = '$Revision: 1.1 $ $Date: 2009-01-30 03:49:27 $'; +fprintf('\nCTF_READ_BADCHANNELS [v %s]\n',ver(11:15)); tic; + + +%---------------------------------------------------------------- +% read the file + +[folderPath,folderName,folderExt] = fileparts(ctf.folder); +BadChannelsFile = findBadChannelsFile( ctf.folder ); + +ctf.sensor.bad = textread(BadChannelsFile,'%s','delimiter','\n'); + +t = toc; fprintf('...done (%6.2f sec)\n\n',t); + +return + + + +% ------------------------------------------------------- +function BadChannelsFile = findBadChannelsFile( folder ) + +filename = dir([ folder filesep 'BadChannels' ]); +if isempty(filename) + filename = dir([ folder filesep 'badchannels' ]); +end; + +if isempty(filename) + error('No BadChannels file in selected folder'); +else + BadChannelsFile = [ folder filesep filename.name ]; +end; + +return diff --git a/ctf_read_classfile.m b/ctf_read_classfile.m new file mode 100644 index 0000000..89261d1 --- /dev/null +++ b/ctf_read_classfile.m @@ -0,0 +1,254 @@ +function class = ctf_read_classfile(ctf,clsFile); + +% class = ctf_read_classfile(ctf,clsFile); +% +% This function reads the ClassFile.cls created by CTF preprocessing +% software. +% +% ctf - a struct returned by ctf_read, it contains ctf.folder, which is a +% .ds path where a ClassFile.cls can be read; eg: +% ctf = ctf_read +% ctf.class = ctf_read_classfile(ctf) +% +% clsFile - this can be used to override the default behavior of reading +% *.ds/ClassFile.cls, it should be a complete path to a .cls file; eg: +% ctf.class = ctf_read_classfile([],clsFile) +% ctf.class = ctf_read_classfile([],'//ClassFile.cls') +% +% It returns a class struct, eg: +% +% class.path: '/data/dnl3/HighN_cuebase/allTrialData/CJ_HiN_alltrials.ds' +% class.number: 4 +% class.data: {[1x1 struct] [1x1 struct] [1x1 struct] [1x1 struct]} +% +% where class.data is a 1xN struct array, eg: +% +% >> class.data(1) +% +% ans = +% +% classgroupid: 3 +% name: 'EYEBLINKa' +% comment: [1x63 char] +% color: '' +% editable: 'Yes' +% classid: 2 +% Ntrials: 67 +% trials: [1x67 double] +% +% To get all the class names, +% [classNames{1:class.number}] = deal(class.data.name); +% classNames = {ctf.class.data(:).name}; +% +% To scan all the class names, use strmatch, eg: +% strmatch('BAD',{ctf.class.data(:).name}); +% +% Note that the class.data(n).trials contains numbers beginning with 1, +% whereas the CTF datafile has values beginning with 0 (this is based on +% differences in array indexing between c/c++ and matlab). +% +% <>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +% < > +% < DISCLAIMER: > +% < > +% < THIS PROGRAM IS INTENDED FOR RESEARCH PURPOSES ONLY. > +% < THIS PROGRAM IS IN NO WAY INTENDED FOR CLINICAL OR > +% < OFFICIAL USE. > +% < > +% <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<> +% + + +% $Revision: 1.1 $ $Date: 2009-01-30 03:49:27 $ + +% Copyright (C) 2005 Darren L. Weber +% +% This program is free software; you can redistribute it and/or +% modify it under the terms of the GNU General Public License +% as published by the Free Software Foundation; either version 2 +% of the License, or (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program; if not, write to the Free Software +% Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +% Created: 12/2005, Darren.Weber_at_radiology.ucsf.edu +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +if ~exist('clsFile','var'), clsFile = ''; end +if isempty(clsFile), clsFile = ''; end +if clsFile, + fid = fopen(clsFile,'r'); +else + fid = -1; +end + +if fid < 0, + % only use the ctf.folder if the above has failed + if isfield(ctf,'folder'), + if isempty(ctf.folder), + error('ctf.folder is empty and no clsFile specified'); + else + clsFile = fullfile(ctf.folder,'ClassFile.cls'); + fid = fopen(clsFile,'r'); + end + end +end + +if fid < 0, + error('failed to open any ClassFile.cls'); +end + + +% Read the dataset path from the classfile +class.path = []; +while isempty(class.path), + curLine = fgetl(fid); + if strcmp(curLine,'PATH OF DATASET:'), + curLine = fgetl(fid); + class.path = curLine; + end +end +frewind(fid); + +% Find the number of classes to read +class.number = []; +while isempty(class.number), + curLine = fgetl(fid); + if strcmp(curLine,'NUMBER OF CLASSES:'), + curLine = fgetl(fid); + class.number = str2num(curLine); + end +end +frewind(fid) + +if isempty(class.number), + warning('ClassFile.cls is empty of classes'); + fclose(fid); + return +end + + +% read the classes, assuming this format: +% +% CLASSGROUPID: +% 3 +% NAME: +% EYEBLINK +% COMMENT: +% Ampl(MEG)=0T; Deriv(MEG)=0T/s; Ampl(EEG)=80uV; Deriv(EEG)=0V/s. +% COLOR: +% +% EDITABLE: +% Yes +% CLASSID: +% 2 +% NUMBER OF TRIALS: +% 3 +% LIST OF TRIALS: +% TRIAL NUMBER +% +527 +% +612 +% +624 + +% initialize a class.data array of structs +class.data(1:class.number) = struct(... + 'classgroupid', '',... + 'name', '',... + 'comment', '',... + 'color', '',... + 'editable', '',... + 'classid', [],... + 'Ntrials', [],... + 'trials', []); + +classCurrent = 0; +while classCurrent < class.number, + + curLine = fgetl(fid); + if strcmp(curLine,'CLASSGROUPID:'); + % update current class no. here only + classCurrent = classCurrent + 1; + curLine = fgetl(fid); + curLine = str2num(curLine); + class.data(classCurrent).classgroupid = curLine; + curLine = fgetl(fid); + end + + if strcmp(curLine,'NAME:'); + curLine = fgetl(fid); + class.data(classCurrent).name = curLine; + curLine = fgetl(fid); + end + + if strcmp(curLine,'COMMENT:'); + curLine = fgetl(fid); + class.data(classCurrent).comment = curLine; + curLine = fgetl(fid); + end + + if strcmp(curLine,'COLOR:'); + curLine = fgetl(fid); + class.data(classCurrent).color = curLine; + curLine = fgetl(fid); + end + + if strcmp(curLine,'EDITABLE:'); + curLine = fgetl(fid); + class.data(classCurrent).editable = curLine; + curLine = fgetl(fid); + end + + if strcmp(curLine,'CLASSID:'); + curLine = fgetl(fid); + curLine = str2num(curLine); + class.data(classCurrent).classid = curLine; + if curLine ~= classCurrent, + error('curLine ~= classCurrent'); + end + curLine = fgetl(fid); + end + + if strcmp(curLine,'NUMBER OF TRIALS:'); + curLine = fgetl(fid); + Ntrials = str2num(curLine); + class.data(classCurrent).Ntrials = Ntrials; + + % read past "LIST OF TRIALS:" + curLine = fgetl(fid); + if strcmp(curLine,'LIST OF TRIALS:'), + % that's good, we expect it + else + warning('Did not find ''LIST OF TRIALS:'' where expected') + end + + % read past "TRIAL NUMBER" + curLine = fgetl(fid); + if strcmp(curLine,'TRIAL NUMBER'), + % that's good, we expect it + else + warning('Did not find ''TRIAL NUMBER'' where expected') + end + + class.data(classCurrent).trials = []; + if class.data(classCurrent).Ntrials > 0, + class.data(classCurrent).trials = zeros(1,Ntrials); + for n = 1:Ntrials, + curLine = fgetl(fid); + % add 1 to trial numbers for matlab compatibility + class.data(classCurrent).trials(n) = str2num(curLine) + 1; + end + end + + end + +end + +return diff --git a/ctf_read_epochs.m b/ctf_read_epochs.m new file mode 100644 index 0000000..5a7a45a --- /dev/null +++ b/ctf_read_epochs.m @@ -0,0 +1,176 @@ +function [data,ctf] = ctf_read_epochs(folder,varargin); + +% ctf_read_epochs - extract epochs from a ctf dataset (.ds) +% +% [data,ctf] = ctf_read_epochs(folder,varargin) +% +% This function will extract epochs for specific markers. The inputs are +% given as 'parameter' => 'value' pairs, where the following parameters and +% values are recognised: +% 'channels' => 'eeg','meg','ref','vc','other','all',[a:b] +% 'markers' => {'marker names'} +% 'window' => [start_sec,end_sec] +% 'trials' => 'all',[a:b] +% +% <>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +% < > +% < DISCLAIMER: > +% < > +% < THIS PROGRAM IS INTENDED FOR RESEARCH PURPOSES ONLY. > +% < THIS PROGRAM IS IN NO WAY INTENDED FOR CLINICAL OR > +% < OFFICIAL USE. > +% < > +% <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<> +% + +% $Revision: 1.1 $ $Date: 2009-01-30 03:49:27 $ + +% Copyright (C) 2004 Darren L. Weber +% +% This program is free software; you can redistribute it and/or +% modify it under the terms of the GNU General Public License +% as published by the Free Software Foundation; either version 2 +% of the License, or (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program; if not, write to the Free Software +% Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +% Modified: 01/2004, Darren.Weber_at_radiology.ucsf.edu +% - modified from NIH code readepochs.m +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +ver = '$Revision: 1.1 $'; +fprintf('\nCTF_READ_EPOCHS [v %s]\n',ver(11:15)); tic; + +if ~exist('folder','var'), + ctf = ctf_folder; +else + ctf = ctf_folder(folder); +end + +ctf = ctf_read_res4(ctf.folder); + +% defaults +CHAN = ctf.sensor.index.meg; +TIME = 'alltimes'; +TRIALS = [1:ctf.setup.number_trials]; +markers = []; + +for i = 1:size(varargin,2) + if iscell(varargin{i}) + if strmatch(varargin{i},'markers'), + markers = varargin{i+1}; + end + elseif ischar(varargin{i}), + switch lower(varargin{i}), + case 'channels', + if isnumeric(varargin{i+1}), + CHAN = varargin{i+1}; + else + switch lower(varargin{i+1}), + case 'eeg', + CHAN = ctf.sensor.index.eeg; + case 'meg', + CHAN = ctf.sensor.index.meg; + case 'ref', + CHAN = ctf.sensor.index.ref; + case 'other', + CHAN = ctf.sensor.index.other; + case 'vc', + CHAN = ctf.sensor.index.vc; + case 'all', + CHAN = [1:ctf.setup.number_channels]; + end + end + case 'window', + if isnumeric(varargin{i+1}), + TIME = varargin{i+1}; + else + error('window argument must be numeric array'); + end + case 'trials', + if isnumeric(varargin{i+1}), + TRIALS = varargin{i+1}; + else + error('trials argument must be numeric array'); + end + end + end +end + +if isempty(markers), + + % If not markers are specified, we just rearrange the ctf.data cell + % array into a 3D matrix + + ctf = ctf_read_meg4(folder,ctf,CHAN,TIME,TRIALS); + + for i = 1:size(ctf.data,1), + + epochs{1}(:,:,i) = ctf.data{i}; + + end + +else + + % read the marker file + ctf = ctf_read_markerfile(ctf.folder,ctf); + + if isempty(ctf.markers), + error('No markers'); + end + + number_markers = length(markers); + + % initialise epoch cell array to hold an ordered set of epochs for each + % marker selected + epochs = cell(number_markers,1); + + for marker = 1:number_markers, + + mk = ismember(ctf.markers.marker_names,markers(marker)); + + keyboard + + ctf.markers.marker_names(mk); + + nsamp = ctf.markers.number_samples(mk) + + nss=0; + + for ns=1:nsamp + + tr = ctf.markers.trial_times{mk}(ns,1); + + if ismember(tr,TRIALS) + + nss=nss+1; + + tim=ctf.markers.trial_times{mk}(ns,2); + + times=TIME+tim; + + ctf = ctf_read_meg4(folder,ctf,CHAN,TIME,tr); + + temp=ctf.data{1}; + + epochs{marker}(:,:,nss)=temp; + + end + end + end +end + +data = struct(... + 'folder',ctf.folder,... + 'setup', ctf.setup,... + 'sensor',ctf.sensor,... + 'epochs',epochs ); + +return diff --git a/ctf_read_fiducials.m b/ctf_read_fiducials.m new file mode 100644 index 0000000..8ede646 --- /dev/null +++ b/ctf_read_fiducials.m @@ -0,0 +1,119 @@ +function HeadModel_Info = ctf_read_fiducials(file) + +% ctf_read_fiducials - read a CTF .fid file +% +% HeadModel_Info = ctf_read_fiducials(fileName) +% +% The *.fid file contains a simple matrix of MRI fiducial +% coordinates in the voxel MRI coordinate system (see ctf_read_mri +% for more about that coordinate system). The file is an ascii +% text file that contains scalar values, in this order: +% Nasion: Sagittal Coronal Axial +% Left Ear: Sagittal Coronal Axial +% Right Ear: Sagittal Coronal Axial +% For example, +% 128 43 158 +% 41 137 196 +% 210 131 199 +% +% This function simply reads these values into the appropriate +% fields of the HeadModel_Info struct: +% +%>> HeadModel_Info +% +%ans = +% +% Nasion_Sag: 128 +% Nasion_Cor: 43 +% Nasion_Axi: 158 +% LeftEar_Sag: 41 +% LeftEar_Cor: 137 +% LeftEar_Axi: 196 +% RightEar_Sag: 210 +% RightEar_Cor: 131 +% RightEar_Axi: 199 +% defaultSphereX: 0 +% defaultSphereY: 0 +% defaultSphereZ: 50 +% defaultSphereRadius: 75 +% +% This function initialises the defaultSphere values. The +% struct returned can be allocated into the mri.hdr.HeadModel_Info +% struct returned by ctf_read_mri, but the defaultSphere values +% may be incorrect. The ctf_read_mri function actually reads all +% these fiducial locations directly from the .mri file, so it +% should not be necessary to use this function very often (unless +% the fiducials are missing from the .mri file, in which case it is +% also unlikely there will be an .fid file!). +% + +% $Revision: 1.1 $ $Date: 2009-01-30 03:49:27 $ + +% Copyright (C) 2004 Darren L. Weber +% +% This program is free software; you can redistribute it and/or +% modify it under the terms of the GNU General Public License +% as published by the Free Software Foundation; either version 2 +% of the License, or (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program; if not, write to the Free Software +% Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +% History: 02/2004, Darren.Weber_at_radiology.ucsf.edu +% - adapted from an appendex to CTF document +% MRIViewer.pdf +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +ver = '[$Revision: 1.1 $]'; +fprintf('\nCTF_READ_FIDUCIALS [v%s]\n',ver(12:16)); tic; + +fprintf('...checking file input parameter\n'); + +if ~exist('file','var'), + [fileName, filePath, filterIndex] = uigetfile('*.fid', 'Locate CTF .fid file'); + file = fullfile(filePath, fileName); +elseif isempty(file), + fprintf('...file is empty\n'); + [fileName, filePath, filterIndex] = uigetfile('*.fid', 'Locate CTF .fid file'); + file = fullfile(filePath, fileName); +end +if ~exist(file,'file'), + fprintf('...file does not exist\n'); + [fileName, filePath, filterIndex] = uigetfile('*.fid', 'Locate CTF .fid file'); + file = fullfile(filePath, fileName); +end + +%----------------------------------------------------- +fprintf('...reading fiducials values.\n'); + +ctf_fiducials = load(file,'ascii'); + +HeadModel_Info.Nasion_Sag = ctf_fiducials(1,1); +HeadModel_Info.Nasion_Cor = ctf_fiducials(1,2); +HeadModel_Info.Nasion_Axi = ctf_fiducials(1,3); +HeadModel_Info.LeftEar_Sag = ctf_fiducials(2,1); +HeadModel_Info.LeftEar_Cor = ctf_fiducials(2,2); +HeadModel_Info.LeftEar_Axi = ctf_fiducials(2,3); +HeadModel_Info.RightEar_Sag = ctf_fiducials(3,1); +HeadModel_Info.RightEar_Cor = ctf_fiducials(3,2); +HeadModel_Info.RightEar_Axi = ctf_fiducials(3,3); + +%----------------------------------------------------- +% These values are not in the .fid file, so we initialise them to +% default values here +fprintf('...initialising defaultSphere values.\n'); +HeadModel_Info.defaultSphereX = 0; +HeadModel_Info.defaultSphereY = 0; +HeadModel_Info.defaultSphereZ = 0; +HeadModel_Info.defaultSphereRadius = 75; + +t=toc; fprintf('...done (%5.2f sec).\n\n',t); + +return diff --git a/ctf_read_gui.m b/ctf_read_gui.m new file mode 100644 index 0000000..929e488 --- /dev/null +++ b/ctf_read_gui.m @@ -0,0 +1,447 @@ +function [ctf,GUI] = ctf_read_gui(command); + +% ctf_read_gui - GUI interface to read data from a CTF .ds folder +% +% [ctf,FIG] = ctf_read_gui( [command] ); +% +% eg, +% ctf = ctf_read_gui; +% +% ctf struct has fields: +% +% ctf.folder +% ctf.header +% ctf.setup +% ctf.sensor +% ctf.data +% +% This function calls: +% ctf_read_res4 - to read in header, gain/offset, and sensor information +% ctf_read_meg4 - to read in the data +% +% <>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> % +% < > % +% < DISCLAIMER: > % +% < > % +% < THIS PROGRAM IS INTENDED FOR RESEARCH PURPOSES ONLY. > % +% < THIS PROGRAM IS IN NO WAY INTENDED FOR CLINICAL OR > % +% < OFFICIAL USE. > % +% < > % +% <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<> % +% + + + +% $Revision: 1.1 $ $Date: 2009-01-30 03:49:27 $ + +% Copyright (C) 2004 Darren L. Weber +% +% This program is free software; you can redistribute it and/or +% modify it under the terms of the GNU General Public License +% as published by the Free Software Foundation; either version 2 +% of the License, or (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program; if not, write to the Free Software +% Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +% Modified: 11/2003, Darren.Weber_at_radiology.ucsf.edu +% - modified from NIH code +% simply to allocate data into one large struct +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +if ~exist('command','var'), command = 'init'; end + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Paint the GUI +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +switch command, + + case 'init', + + [ctf,GUI] = INIT; + + case 'update', + + CTFopen = get(gcbf,'Userdata'); + + ctf = CTFopen.ctf; + + % update the folder + set(CTFopen.handles.EctfFolder,'String',ctf.folder); + + CTFopen.CHANNELS = 1:ctf.setup.number_channels; + CTFopen.TIME = ctf.setup.time_sec; + CTFopen.TRIALS = 1:ctf.setup.number_trials; + + % update the channels + channelvalue = get(CTFopen.handles.PctfCHANNELS,'Value'); + channeltype = CTFopen.channeltypes{channelvalue}; + switch channeltype, + case 'all', CTFopen.CHANNELS = 1:ctf.setup.number_channels; + case 'eeg', CTFopen.CHANNELS = ctf.sensor.index.eeg; + case 'meg', CTFopen.CHANNELS = ctf.sensor.index.meg; + case 'ref', CTFopen.CHANNELS = ctf.sensor.index.ref; + case 'other', CTFopen.CHANNELS = ctf.sensor.index.other; + otherwise, CTFopen.CHANNELS = []; + end; + set(CTFopen.handles.EctfCHANNELS,'value',CTFopen.CHANNELS); + set(CTFopen.handles.EctfCHANNELS,'string',num2str(CTFopen.CHANNELS)); + + % update time + start = sprintf('%6.5f', CTFopen.TIME(1)); + step = sprintf('%6.5f',[CTFopen.TIME(2) - CTFopen.TIME(1)]); + stop = sprintf('%6.5f', CTFopen.TIME(end)); + timestring = [start,':',step,':',stop]; + + set(CTFopen.handles.TctfTIME,'String',timestring); + + set(CTFopen.handles.EctfTIME,'Value',CTFopen.TIME); + set(CTFopen.handles.EctfTIME,'String',num2str(CTFopen.TIME')); + + % update trials + start = num2str(CTFopen.TRIALS(1)); + stop = num2str(CTFopen.TRIALS(end)); + trialstring = [start,':',stop]; + set(CTFopen.handles.TctfTRIALS,'String',trialstring); + + set(CTFopen.handles.EctfTRIALS,'Value',CTFopen.TRIALS); + + set(CTFopen.handles.EctfTRIALS,'String',num2str(CTFopen.TRIALS)); + set(CTFopen.handles.EctfTRIALS,'Value',CTFopen.TRIALS); + + set(gcbf,'Userdata',CTFopen); + + + + case 'return', + + CTFopen = get(gcbf,'Userdata'); + + ctf = CTFopen.ctf; + + CHANNELS = CTFopen.CHANNELS; + TIME = CTFopen.TIME; + TRIALS = CTFopen.TRIALS; + + ctf = ctf_read_meg4(ctf.folder, ctf, CHANNELS, TIME, TRIALS ); + + close gcbf; + + + case 'plot', + + fprintf('\nCTF_GUI_READ: Plot not implemented yet.\n'); + +% CTFopen = get(gcbf,'Userdata'); +% +% CTFopen.p = ctf_open(CTFopen.p,CTFopen.gui); +% set(CTFopen.gui,'Userdata',CTFopen); % update GUI with CNT data +% +% p = gui_updateparent(CTFopen,0); +% +% if isequal(get(CTFopen.handles.Bhold,'Value'),0), +% close gcbf; +% if isfield(CTFopen,'parent'), +% parent = CTFopen.parent.gui; +% else +% parent = []; +% end +% else +% parent = CTFopen.gui; +% end +% +% plotfig = figure('Name',CTFopen.p.ctf.file,... +% 'NumberTitle','off',... +% 'UserData',CTFopen.p); +% movegui(plotfig,'center'); +% +% plot(CTFopen.p.ctf.timeArray,CTFopen.p.ctf.data); axis tight; +% eeg_plot_metric; +% +% if isempty(parent), [Xpoint,Ypoint] = eeg_crosshair('init',CTFopen.p); +% else [Xpoint,Ypoint] = eeg_crosshair('init',CTFopen.p,parent); +% end + + case 'save', + + fprintf('\nCTF_GUI_READ: Save not implemented yet.\n'); + + otherwise, + + CTFopen = get(gcbf,'Userdata'); + GUI.parent = CTFopen.parent; + gui_updateparent(GUI); + close gcbf; + +end + +return + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [ctf,GUI] = INIT +% GUI General Parameters + +ctf = ctf_folder; +ctf = ctf_read_res4(ctf.folder); + +% check if the data is greater than 500 Mb +data_size = ctf.setup.number_samples * ctf.setup.number_channels * ctf.setup.number_trials; +data_bytes = data_size * 8; +if data_bytes > 5e9, warning('data is greater than 500 Mb'); end +clear data_size data_bytes; + +CTFopen.CHANNELS = 1:ctf.setup.number_channels; +CTFopen.TIME = ctf.setup.time_sec; +CTFopen.TRIALS = 1:ctf.setup.number_trials; + +GUIwidth = 800; +GUIheight = 150; + +ver = '$Revision: 1.1 $'; +name = sprintf('CTF Open [v %s]\n',ver(11:15)); + +GUI = figure('Name',name,'Tag','CTF_OPEN',... + 'NumberTitle','off',... + 'MenuBar','none','Position',[1 1 GUIwidth GUIheight]); +movegui(GUI,'center'); + +%Font.FontName = 'Helvetica'; +Font.FontUnits = 'Pixels'; +Font.FontSize = 12; +Font.FontWeight = 'normal'; +Font.FontAngle = 'normal'; + +boxdepth = 0.15; + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% CTF Data Selection and Parameters + +Font.FontWeight = 'bold'; + +% BROWSE for a .ds folder +browsecommand = strcat('CTFopen = get(gcbf,''Userdata'');',... + 'ctf = CTFopen.ctf; ',... + 'ctf = ctf_folder([],ctf); ',... + 'ctf = ctf_read_res4(ctf.folder); ',... + 'CTFopen.ctf = ctf; ',... + 'set(CTFopen.handles.EctfFolder,''String'',ctf.folder); ',... + 'set(gcbf,''Userdata'',CTFopen);',... + 'clear CTFopen; ctf = ctf_read_gui(''update'');'); +G.BctfFile = uicontrol('Parent',GUI,'Style','pushbutton','Units','Normalized',Font, ... + 'Position',[.01 .80 .17 boxdepth], 'String','CTF Folder (*.ds)',... + 'BackgroundColor',[0.8 0.8 0.0], 'ForegroundColor', [1 1 1], ... + 'HorizontalAlignment', 'center', ... + 'TooltipString','Browse for CTF folder', ... + 'Callback', browsecommand ); + +Font.FontWeight = 'normal'; + +% EDIT the .ds folder name +editcommand = strcat('CTFopen = get(gcbf,''Userdata'');',... + 'CTFopen.ctf.folder = get(CTFopen.handles.EctfFolder,''String''); ',... + 'ctf = CTFopen.ctf; ',... + 'ctf = ctf_folder(ctf.folder,ctf); ',... + 'ctf = ctf_read_res4(ctf.folder); ',... + 'CTFopen.ctf = ctf; ',... + 'set(CTFopen.handles.EctfFolder,''String'',ctf.folder); ',... + 'set(gcbf,''Userdata'',CTFopen);',... + 'clear CTFopen; ctf = ctf_read_gui(''update'');'); +G.EctfFolder = uicontrol('Parent',GUI,'Style','edit','Units','Normalized',Font, ... + 'Position',[.20 .80 .75 boxdepth], 'String',ctf.folder,... + 'Callback', editcommand ); + + + +%--------------------------------------------------------------- +% Channels +height = 0.6; + +G.Title_channels = uicontrol('Parent',GUI,'Style','text','Units','Normalized',Font, ... + 'Position',[.01 height .17 boxdepth],'HorizontalAlignment', 'center','String','Channels:'); + +% Channel types +CTFopen.channeltypes = {'all', 'eeg', 'meg', 'ref', 'other', '[array]'}; +channelpopup = strcat('CTFopen = get(gcbf,''Userdata'');',... + 'channelvalue = get(CTFopen.handles.PctfCHANNELS,''Value''); ',... + 'channeltype = CTFopen.channeltypes{channelvalue}; ',... + 'switch channeltype, ',... + ' case ''all'', CTFopen.CHANNELS = 1:CTFopen.ctf.setup.number_channels; ',... + ' case ''eeg'', CTFopen.CHANNELS = CTFopen.ctf.sensor.index.eeg; ',... + ' case ''meg'', CTFopen.CHANNELS = CTFopen.ctf.sensor.index.meg; ',... + ' case ''ref'', CTFopen.CHANNELS = CTFopen.ctf.sensor.index.ref; ',... + ' case ''other'', CTFopen.CHANNELS = CTFopen.ctf.sensor.index.other; ',... + ' otherwise, CTFopen.CHANNELS = []; ',... + 'end; ',... + 'set(CTFopen.handles.EctfCHANNELS,''Value'',CTFopen.CHANNELS); ',... + 'set(CTFopen.handles.EctfCHANNELS,''string'',num2str(CTFopen.CHANNELS)); ',... + 'set(gcbf,''Userdata'',CTFopen);',... + 'clear CTFopen channelvalue channeltype;'); +G.PctfCHANNELS = uicontrol('Parent',GUI,'Style','popup','Units','Normalized',Font, ... + 'Position',[.20 height .20 boxdepth], ... + 'String',CTFopen.channeltypes,... + 'Value',1, ... + 'TooltipString','Channel selection - enter values for [array]', ... + 'Callback', channelpopup ); + +% Channels array +channelarray = strcat('CTFopen = get(gcbf,''Userdata'');',... + 'CTFopen.CHANNELS = str2num(get(CTFopen.handles.EctfCHANNELS,''String'')); ',... + 'set(CTFopen.handles.EctfCHANNELS,''Value'',CTFopen.CHANNELS); ',... + 'set(gcbf,''Userdata'',CTFopen); clear CTFopen;'); +G.EctfCHANNELS = uicontrol('Parent',GUI,'Style','edit','Units','Normalized',Font, ... + 'Position',[.40 height .50 boxdepth], ... + 'String',num2str(CTFopen.CHANNELS),'Value',CTFopen.CHANNELS,... + 'TooltipString','Channels array - enter values for [array] selection', ... + 'Callback', channelarray ); +G.EctfCHANNELSCLEAR = uicontrol('Parent',GUI,'Style','pushbutton','Units','Normalized',Font, ... + 'Position',[.90 height .05 boxdepth], ... + 'String','Clear',... + 'TooltipString','Clear channels array', ... + 'Callback', strcat('CTFopen = get(gcbf,''Userdata'');',... + 'CTFopen.CHANNELS = []; ',... + 'set(CTFopen.handles.EctfCHANNELS,''String'',''''); ',... + 'set(CTFopen.handles.EctfCHANNELS,''Value'',CTFopen.CHANNELS); ',... + 'set(gcbf,''Userdata'',CTFopen); clear CTFopen;') ); + + + + +%--------------------------------------------------------------- +% Time +height = 0.4; + +G.Title_channels = uicontrol('Parent',GUI,'Style','text','Units','Normalized',Font, ... + 'Position',[.01 height .17 boxdepth],'HorizontalAlignment', 'center','String','Time (sec):'); + +% Time array +start = sprintf('%6.5f', CTFopen.TIME(1)); +step = sprintf('%6.5f',[CTFopen.TIME(2) - CTFopen.TIME(1)]); +stop = sprintf('%6.5f', CTFopen.TIME(end)); +timestring = [start,':',step,':',stop]; + +G.TctfTIME = uicontrol('Parent',GUI,'Style','text','Units','Normalized',Font, ... + 'Position',[.20 height .20 boxdepth],'HorizontalAlignment', 'center',... + 'TooltipString','Time array (sec)', ... + 'String',timestring); + + +timearray = strcat('CTFopen = get(gcbf,''Userdata'');',... + 'CTFopen.TIME = str2num(get(CTFopen.handles.EctfTIME,''String''))''; ',... + 'set(CTFopen.handles.EctfTIME,''Value'',CTFopen.TIME); ',... + 'set(gcbf,''Userdata'',CTFopen); clear CTFopen;'); +G.EctfTIME = uicontrol('Parent',GUI,'Style','edit','Units','Normalized',Font, ... + 'Position',[.40 height .50 boxdepth], ... + 'String',num2str(CTFopen.TIME'),'Value',CTFopen.TIME,... + 'TooltipString','Time array (sec)', ... + 'Callback', timearray ); +G.EctfTIMECLEAR = uicontrol('Parent',GUI,'Style','pushbutton','Units','Normalized',Font, ... + 'Position',[.90 height .05 boxdepth], ... + 'String','Clear',... + 'TooltipString','Clear time array', ... + 'Callback', strcat('CTFopen = get(gcbf,''Userdata'');',... + 'CTFopen.TIME = []; ',... + 'set(CTFopen.handles.EctfTIME,''String'',''''); ',... + 'set(CTFopen.handles.EctfTIME,''Value'',CTFopen.TIME); ',... + 'set(gcbf,''Userdata'',CTFopen); clear CTFopen;') ); + + + +%--------------------------------------------------------------- +% Trials +height = 0.2; + +G.Title_trials = uicontrol('Parent',GUI,'Style','text','Units','Normalized',Font, ... + 'Position',[.01 height .17 boxdepth],'HorizontalAlignment', 'center','String','Trials:'); + +start = num2str(CTFopen.TRIALS(1)); +stop = num2str(CTFopen.TRIALS(end)); +trialstring = [start,':',stop]; + +G.TctfTRIALS = uicontrol('Parent',GUI,'Style','text','Units','Normalized',Font, ... + 'Position',[.20 height .20 boxdepth],'HorizontalAlignment', 'center',... + 'String',trialstring); + +% Trials array +trialsarray = strcat('CTFopen = get(gcbf,''Userdata'');',... + 'CTFopen.TRIALS = str2num(get(CTFopen.handles.EctfTRIALS,''String'')); ',... + 'set(CTFopen.handles.EctfTRIALS,''Value'',CTFopen.TRIALS); ',... + 'set(gcbf,''Userdata'',CTFopen); clear CTFopen;'); +G.EctfTRIALS = uicontrol('Parent',GUI,'Style','edit','Units','Normalized',Font, ... + 'Position',[.40 height .50 boxdepth], ... + 'String',num2str(CTFopen.TRIALS),'Value',CTFopen.TRIALS,... + 'TooltipString','Trials array', ... + 'Callback', trialsarray ); +G.EctfTRIALSCLEAR = uicontrol('Parent',GUI,'Style','pushbutton','Units','Normalized',Font, ... + 'Position',[.90 height .05 boxdepth], ... + 'String','Clear',... + 'TooltipString','Clear trials array', ... + 'Callback', strcat('CTFopen = get(gcbf,''Userdata'');',... + 'CTFopen.TRIALS = []; ',... + 'set(CTFopen.handles.EctfTRIALS,''String'',''''); ',... + 'set(CTFopen.handles.EctfTRIALS,''Value'',CTFopen.TRIALS); ',... + 'set(gcbf,''Userdata'',CTFopen); clear CTFopen;') ); + + +% % PLOT: Load & plot the data! +% G.Bplot = uicontrol('Parent',GUI,'Style','pushbutton','Units','Normalized', Font, ... +% 'Position',[.20 .01 .18 .2],... +% 'String','PLOT','BusyAction','queue',... +% 'TooltipString','Plot the EEG data and return p struct.',... +% 'BackgroundColor',[0.0 0.5 0.0],... +% 'ForegroundColor', [1 1 1], 'HorizontalAlignment', 'center',... +% 'Callback',strcat('CTFopen = get(gcbf,''Userdata'');',... +% 'p = ctf_read_gui(CTFopen.p,''plot'');',... +% 'clear CTFopen;')); +% +% % Save As +% G.Bsave = uicontrol('Parent',GUI,'Style','pushbutton','Units','Normalized', Font, ... +% 'Position',[.40 .01 .18 .2],'HorizontalAlignment', 'center',... +% 'String','SAVE AS','TooltipString','EEG File Conversion Tool (not implemented yet)',... +% 'BusyAction','queue',... +% 'Visible','off',... +% 'BackgroundColor',[0.0 0.0 0.75],... +% 'ForegroundColor', [1 1 1], 'HorizontalAlignment', 'center',... +% 'Callback',strcat('CTFopen = get(gcbf,''Userdata'');',... +% 'p = ctf_read_gui(CTFopen.p,''save'');',... +% 'clear CTFopen;')); + +Font.FontWeight = 'bold'; + +% Quit, return file parameters +G.Breturn = uicontrol('Parent',GUI,'Style','pushbutton','Units','Normalized', Font, ... + 'Position',[.70 .01 .10 boxdepth],... + 'String','RETURN','BusyAction','queue',... + 'TooltipString','Return p struct to workspace and parent GUI.',... + 'BackgroundColor',[0.0 0.75 0.0],... + 'ForegroundColor', [1 1 1], 'HorizontalAlignment', 'center',... + 'Callback','ctf = ctf_read_gui(''return'');' ); + +% Cancel +G.Bcancel = uicontrol('Parent',GUI,'Style','pushbutton','Units','Normalized', Font, ... + 'Position',[.85 .01 .10 boxdepth],... + 'String','CANCEL','BusyAction','queue',... + 'TooltipString','Close, do not read data.',... + 'BackgroundColor',[0.75 0.0 0.0],... + 'ForegroundColor', [1 1 1], 'HorizontalAlignment', 'center',... + 'Callback','close(gcbf);'); + +% Store userdata +CTFopen.gui = GUI; +CTFopen.handles = G; +CTFopen.ctf = ctf; +set(GUI,'Userdata',CTFopen); +set(GUI,'HandleVisibility','callback'); + +return diff --git a/ctf_read_headshape.m b/ctf_read_headshape.m new file mode 100644 index 0000000..2735bc8 --- /dev/null +++ b/ctf_read_headshape.m @@ -0,0 +1,104 @@ +function HeadShape = ctf_read_headshape(file) + +% ctf_read_headshape - read a CTF .shape file +% +% HeadShape = ctf_read_headshape(fileName) +% +% The *.shape file is an ascii text file in the following format: +% +% Number of Points +% x1 y1 z1 +% x2 y2 z2 +% . +% . +% . +% xn yn zn +% +% +% These vertex coordinates are returned into HeadShape (Nx3). The +% coordinate values are in centimeters in either the voxel MRI +% coordinate system or the MEG Head Coordinate System (see +% ctf_read_mri for more about the coordinate system). +% + +% $Revision: 1.1 $ $Date: 2009-01-30 03:49:27 $ + +% Copyright (C) 2004 Darren L. Weber +% +% This program is free software; you can redistribute it and/or +% modify it under the terms of the GNU General Public License +% as published by the Free Software Foundation; either version 2 +% of the License, or (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program; if not, write to the Free Software +% Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +% History: 02/2004, Darren.Weber_at_radiology.ucsf.edu +% - adapted from an appendex to CTF document +% MRIViewer.pdf +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +ver = '[$Revision: 1.1 $]'; +fprintf('CTF_READ_HEADSHAPE [v%s]\n',ver(12:16)); tic; + +fprintf('...checking file input parameter\n'); + +if ~exist('file','var'), + [fileName, filePath, filterIndex] = uigetfile('*.shape', 'Locate CTF .shape file'); + file = fullfile(filePath, fileName); +elseif isempty(file), + fprintf('...file is empty\n'); + [fileName, filePath, filterIndex] = uigetfile('*.shape', 'Locate CTF .shape file'); + file = fullfile(filePath, fileName); +end +if ~exist(file,'file'), + fprintf('...file does not exist\n'); + [fileName, filePath, filterIndex] = uigetfile('*.shape', 'Locate CTF .shape file'); + file = fullfile(filePath, fileName); +end + + +fid = fopen(file,'r'); + +if isequal(fid,-1), + S=sprintf('Could not open file: "%s"',file); + error(S); +else + + fprintf('...reading CTF head shape file (.shape)\n'); + + tic; + + % Check for comment on first line of file + frewind(fid); temp = fscanf(fid,'%s',1); frewind(fid); + if findstr(temp,'#'), temp = fgetl(fid); end + + % Read vertices + Nvertices = fscanf(fid,'%d',1); + fprintf('...reading %d vertices\n',Nvertices); + vertices = fscanf(fid,'%f',[3,Nvertices]); + % translate + HeadShape = vertices'; + + % Read faces + %Nfaces = fscanf(fid,'%d',1); + %fprintf('...Reading %d Faces\n',Nfaces); + %faces = fscanf(fid,'%d',[4,Nfaces]); + % remove first row (index) & translate + %faces = faces(2:4,:)'; + + fclose(fid); + + t = toc; + fprintf('...done (%6.2f sec).\n\n',t); + +end + +return diff --git a/ctf_read_markerfile.m b/ctf_read_markerfile.m new file mode 100644 index 0000000..ec9f09f --- /dev/null +++ b/ctf_read_markerfile.m @@ -0,0 +1,189 @@ +function [markers] = ctf_read_markerfile(ctf,mrkFile); + +% ctf_read_markerfile - load data from MarkerFile.mrk in .ds folder +% +% [markers] = ctf_read_markerfile([ctf],[mrkFile]); +% +% ctf.folder is a .ds path, if it is missing or invalid a gui prompts +% for the folder. ctf is a struct generated by this and other +% ctf_read_*.m functions. +% +% mrkFile - this can be used to override the default behavior of reading +% *.ds/MarkerFile.cls, it should be a complete path to a .mrk file; eg: +% ctf = ctf_read_markerfile([],mrkFile) +% ctf = ctf_read_markerfile([],'//MarkerFile.mrk') +% +% Returns the 'markers' struct: +% +% markers.number_markers - scalar +% markers.number_samples - column array, number_markers x 1 +% markers.marker_names - cell array of strings, number_markers x 1 +% markers.trial_times - cell array of matrices, number_markers x 1 each +% containing number_samples x 2 matrix, where column 1 indicates the trial +% number containing the marker and column 2 indicates the offset (in sec). +% +% <>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +% < > +% < DISCLAIMER: > +% < > +% < THIS PROGRAM IS INTENDED FOR RESEARCH PURPOSES ONLY. > +% < THIS PROGRAM IS IN NO WAY INTENDED FOR CLINICAL OR > +% < OFFICIAL USE. > +% < > +% <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<> +% + +% $Revision: 1.1 $ $Date: 2009-01-30 03:49:27 $ + +% Copyright (C) 2004 Darren L. Weber +% +% This program is free software; you can redistribute it and/or +% modify it under the terms of the GNU General Public License +% as published by the Free Software Foundation; either version 2 +% of the License, or (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program; if not, write to the Free Software +% Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +% Modified: 12/2003, Darren.Weber_at_radiology.ucsf.edu +% - modified from NIH code readmarkerfile.m +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +markers = []; +ver = '$Revision: 1.1 $'; +fprintf('\nCTF_READ_MARKERFILE [v %s]\n',ver(11:15)); tic; + + + +if ~exist('mrkFile','var'), mrkFile = ''; end +if isempty(mrkFile), mrkFile = ''; end +if isstruct(mrkFile), mrkFile = ''; end +if mrkFile, + fid = fopen(mrkFile,'r'); +else + fid = -1; +end + +if fid < 0, + + % check the ctf.folder + if ~exist('ctf','var'), + ctf = ctf_folder; + else + ctf = ctf_folder([],ctf); + end + %fprintf('...reading from %s\n',ctf.folder); + + % use the ctf.folder to find .mrk file + if isfield(ctf,'folder'), + if isempty(ctf.folder), + error('ctf.folder is empty and no mrkFile specified'); + else + % check for a marker file + mrkFile = findmrkfile( ctf.folder ); + if exist(mrkFile) == 2, + fid = fopen(mrkFile,'r'); + else, + warning('...MarkerFile.mrk does not exist in this .ds folder.'); + ctf.markers = []; + return + end + end + else + error('ctf.folder is not a field of the ctf struct'); + end +end + + + + +% read the marker file, delimited by carriage returns. This new array is +% used below to extract relevant information +fprintf('...reading marker file:\n...%s\n', mrkFile); +fprintf('...reading file text, using ''\\n'' delimiter\n'); +mrkFileText = textread(mrkFile,'%s','delimiter','\n'); + +% extract the number of markers +number_markers_index = strmatch('NUMBER OF MARKERS:',mrkFileText,'exact'); +number_markers = str2num(mrkFileText{number_markers_index + 1}); +fprintf('...found %d marker types:\n',number_markers); + +% extract marker names (this can be an array, if number_markers > 1) +marker_names_index = strmatch('NAME:',mrkFileText,'exact'); +marker_names = mrkFileText(marker_names_index + 1); +for m = 1:length(marker_names), + fprintf(' %40s\n',marker_names{m}); +end + +% replace any '-' with '_' symbols in the marker names +marker_names = strrep(marker_names,'-','_'); +fprintf('...replaced any - with _ symbol in marker names\n'); + +% extract number of marker samples +% (this can be an array, if number_markers > 1) +number_samples_index = strmatch('NUMBER OF SAMPLES:',mrkFileText,'exact'); +number_samples = str2num(char(mrkFileText(number_samples_index + 1))); + +% check that all the marker samples are defined +if ~all(number_samples), + disp('One of the markers has no samples and was ignored.'); +end + + +% extract marker trial number and time (sec), eg, find & read: +% LIST OF SAMPLES: +% TRIAL NUMBER TIME FROM SYNC POINT (in seconds) +% +0 +0 +% +1 +0 +% +2 +0 + +fprintf('...reading trial numbers and offset time (sec)\n'); + +HEADER_LINES = 2; +trial = strmatch('LIST OF SAMPLES:',mrkFileText,'exact') + HEADER_LINES; + +for i = find(number_samples)' + % extract the lines of the samples, where each line contains a trial + % number in the first column and a time offset (sec) in the 2nd column + sample_text_rows = mrkFileText( trial(i):[trial(i) + number_samples(i)] ); + trials{i} = str2num(char(sample_text_rows)); + % add 1 to the trial numbers (which start at 0 for CTF software) + trials{i}(:,1) = trials{i}(:,1) + 1; +end +fprintf('...added 1 to trial numbers for matlab compatibility\n'); + +% allocate marker information into the marker stucture +markers = struct(... + 'file',mrkFile,... + 'number_markers',number_markers,... + 'number_samples',number_samples,... + 'marker_names',marker_names,... + 'trial_times',trials'); + +t = toc; fprintf('...done (%6.2f sec)\n\n',t); + +return + + + +% ------------------------------------------------------- +% find file name if truncated or with uppercase extension +% added by Arnaud Delorme, June 15, 2004 +function mrkname = findmrkfile( folder ) + mrkname = dir([ folder filesep '*.mrk' ]); + if isempty(mrkname) + mrkname = dir([ folder filesep '*.MRK' ]); + end; + if isempty(mrkname) + fprintf('...no file with extension .mrk or .MRK in .ds folder\n'); + mrkname = []; + else + mrkname = [ folder filesep mrkname.name ]; + end; +return diff --git a/ctf_read_meg4.m b/ctf_read_meg4.m new file mode 100644 index 0000000..1df32c1 --- /dev/null +++ b/ctf_read_meg4.m @@ -0,0 +1,458 @@ +function [ctf] = ctf_read_meg4(folder,ctf,CHAN,TIME,TRIALS,COEFS); + +% ctf_read_meg4 - read meg4 format data from a CTF .ds folder +% +% [ctf] = ctf_read_meg4([folder],[ctf],[CHAN],[TIME],[TRIALS]); +% +% This function reads all or select portions of the raw meg data matrix in +% the .meg4 file within any .ds folder. It may call the ctf_read_res4 +% function to identify the relevant parameters of the dataset. +% +% The .meg4 file contains the raw numbers sampled from the electronics. In +% this function, these raw analog2digial numbers are multiplied by the +% appropriate sensor gains, which are read from the .res4 file. However, +% note that the data values returned can be very small (10^-12 Tesla), +% which may be a problem for some computations. +% +% INPUTS +% +% If you do not wish to specify an input option, use [], but keep the order +% of the input options as above. Only specify as many input options as +% required. With no input options, the function will prompt for a folder, +% call ctf_read_res4 and then read all of the data matrix. +% +% folder - the directory of the .ds data set to read. By +% default, a gui prompts for the folder. +% +% ctf - a struct with setup, sensor and data fields. If the setup field is +% missing or empty, this function calls ctf_read_res4. +% +% CHAN - a integer array of channel numbers to read. +% eg, [30:35] reads channels 30 to 35. Also +% If CHAN = 'eeg', read only eeg channels/sensorIndices +% If CHAN = 'meg', read only meg channels/sensorIndices +% If CHAN = 'ref', read only reference channels/sensorIndices +% If CHAN = 'other', read only the other channels/sensorIndices +% If CHAN = 'megeeg', read meg and eeg channels/sensorIndices +% If CHAN = 'eegmeg', read eeg and meg channels/sensorIndices +% +% TIME - eg. [0 5] - the desired time interval to read, in sec. +% If TIME = 'all', all data is read (the default) +% +% TRIALS - If TRIALS = n, the nth trial will be read. +% If TRIALS = [3,5,8], reads trials 3,5, and 8 such that +% ctf.data(:,:,1) = data for trial 3, +% ctf.data(:,:,2) = data for trial 5, and +% ctf.data(:,:,3) = data for trial 8. +% If TRIALS = [3:7], reads trials 3 to 7 +% If TRIALS = 'all', reads all data (the default) +% +% OUTPUTS +% +% ctf.data - matrix of all the data read, such that data(x,y,z) +% contains sample point x, channel y and trial z. The +% input options, CHAN, TIME, TRIALS can be used to +% select subsections of the .meg4 data matrix +% +% ctf.sensor - has the following fields: +% .names - cell array of sensor names +% .location - array of sensor locations for plotting +% .orientation - array of sensor orientations +% +% ctf.res4 - has the following fields +% .file - the .res4 file path and file name +% .header - the format of the .res4 file +% +% ctf.meg4 - has the following fields +% .file - the .meg4 file path and file name +% .header - the format of the .meg4 file +% +% +% <>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> % +% < > % +% < DISCLAIMER: > % +% < > % +% < THIS PROGRAM IS INTENDED FOR RESEARCH PURPOSES ONLY. > % +% < THIS PROGRAM IS IN NO WAY INTENDED FOR CLINICAL OR > % +% < OFFICIAL USE. > % +% < > % +% <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<> % +% + + +% $Revision: 1.1 $ $Date: 2009-01-30 03:49:27 $ + +% Copyright (C) 2003 Darren L. Weber +% +% This program is free software; you can redistribute it and/or +% modify it under the terms of the GNU General Public License +% as published by the Free Software Foundation; either version 2 +% of the License, or (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program; if not, write to the Free Software +% Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +% Modified: 11/2003, Darren.Weber_at_radiology.ucsf.edu +% - modified from NIH code simply to allocate data into +% one large struct (ctf) +% - modified channel selection section at the end so +% that it doesn't try to get orientation information for +% EEG channels +% - changed ctf.data into a 3D matrix, rather than a +% cell array of matrices +% Modified: 07/2004, Arnaud Delorme, fixed reading time interval +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%-------------------------------------------------------------- +% check the function input parameters and assign any defaults + +if ~exist('CHAN','var'), CHAN = 'all'; end +if ~exist('TIME','var'), TIME = 'all'; end +if ~exist('TRIALS','var'), TRIALS = 'all'; end + +if isempty(CHAN), CHAN = 'all'; end +if isempty(TIME), TIME = 'all'; end +if isempty(TRIALS), TRIALS = 'all'; end + +CHAN = ctf_channel_select(ctf,CHAN); + +%----------------------------------------------- +% ensure we have the data parameters + +if ~exist('COEFS','var'), + COEFS = false; +end + +if ~exist('folder','var'), + if ~exist('ctf','var'), + ctf = ctf_folder; + else + ctf = ctf_folder([],ctf); + end +else + if ~exist('ctf','var'), + ctf = ctf_folder(folder); + else + ctf = ctf_folder(folder,ctf); + end +end + +if ~isfield(ctf,'setup'), + ctf = ctf_read_res4(ctf.folder,1,COEFS); +end + + + + +%-------------------------------------------------------------- +ver = '$Revision: 1.1 $'; +fprintf('\nCTF_READ_MEG4 [v %s]\n',ver(11:15)); tic; + + +%---------------------------------------------------------------- +% open the data file + +[folderPath,folderName,folderExt] = fileparts(ctf.folder); +ctf.meg4.file = findmeg4file( ctf.folder ); +[fid,message] = fopen(ctf.meg4.file,'rb','s'); +if fid < 0, error('cannot open .meg4 file'); end + + +%---------------------------------------------------------------- +% Read the header + +% The data file consists of a header and the raw samples from the +% electronics. The header is the 8-byte character sequence: MEG41CP+NULL. + +header_bytes = 8; + +ctf.meg4.header = char(fread(fid,[1,header_bytes],'char')); + +% check the format +if strmatch('MEG41CP',ctf.meg4.header), + % OK, we can handle this format +else + msg = sprintf('May not read "%s" format correctly',ctf.meg4.header); + warning(msg); +end + + + +%------------------------------------------------------------------- +% double check the input parameters + +switch num2str(TIME), + case 'all', + TIME = ctf.setup.time_sec; + TIME_index = 1:ctf.setup.number_samples; + otherwise + % assume the input is a range of times in sec + % check the range + if TIME(1) < ctf.setup.time_sec(1), + fprintf('...setting TIME(1) = ctf.setup.time_sec(1)\n'); + TIME(1) = ctf.setup.time_sec(1); + end + if TIME(end) > ctf.setup.time_sec(end), + fprintf('...setting TIME(end) = ctf.setup.time_sec(end)\n'); + TIME(end) = ctf.setup.time_sec(end); + end + % now find the nearest indices into the samples matrix + TIME_index = intersect(find(ctf.setup.time_sec >= TIME(1)), find(ctf.setup.time_sec <= TIME(end))); + % TIME_index = interp1(ctf.setup.time_sec,1:ctf.setup.number_samples,TIME,'nearest'); + % now ensure that the TIME array is consistent with ctf.setup.time_sec + TIME = ctf.setup.time_sec(TIME_index); +end +TIME = sort(TIME); + +% check the duration +duration = TIME(end) - TIME(1); +if duration > ctf.setup.duration_trial, + fprintf('...TIME input too large for trial\n'); + fprintf('...setting TIME = %g seconds (ctf.setup.duration_trial)',ctf.setup.duration_trial); + duration = ctf.setup.duration_trial; +end +if duration <= 0, + fprintf('...TIME(end) - TIME(1) is <= 0, quitting now!\n'); + return +end + + +% calculate the number of samples selected +number_samples = round((duration) * ctf.setup.sample_rate) + 1; + + + +switch num2str(TRIALS), + case 'all', + TRIALS = 1:ctf.setup.number_trials; + otherwise + % assume the input is an array of trials +end +TRIALS = unique(sort(TRIALS)); + + + + +%---------------------------------------------------------------- +% Calculate sensor gains + +megIndex = ctf.sensor.index.meg_sens; +refIndex = ctf.sensor.index.meg_ref; +eegIndex = ctf.sensor.index.eeg_sens; +otherIndex = ctf.sensor.index.other; + +channel_gain = zeros(1,ctf.setup.number_channels); + +channel_gain(megIndex) = [ctf.sensor.info(megIndex).proper_gain] .* [ctf.sensor.info(megIndex).q_gain]; +channel_gain(refIndex) = [ctf.sensor.info(refIndex).proper_gain] .* [ctf.sensor.info(refIndex).q_gain]; +channel_gain(eegIndex) = [ctf.sensor.info(eegIndex).q_gain]; +channel_gain(otherIndex) = [ctf.sensor.info(otherIndex).q_gain]; + + +%------------------------------------------------------------------------- +% Read trial data from .meg4 file + +% The data is stored as a sequence of (signed) 4-byte integers, starting +% with the first trial and first channel, then the first trial and second +% channel, etc. The number of channels per trial and the number of samples +% in every trialchannel block are constant per dataset. The constants are +% found in the general resources stored in the resource file, see 'The +% Resource File Format'. The numbers stored in the data file are the raw +% numbers collected from the electronics. For these numbers to be useful, +% the various gains, stored in the sensor resources, must be applied. + +number_trials = length(TRIALS); +number_channels = length(CHAN); + +dataSize = [number_samples, number_channels, number_trials]; +v = version('-release'); +if strmatch(v, {'11','12','13'}), + ctf.data = zeros(dataSize); +else, + ctf.data = repmat(single(0), dataSize); +end + +% Calculate trial byte size +trial_bytes = 4 * ctf.setup.number_samples * ctf.setup.number_channels; + +trial_count = 0; +for trial = 1:length(TRIALS), + + trial_number = TRIALS(trial); + + if trial > 1, + fprintf('\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b'); + end + fprintf('...reading %4d of %4d trials\n', trial, ctf.setup.number_trials); + + % calculate the byte offset in the file for this trial + trial_offset = header_bytes + ( trial_bytes * ( trial_number - 1 ) ); + + for channel = 1:length(CHAN), + + channel_number = CHAN(channel); + + % calculate the channel offset in the current trial + channel_offset = 4 * ctf.setup.number_samples * ( channel_number - 1 ); + + % seek to the trial offset, relative to the beginning of the file + fseek(fid,trial_offset,-1); + + % now seek to the channel offset, in the current trial + fseek(fid,channel_offset,0); + + % read the entire set of samples for this channel + channel_samples = fread(fid, [ctf.setup.number_samples,1], 'int32'); + + % extract just the selected time array + channel_samples = channel_samples(TIME_index); + + if channel_gain(channel_number), + channel_samples2tesla = channel_samples ./ channel_gain(channel_number); + else + channel_samples2tesla = channel_samples; + end + + % assign the selected time samples into the ctf.data matrix + ctf.data(:,channel,trial) = channel_samples2tesla; + + end +end + +fclose(fid); + + + + + + + + + + +%------------------------------------------------------------------------- +% assign sensor locations and orientations for selected channels, this +% section will simplify the data allocated by ctf_read_res4 + +fprintf('...sorting %d from %d sensors\n',number_channels, ctf.setup.number_channels); + +ctf.sensor.location = zeros(3,number_channels); +ctf.sensor.orientation = zeros(3,number_channels); + +ctf.sensor.label = []; +ctf.sensor.location = []; +ctf.sensor.orientation = []; + +for c = 1:length(CHAN), + + channel = CHAN(c); + + % All channels have a label + ctf.sensor.label{1,c} = ctf.sensor.info(channel).label; + + % All channels have a location + + % EEG channels do not have any orientation + + switch ctf.sensor.info(channel).index, + + case {ctf.sensor.type.meg_sens, ctf.sensor.type.meg_ref}, + %0=Reference Channels, + %1=More Reference Channels, + %5=MEG Channels + + % MEG channels are radial gradiometers, so they have an inner (1) and + % an outer (2) location - it might be better to take the average of + % their locations + if ~isempty(ctf.sensor.info(channel).location), + ctf.sensor.location(:,c) = ctf.sensor.info(channel).location(:,1); + end + + if ~isempty(ctf.sensor.info(channel).orientation), + ctf.sensor.orientation(:,c) = ctf.sensor.info(channel).orientation(:,1); + end + + case ctf.sensor.type.eeg_sens, + %9=EEG Channels + + if ~isempty(ctf.sensor.info(channel).location), + ctf.sensor.location(:,c) = ctf.sensor.info(channel).location(:,1); + end + + end +end + + + + + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% NEED TO CHECK ctf.setup parameters here, to adjust for any changes +% required by the CHAN, TIME, TRIALS inputs +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +% modify the setup parameters so they correspond with the data selected +ctf.setup.number_samples = number_samples; +ctf.setup.number_channels = number_channels; +ctf.setup.number_trials = number_trials; + +if ctf.setup.number_samples ~= size(ctf.data,1), + error('ctf.setup.number_samples ~= size(ctf.data,1)'); +end +if ctf.setup.number_channels ~= size(ctf.data,2), + error('ctf.setup.number_channels ~= size(ctf.data,2)'); +end +if ctf.setup.number_trials ~= size(ctf.data,3), + error('ctf.setup.number_trials ~= size(ctf.data,3)'); +end + + +t = toc; fprintf('...done (%6.2f sec)\n\n',t); + +return + + + +% find file name if truncated or with uppercase extension +% added by Arnaud Delorme June 15, 2004 +% ------------------------------------------------------- +function meg4name = findmeg4file( folder ) + +meg4name = dir([ folder filesep '*.meg4' ]); +if isempty(meg4name) + meg4name = dir([ folder filesep '*.MEG4' ]); +end; + +if isempty(meg4name) + error('No file with extension .meg4 or .MEG4 in selected folder'); +else + meg4name = [ folder filesep meg4name.name ]; +end; + +return + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% ------------------------------------------------------- +function sensorName = parse_sensor_label(temp) + +% sensorName = parse_sensor_label(temp) +% parse sensor label names + +temp(temp>127) = 0; +temp(temp<0) = 0; +temp = strtok(temp,char(0)); +temp = strtok(temp,'-'); +sensorName = char(temp)'; + +return diff --git a/ctf_read_mri.m b/ctf_read_mri.m new file mode 100644 index 0000000..ea002b8 --- /dev/null +++ b/ctf_read_mri.m @@ -0,0 +1,433 @@ +function mri = ctf_read_mri(file) + +% ctf_read_mri - read a CTF .mri file +% +% mri = ctf_read_mri(fileName) +% +% The CTF MRI File format used by MRIViewer consists of a binary file with +% a 1,028 byte header. The MRI data can be in 8-bit (unsigned character) or +% 16-bit (unsigned short integer) format and consists of 256 x 256 pixel +% slices, stored as 256 contiguous sagittal slices from left to right (or +% right to left if head orientation is left-on-right). Each slice is stored +% as individual pixels starting at the left, anterior, superior +% corner and scanning downwards row by row. Therefore the coronal +% position is fastest changing, axial position second fastest +% changing and sagittal position slowest changing value in the +% file, always in the positive direction for each axis (see section +% on Head Coordinate System for axis definitions). By default CTF +% MRI files have the file extension .mri +% + +% $Revision: 1.1 $ $Date: 2009-01-30 03:49:27 $ + +% Copyright (C) 2003 Darren L. Weber +% +% This program is free software; you can redistribute it and/or +% modify it under the terms of the GNU General Public License +% as published by the Free Software Foundation; either version 2 +% of the License, or (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program; if not, write to the Free Software +% Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +% History: 08/2003, Darren.Weber_at_radiology.ucsf.edu +% - adapted from an appendex to CTF document +% MRIConverter.pdf, which is copied at the end of this +% function. +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +ver = '[$Revision: 1.1 $]'; +fprintf('\nCTF_READ_MRI [v%s]\n',ver(12:16)); tic; + +if ~exist('file','var'), + [fileName, filePath, filterIndex] = uigetfile('*.mri', 'Locate CTF .mri file'); + file = fullfile(filePath, fileName); +elseif isempty(file), + fprintf('...file is empty\n'); + [fileName, filePath, filterIndex] = uigetfile('*.mri', 'Locate CTF .mri file'); + file = fullfile(filePath, fileName); +end +if ~exist(file,'file'), + fprintf('...file does not exist\n'); + [fileName, filePath, filterIndex] = uigetfile('*.mri', 'Locate CTF .mri file'); + file = fullfile(filePath, fileName); +end + +mri.file = file; +fprintf('...reading %s\n', file); + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% open the file for reading +% 'ieee-be.l64' or 's' - IEEE floating point with big-endian byte +% ordering and 64 bit long data type. +[fid,message] = fopen(mri.file,'rb','s'); +if fid < 0, error('cannot open file'); end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% read the file header +fprintf('...reading header '); +mri.hdr = Version_2_Header_read(fid); + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% check header size, header should be 1028 bytes +header_bytes = ftell(fid); +fprintf('(%d bytes)\n',header_bytes); +if header_bytes ~= 1028, + msg = sprintf('failed to read 1028 bytes from the header, read %d bytes',header_bytes); + error(msg); +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% seek beyond the header, to the beginning of the data matrix +fseek(fid,1028,'bof'); + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% check if the data is 8 or 16 bits +switch mri.hdr.dataSize, + case 1, % we have 8 bit data + fprintf('...reading 8 bit image data\n'); + precision = 'uchar'; + case 2, % we have 16 bit data + fprintf('...reading 16 bit image data\n'); + precision = 'int16'; + otherwise, + msg = sprintf('unknown mri.hdr.dataSize: %g',mri.hdr.dataSize); + error(msg); +end + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% read the image data array + +% adjust for matlab version +ver = version; +ver = str2num(ver(1)); +if ver < 6, + data = fread(fid,inf,sprintf('%s',precision)); +else, + data = fread(fid,inf,sprintf('%s=>double',precision)); +end +fclose(fid); + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% now we have the data array, allocate it to a 3D matrix + +% The CTF MRI File format used by MRIViewer consists of a binary file with a +% 1,028 byte header. The MRI data can be in 8-bit (unsigned character) or 16-bit +% (unsigned short integer) format and consists of 256 x 256 pixel slices, stored as +% 256 contiguous sagittal slices from left to right (or right to left if head orientation +% is "left-on-right"). Each slice is stored as individual pixels starting at the +% top left corner and scanning downwards row by row. Therefore the coronal +% position is fastest changing, axial position second fastest changing and sagittal +% position slowest changing value in the file, always in the positive direction for +% each axis (see section on Head Coordinate System for axis definitions). By +% default CTF MRI files have the file extension ".mri" + +% MRIViewer uses these cardinal directions as axes in an internal coordinate system +% where sagittal = X, coronal = Y and axial = Z forming an additional +% right-handed coordinate system which is translated and rotated with respect to +% the Head Coordinate System and has its origin at the upper left anterior corner +% of the volume. + +PixelDim = 256; +RowDim = 256; +SliceDim = 256; + +% imageOrientation, 0 = left on left, 1 = left on right +switch mri.hdr.imageOrientation, + case 0, + fprintf('...sagittal slices are neurological orientation (left is on the left)\n'); + fprintf('...+X left to right, +Y anterior to posterior, +Z superior to inferior\n'); + case 1, + fprintf('...sagittal slices are radiological orientation (left is on the right)\n'); + fprintf('...+X right to left, +Y anterior to posterior, +Z superior to inferior\n'); + otherwise, + msg = sprintf('...unknown mri.hdr.imageOrientation: %d\n',mri.hdr.imageOrientation); + error(msg); +end + +mri.img = zeros(SliceDim,PixelDim,RowDim); + +n = 1; +y = 1:PixelDim; % +Y is from anterior to posterior + +for x = 1:SliceDim, % +X is from left to right + for z = 1:RowDim, % +Z is from superior to inferior + mri.img(x,y,z) = data(n:n+(PixelDim-1)); + n = n + PixelDim; + end +end + + + +t=toc; fprintf('...done (%5.2f sec).\n\n',t); + +return + + + + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function Version_2_Header = Version_2_Header_read(fid), + +tmp = fread(fid,[1,32],'char'); +tmp(find(tmp<0)) = 0; +Version_2_Header.identifierString = char( tmp ); + +% check the header format version is 2.2 +if strmatch('CTF_MRI_FORMAT VER 2.2',Version_2_Header.identifierString), + % OK this function should read this +else + msg = sprintf('this function is not designed to read this format:\n%s\n',Version_2_Header.identifierString); + warning(msg); +end + +Version_2_Header.imageSize = fread(fid,1,'short'); % always = 256 +Version_2_Header.dataSize = fread(fid,1,'short'); % 1 or 2 (bytes), 8 or 16 bits +Version_2_Header.clippingRange = fread(fid,1,'short'); % max. integer value of data +Version_2_Header.imageOrientation = fread(fid,1,'short'); % eg., 0 = left on left, 1 = left on right + +% voxel dimensions in mm +Version_2_Header.mmPerPixel_sagittal = fread(fid,1,'float'); +Version_2_Header.mmPerPixel_coronal = fread(fid,1,'float'); +Version_2_Header.mmPerPixel_axial = fread(fid,1,'float'); + +Version_2_Header.HeadModel_Info = headModel(fid); % defined below... +Version_2_Header.Image_Info = imageInfo(fid); % defined below... + +% voxel location of head origin +Version_2_Header.headOrigin_sagittal = fread(fid,1,'float'); +Version_2_Header.headOrigin_coronal = fread(fid,1,'float'); +Version_2_Header.headOrigin_axial = fread(fid,1,'float'); + +% euler angles to align MR to head coordinate system (angles in degrees!) +% 1. rotate in coronal plane by this angle +% 2. rotate in sagittal plane by this angle +% 3. rotate in axial plane by this angle +Version_2_Header.rotate_coronal = fread(fid,1,'float'); +Version_2_Header.rotate_sagittal = fread(fid,1,'float'); +Version_2_Header.rotate_axial = fread(fid,1,'float'); + +Version_2_Header.orthogonalFlag = fread(fid,1,'short'); % if set then image is orthogonal +Version_2_Header.interpolatedFlag = fread(fid,1,'short'); % if set than image was interpolated + +% original spacing between slices before interpolation to CTF format +Version_2_Header.originalSliceThickness = fread(fid,1,'float'); + +% transformation matrix head->MRI [column][row] +Version_2_Header.transformMatrix = fread(fid,[4 4],'float')'; + + +Version_2_Header.transformMatrixHead2MRI = Version_2_Header.transformMatrix; +Version_2_Header.transformMatrixMRI2Head = inv(Version_2_Header.transformMatrix); + +% padding to 1028 bytes +%tmp = fread(fid,[1,202],'uchar'); % according to CTF manual, this should +%be 202, but it reads out to the 1028 bytes with 204. So maybe there are a +%few bytes in the file read operations above that are missed? +tmp = fread(fid,[1,204],'uchar'); +tmp = zeros(size(tmp)); +Version_2_Header.unused = char( tmp ); % uchar + +return + + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function HeadModel_Info = headModel(fid), + +% this function is called from Version_2_Header_read + +% fid. point coordinate (in voxels) +HeadModel_Info.Nasion_Sag = fread(fid,1,'short'); % nasion - sagittal +HeadModel_Info.Nasion_Cor = fread(fid,1,'short'); % nasion - coronal +HeadModel_Info.Nasion_Axi = fread(fid,1,'short'); % nasion - axial +HeadModel_Info.LeftEar_Sag = fread(fid,1,'short'); % left ear - sagittal +HeadModel_Info.LeftEar_Cor = fread(fid,1,'short'); % left ear - coronal +HeadModel_Info.LeftEar_Axi = fread(fid,1,'short'); % left ear - axial +HeadModel_Info.RightEar_Sag = fread(fid,1,'short'); % right ear - sagittal +HeadModel_Info.RightEar_Cor = fread(fid,1,'short'); % right ear - coronal +HeadModel_Info.RightEar_Axi = fread(fid,1,'short'); % right ear - axial + +fread(fid,2,'char'); % padding to 4 byte boundary - from Robert Oostenveld + +% default sphere origin +HeadModel_Info.defaultSphereX = fread(fid,1,'float'); % sphere origin x coordinate ( in mm ) +HeadModel_Info.defaultSphereY = fread(fid,1,'float'); % sphere origin y coordinate ( in mm ) +HeadModel_Info.defaultSphereZ = fread(fid,1,'float'); % sphere origin z coordinate ( in mm ) +HeadModel_Info.defaultSphereRadius = fread(fid,1,'float'); % default sphere radius ( in mm ) + +return + + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function Image_Info = imageInfo(fid), + +% this function is called from Version_2_Header_read + +Image_Info.modality = fread(fid,1,'short'); % 0 = MRI, 1 = CT, 2 = PET, 3 = SPECT, 4 = OTHER +Image_Info.manufacturerName = char( fread(fid,[1,64],'char') ); +Image_Info.instituteName = char( fread(fid,[1,64],'char') ); +Image_Info.patientID = char( fread(fid,[1,32],'char') ); +Image_Info.dateAndTime = char( fread(fid,[1,32],'char') ); +Image_Info.scanType = char( fread(fid,[1,32],'char') ); +Image_Info.contrastAgent = char( fread(fid,[1,32],'char') ); +Image_Info.imagedNucleus = char( fread(fid,[1,32],'char') ); + +fread(fid,2,'char'); % padding to 4 byte boundary - from Robert Oostenveld + +Image_Info.Frequency = fread(fid,1,'float'); +Image_Info.FieldStrength = fread(fid,1,'float'); +Image_Info.EchoTime = fread(fid,1,'float'); +Image_Info.RepetitionTime = fread(fid,1,'float'); +Image_Info.InversionTime = fread(fid,1,'float'); +Image_Info.FlipAngle = fread(fid,1,'float'); +Image_Info.NoExcitations = fread(fid,1,'short'); +Image_Info.NoAcquisitions = fread(fid,1,'short'); + +tmp = fread(fid,[1,256],'char'); +tmp = zeros(size(tmp)); +Image_Info.commentString = char( tmp ); + +tmp = fread(fid,[1,64],'char'); +tmp = zeros(size(tmp)); +Image_Info.forFutureUse = char( tmp ); + +return + + + + + + + + +% The CTF MRI File format used by MRIViewer consists of a binary file with a +% 1,028 byte header. The MRI data can be in 8-bit (unsigned character) or 16-bit +% (unsigned short integer) format and consists of 256 x 256 pixel slices, stored as +% 256 contiguous sagittal slices from left to right (or right to left if head orientation +% is “left-on-right”). Each slice is stored as individual pixels starting at the +% top left corner and scanning downwards row by row. Therefore the coronal +% position is fastest changing, axial position second fastest changing and sagittal +% position slowest changing value in the file, always in the positive direction for +% each axis (see section on Head Coordinate System for axis definitions). By +% default CTF MRI files have the file extension ".mri" +% The following is the C language header definitions for the CTF Format MRI +% File (current version is 2.2). Note that the Version_2_Header structure comprises +% the file header and contains other structures also defined below and is +% padded out to 1028 bytes. This is followed immediately by the voxel data +% itself. +% typedef struct Version_2_Header { +% char identifierString[32]; // "CTF_MRI_FORMAT VER 2.2" +% short imageSize; // always = 256 +% short dataSize; // 1 or 2 (bytes) +% short clippingRange; // max. integer value of data +% short imageOrientation; // eg., 0 = left on left, 1 = left on right +% float mmPerPixel_sagittal; // voxel dimensions in mm +% float mmPerPixel_coronal; // voxel dimensions in mm +% float mmPerPixel_axial; // voxel dimensions in mm +% HeadModel_Info headModel; // defined below... +% Image_Info imageInfo; // defined below.. +% float headOrigin_sagittal; // voxel location of head origin +% float headOrigin_coronal; // voxel location of head origin +% float headOrigin_axial; // voxel location of head origin +% // euler angles to align MR to head coordinate system (angles in degrees!) +% float rotate_coronal; // 1. rotate in coronal plane by this angle +% float rotate_sagittal; // 2. rotate in sagittal plane by this angle +% float rotate_axial; // 3. rotate in axial plane by this angle +% short orthogonalFlag; // if set then image is orthogonal +% short interpolatedFlag // if set than image was interpolated +% float originalSliceThickness // original spacing between slices before interpolation +% float transformMatrix[4][4] // transformation matrix head->MRI [column][row] +% unsigned char unused[202]; // padding to 1028 bytes +% } Version_2_Header; +% typedef struct HeadModel_Info { +% short Nasion_Sag; // fid. point coordinate (in voxels) for nasion - sagittal +% short Nasion_Cor; // nasion - coronal +% short Nasion_Axi; // nasion - axial +% short LeftEar_Sag; // left ear - sagittal +% short LeftEar_Cor; // left ear - coronal +% short LeftEar_Axi; // left ear - axial +% short RightEar_Sag; // right ear - sagittal +% short RightEar_Cor; // right ear - coronal +% short RightEar_Axi; // right ear - axial +% float defaultSphereX; // default sphere origin x coordinate ( in mm ) +% float defaultSphereY; // sphere origin y coordinate ( in mm ) +% float defaultSphereZ; // sphere origin z coordinate ( in mm ) +% float defaultSphereRadius; // default sphere radius ( in mm ) +% } HeadModel_Info; +% typedef struct Image_Info { +% short modality; // 0 = MRI, 1 = CT, 2 = PET, 3 = SPECT, 4 = OTHER +% char manufacturerName[64]; +% char instituteName[64]; +% char patientID[32]; +% char dateAndTime[32]; +% char scanType[32]; +% char contrastAgent[32]; +% char imagedNucleus[32]; +% float Frequency; +% float FieldStrength; +% float EchoTime; +% float RepetitionTime; +% float InversionTime; +% float FlipAngle; +% short NoExcitations; +% short NoAcquisitions; +% char commentString[256]; +% char forFutureUse[64]; +% } Image_Info; + + + + +% From MRIViewer.pdf + +% CTF MRI Coordinate System +% In contrast, the MRI coordinate system, shown in Figure 3, is defined by the +% orthogonal viewing directions typically used in radiology -- sagittal, coronal +% (also termed frontal) and axial (also termed horizontal). +% +% MRIViewer uses these cardinal directions as axes in an internal coordinate system +% where sagittal = X, coronal = Y and axial = Z forming an additional +% right-handed coordinate system which is translated and rotated with respect to +% the Head Coordinate System and has its origin at the upper left anterior corner +% of the volume. +% Upon defining the landmark or “fiduciary” locations set by the placement of +% the head localization coils an internal representation of the MEG Head Coordinate +% System is defined using the same convention as that of the MEG acquisition +% software described above. This information combined with the voxel +% resolution in each direction is used to construct an internal transformation +% matrix (T) that is used to automatically convert any 3-dimensional location in +% the Head Coordinate System to any voxel location in the MRI. Thus, a point +% P(x, y, z) specified in the Head Coordinate System (see Figure 3) can be converted +% to the MRI voxel P'(x', y', z') by multiplication by the transformation +% matrix T where P' = TP. This immediate conversion can be seen by moving +% the cursor through any given view (hold left mouse button down and drag) +% which will display at the top of the image the voxel location and x, y, z location +% (in centimeters) in the Head Coordinate System for the current cursor position. +% In a similar manner an inverse transformation, P = T^-1 P' can be used to convert +% any MRI voxel to the corresponding location in the Head Coordinate System. For a +% transformation matrix of this type, T^-1 = T'. The fiduciary location information +% is stored with the MRI data file and retrieved upon rereading +% the image file into MRIViewer. +% +% The command-line program 'mrihead' can be used to print the transformation matrix and other MRI +% parameters to the screen for any given CTF format MRI file, based on the default fiduciary points +% last saved with the file. diff --git a/ctf_read_res4.m b/ctf_read_res4.m new file mode 100644 index 0000000..7bb38c8 --- /dev/null +++ b/ctf_read_res4.m @@ -0,0 +1,616 @@ +function [ctf] = ctf_read_res4(folder,VERBOSE,COEFS); + +% ctf_read_res4 - Read a CTF .res4 file +% +% ctf = ctf_read_res4( [folder], [verbose], [coefs]) +% +% This function reads the resource information from a CTF .ds folder. This +% resource information must be read before reading the .meg4 data file. +% All input arguments are optional. +% +% INPUTS +% +% folder: the .ds directory containing the data to be read. With +% no input, it will prompt with a gui folder locator +% (called by ctf_folder). +% +% verbose: If verbose = 1, display 'ctf.setup' structure (default) +% If verbose = 0, do not display 'ctf.setup' structure +% +% coefs: an option to read the MEG sensor and reference coefficients, +% which give the weights for calculation of synthetic 2nd or 3rd +% order gradiometers. +% If coefs = 1, read the sensor coefficients +% If coefs = 0, do not read the sensor coefficients (this is the +% default because it is assumed that data preprocessing with +% CTF tools has already applied AND saved a synthetic +% gradiometer transformation for the meg4 data file). The +% ctf.sensor.info(x).grad_order_no will indicate the gradient +% order of the data (this only applies to MEG sensors, other +% channels have zero values). +% +% OUTPUTS +% +% ctf.folder - path of the .ds folder +% +% ctf.res4.file - data file path/name +% ctf.res4.header - data format header +% +% ctf.setup - a header structure consisting of date, time, run name, run +% title, subject, run description, operator, number of channels, number +% of samples, sample rate, number of trials, duration, pretrigger_samples, +% sensor filename, head zeroing, and number of filters. +% +% ctf.sensor.index - a sensor structure consisting of EEG sensors, MEG +% sensors, reference sensors, and other sensors. +% +% ctf.sensor.info - a structure with gain and offset information consisting +% of proper gain, Q gain, io gain, io offset, and index. +% +% The proper gain is the channel-wide constant quotient of a value in raw +% units and a value in user units. (For EEG this is one because there is +% no conversion; i.e., the values are in volts, for MEG there is conversion +% between phi0 and teslas). +% proper gain = raw value / user value +% +% The Q-gain is used to convert the 32-bit integers produced by the +% electronics to the raw values stored in the data file. +% raw value = 32 bit value / Q gain +% +% The IO-gain is essentially a correction factor that is applied to the +% raw values before they are stored to disk. +% +% +% <>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +% < > +% < DISCLAIMER: > +% < > +% < THIS PROGRAM IS INTENDED FOR RESEARCH PURPOSES ONLY. > +% < THIS PROGRAM IS IN NO WAY INTENDED FOR CLINICAL OR > +% < OFFICIAL USE. > +% < > +% <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<> +% + +% $Revision: 1.1 $ $Date: 2009-01-30 03:49:27 $ + +% Copyright (C) 2003 Darren L. Weber +% +% This program is free software; you can redistribute it and/or +% modify it under the terms of the GNU General Public License +% as published by the Free Software Foundation; either version 2 +% of the License, or (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program; if not, write to the Free Software +% Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +% Modified: 11/2003, Darren.Weber_at_radiology.ucsf.edu +% - modified from NIH code readresfile.m +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +ver = '$Revision: 1.1 $'; +fprintf('\nCTF_READ_RES4 [v %s]\n',ver(11:15)); tic; + +if ~exist('folder','var'), + ctf = ctf_folder; +else + ctf = ctf_folder(folder); +end +%[folderPath,folderName,folderExt] = fileparts(ctf.folder); +ctf.res4.file = findres4file(ctf.folder); + +if ~exist('VERBOSE','var'), VERBOSE = 1; end +if ~exist('COEFS','var'), COEFS = 0; end + +%---------------------------------------------------------------- +% open the data file + +[fid,message] = fopen(ctf.res4.file,'rb','ieee-be.l64'); +if fid < 0, error('cannot open .res4 file'); end + + +%------------------------------------------------------------- +% READ HEADER + +fseek(fid,0,-1); +ctf.res4.header = char(fread(fid,8,'char'))'; + +% check for the right format +if strmatch('MEG41RS',ctf.res4.header), + % OK, we can handle this format +else + msg = sprintf('This function is designed to read MEG41RS format.\nIt may not read "%s" format correctly',ctf.res4.header); + warning(msg); +end + + +%------------------------------------------------------------- +% READ SETUP + + +%---DATE/TIME +fseek(fid, 778,-1); +ctf.setup.time = char(fread(fid,255,'char'))'; +fseek(fid,1033,-1); +ctf.setup.date = char(fread(fid,255,'char'))'; + +%---NUMBER OF SAMPLES +fseek(fid,1288,-1); +ctf.setup.number_samples = (fread(fid,1,'int32')'); + +%---NUMBER OF CHANNELS +fseek(fid,1292,-1); +ctf.setup.number_channels = (fread(fid,1,'int16')'); + +%---SAMPLE RATE +fseek(fid,1296,-1); +ctf.setup.sample_rate = fread(fid,1,'double')'; +ctf.setup.sample_msec = 1000 / ctf.setup.sample_rate; +ctf.setup.sample_sec = 1 / ctf.setup.sample_rate; + +%---NUMBER OF TRIALS +fseek(fid,1312,-1); +ctf.setup.number_trials = fread(fid,1,'int16')'; +fseek(fid, 776,-1); +ctf.setup.number_trials_averaged = fread(fid,1,'int16'); + +%---DURATION +fseek(fid,1304,-1); +ctf.setup.duration_total = fread(fid,1,'double'); +ctf.setup.duration_trial = ctf.setup.duration_total / ctf.setup.number_trials; + +%---PRE_TRIG POINTS +fseek(fid,1316,-1); +ctf.setup.pretrigger_samples = fread(fid,1,'int32'); +ctf.setup.pretrigger_msec = (ctf.setup.pretrigger_samples / ctf.setup.sample_rate) * 1000; + +%---HEAD ZEROING +fseek(fid,1348,-1); +h_zero = fread(fid,1,'int32')'; +no_yes = {'no','yes'}; +ctf.setup.head_zero = no_yes{h_zero+1}; + +%---RUN NAME +fseek(fid,1360,-1); +ctf.setup.run_name = char(fread(fid,32,'char'))'; + +%---RUN TITLE +fseek(fid,1392,-1); +ctf.setup.run_title = char(fread(fid,256,'char'))'; + +%---SUBJECT +fseek(fid,1712,-1); +ctf.setup.subject = char(fread(fid,32,'char'))'; + +%---OPERATOR +fseek(fid,1744,-1); +ctf.setup.operator = char(fread(fid,32,'char'))'; + +%---SENSOR FILE NAME +fseek(fid,1776,-1); +ctf.setup.sensor_file_name = char(fread(fid,60,'char'))'; + +%---RUN DESCRIPTION & FILTERS +fseek(fid,1836,-1); +run_size = fread(fid,1,'int32'); +fseek(fid,1844,-1); +ctf.setup.run_description = char(fread(fid,run_size,'char')); + +ctf.setup.number_filters = fread(fid,1,'int16'); + +for i = 1:ctf.setup.number_filters, + ctf.setup.filters(i).freq = fread(fid,1,'double'); + ctf.setup.filters(i).class = fread(fid,1,'int32'); + ctf.setup.filters(i).type = fread(fid,1,'int32'); + ctf.setup.filters(i).numparam = fread(fid,1,'int16'); + ctf.setup.filters(i).params = fread(fid,ctf.setup.filters(i).numparam,'double'); +end + +if(COEFS) + b = 1846 + run_size; + if(ctf.setup.number_filters == 0) + np = 0; + else + np = sum([ctf.setup.filters.numparam]); + warning('3rd gradient + hardware filter parameters not fully tested! let''s see what happens... :)'); + end + nf = ctf.setup.number_filters; + f = ( nf * 18 ) + ( np * 8 ); + offset = b + f + ctf.setup.number_channels * 1360; +end + + +%------------------------------------------------------------- +% CREATE TIME ARRAYS + +% the time arrays must be based on increments of the sample_msec +ctf.setup.time_msec = [0:ctf.setup.number_samples - 1]' * ctf.setup.sample_msec; +ctf.setup.time_msec = ctf.setup.time_msec - ctf.setup.pretrigger_msec; + +% adjust the sample point closest to zero so that it is zero, if it +% is reasonably close to zero, say within 3 decimal places for msec timing +zero_index = find(abs(ctf.setup.time_msec) == min(abs(ctf.setup.time_msec))); +zero_value = ctf.setup.time_msec(zero_index); +if (-0.0001 < zero_value) & (zero_value < 0.0001), + ctf.setup.time_msec(zero_index) = 0; +end + +ctf.setup.start_msec = ctf.setup.time_msec(1); +ctf.setup.end_msec = ctf.setup.time_msec(end); + +ctf.setup.time_sec = ctf.setup.time_msec / 1000; +ctf.setup.start_sec = ctf.setup.time_sec(1); +ctf.setup.end_sec = ctf.setup.time_sec(end); + + +%------------------------------------------------------------- +% PRINT SETUP +if VERBOSE, + ctf_print_setup(ctf); +end + + + + + +%------------------------------------------------------------- +% READ SENSOR INFORMATION + +ctf.sensor.info = struct(... + 'proper_gain',[],... + 'q_gain',[],... + 'io_gain',[],... + 'io_offset',[],... + 'index',[],... + 'extra',[],... + 'label',[],... + 'grad_order_no',[]); + +% read channel names +for chan = 1:ctf.setup.number_channels, + temp = fread(fid,32,'char'); + ctf.sensor.info(chan).label = parse_sensor_label(temp); +end + +for chan = 1:ctf.setup.number_channels, + + + % The proper gain is the channel-wide constant quotient of a value in raw + % units and a value in user units. (For EEG this is one because there is + % no conversion; i.e., the values are in volts, for MEG there is conversion + % between phi0 and teslas). + % proper gain = raw value / user value + % + % The Q-gain is used to convert the 32-bit integers produced by the + % electronics to the raw values stored in the data file. + % raw value = 32 bit value / Q gain + % + % The IO-gain is essentially a correction factor that is applied to the + % raw values before they are stored to disk. + + + %ftell(fid); + + ctf.sensor.info(chan).index = fread(fid,1,'int16'); + ctf.sensor.info(chan).extra = fread(fid,1,'int16'); + id = fread(fid,1,'int32')+1; + ctf.sensor.info(chan).proper_gain = fread(fid,1,'double'); + ctf.sensor.info(chan).q_gain = fread(fid,1,'double'); + ctf.sensor.info(chan).io_gain = fread(fid,1,'double'); + ctf.sensor.info(chan).io_offset = fread(fid,1,'double'); + fread(fid,1,'int16'); + ctf.sensor.info(chan).grad_order_no = fread(fid,1,'int16'); + fread(fid,1,'int32'); + + %fseek(fid,ftell(fid)+6,0); + + for pos = 1:8, + ctf.sensor.info(chan).coil(pos).position.x = fread(fid,1,'double'); + ctf.sensor.info(chan).coil(pos).position.y = fread(fid,1,'double'); + ctf.sensor.info(chan).coil(pos).position.z = fread(fid,1,'double'); + fread(fid,1,'double'); + ctf.sensor.info(chan).coil(pos).orient.x = fread(fid,1,'double'); + ctf.sensor.info(chan).coil(pos).orient.y = fread(fid,1,'double'); + ctf.sensor.info(chan).coil(pos).orient.z = fread(fid,1,'double'); + fread(fid,1,'double'); + fread(fid,1,'int16'); + fread(fid,1,'int32'); + fread(fid,1,'int16'); + fread(fid,1,'double'); + + %fseek(fid,ftell(fid)+56,0); + %fseek(fid,ftell(fid)-80,0); + end + + for pos = 1:8, + ctf.sensor.info(chan).hcoil(pos).position.x = fread(fid,1,'double'); + ctf.sensor.info(chan).hcoil(pos).position.y = fread(fid,1,'double'); + ctf.sensor.info(chan).hcoil(pos).position.z = fread(fid,1,'double'); + fread(fid,1,'double'); + ctf.sensor.info(chan).hcoil(pos).orient.x = fread(fid,1,'double'); + ctf.sensor.info(chan).hcoil(pos).orient.y = fread(fid,1,'double'); + ctf.sensor.info(chan).hcoil(pos).orient.z = fread(fid,1,'double'); + fread(fid,1,'double'); + fread(fid,1,'int16'); + fread(fid,1,'int32'); + fread(fid,1,'int16'); + fread(fid,1,'double'); + + %fseek(fid,ftell(fid)+56,0); + %fseek(fid,ftell(fid)+80,0); + end + %fseek(fid,ftell(fid)+1288,-1); +end + + + + +%------------------------------------------------------------- +% Find channel types and define channel sets, see the +% System Administrators .pdf, 'Channel Sets Configuration' + +ctf = ctf_channel_sets(ctf); + + + +%------------------------------------------------------------- +% Channel coordinates, in centimeters, in subject head space + +for chan = 1:ctf.setup.number_channels, + + switch ctf.sensor.info(chan).index, + + case {0,1,5}, + %0=Reference Magnetometers + %1=Reference Gradiometers + %5=MEG Channels + + coord = [ctf.sensor.info(chan).hcoil(1:2).position]; + ctf.sensor.info(chan).location = [coord.x; coord.y; coord.z]; + + orient = [ctf.sensor.info(chan).hcoil(1).orient]; + ctf.sensor.info(chan).orientation = [orient.x; orient.y; orient.z]; + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % This ensures that the orientation of the sensor is away from the + % center of a sphere. It uses the sign of the dot product between + % the orientation vector and the location vector. + tmp = ctf.sensor.info(chan).orientation' * ctf.sensor.info(chan).location; + tmp = sign(tmp(1)); + ctf.sensor.info(chan).orientation = tmp * ctf.sensor.info(chan).orientation; + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + case 9, + %EEG Channels + + coord = [ctf.sensor.info(chan).hcoil(1:2).position]; + ctf.sensor.info(chan).location = [coord.x; coord.y; coord.z]; + ctf.sensor.info(chan).orientation = []; + + end +end + + +%------------------------------------------------------------------------- +% assign sensor locations and orientations +% simplify information in the ctf.sensor.info struct + +ctf.sensor.location = zeros(3,ctf.setup.number_channels); +ctf.sensor.orientation = zeros(3,ctf.setup.number_channels); + +ctf.sensor.label = []; +ctf.sensor.location = []; +ctf.sensor.orientation = []; + +for c = 1:ctf.setup.number_channels, + + % All channels have a label + ctf.sensor.label{1,c} = strtok(ctf.sensor.info(c).label,'-'); + + % All channels have a location + % EEG channels do not have any orientation + if length(ctf.sensor.type.meg_ref) > 1, ind2 = 2; else ind2 = 1; end; + + switch ctf.sensor.info(c).index, + + case {ctf.sensor.type.meg_sens, ctf.sensor.type.meg_ref(1), ctf.sensor.type.meg_ref(ind2)}, + % modification above based on bug 438 of EEGLAB - Arnaud Delorme, August 2007 + %0=Reference Channels, + %1=More Reference Channels, + %5=MEG Channels + + % MEG channels are radial gradiometers, so they have an inner (1) and + % an outer (2) location - it might be better to take the average of + % their locations + if ~isempty(ctf.sensor.info(c).location), + ctf.sensor.location(:,c) = ctf.sensor.info(c).location(:,1); + end + + if ~isempty(ctf.sensor.info(c).orientation), + ctf.sensor.orientation(:,c) = ctf.sensor.info(c).orientation(:,1); + end + + case ctf.sensor.type.eeg_sens, + %9=EEG Channels + + if ~isempty(ctf.sensor.info(c).location), + ctf.sensor.location(:,c) = ctf.sensor.info(c).location(:,1); + end + + end +end + + + + + + +%%%%%% Coefficient reading appended by SSD %%%%%% + +if(COEFS) + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % NUMBER OF COEFFICIENTS, byte offset = b+f+nc*1360, byte size = 1 + + fseek(fid,offset,-1); + ctf.res4.numberCoefficients = fread(fid,1,'int16'); + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % SENSOR COEFFICIENT RECORDS, byte offset = b+f+nc*1360+2, byte size = 1992 + + if VERBOSE & ctf.res4.numberCoefficients, + fprintf('...reading %d coefficients\n',ctf.res4.numberCoefficients); + end + + SENSOR_LABEL = 31; + MAX_NUM_COEFS = 50; + MAX_BALANCING = MAX_NUM_COEFS; + + hexadef = {'00000000','47314252','47324252','47334252','47324f49','47334f49'}; + strdef = {'NOGRAD','G1BR','G2BR','G3BR','G2OI','G3OI'}; + + for i = 1:ctf.res4.numberCoefficients, + + % read the sensor name (channel label) + temp = fread(fid,[1,32],'char'); + sensorName = parse_sensor_label(temp); + sensorIndex = strmatch( sensorName, {ctf.sensor.info.label} ); + + % read the coefficient type + coefType = fread(fid,1,'bit32'); + + padding = fread(fid,1,'int32'); % not sure why this is needed??? + + % read the coefficient record + numberCoefs = fread(fid,1,'int16'); + + if numberCoefs > MAX_NUM_COEFS, + msg = sprintf('numberCoefs > MAX_NUM_COEFS\n'); + warning(msg); + end + + sensor_list = char(fread(fid,[SENSOR_LABEL,MAX_BALANCING],'uchar')'); + % clean-up the sensor_list + sensor_list = sensor_list(1:numberCoefs,:); + for j=1:numberCoefs, + temp = strtok(sensor_list(j,:),char(0)); + temp = strtok(temp,'-'); + % check if this sensor is a reference + refLabels = {ctf.sensor.info(ctf.sensor.index.meg_ref).label}; + refIndex = strmatch(temp,refLabels); + if refIndex, + % ensure this one has the same label + temp = refLabels{refIndex}; + end + + new_sensor_list(j) = refIndex; + end + sensor_list = ctf.sensor.index.meg_ref(:,new_sensor_list)'; + + coefs_list = fread(fid,MAX_BALANCING,'double'); + % clean-up the coefs_list + coefs_list = coefs_list(1:numberCoefs,:)'; + + % allocate the coefficient parameters into the ctf struct + ctf.res4.sensorCoef(i).sensorName = sensorName; + ctf.res4.sensorCoef(i).coefType = coefType; + ctf.res4.sensorCoef(i).coefRec.numberCoefs = numberCoefs; + ctf.res4.sensorCoef(i).coefRec.sensor_list = sensor_list; + ctf.res4.sensorCoef(i).coefRec.coefs_list = coefs_list; + + + + % DLW: + % This is a brainstorm variable, note the use of coefType + % Not clear why this is checked and allocated as such + coefType = find( hex2dec(hexadef) == coefType ); + if coefType, + CoefInfo{sensorIndex,coefType-1}.numberCoefs = numberCoefs; + CoefInfo{sensorIndex,coefType-1}.sensor_list = sensor_list; + CoefInfo{sensorIndex,coefType-1}.coefs = coefs_list; + end + end + + + + % Channel Gains + gain_chan = zeros(size(ctf.setup.number_channels,1),1); + gain_chan(ctf.sensor.index.meg_sens) = ([ctf.sensor.info(ctf.sensor.index.meg_sens).proper_gain]'.*[ctf.sensor.info(ctf.sensor.index.meg_sens).q_gain]'); + gain_chan(ctf.sensor.index.meg_ref) = ([ctf.sensor.info(ctf.sensor.index.meg_ref).proper_gain]'.*[ctf.sensor.info(ctf.sensor.index.meg_ref).q_gain]'); + % gain_chan(ieegsens) = 1./([SensorRes(ieegsens).qGain]'*1e-6); + % gain_chan(ieegsens) = 1./([SensorRes(ieegsens).qGain]'); + % gain_chan(iothersens) = ([SensorRes(iothersens).qGain]'); % Don't know exactly which gain to apply here + + + + % Calculus of the matrix for nth-order gradient correction + % Coefficients for unused reference channels are weigthed by zeros in + % the correction matrix. + Gcoef = zeros(length(ctf.sensor.index.meg_sens),length(min(ctf.sensor.index.meg_ref):max(ctf.sensor.index.meg_ref))); + grad_order_no = 3*ones(306,1); + for k = 1:length(ctf.sensor.index.meg_sens) + + % Reference coils for channel k + if grad_order_no(ctf.sensor.index.meg_sens(k)) == 0 + %Data is saved as RAW + %Save 3rd order gradient sensor-list for subsequent correction if requested later by the user + [refs] = (CoefInfo{ctf.sensor.index.meg_sens(k),3}.sensor_list); + Gcoef(k,refs-min(ctf.sensor.index.meg_ref)+1) = CoefInfo{ctf.sensor.index.meg_sens(k),3}.coefs ... + .* gain_chan(refs)'/gain_chan(ctf.sensor.index.meg_sens(k)); + else + [refs] = (CoefInfo{ctf.sensor.index.meg_sens(k),grad_order_no(ctf.sensor.index.meg_sens(k))}.sensor_list); + Gcoef(k,refs-min(ctf.sensor.index.meg_ref)+1) = CoefInfo{ctf.sensor.index.meg_sens(k),grad_order_no(ctf.sensor.index.meg_sens(k))}.coefs ... + .* gain_chan(refs)/gain_chan(ctf.sensor.index.meg_sens(k)); + end + ctf.sensor.info(ctf.sensor.index.meg_sens(k)).Gcoef = Gcoef(k,:); + end +end %% end COEF block + + +fclose(fid); + +t = toc; fprintf('...done (%6.2f sec)\n\n',t); + +return + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% ------------------------------------------------------- +function res4name = findres4file( folder ) + +% find file name if truncated or with uppercase extension +% added by Arnaud Delorme June 15, 2004 + +res4name = dir([ folder filesep '*.res4' ]); +if isempty(res4name) + res4name = dir([ folder filesep '*.RES4' ]); +end + +if isempty(res4name) + error('No file with extension .res4 or .RES4 in selected folder'); +else + res4name = [ folder filesep res4name(1).name ]; +end; +return + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% ------------------------------------------------------- +function sensorName = parse_sensor_label(temp) + +% sensorName = parse_sensor_label(temp) +% parse sensor label names + +temp(temp>127) = 0; +temp(temp<0) = 0; +temp = strtok(temp,char(0)); +temp = strtok(temp,'-'); +sensorName = char(temp)'; + +return diff --git a/ctf_read_svl.m b/ctf_read_svl.m new file mode 100644 index 0000000..58a6fa3 --- /dev/null +++ b/ctf_read_svl.m @@ -0,0 +1,100 @@ +function [SAMimage, coords, stepsize] = ctf_read_svl(filename) +% ctf_read_svl - reads SAM image from a .svl file (generated by SAMsrc) +% +% [SAMimage, coords, stepsize] = ctf_read_svl(filename) +% +% Returns SAMimage as voxels x 1 array of intensities +% coords contains corresponding voxel locations +% + +% $Revision: 1.1 $ $Date: 2009-01-30 03:49:27 $ + +% Copyright (C) 2005, Sarang Dalal and Darren Weber +% +% This program is free software; you can redistribute it and/or +% modify it under the terms of the GNU General Public License +% as published by the Free Software Foundation; either version 2 +% of the License, or (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program; if not, write to the Free Software +% Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, +% USA. + +% History: 10/2005, Darren.Weber_at_radiology.ucsf.edu +% Sarang Dalal developed nut_read_svl.m +% DLW adapted nut_read_svl.m into ctf functions +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +ver = '$Revision: 1.1 $ $Date: 2009-01-30 03:49:27 $'; +fprintf('CTF_READ_SVL [v %s]\n',ver(11:15)); + +if(nargin < 1) + help ctf_read_svl; + return; +end + +fid=fopen(filename,'r','b'); +identity = transpose(fread(fid,8,'*char')); +if(~strcmp(identity,'SAMIMAGE')) + error('This doesn''t look like a SAM IMAGE file.'); +end +vers = fread(fid,1,'int32'); +setname = fread(fid,256,'*char'); + +% int32 vs. double for fiducial locations: +% The CTF svl format assumes that the fiducials will be +% integer values when defined in terms of MRI voxel +% indices, but will be floating point values when +% defined in MEG head coordinates. +numchans = fread(fid,1,'int32'); +numweights = fread(fid,1,'int32'); +if(numweights ~= 0) + warning('... numweights ~= 0'); +end + +padbytes1 = fread(fid,1,'int32'); + +xstart = fread(fid,1,'double'); +xend = fread(fid,1,'double'); +ystart = fread(fid,1,'double'); +yend = fread(fid,1,'double'); +zstart = fread(fid,1,'double'); +zend = fread(fid,1,'double'); +stepsize = fread(fid,1,'double'); + +[meshz,meshy,meshx]=ndgrid(zstart:stepsize:zend,ystart:stepsize:yend,xstart:stepsize:xend); +coords = [meshx(:) meshy(:) meshz(:)]; + +hpfreq = fread(fid,1,'double'); +lpfreq = fread(fid,1,'double'); +bwfreq = fread(fid,1,'double'); +meannoise = fread(fid,1,'double'); + +MRIname = transpose(fread(fid,256,'*char')); +nasion = fread(fid,3,'int32'); +rightPA = fread(fid,3,'int32'); +leftPA = fread(fid,3,'int32'); + +SAMtype = fread(fid,1,'int32'); +SAMunit = fread(fid,1,'int32'); + +padbytes2 = fread(fid,1,'int32'); + +% DLW: why are these doubles and those above are int32? +nasion_meg = fread(fid,3,'double'); +rightPA_meg = fread(fid,3,'double'); +leftPA_meg = fread(fid,3,'double'); + +SAMunitname = fread(fid,32,'*char'); + +SAMimage = fread(fid,inf,'double'); + +fclose(fid); + +return diff --git a/ctf_regions.m b/ctf_regions.m new file mode 100644 index 0000000..d998a42 --- /dev/null +++ b/ctf_regions.m @@ -0,0 +1,246 @@ +function [ctf] = ctf_regions(ctf); + +% ctf_channel_sets - Define CTF MEG sensor regions +% +% ctf = ctf_read_res4(ctf) +% +% This function parses the resource information in ctf.sensor, +% which is returned from ctf_read_res4 +% +% INPUTS +% +% ctf - the struct created by ctf_read_res4 +% +% OUTPUTS +% +% ctf.sensor.index - various regional sensor indices +% +% <>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +% < > +% < DISCLAIMER: > +% < > +% < THIS PROGRAM IS INTENDED FOR RESEARCH PURPOSES ONLY. > +% < THIS PROGRAM IS IN NO WAY INTENDED FOR CLINICAL OR > +% < OFFICIAL USE. > +% < > +% <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<> +% + +% $Revision: 1.1 $ $Date: 2009-01-30 03:49:27 $ + +% Copyright (C) 2004 Darren L. Weber +% +% This program is free software; you can redistribute it and/or +% modify it under the terms of the GNU General Public License +% as published by the Free Software Foundation; either version 2 +% of the License, or (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program; if not, write to the Free Software +% Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +% Modified: 02/2004, Darren.Weber_at_radiology.ucsf.edu +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +ver = '$Revision: 1.1 $'; +fprintf('\nCTF_CHANNEL_SETS [v %s]\n',ver(11:15)); tic; + +if ~exist('ctf','var'), + ctf = ctf_folder; +end + +if ~isfield(ctf,'setup'), + ctf = ctf_read_res4(ctf.folder); +end + +%------------------------------------------------------------- +% Find channel types and define channel sets, see the +% System Administrators .pdf, 'Channel Sets Configuration' + +%types = unique([ctf.sensor.info.index]) +% 0 1 5 9 11 17 +%for typeValue = types, +% index = find([ctf.sensor.info.index] == typeValue); +% labels = ctf.sensor.info(index).label; +%end + + +% find the indices of the MEG reference sensors + +ctf.sensor.type.meg_ref = [0 1]; +ctf.sensor.type.refMagnetometers = 0; % include B* +ctf.sensor.type.refGradiometers = 1; % include G*,P*,Q*,R* + +magref = find([ctf.sensor.info.index] == 0); +gradref = find([ctf.sensor.info.index] == 1); + +ctf.sensor.index.ref_mag = magref; +ctf.sensor.index.ref_grad = gradref; +ctf.sensor.index.meg_ref = [magref,gradref]; + + +% find the indices of the MEG head sensors + +ctf.sensor.type.meg_sens = 5; % include B* +ctf.sensor.index.meg_sens = find([ctf.sensor.info.index] == 5); + + +% find the indices of the EEG head sensors + +ctf.sensor.type.eeg_sens = 9; % include EEG* +ctf.sensor.index.eeg_sens = find([ctf.sensor.info.index] == 9); + + +% find the indices of the STIM channels + +ctf.sensor.type.stim_ref = 11; % include STIM* +ctf.sensor.index.stim_ref = find([ctf.sensor.info.index] == 11); + + +% find the indices of the system clock + +ctf.sensor.type.sclk_ref = 17; % include SCLK* + +ctf.sensor.index.sclk_ref = find([ctf.sensor.info.index] == 17); + + +% find the indices of virtual channels +%ctf.sensor.type.vc = ??; +%vcsens = find([ctf.sensor.info.index] == ??); + + +ctf.sensor.index.all_sens = [ ctf.sensor.index.meg_sens, ctf.sensor.index.eeg_sens ]; + +all = [ ctf.sensor.index.all_sens, ctf.sensor.index.meg_ref, ... + ctf.sensor.index.stim_ref, ctf.sensor.index.sclk_ref ]; + +ctf.sensor.index.other = setdiff([1:ctf.setup.number_channels],all); + + +% define regions of MEG sensors + + +ctf.sensor.index.meg_left_central = []; +ctf.sensor.index.meg_left_frontal = []; +ctf.sensor.index.meg_left_occipital = []; +ctf.sensor.index.meg_left_parietal = []; +ctf.sensor.index.meg_left_temporal = []; +ctf.sensor.index.meg_right_central = []; +ctf.sensor.index.meg_right_frontal = []; +ctf.sensor.index.meg_right_occipital = []; +ctf.sensor.index.meg_right_parietal = []; +ctf.sensor.index.meg_right_temporal = []; +ctf.sensor.index.meg_mid_central = []; +ctf.sensor.index.meg_mid_frontal = []; +ctf.sensor.index.meg_mid_occipital = []; +ctf.sensor.index.meg_mid_parietal = []; + + +for megIndex = ctf.sensor.index.meg_sens, + megLabel = ctf.sensor.info(megIndex).label; + if findstr('MLC',megLabel), + % these are MEG left central + ctf.sensor.index.meg_left_central(end+1) = megIndex; + end + if findstr('MLF',megLabel), + % these are MEG left frontal + ctf.sensor.index.meg_left_frontal(end+1) = megIndex; + end + if findstr('MLO',megLabel), + % these are MEG left occipital + ctf.sensor.index.meg_left_occipital(end+1) = megIndex; + end + if findstr('MLP',megLabel), + % these are MEG left parietal + ctf.sensor.index.meg_left_parietal(end+1) = megIndex; + end + if findstr('MLT',megLabel), + % these are MEG left temporal + ctf.sensor.index.meg_left_temporal(end+1) = megIndex; + end + if findstr('MRC',megLabel), + % these are MEG right central + ctf.sensor.index.meg_right_central(end+1) = megIndex; + end + if findstr('MRF',megLabel), + % these are MEG right frontal + ctf.sensor.index.meg_right_frontal(end+1) = megIndex; + end + if findstr('MRO',megLabel), + % these are MEG right occipital + ctf.sensor.index.meg_right_occipital(end+1) = megIndex; + end + if findstr('MRP',megLabel), + % these are MEG right parietal + ctf.sensor.index.meg_right_parietal(end+1) = megIndex; + end + if findstr('MRT',megLabel), + % these are MEG right temporal + ctf.sensor.index.meg_right_temporal(end+1) = megIndex; + end + if findstr('MZC',megLabel), + % these are MEG mid central + ctf.sensor.index.meg_mid_central(end+1) = megIndex; + end + if findstr('MZF',megLabel), + % these are MEG mid frontal + ctf.sensor.index.meg_mid_frontal(end+1) = megIndex; + end + if findstr('MZO',megLabel), + % these are MEG mid occipital + ctf.sensor.index.meg_mid_occipital(end+1) = megIndex; + end + if findstr('MZP',megLabel), + % these are MEG mid parietal + ctf.sensor.index.meg_mid_parietal(end+1) = megIndex; + end +end + +ctf.sensor.index.meg_left = [ ... + ctf.sensor.index.meg_left_central, ... + ctf.sensor.index.meg_left_frontal, ... + ctf.sensor.index.meg_left_occipital, ... + ctf.sensor.index.meg_left_parietal, ... + ctf.sensor.index.meg_left_temporal ]; + +ctf.sensor.index.meg_right = [ ... + ctf.sensor.index.meg_right_central, ... + ctf.sensor.index.meg_right_frontal, ... + ctf.sensor.index.meg_right_occipital, ... + ctf.sensor.index.meg_right_parietal, ... + ctf.sensor.index.meg_right_temporal ]; + +ctf.sensor.index.meg_central = [ ... + ctf.sensor.index.meg_left_central, ... + ctf.sensor.index.meg_right_central, ... + ctf.sensor.index.meg_mid_central ]; + +ctf.sensor.index.meg_frontal = [ ... + ctf.sensor.index.meg_left_frontal, ... + ctf.sensor.index.meg_right_frontal, ... + ctf.sensor.index.meg_mid_frontal ]; + +ctf.sensor.index.meg_occipital = [ ... + ctf.sensor.index.meg_left_occipital, ... + ctf.sensor.index.meg_right_occipital, ... + ctf.sensor.index.meg_mid_occipital ]; + +ctf.sensor.index.meg_parietal = [ ... + ctf.sensor.index.meg_left_parietal, ... + ctf.sensor.index.meg_right_parietal, ... + ctf.sensor.index.meg_mid_parietal ]; + +ctf.sensor.index.meg_temporal = [ ... + ctf.sensor.index.meg_left_temporal, ... + ctf.sensor.index.meg_right_temporal ]; + + +t = toc; fprintf('...done (%6.2f sec)\n\n',t); + +return diff --git a/ctf_resample.m b/ctf_resample.m new file mode 100644 index 0000000..8157086 --- /dev/null +++ b/ctf_resample.m @@ -0,0 +1,268 @@ +function ctf = ctf_resample(folder,newFreq) +% ctf_resample - Resamples a CTF .ds folder to a different sampling rate. +% +% ctf = ctf_resample(folder,newFreq) +% +% The function modifies two files in the .ds folder: +% +% *.meg4 - the raw data +% *.res4 - the data resource file (essentially a header). +% +% This function calls the matlab resample function. There is also a +% -resample option in the ctf software command, newDs, but it does not +% specify the sample rate in Hz. +% +% INPUTS: folder (optional - brings up a file selector if not specified): +% This is the .ds folder containing both the .meg4 and the .res4 +% files +% NEWFREQ: Frequency (in Hz) that you want to pretend the data were sampled +% at. This can be lower or higher than the actual sampling +% frequency. +% RETURNS: 'ctf': the ctf data structure (without the raw data): contains the new +% parameters for sample_rate etc +% + +% $Revision: 1.1 $ $Date: 2009-01-30 03:49:27 $ +% +% Copyright (C) 2003 Alex Wade wade@ski.org +% +% This program is free software; you can redistribute it and/or +% modify it under the terms of the GNU General Public License +% as published by the Free Software Foundation; either version 2 +% of the License, or (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program; if not, write to the Free Software +% Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +% Modified: 05/2003, Alex Wade wade@ski.org +% - Wrote it +% Not tested with pretrigger points or averaged data sets. +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +%-------------------------------------------------------------- +ver = '$Revision: 1.1 $'; + +fprintf('\nCTF_RESAMPLE [v %s]\n',ver(11:15)); tic; + +% Populate the 'ctf' data structure +if exist('folder','var') + if(~isempty(folder)) + ctf = ctf_read_meg4(folder,[],[],[0 0]); % Read in no actual data + else + ctf = ctf_read_meg4([],[],[],[0 0]); % + end +else + ctf = ctf_read_meg4([],[],[],[0 0]); % +end + + + + + + +if ~exist('COEFS','var'), + COEFS = false; +end + +if ~exist('folder','var'), + if ~exist('ctf','var'), + ctf = ctf_folder; + else + ctf = ctf_folder([],ctf); + end +else + if ~exist('ctf','var'), + ctf = ctf_folder(folder); + else + ctf = ctf_folder(folder,ctf); + end +end + +if ~isfield(ctf,'setup'), + ctf = ctf_read_res4(ctf.folder,1,COEFS); +end + + + + + +% RESAMPLING GOES HERE... +% A typical ctf data structure looks like... +% folder: [1x97 char] +% res4: [1x1 struct] +% setup: [1x1 struct] +% sensor: [1x1 struct] +% meg4: [1x1 struct] +% data: [294000x275 double] + +% The fields to change are: +% ctf.setup.sample_rate +% ctf.setup.number_samples +% ctf.setup.sample_sec +% ctf.setup.sample_msec +% ctf.setup.pretrigger_samples (if there were any) +% ctf.setup.run_description (to append the fact that we've resampled the +% data) +% +% + +oldFreq = ctf.setup.sample_rate; + +nChannels = ctf.setup.number_channels; +nPoints = ctf.setup.sample_rate * ctf.setup.duration_trial; +nTrials = ctf.setup.number_trials; +newNPoints = round(nPoints * newFreq / oldFreq); % This should match 'resample's idea of the new number of points + +ctf.setup.sample_rate = newFreq; +ctf.setup.number_samples = newNPoints; +ctf.setup.sample_sec = (ctf.setup.sample_sec * oldFreq / newFreq); +ctf.setup.sample_msec = ctf.setup.sample_sec * 1000; +ctf.setup.pretrigger_samples = round(ctf.setup.pretrigger_samples * newFreq / oldFreq); + +% When we write out the meg4 file, we will just skip the first 8 bytes (the +% header 'MEG41CP'+13? and then start fwriting (signed) 4-byte integers +% ('int32') + +fidOld = fopen(ctf.meg4.file,'rb+','s'); % 'ieee-be.l64' or 's' - IEEE floating point with big-endian byte +fidNew = fopen([ctf.meg4.file,'.resamp'],'wb','s'); +% ordering and 64 bit long data type. + +if (fidOld<0) + error('Could not open meg4 file for reading - does it exist?'); +end +if (fidNew<0) + fclose(fidOld); + error('Could not open new meg4 file for writing - check file permissions'); +end + +disp('Copying header'); +header=fread(fidOld,8,'char'); % Start writing at the 9th byte (first 8 are the header) +cnt=fwrite(fidNew,header,'char'); +if (cnt~=8) + fclose(fidOld); + fclose(fidNew); + error('Failed to write to the new meg4 file.'); +end +% Loop over trials and channels +disp('Resampling...'); +h=waitbar(0,'Resampling'); + +% Resample will work on the columns of a data matrix. But it runs out of +% memory if we try to process the whole thing at once. So we will do it +% channel by channel at the same time that we write it out... + +for thisTrial = 1:nTrials + for thisChannel = 1:nChannels + % Do resampling on raw data from disk - not stuff stored in + % ctf.data. Avoids any messing around with channel gains... + + origData = fread(fidOld,nPoints,'int32'); + % Using the default matlab resamp params. + newDataVector = round((resample(double(origData),newFreq,oldFreq))); + + cnt = fwrite(fidNew,newDataVector,'int32'); + + if (cnt ~= newNPoints) % Check for write success + disp(cnt); + disp(newNPoints); + fclose(fidNew); + error('Failed to write all the data - check to see if the disk is full and whether you have the correct permissions'); + end + waitbar(thisChannel/nChannels); + end +end + +close(h); % Close the progress bar + +% Close the files +fclose(fidOld); +fclose(fidNew); +fprintf('\nDone meg4\n'); + +% Finished writing the raw data.... + +% Now create a new .res4 file. +fidOld = fopen(ctf.res4.file,'rb','ieee-be.l64'); +fidNew = fopen([ctf.res4.file,'.resamp'],'wb','ieee-be.l64'); + +if fidOld < 0, error('cannot open original.res4 file'); end +if fidNew < 0 + fclose(fidOld); + error('Cannot open temp.res4 file'); +end + +% Copy the first set of data from the file +buff = fread(fidOld,1288,'uint8'); +cnt = fwrite(fidNew,buff,'uint8'); +if (cnt ~= length(buff)) + fclose(fidOld); + fclose(fidNew); + error('Failed to write to the new res4 file.'); +end + +%---NUMBER OF SAMPLES +dummy = fread(fidOld,1,'int32'); +cnt = fwrite(fidNew,ctf.setup.number_samples,'int32'); + +% Only check writing once +if (cnt~=1) + fclose(fidOld); + fclose(fidNew); + error('Failed to write to the new res4 file.'); +end + +%---SAMPLE RATE +% Copy next 4 bytes +buff = fread(fidOld,4,'uint8'); +cnt = fwrite(fidNew,buff,'uint8'); +if (cnt ~= length(buff)) + fclose(fidOld); + fclose(fidNew); + error('Failed to write to the new res4 file.'); +end +dummy = fread(fidOld,1,'double'); +cnt = fwrite(fidNew,ctf.setup.sample_rate,'double'); +if (cnt ~= 1) + fclose(fidOld); + fclose(fidNew); + error('Failed to write to the new res4 file.'); +end +% copy next 16 bytes +buff = fread(fidOld,16,'uint8'); +cnt = fwrite(fidNew,buff,'uint8'); +if (cnt ~= length(buff)) + fclose(fidOld); + fclose(fidNew); + error('Failed to write to the new res4 file.'); +end + +%---PRETRIGGER POINTS +cnt = fwrite(fidNew,ctf.setup.pretrigger_samples,'int32'); +if (cnt ~= 1) + fclose(fidOld); + fclose(fidNew); + error('Failed to write to the new res4 file.'); +end + +dummy = fread(fidOld,1,'int32'); + +buff = fread(fidOld,inf,'uint8'); +cnt = fwrite(fidNew,buff,'uint8'); +if (cnt ~= length(buff)) + fclose(fidOld); + fclose(fidNew); + error('Failed to write to the new res4 file.'); +end + +fclose(fidOld); +fclose(fidNew); + + +return diff --git a/ctf_stim2dat.m b/ctf_stim2dat.m new file mode 100644 index 0000000..5c6dd7a --- /dev/null +++ b/ctf_stim2dat.m @@ -0,0 +1,104 @@ +function makeDatFromCTF(filesearch,datfilename,typego,typebutton) + +% makeDatFromCTF +% filesearch is a string that if used with dir, can identify all files +% necssary to include. Make sure you're in the right directory. It should +% lead to files with columns of continuous STIM channel output +% typego lists the types of stim that one should expect button responses +% to. +% typebutton is the button response one should get. 0 if not buttonpress + +if (nargin < 3) + typego = [6 7 8 9]; + typebutton = [2 0 0 0]; +end + +respvals = [33554432 65536 262144 327680 393216 458752 524288 589824]; +resptype = [2 1 4 5 6 7 8 9]; +maxtypeval = 589824; % above this should be button presses only. +RESPLENGTH = 50; + +fs = 1200; +buttonwait = fs*1.5; +numHeaderLines = 19; +files = dir(filesearch); + +allStim = []; +for i = 1:length(files) + fprintf('Getting Data from %s ... \n',files(i).name); + [time,stim] = textread(files(i).name,'%f %f','delimiter','\t','headerlines',2); + allStim = [allStim;stim]; + clear time stim; +end + +fid = fopen(datfilename,'W'); + +for i = 1:numHeaderLines + fprintf(fid,'\n'); +end + +fprintf(fid,'Trial\tResp\tType\tCorrect\tLatency\tStim/Resp\n'); +fprintf(fid,'-----\t----\t----\t-------\t-------\t---------\n'); +fprintf(fid,'1\t0\t1\t1\t1000\tStim\n'); + +i = 1; +trialnum = 2; +while i <= length(allStim) + nextJump = 1; + tmp = allStim(i:min(i+RESPLENGTH,length(allStim))); + if (tmp(1) > 10 && ~isempty(find(respvals == max(tmp))) && max(tmp) <= maxtypeval) + type = resptype(find(respvals == max(allStim(i:i+RESPLENGTH)))); + + correct = 1; + latency = 0; + buttonPressed = 0; + + if (~isempty(find(typego == type))) % s2 occured, look for button press + validButton = typebutton(find(typego == type)); + j = i + RESPLENGTH; + correct = 0; + + while j < i + buttonwait % see if a button was pressed during the wait period + tmp = allStim(j:min(j+RESPLENGTH,length(allStim))); + if (~isempty(tmp) && tmp(1) > 10 && ~isempty(find(respvals == max(tmp)))) + latency = round((j - i) * 1000 / fs); + buttonPressed = resptype(find(respvals == max(tmp))); + j = i + buttonwait; + + end + j = j + 1; + end + + if (buttonPressed == validButton) + correct = 1; + end + + end + + if (~buttonPressed) % get Latency if not button pressed + j = i + RESPLENGTH; + cont = 1; + while (cont && j < length(allStim)) + j = j + 1; + tmp = allStim(j:min(j+RESPLENGTH,length(allStim))); + if (isempty(tmp)) + cont = 0; + elseif (tmp(1) > 10 && ~isempty(find(respvals == max(tmp))) && max(tmp) <= maxtypeval) + cont = 0; + end + end + latency = round((j - i) * 1000 / fs); + nextJump = (j - i) - 1; + else + nextJump = round(latency * fs / 1000) + RESPLENGTH; + end + fprintf(fid,'%d\t%d\t%d\t%d\t%d\tStim\n',trialnum,buttonPressed,type,correct,latency); + trialnum = trialnum+1; + end + i = i + nextJump; +end + +fclose(fid); + +fprintf('***********************************************\n'); +fprintf('%s created successfully: %d events found\n\n',datfilename,trialnum); diff --git a/ctf_stim_sortRT.m b/ctf_stim_sortRT.m new file mode 100644 index 0000000..567086c --- /dev/null +++ b/ctf_stim_sortRT.m @@ -0,0 +1,28 @@ +function ctf = sortrtctf(ctfds) + +RESPTHRESH = 10^7; + +if nargin < 1 + ctfds = ''; +end + +ctf = ctf_read(ctfds); + +stim_chan = find(strcmp(ctf.sensor.label,'STIM')); + +if (length(stim_chan) == 1) + stim_data = ctf.data(:,stim_chan,:); +else + error('ERROR: could not properly locate STIM channel'); +end + +RTs = []; +for i = 1:size(stim_data,3) + tmp = stim_data(:,1,i); + RTs(end+1) = min(find(tmp > RESPTHRESH)); +end + +[RTs_sorted,RTsx] = sort(RTs); + +ctf.data = ctf.data(:,:,RTsx); + diff --git a/ctf_write_ascii.m b/ctf_write_ascii.m new file mode 100644 index 0000000..7abee9d --- /dev/null +++ b/ctf_write_ascii.m @@ -0,0 +1,134 @@ +function ctf_write_ascii(OutputFilePrefix,ctf,CHAN,TIME,TRIALS) + +% ctf_write_ascii - write ctf.data into ascii file +% +% ctf_write_ascii(OutputFilePrefix,ctf,CHAN,TIME,TRIALS) +% +% OutputFilePrefix - a file prefix is used so that data information can be +% appended to the file name. The default value is to use the ctf.folder +% filename. +% +% CHAN - see ctf_channel_select for options +% TIME - see ctf_read for options (given in msec) +% TRIALS - select 1 trial to plot (the default is trial = 1) +% +% The output data matrix is time (rows) x channels (columns) +% +% <>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +% < > +% < DISCLAIMER: > +% < > +% < THIS PROGRAM IS INTENDED FOR RESEARCH PURPOSES ONLY. > +% < THIS PROGRAM IS IN NO WAY INTENDED FOR CLINICAL OR > +% < OFFICIAL USE. > +% < > +% <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<> +% + +% $Revision: 1.1 $ $Date: 2009-01-30 03:49:27 $ + +% Copyright (C) 2004 Darren L. Weber +% +% This program is free software; you can redistribute it and/or +% modify it under the terms of the GNU General Public License +% as published by the Free Software Foundation; either version 2 +% of the License, or (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program; if not, write to the Free Software +% Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +% Modified: 07/2004, Darren.Weber_at_radiology.ucsf.edu +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +ver = '$Revision: 1.1 $'; +fprintf('\nCTF_WRITE_ASCII [v %s]\n',ver(11:15)); tic; + +if ~exist('ctf','var'), + error('no input ctf data struct!'); +end + +if ~exist('OutputFilePrefix','var'), + [ctfPath, ctfFolder, ext] = fileparts(ctf.folder); + OutputFilePrefix = ctfFolder; +end +if isempty(OutputFilePrefix), + [ctfPath, ctfFolder, ext] = fileparts(ctf.folder); + OutputFilePrefix = ctfFolder; +end + +if ~exist('CHAN','var'), CHAN = 'all'; end +if ~exist('TIME','var'), TIME = 'all'; end +if ~exist('TRIALS','var'), TRIALS = 1; end + +if isempty(CHAN), CHAN = 'all'; end +if isempty(TIME), TIME = 'all'; end +if isempty(TRIALS), TRIALS = 1; end + +% This function calls ctf_channel_select +[CHAN,type] = ctf_channel_select(ctf,CHAN); + +switch num2str(TIME), + case 'all', + TIME = ctf.setup.time_msec; + TIME_index = 1:ctf.setup.number_samples; +otherwise + fprintf('...sorry, time restrictions not implemented correctly (03/2004)\n'); + TIME = ctf.setup.time_msec; + TIME_index = 1:ctf.setup.number_samples; + + + % % assume the input is a range of times in sec + % % check the range + % if TIME(1) > ctf.setup.time_msec(1), + % fprintf('...setting TIME(1) = ctf.setup.time_msec(1)\n'); + % TIME(1) = ctf.setup.time_msec(1); + % end + % if TIME(end) > ctf.setup.time_msec(end), + % fprintf('...setting TIME(end) = ctf.setup.time_msec(end)\n'); + % TIME(end) = ctf.setup.time_msec(end); + % end + % % now find the nearest indices into the samples matrix + % TIME_index = interp1(ctf.setup.time_msec,1:ctf.setup.number_samples,TIME,'nearest'); + % % now ensure that the TIME array is consistent with ctf.setup.time_sec + % TIME = ctf.setup.time_msec(TIME_index); +end +TIME = sort(TIME); + + + +Ntrials = size(ctf.data,3); +switch num2str(TRIALS), + case 'all', + TRIALS = 1:ctf.setup.number_trials; + otherwise + % assume the input is an array of trials +end +TRIALS = unique(sort(TRIALS)); + + + +for trial = TRIALS, + + fprintf('...exporting trial %d of %d trials in ctf.data\n',trial,Ntrials); + + % now export the data + + data = ctf.data(TIME_index,CHAN,trial); + + OutputFileName = [OutputFilePrefix,'_trial',num2str(trial),'.txt']; + + save(OutputFileName, 'data', '-ascii', '-double', '-tabs') + +end + + +t = toc; fprintf('...done (%6.2f sec)\n\n',t); + +return diff --git a/ctf_write_headshape.m b/ctf_write_headshape.m new file mode 100644 index 0000000..28f85b9 --- /dev/null +++ b/ctf_write_headshape.m @@ -0,0 +1,206 @@ +function ctf_write_headshape(HeadShape,mri,file) + +% ctf_write_headshape - write a CTF .shape file +% +% ctf_write_headshape(HeadShape,mri,file) +% +% - HeadShape is Nx3 list of coordinates in the CTF head shape coordinates. +% - mri is a struct returned by ctf_read_mri; if it is empty, this function +% will prompt with a file browser and read in the file identified. The mri +% struct contains the mri.file field, which is used to define the name of +% the .shape and the .shape_info output files (unless the optional 'file' +% input is given). Also, the fiducials and other information in this +% struct are required to output the .shape_info file. The .shape and +% .shape_info files are required to import the data into CTF's MRIViewer. +% +% The *.shape file is an ascii text file in the following format: +% +% Number of Points +% x1 y1 z1 +% x2 y2 z2 +% . +% . +% . +% xn yn zn +% +% These vertex coordinates are contained in the input HeadShape +% matrix (Nx3). The coordinate values must be in centimeters in +% either the voxel MRI coordinate system or the MEG Head Coordinate +% System (see ctf_read_mri for more about the coordinate system). +% +% This function assumes the MEG head coordinate system is required. +% The values in the input HeadShape matrix (Nx3) should be in +% centimeteres, with the column values representing X, Y, Z, such +% that +X is toward the nasion, +Y is left preauricular and +Z is +% superior. The values are given with respect to the origin, which +% lies half way between the left and right preauricular fiducials. It is +% essential that the fiducials are defined and saved in the .mri file for +% this function to operate correctly. +% +% see also ctf_write_mrishape ctf_read_mri ctf_mri2head ctf_head2mri +% + +% $Revision: 1.1 $ $Date: 2009-01-30 03:49:27 $ + +% Copyright (C) 2004 Darren L. Weber +% +% This program is free software; you can redistribute it and/or +% modify it under the terms of the GNU General Public License +% as published by the Free Software Foundation; either version 2 +% of the License, or (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program; if not, write to the Free Software +% Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +% History: 02/2004, Darren.Weber_at_radiology.ucsf.edu +% - adapted from an appendex to CTF document +% MRIViewer.pdf +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +ver = '[$Revision: 1.1 $]'; +fprintf('CTF_WRITE_HEADSHAPE [v%s]\n',ver(12:16)); tic; + + + +%-------------------------------------------------- +% check the mri input variable + +if exist('mri','var'), + if isfield(mri,'file'), + % great! + else + fprintf('...cannot find mri.file\n'); + [fileName, filePath] = uigetfile('*.mri', 'Pick a CTF .mri file'); + mri.file = fullfile(filePath,fileName); + mri = ctf_read_mri(mri.file); + end +else + [fileName, filePath] = uigetfile('*.mri', 'Pick a CTF .mri file'); + mri.file = fullfile(filePath,fileName); + mri = ctf_read_mri(mri.file); +end + +if exist('file','var'), + shapeFile = file; +else + shapeFile = [mri.file,'.head.shape']; +end +shapeInfoFile = [shapeFile,'_info']; + + +%-------------------------------------------------- +% output the .shape file + +fid = fopen(shapeFile,'w'); + +if isequal(fid,-1), + S=sprintf('Could not open file: "%s"',shapeFile); + error(S); +else + + fprintf('...writing to file:\n %s\n',shapeFile); + fprintf('...writing CTF .shape file, with head coordinates\n'); + tic; + + % Write vertices + Nvertices = size(HeadShape,1); + fprintf(fid,'%d\n',Nvertices); + + for v = 1:Nvertices, + fprintf(fid,'%6.3f %6.3f %6.3f\n',HeadShape(v,1),HeadShape(v,2),HeadShape(v,3)); + end + + fclose(fid); + + t = toc; + fprintf('...done (%6.2f sec).\n',t); + +end + +%-------------------------------------------------- +% output the .shape_info file + +fid = fopen(shapeInfoFile,'w'); + +if isequal(fid,-1), + S=sprintf('Could not open file: "%s"',shapeInfoFile); + error(S); +else + + fprintf('...writing to file:\n %s\n',shapeInfoFile); + fprintf('...writing CTF .shape_info file, with head coordinates\n'); + tic; + + [mriFilePath,mriFileName,mriFileExt] = fileparts(mri.file); + + nasion = [ mri.hdr.HeadModel_Info.Nasion_Sag, mri.hdr.HeadModel_Info.Nasion_Cor, mri.hdr.HeadModel_Info.Nasion_Axi ]; + left = [ mri.hdr.HeadModel_Info.LeftEar_Sag, mri.hdr.HeadModel_Info.LeftEar_Cor, mri.hdr.HeadModel_Info.LeftEar_Axi ]; + right = [ mri.hdr.HeadModel_Info.RightEar_Sag, mri.hdr.HeadModel_Info.RightEar_Cor, mri.hdr.HeadModel_Info.RightEar_Axi ]; + + fprintf(fid,'// *************************************\n'); + fprintf(fid,'// Headshape File Information \n'); + fprintf(fid,'// *************************************\n'); + fprintf(fid,'\n'); + fprintf(fid,'MRI_Info\n'); + fprintf(fid,'{\n'); + fprintf(fid,' VERSION: 1.00\n'); + fprintf(fid,'\n'); + fprintf(fid,' FILENAME: %s\n',[mriFileName,mriFileExt]); + fprintf(fid,'\n'); + fprintf(fid,' // Fid. Points Sag Cor Axi\n'); + fprintf(fid,' NASION:\t\t\t%5.1f %5.1f %5.1f\n',nasion(1),nasion(2),nasion(3)); + fprintf(fid,' LEFT_EAR:\t\t%5.1f %5.1f %5.1f\n',left(1),left(2),left(3)); + fprintf(fid,' RIGHT_EAR:\t%5.1f %5.1f %5.1f\n',right(1),right(2),right(3)); + fprintf(fid,'\n'); + fprintf(fid,' MM_PER_VOXEL_SAGITTAL:\t\t%10.8f\n', mri.hdr.mmPerPixel_sagittal); + fprintf(fid,' MM_PER_VOXEL_CORONAL:\t\t%10.8f\n', mri.hdr.mmPerPixel_coronal); + fprintf(fid,' MM_PER_VOXEL_AXIAL:\t\t\t%10.8f\n', mri.hdr.mmPerPixel_axial); + fprintf(fid,'\n'); + fprintf(fid,' COORDINATES: HEAD\n'); + fprintf(fid,'\n'); + fprintf(fid,'}\n'); + + fclose(fid); + + t = toc; + fprintf('...done (%6.2f sec).\n\n',t); + +end + + +return + + + + + + +%// ************************************* +%// Headshape File Information +%// ************************************* +% +%MRI_Info +%{ +% VERSION: 1.00 +% +% FILENAME: ucsf_mh_orig_axial_las2ctf.mri +% +% // Fid. Points Sag Cor Axi +% NASION: 128.0 35.0 130.0 +% LEFT_EAR: 53.0 123.0 152.0 +% RIGHT_EAR: 207.0 123.0 152.0 +% +% MM_PER_VOXEL_SAGITTAL: 1.00000000 +% MM_PER_VOXEL_CORONAL: 1.00000000 +% MM_PER_VOXEL_AXIAL: 1.00000000 +% +% COORDINATES: MRI +% +%} diff --git a/ctf_write_meg4.m b/ctf_write_meg4.m new file mode 100644 index 0000000..099bf09 --- /dev/null +++ b/ctf_write_meg4.m @@ -0,0 +1,39 @@ +function writeTrials(datfile,savefile,types,bottop_perc) + +% writeTrials(datfile,savefile,types,bottop_perc) +% datfile = *.dat file used to create the appropriate types +% savefile = file to write trials to +% types = trial type codes as discussed in groupDatHiN + + +DATDIR = '/data/dnl3/HighN_cuebase/dat_session_files/'; +SAVEDIR = '/data/dnl3/HighN_cuebase/trialLists/'; + +[alltypes,resps] = groupDatHiN([DATDIR datfile]); +vals = selectDatHiN(alltypes,resps,types); + +if (nargin == 4) + [tmp,sortorder] = sort(vals.Latencies); + trials = vals.ETrials(sortorder); + + bottom_trials = trials(end:-1:end-round(bottop_perc*length(trials)/100)+1); + top_trials = trials(1:round(bottop_perc*length(trials)/100)); + + fid = fopen([SAVEDIR savefile 'top' num2str(bottop_perc)],'w'); + for i = 1:length(top_trials) + fprintf(fid,[num2str(top_trials(i)) ' ']); + end + fclose(fid); + + fid = fopen([SAVEDIR savefile 'bottom' num2str(bottop_perc)],'w'); + for i = 1:length(bottom_trials) + fprintf(fid,[num2str(bottom_trials(i)) ' ']); + end + fclose(fid); +else + fid = fopen([SAVEDIR savefile],'w'); + for i = 1:length(vals.ETrials) + fprintf(fid,[num2str(vals.ETrials(i)) ' ']); + end + fclose(fid); +end diff --git a/ctf_write_mri.m b/ctf_write_mri.m new file mode 100644 index 0000000..6c24cad --- /dev/null +++ b/ctf_write_mri.m @@ -0,0 +1,523 @@ +function ctf_write_mri(mri, fileName, force) + +% ctf_write_mri - write a CTF .mri file +% +% ctf_write_mri(mri,fileName,force) +% +% mri is a data struct returned from ctf_read_mri. It may contain +% mri.file, in which case, you do not need the fileName input here. If the +% file exists, you are prompted for a new file name, unless force = 1. +% +% The CTF MRI File format used by MRIViewer consists of a binary file with +% a 1,028 byte header. The MRI data can be in 8-bit (unsigned character) or +% 16-bit (unsigned short integer) format and consists of 256 x 256 pixel +% slices, stored as 256 contiguous sagittal slices from left to right (or +% right to left if head orientation is left-on-right). Each slice is stored +% as individual pixels starting at the left, anterior, superior +% corner and scanning downwards row by row. Therefore the coronal +% position is fastest changing, axial position second fastest +% changing and sagittal position slowest changing value in the +% file, always in the positive direction for each axis (see section +% on Head Coordinate System for axis definitions). By default CTF +% MRI files have the file extension .mri +% +% <>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> % +% < > % +% < DISCLAIMER: > % +% < > % +% < THIS PROGRAM IS INTENDED FOR RESEARCH PURPOSES ONLY. > % +% < THIS PROGRAM IS IN NO WAY INTENDED FOR CLINICAL OR > % +% < OFFICIAL USE. > % +% < > % +% <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<> % +% + + + +% $Revision: 1.1 $ $Date: 2009-01-30 03:49:27 $ + +% Copyright (C) 2003 Darren L. Weber +% +% This program is free software; you can redistribute it and/or +% modify it under the terms of the GNU General Public License +% as published by the Free Software Foundation; either version 2 +% of the License, or (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program; if not, write to the Free Software +% Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +% History: 08/2003, Darren.Weber_at_radiology.ucsf.edu +% - adapted from an appendex to CTF document +% MRIConverter.pdf, which is copied at the end of this +% function. +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +ver = '[$Revision: 1.1 $]'; +fprintf('\nCTF_WRITE_MRI [v%s]\n',ver(12:16)); tic; + +if ~exist('mri','var'), error('no input mri data struct'); end +if isempty(mri), error('empty input mri data struct'); end + +if ~exist('force','var'), force = 0; end % don't overwrite +if isempty(force), force = 0; end + +if ~exist('fileName','var'), + if isfield(mri,'file'), + file = mri.file; + else + [fileName, filePath, filterIndex] = uigetfile('*.mri', 'Locate CTF .mri file'); + file = fullfile(filePath, fileName); + end +else + [filePath, fileName, fileExt] = fileparts(fileName); + file = fullfile(filePath, [fileName,'.mri']); +end + +if isempty(file), + error('...file is empty\n'); +end + +if exist(file,'file'), + if force, + fprintf('...file already exists, overwriting it.\n'); + else + fprintf('...file already exists\n'); + [fileName, pathName] = uiputfile('*.mri', 'Specify CTF .mri file to write'); + file = fullfile(filePath, [fileName,'.mri']); + end +end + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% open the file for writing +% 'ieee-be.l64' or 's' - IEEE floating point with big-endian byte +% ordering and 64 bit long data type. +[fid,message] = fopen(file,'wb','s'); +if fid < 0, error('cannot open file for writing'); end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% write the file header +fprintf('...writing header '); +Version_2_Header_write(fid, mri.hdr); + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% check header size, header should be 1028 bytes +header_bytes = ftell(fid); +fprintf('(wrote %d bytes)\n',header_bytes); +if header_bytes ~= 1028, + msg = sprintf('failed to write 1028 bytes into the header, wrote %d bytes',header_bytes); + error(msg); +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% seek beyond the header, to the beginning of the data matrix +%fseek(fid,1028,'bof'); + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% check if the data is 8 or 16 bits +switch mri.hdr.dataSize, + case 1, % we have 8 bit data + fprintf('...writing unsigned char (8 bit) image data\n'); + precision = 'uchar'; + case 2, % we have 16 bit data + fprintf('...writing unsigned short (16 bit) image data\n'); + precision = 'ushort'; + otherwise, + msg = sprintf('unknown mri.hdr.dataSize: %g',mri.hdr.dataSize); + error(msg); +end + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% now have the data array in a 3D matrix, we have to write it out in the +% correct byte order + +% The CTF MRI File format used by MRIViewer consists of a binary file with a +% 1,028 byte header. The MRI data can be in 8-bit (unsigned character) or 16-bit +% (unsigned short integer) format and consists of 256 x 256 pixel slices, stored as +% 256 contiguous sagittal slices from left to right (or right to left if head orientation +% is "left-on-right"). Each slice is stored as individual pixels starting at the +% top left corner and scanning downwards row by row. Therefore the coronal +% position is fastest changing, axial position second fastest changing and sagittal +% position slowest changing value in the file, always in the positive direction for +% each axis (see section on Head Coordinate System for axis definitions). By +% default CTF MRI files have the file extension ".mri" + +% MRIViewer uses these cardinal directions as axes in an internal coordinate system +% where sagittal = X, coronal = Y and axial = Z forming an additional +% right-handed coordinate system which is translated and rotated with respect to +% the Head Coordinate System and has its origin at the upper left anterior corner +% of the volume. + +PixelDim = 256; +RowDim = 256; +SliceDim = 256; + +% imageOrientation, 0 = left on left, 1 = left on right +switch mri.hdr.imageOrientation, + case 0, + fprintf('...sagittal slices are neurological orientation (left is on the left)\n'); + fprintf('...+X left to right, +Y anterior to posterior, +Z superior to inferior\n'); + case 1, + fprintf('...sagittal slices are radiological orientation (left is on the right)\n'); + fprintf('...+X right to left, +Y anterior to posterior, +Z superior to inferior\n'); + otherwise, + msg = sprintf('...unknown mri.hdr.imageOrientation: %d\n',mri.hdr.imageOrientation); + error(msg); +end + +% output into sagittal slices, with the fastest moving index being Y, +% from anterior to posterior, then Z, from superior to inferior, then X, +% from left to right (or vice versa; depending on input mri struct). + +n = 1; +y = 1:PixelDim; % +Y is from anterior to posterior + +for x = 1:SliceDim, % +X is from left to right (or vice versa) + for z = 1:RowDim, % +Z is from superior to inferior + + count = fwrite(fid,mri.img(x,y,z),precision); + + if count ~= PixelDim, + error('failed to output 256 data points'); + end + + end +end + +fclose(fid); + +t=toc; fprintf('...done (%5.2f sec).\n\n',t); + +return + + + + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function Version_2_Header_write(fid,Version_2_Header), + +identifierString = sprintf('%-32s', Version_2_Header.identifierString); +if length(identifierString) < 32, + paddingN = 32 - length(identifierString); + padding = char(repmat(double(' '),1,paddingN)); + identifierString = [identifierString,padding]; +end + +fwrite(fid,identifierString(1:32),'char'); + +fwrite(fid,Version_2_Header.imageSize ,'short'); % always = 256 +fwrite(fid,Version_2_Header.dataSize ,'short'); % 1 or 2 (bytes), 8 or 16 bits +fwrite(fid,Version_2_Header.clippingRange ,'short'); % max. integer value of data +fwrite(fid,Version_2_Header.imageOrientation ,'short'); % eg., 0 = left on left, 1 = left on right + +% voxel dimensions in mm +fwrite(fid,Version_2_Header.mmPerPixel_sagittal ,'float'); +fwrite(fid,Version_2_Header.mmPerPixel_coronal ,'float'); +fwrite(fid,Version_2_Header.mmPerPixel_axial ,'float'); + +headModel_write(fid,Version_2_Header.HeadModel_Info); % defined below... +imageInfo_write(fid,Version_2_Header.Image_Info); % defined below... + +% voxel location of head origin +fwrite(fid,Version_2_Header.headOrigin_sagittal ,'float'); +fwrite(fid,Version_2_Header.headOrigin_coronal ,'float'); +fwrite(fid,Version_2_Header.headOrigin_axial ,'float'); + +% euler angles to align MR to head coordinate system (angles in degrees!) +% 1. rotate in coronal plane by this angle +% 2. rotate in sagittal plane by this angle +% 3. rotate in axial plane by this angle +fwrite(fid,Version_2_Header.rotate_coronal ,'float'); +fwrite(fid,Version_2_Header.rotate_sagittal ,'float'); +fwrite(fid,Version_2_Header.rotate_axial ,'float'); + +fwrite(fid,Version_2_Header.orthogonalFlag ,'short'); % if set then image is orthogonal +fwrite(fid,Version_2_Header.interpolatedFlag ,'short'); % if set than image was interpolated + +% original spacing between slices before interpolation to CTF format +fwrite(fid,Version_2_Header.originalSliceThickness ,'float'); + +% transformation matrix head->MRI [column][row] +fwrite(fid,Version_2_Header.transformMatrix' ,'float')'; + +% padding to 1028 bytes +% according to CTF manual, this should +%be 202, but it works out to the 1028 bytes with 204. +spaces = char(repmat(double(' '),1,204)); +fwrite(fid,spaces,'uchar'); + +return + + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function headModel_write(fid,HeadModel_Info), + +% this function is called from Version_2_Header_read + +% fid. point coordinate (in voxels) +fwrite(fid,HeadModel_Info.Nasion_Sag ,'short'); % nasion - sagittal +fwrite(fid,HeadModel_Info.Nasion_Cor ,'short'); % nasion - coronal +fwrite(fid,HeadModel_Info.Nasion_Axi ,'short'); % nasion - axial +fwrite(fid,HeadModel_Info.LeftEar_Sag ,'short'); % left ear - sagittal +fwrite(fid,HeadModel_Info.LeftEar_Cor ,'short'); % left ear - coronal +fwrite(fid,HeadModel_Info.LeftEar_Axi ,'short'); % left ear - axial +fwrite(fid,HeadModel_Info.RightEar_Sag ,'short'); % right ear - sagittal +fwrite(fid,HeadModel_Info.RightEar_Cor ,'short'); % right ear - coronal +fwrite(fid,HeadModel_Info.RightEar_Axi ,'short'); % right ear - axial + +fwrite(fid,' ','char'); % padding to 4 byte boundary - from Robert Oostenveld + +% default sphere origin +fwrite(fid,HeadModel_Info.defaultSphereX ,'float'); % sphere origin x coordinate ( in mm ) +fwrite(fid,HeadModel_Info.defaultSphereY ,'float'); % sphere origin y coordinate ( in mm ) +fwrite(fid,HeadModel_Info.defaultSphereZ ,'float'); % sphere origin z coordinate ( in mm ) +fwrite(fid,HeadModel_Info.defaultSphereRadius ,'float'); % default sphere radius ( in mm ) + +return + + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function imageInfo_write(fid,Image_Info), + +% this function is called from Version_2_Header_read + +fwrite(fid,Image_Info.modality,'short'); % 0 = MRI, 1 = CT, 2 = PET, 3 = SPECT, 4 = OTHER + + +% check the length of char variables + +% Image_Info.manufacturerName = char( fread(fid,[1,64],'char') ); +% Image_Info.instituteName = char( fread(fid,[1,64],'char') ); +% Image_Info.patientID = char( fread(fid,[1,32],'char') ); +% Image_Info.dateAndTime = char( fread(fid,[1,32],'char') ); +% Image_Info.scanType = char( fread(fid,[1,32],'char') ); +% Image_Info.contrastAgent = char( fread(fid,[1,32],'char') ); +% Image_Info.imagedNucleus = char( fread(fid,[1,32],'char') ); + +manufacturerName = sprintf('%-64s', Image_Info.manufacturerName); +if length(manufacturerName) < 64, + paddingN = 64 - length(manufacturerName); + padding = char(repmat(double(' '),1,paddingN)); + manufacturerName = [manufacturerName,padding]; +end + +instituteName = sprintf('%-64s', Image_Info.instituteName); +if length(instituteName) < 64, + paddingN = 64 - length(instituteName); + padding = char(repmat(double(' '),1,paddingN)); + instituteName = [instituteName,padding]; +end + +patientID = sprintf('%-32s', Image_Info.patientID); +if length(patientID) < 32, + paddingN = 32 - length(patientID); + padding = char(repmat(double(' '),1,paddingN)); + patientID = [patientID,padding]; +end + +dateAndTime = sprintf('%-32s', Image_Info.dateAndTime); +if length(dateAndTime) < 32, + paddingN = 32 - length(dateAndTime); + padding = char(repmat(double(' '),1,paddingN)); + dateAndTime = [dateAndTime,padding]; +end + +scanType = sprintf('%-32s', Image_Info.scanType); +if length(scanType) < 32, + paddingN = 32 - length(scanType); + padding = char(repmat(double(' '),1,paddingN)); + scanType = [scanType,padding]; +end + +contrastAgent = sprintf('%-32s', Image_Info.contrastAgent); +if length(contrastAgent) < 32, + paddingN = 32 - length(contrastAgent); + padding = char(repmat(double(' '),1,paddingN)); + contrastAgent = [contrastAgent,padding]; +end + +imagedNucleus = sprintf('%-32s', Image_Info.imagedNucleus); +if length(imagedNucleus) < 32, + paddingN = 32 - length(imagedNucleus); + padding = char(repmat(double(' '),1,paddingN)); + imagedNucleus = [imagedNucleus,padding]; +end + +% output these char variables + +fwrite(fid,manufacturerName(1:64),'char'); +fwrite(fid,instituteName(1:64),'char'); +fwrite(fid,patientID(1:32),'char'); +fwrite(fid,dateAndTime(1:32),'char'); +fwrite(fid,scanType(1:32),'char'); +fwrite(fid,contrastAgent(1:32),'char'); +fwrite(fid,imagedNucleus(1:32),'char'); + +fwrite(fid,' ','char'); % padding to 4 byte boundary - from Robert Oostenveld + +fwrite(fid,Image_Info.Frequency ,'float'); +fwrite(fid,Image_Info.FieldStrength ,'float'); +fwrite(fid,Image_Info.EchoTime ,'float'); +fwrite(fid,Image_Info.RepetitionTime ,'float'); +fwrite(fid,Image_Info.InversionTime ,'float'); +fwrite(fid,Image_Info.FlipAngle ,'float'); +fwrite(fid,Image_Info.NoExcitations ,'short'); +fwrite(fid,Image_Info.NoAcquisitions ,'short'); + + +commentString = sprintf('%-256s', Image_Info.commentString); +if length(commentString) < 256, + paddingN = 256 - length(commentString); + padding = char(repmat(double(' '),1,paddingN)); + commentString = [commentString,padding]; +end + +forFutureUse = sprintf('%-64s', Image_Info.forFutureUse); +if length(forFutureUse) < 64, + paddingN = 64 - length(forFutureUse); + padding = char(repmat(double(' '),1,paddingN)); + forFutureUse = [forFutureUse,padding]; +end + +fwrite(fid,commentString(1:256),'char'); +fwrite(fid,forFutureUse(1:64),'char'); + +return + + + + + + + + +% The CTF MRI File format used by MRIViewer consists of a binary file with a +% 1,028 byte header. The MRI data can be in 8-bit (unsigned character) or 16-bit +% (unsigned short integer) format and consists of 256 x 256 pixel slices, stored as +% 256 contiguous sagittal slices from left to right (or right to left if head orientation +% is “left-on-right”). Each slice is stored as individual pixels starting at the +% top left corner and scanning downwards row by row. Therefore the coronal +% position is fastest changing, axial position second fastest changing and sagittal +% position slowest changing value in the file, always in the positive direction for +% each axis (see section on Head Coordinate System for axis definitions). By +% default CTF MRI files have the file extension ".mri" +% The following is the C language header definitions for the CTF Format MRI +% File (current version is 2.2). Note that the Version_2_Header structure comprises +% the file header and contains other structures also defined below and is +% padded out to 1028 bytes. This is followed immediately by the voxel data +% itself. +% typedef struct Version_2_Header { +% char identifierString[32]; // "CTF_MRI_FORMAT VER 2.2" +% short imageSize; // always = 256 +% short dataSize; // 1 or 2 (bytes) +% short clippingRange; // max. integer value of data +% short imageOrientation; // eg., 0 = left on left, 1 = left on right +% float mmPerPixel_sagittal; // voxel dimensions in mm +% float mmPerPixel_coronal; // voxel dimensions in mm +% float mmPerPixel_axial; // voxel dimensions in mm +% HeadModel_Info headModel; // defined below... +% Image_Info imageInfo; // defined below.. +% float headOrigin_sagittal; // voxel location of head origin +% float headOrigin_coronal; // voxel location of head origin +% float headOrigin_axial; // voxel location of head origin +% // euler angles to align MR to head coordinate system (angles in degrees!) +% float rotate_coronal; // 1. rotate in coronal plane by this angle +% float rotate_sagittal; // 2. rotate in sagittal plane by this angle +% float rotate_axial; // 3. rotate in axial plane by this angle +% short orthogonalFlag; // if set then image is orthogonal +% short interpolatedFlag // if set than image was interpolated +% float originalSliceThickness // original spacing between slices before interpolation +% float transformMatrix[4][4] // transformation matrix head->MRI [column][row] +% unsigned char unused[202]; // padding to 1028 bytes +% } Version_2_Header; +% typedef struct HeadModel_Info { +% short Nasion_Sag; // fid. point coordinate (in voxels) for nasion - sagittal +% short Nasion_Cor; // nasion - coronal +% short Nasion_Axi; // nasion - axial +% short LeftEar_Sag; // left ear - sagittal +% short LeftEar_Cor; // left ear - coronal +% short LeftEar_Axi; // left ear - axial +% short RightEar_Sag; // right ear - sagittal +% short RightEar_Cor; // right ear - coronal +% short RightEar_Axi; // right ear - axial +% float defaultSphereX; // default sphere origin x coordinate ( in mm ) +% float defaultSphereY; // sphere origin y coordinate ( in mm ) +% float defaultSphereZ; // sphere origin z coordinate ( in mm ) +% float defaultSphereRadius; // default sphere radius ( in mm ) +% } HeadModel_Info; +% typedef struct Image_Info { +% short modality; // 0 = MRI, 1 = CT, 2 = PET, 3 = SPECT, 4 = OTHER +% char manufacturerName[64]; +% char instituteName[64]; +% char patientID[32]; +% char dateAndTime[32]; +% char scanType[32]; +% char contrastAgent[32]; +% char imagedNucleus[32]; +% float Frequency; +% float FieldStrength; +% float EchoTime; +% float RepetitionTime; +% float InversionTime; +% float FlipAngle; +% short NoExcitations; +% short NoAcquisitions; +% char commentString[256]; +% char forFutureUse[64]; +% } Image_Info; + + + + +% From MRIViewer.pdf + +% CTF MRI Coordinate System +% In contrast, the MRI coordinate system, shown in Figure 3, is defined by the +% orthogonal viewing directions typically used in radiology -- sagittal, coronal +% (also termed frontal) and axial (also termed horizontal). +% +% MRIViewer uses these cardinal directions as axes in an internal coordinate system +% where sagittal = X, coronal = Y and axial = Z forming an additional +% right-handed coordinate system which is translated and rotated with respect to +% the Head Coordinate System and has its origin at the upper left anterior corner +% of the volume. +% Upon defining the landmark or “fiduciary” locations set by the placement of +% the head localization coils an internal representation of the MEG Head Coordinate +% System is defined using the same convention as that of the MEG acquisition +% software described above. This information combined with the voxel +% resolution in each direction is used to construct an internal transformation +% matrix (T) that is used to automatically convert any 3-dimensional location in +% the Head Coordinate System to any voxel location in the MRI. Thus, a point +% P(x, y, z) specified in the Head Coordinate System (see Figure 3) can be converted +% to the MRI voxel P'(x', y', z') by multiplication by the transformation +% matrix T where P' = TP. This immediate conversion can be seen by moving +% the cursor through any given view (hold left mouse button down and drag) +% which will display at the top of the image the voxel location and x, y, z location +% (in centimeters) in the Head Coordinate System for the current cursor position. +% In a similar manner an inverse transformation, P = T^-1 P' can be used to convert +% any MRI voxel to the corresponding location in the Head Coordinate System. For a +% transformation matrix of this type, T^-1 = T'. The fiduciary location information +% is stored with the MRI data file and retrieved upon rereading +% the image file into MRIViewer. +% +% The command-line program 'mrihead' can be used to print the transformation matrix and other MRI +% parameters to the screen for any given CTF format MRI file, based on the default fiduciary points +% last saved with the file. diff --git a/ctf_write_mrishape.m b/ctf_write_mrishape.m new file mode 100644 index 0000000..528a07f --- /dev/null +++ b/ctf_write_mrishape.m @@ -0,0 +1,208 @@ +function ctf_write_mrishape(MRIShape,mri) + +% ctf_write_mrishape - write a CTF .shape file +% +% ctf_write_mrishape(MRIShape,mri) +% +% - MRIshape is an Nx3 list of MRI voxel locations (described below) +% - mri is a struct returned by ctf_read_mri; if it is empty, this function +% will prompt with a file browser and read in the file identified. The mri +% struct contains the mri.file field, which is used to define the name of +% the .shape and the .shape_info output files. Also, the fiducials and +% other information in this struct are required to output the .shape_info +% file. The .shape and .shape_info files are required to import the data +% into CTF's MRIViewer. +% +% The *.shape file is an ascii text file in the following format: +% +% Number of Points +% x1 y1 z1 +% x2 y2 z2 +% . +% . +% . +% xn yn zn +% +% These vertex coordinates are contained in the input MRIShape +% matrix (Nx3). The coordinate values must be in centimeters in +% either the voxel MRI coordinate system or the MEG Head Coordinate +% System (see ctf_read_mri for more about the coordinate system). +% +% This function assumes the MRI coordinate system is required. The +% CTF MRI volume is 256x256x256 voxels, each has 1mm isotropic +% dimensions. Hence, the mm coordinates are also the slice +% indices. In this function, the first column of MRIShape is the +% Sagittal slice dimension, the second column is the Coronal slice +% dimension and the last column is the Axial slice dimension. The +% values should range from 1 to 256, with higher values indicating +% Right, Posterior and Inferior directions, respectively. This +% function converts MRIShape to integers and applies the unique +% function to sort and remove any duplicate values. +% +% see also ctf_write_headshape ctf_read_mri ctf_mri2head ctf_head2mri +% + +% $Revision: 1.1 $ $Date: 2009-01-30 03:49:27 $ + +% Copyright (C) 2004 Darren L. Weber +% +% This program is free software; you can redistribute it and/or +% modify it under the terms of the GNU General Public License +% as published by the Free Software Foundation; either version 2 +% of the License, or (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program; if not, write to the Free Software +% Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +% History: 02/2004, Darren.Weber_at_radiology.ucsf.edu +% - adapted from an appendex to CTF document +% MRIViewer.pdf +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +ver = '[$Revision: 1.1 $]'; +fprintf('\nCTF_WRITE_MRISHAPE [v%s]\n',ver(12:16)); + +if exist('mri','var'), + if isfield(mri,'file'), + file = [mri.file,'.shape']; + else + fprintf('...cannot find mri.file\n'); + [fileName, filePath] = uigetfile('*.mri', 'Pick a CTF .mri file'); + mri.file = fullfile(filePath,fileName); + mri = ctf_read_mri(mri.file); + end +else + [fileName, filePath] = uigetfile('*.mri', 'Pick a CTF .mri file'); + mri.file = fullfile(filePath,fileName); + mri = ctf_read_mri(mri.file); +end + +shapeFile = [mri.file,'.mri.shape']; +shapeInfoFile = [mri.file,'.mri.shape_info']; + + + + +%------------------------------------------------------------- +% Write out the MRI shape vertices + +fid = fopen(shapeFile,'w'); + +if isequal(fid,-1), + S=sprintf('Could not open file: "%s"',shapeFile); + error(S); +else + + fprintf('...writing to file:\n %s\n',shapeFile); + fprintf('...writing CTF .shape file, with MRI coordinates\n'); + tic + + % convert to integer + MRIShape = round(MRIShape); + + % sort the headshape values by the first column and remove any duplicates + MRIShape = unique(MRIShape,'rows'); + + % Write vertices + Nvertices = size(MRIShape,1); + fprintf(fid,'%d\n',Nvertices); + + for v = 1:Nvertices, + fprintf(fid,'%d %d %d\n',MRIShape(v,1),MRIShape(v,2),MRIShape(v,3)); + end + + fclose(fid); + + t = toc; + fprintf('...done (%6.2f sec).\n',t); + +end + + +%-------------------------------------------------- +% output the .shape_info file + +fid = fopen(shapeInfoFile,'w'); + +if isequal(fid,-1), + S=sprintf('Could not open file: "%s"',shapeInfoFile); + error(S); +else + + fprintf('...writing to file:\n %s\n',shapeInfoFile); + fprintf('...writing CTF .shape_info file, with MRI coordinates\n'); + tic; + + [mriFilePath,mriFileName,mriFileExt] = fileparts(mri.file); + + nasion = [ mri.hdr.HeadModel_Info.Nasion_Sag, mri.hdr.HeadModel_Info.Nasion_Cor, mri.hdr.HeadModel_Info.Nasion_Axi ]; + left = [ mri.hdr.HeadModel_Info.LeftEar_Sag, mri.hdr.HeadModel_Info.LeftEar_Cor, mri.hdr.HeadModel_Info.LeftEar_Axi ]; + right = [ mri.hdr.HeadModel_Info.RightEar_Sag, mri.hdr.HeadModel_Info.RightEar_Cor, mri.hdr.HeadModel_Info.RightEar_Axi ]; + + fprintf(fid,'// *************************************\n'); + fprintf(fid,'// Headshape File Information \n'); + fprintf(fid,'// *************************************\n'); + fprintf(fid,'\n'); + fprintf(fid,'MRI_Info\n'); + fprintf(fid,'{\n'); + fprintf(fid,' VERSION: 1.00\n'); + fprintf(fid,'\n'); + fprintf(fid,' FILENAME: %s\n',[mriFileName,mriFileExt]); + fprintf(fid,'\n'); + fprintf(fid,' // Fid. Points Sag Cor Axi\n'); + fprintf(fid,' NASION:\t\t\t%5.1f %5.1f %5.1f\n',nasion(1),nasion(2),nasion(3)); + fprintf(fid,' LEFT_EAR:\t\t%5.1f %5.1f %5.1f\n',left(1),left(2),left(3)); + fprintf(fid,' RIGHT_EAR:\t%5.1f %5.1f %5.1f\n',right(1),right(2),right(3)); + fprintf(fid,'\n'); + fprintf(fid,' MM_PER_VOXEL_SAGITTAL:\t\t%10.8f\n', mri.hdr.mmPerPixel_sagittal); + fprintf(fid,' MM_PER_VOXEL_CORONAL:\t\t%10.8f\n', mri.hdr.mmPerPixel_coronal); + fprintf(fid,' MM_PER_VOXEL_AXIAL:\t\t\t%10.8f\n', mri.hdr.mmPerPixel_axial); + fprintf(fid,'\n'); + fprintf(fid,' COORDINATES: MRI\n'); + fprintf(fid,'\n'); + fprintf(fid,'}\n'); + + fclose(fid); + + t = toc; + fprintf('...done (%6.2f sec).\n\n',t); + +end + + + + +return + + + + +%// ************************************* +%// Headshape File Information +%// ************************************* +% +%MRI_Info +%{ +% VERSION: 1.00 +% +% FILENAME: ucsf_mh_orig_axial_las2ctf.mri +% +% // Fid. Points Sag Cor Axi +% NASION: 128.0 35.0 130.0 +% LEFT_EAR: 53.0 123.0 152.0 +% RIGHT_EAR: 207.0 123.0 152.0 +% +% MM_PER_VOXEL_SAGITTAL: 1.00000000 +% MM_PER_VOXEL_CORONAL: 1.00000000 +% MM_PER_VOXEL_AXIAL: 1.00000000 +% +% COORDINATES: MRI +% +%} diff --git a/ctf_write_sam_targets.m b/ctf_write_sam_targets.m new file mode 100644 index 0000000..7696039 --- /dev/null +++ b/ctf_write_sam_targets.m @@ -0,0 +1,84 @@ +function ctf_write_sam_targets(vertices,file) + +% ctf_write_sam_targets - write a CTF SAM target file +% +% ctf_write_sam_targets(vertices,file) +% +% vertices - is Nx3 list of coordinates in CTF head coordinates (in cm). +% file - an output path/file +% +% The output file is an ascii text file in the following format: +% +% Number of Points +% x1 y1 z1 +% x2 y2 z2 +% . +% . +% . +% xn yn zn +% +% These vertex coordinates are contained in the input vertices +% matrix (Nx3). The coordinate values must be in centimeters in +% the MEG Head Coordinate system (see ctf_read_mri for more about +% the coordinate system). +% + +% $Revision: 1.1 $ $Date: 2009-01-30 03:49:27 $ + +% Copyright (C) 2004 Darren L. Weber +% +% This program is free software; you can redistribute it and/or +% modify it under the terms of the GNU General Public License +% as published by the Free Software Foundation; either version 2 +% of the License, or (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program; if not, write to the Free Software +% Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +% History: 02/2004, Darren.Weber_at_radiology.ucsf.edu +% - adapted from an appendex to CTF document +% MRIViewer.pdf +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +ver = '[$Revision: 1.1 $]'; +fprintf('CTF_WRITE_SAM_TARGETS [v%s]\n',ver(12:16)); + + + +%-------------------------------------------------- +% output an ascii file + +fid = fopen(file,'w'); + +if isequal(fid,-1), + S=sprintf('Could not open file: "%s"',file); + error(S); +else + + fprintf('...writing to file:\n %s\n',file); + fprintf('...writing CTF SAM target file, assuming head coordinates\n'); + tic; + + % Write vertices + Nvertices = size(vertices,1); + fprintf(fid,'%d\n',Nvertices); + + for v = 1:Nvertices, + fprintf(fid,'%6.3f %6.3f %6.3f\n',vertices(v,1),vertices(v,2),vertices(v,3)); + end + + fclose(fid); + + t = toc; + fprintf('...done (%6.2f sec).\n\n',t); + +end + +return diff --git a/eegplugin_ctfimport.m b/eegplugin_ctfimport.m new file mode 100644 index 0000000..9919a60 --- /dev/null +++ b/eegplugin_ctfimport.m @@ -0,0 +1,65 @@ +% eegplugin_ctfimport() - EEGLAB plugin for importing CTF data files. +% +% Usage: +% >> eegplugin_ctfimport(fig, trystrs, catchstrs); +% +% Inputs: +% fig - [integer] EEGLAB figure +% trystrs - [struct] "try" strings for menu callbacks. +% catchstrs - [struct] "catch" strings for menu callbacks. +% +% Notes: +% This plugins consist of the following Matlab files: +% +% Create a plugin: +% For more information on how to create an EEGLAB plugin see the +% help message of eegplugin_besa() or visit http://www.sccn.ucsd.edu/eeglab/contrib.html +% +% Author: Arnaud Delorme (SCCN, UCSD) and Daren Weber (DNL, UCSF) +% for the EEGLAB interface. Fredrick Carver (NIH) and Daren Weber for +% the CTF Matlab reading functions. +% +% See also: pop_ctf_read(), ctf_read(), ctf_readmarkerfile() + +% Copyright (C) 2003 Arnaud Delorme, Salk Institute, arno@salk.edu +% +% This program is free software; you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation; either version 2 of the License, or +% (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program; if not, write to the Free Software +% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +function vers = eegplugin_ctfimport(fig, trystrs, catchstrs) + + vers = 'ctfimport1.04'; + if nargin < 3 + error('eegplugin_ctfimport requires 3 arguments'); + end; + + % add folder to path + % ------------------ + if ~exist('ctf_read_markerfile') + p = which('eegplugin_ctfimport.m'); + p = p(1:findstr(p,'eegplugin_ctfimport.m')-1); + addpath([ p 'ctfimport1.0' ] ); + end; + + % find import data menu + % --------------------- + menu = findobj(fig, 'tag', 'import data'); + + % menu callbacks + % -------------- + comcnt = [ trystrs.no_check '[EEG LASTCOM] = pop_ctf_read;' catchstrs.new_and_hist ]; + + % create menus + % ------------ + uimenu( menu, 'label', 'From CTF folder (MEG)', 'callback', comcnt, 'separator', 'on' ); diff --git a/elec_1020all_cart.m b/elec_1020all_cart.m new file mode 100644 index 0000000..d674597 --- /dev/null +++ b/elec_1020all_cart.m @@ -0,0 +1,783 @@ +function [elec] = elec_1020all_cart + +% elec_1020all_cart - all 10-20 electrode Cartesian coordinates +% +% [elec] = elec_1020all_cart +% +% elec is a struct array with fields: +% +% elec.labels +% elec.X +% elec.Y +% elec.Z +% +% We gratefully acknowledge the provision of this data from +% Robert Oostenveld. The elec struct contains all channel names and +% locations for the International 10-20 electrode placement system, please +% see details in: +% +% Oostenveld, R. & Praamstra, P. (2001). The five percent electrode system +% for high-resolution EEG and ERP measurements. Clinical Neurophysiology, +% 112:713-719. +% + +% $Revision: 1.1 $ $Date: 2009-01-30 03:49:27 $ + +% Copyright (C) 2005 Darren L. Weber +% +% This program is free software; you can redistribute it and/or +% modify it under the terms of the GNU General Public License +% as published by the Free Software Foundation; either version 2 +% of the License, or (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program; if not, write to the Free Software +% Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +% Modified: 02/2004, Darren.Weber_at_radiology.ucsf.edu +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +ver = '$Revision: 1.1 $ $Date: 2009-01-30 03:49:27 $'; +fprintf('\nELEC_1020ALL_CART [v %s]\n',ver(11:15)); + + +names = {'LPA','RPA','Nz','Fp1','Fpz','Fp2','AF9','AF7','AF5','AF3',... + 'AF1','AFz','AF2','AF4','AF6','AF8','AF10','F9','F7','F5','F3','F1',... + 'Fz','F2','F4','F6','F8','F10','FT9','FT7','FC5','FC3','FC1','FCz',... + 'FC2','FC4','FC6','FT8','FT10','T9','T7','C5','C3','C1','Cz','C2',... + 'C4','C6','T8','T10','TP9','TP7','CP5','CP3','CP1','CPz','CP2','CP4',... + 'CP6','TP8','TP10','P9','P7','P5','P3','P1','Pz','P2','P4','P6','P8',... + 'P10','PO9','PO7','PO5','PO3','PO1','POz','PO2','PO4','PO6','PO8',... + 'PO10','O1','Oz','O2','I1','Iz','I2','AFp9h','AFp7h','AFp5h','AFp3h',... + 'AFp1h','AFp2h','AFp4h','AFp6h','AFp8h','AFp10h','AFF9h','AFF7h',... + 'AFF5h','AFF3h','AFF1h','AFF2h','AFF4h','AFF6h','AFF8h','AFF10h',... + 'FFT9h','FFT7h','FFC5h','FFC3h','FFC1h','FFC2h','FFC4h','FFC6h',... + 'FFT8h','FFT10h','FTT9h','FTT7h','FCC5h','FCC3h','FCC1h','FCC2h',... + 'FCC4h','FCC6h','FTT8h','FTT10h','TTP9h','TTP7h','CCP5h','CCP3h',... + 'CCP1h','CCP2h','CCP4h','CCP6h','TTP8h','TTP10h','TPP9h','TPP7h',... + 'CPP5h','CPP3h','CPP1h','CPP2h','CPP4h','CPP6h','TPP8h','TPP10h',... + 'PPO9h','PPO7h','PPO5h','PPO3h','PPO1h','PPO2h','PPO4h','PPO6h',... + 'PPO8h','PPO10h','POO9h','POO7h','POO5h','POO3h','POO1h','POO2h',... + 'POO4h','POO6h','POO8h','POO10h','OI1h','OI2h','Fp1h','Fp2h','AF9h',... + 'AF7h','AF5h','AF3h','AF1h','AF2h','AF4h','AF6h','AF8h','AF10h',... + 'F9h','F7h','F5h','F3h','F1h','F2h','F4h','F6h','F8h','F10h','FT9h',... + 'FT7h','FC5h','FC3h','FC1h','FC2h','FC4h','FC6h','FT8h','FT10h',... + 'T9h','T7h','C5h','C3h','C1h','C2h','C4h','C6h','T8h','T10h','TP9h',... + 'TP7h','CP5h','CP3h','CP1h','CP2h','CP4h','CP6h','TP8h','TP10h',... + 'P9h','P7h','P5h','P3h','P1h','P2h','P4h','P6h','P8h','P10h','PO9h',... + 'PO7h','PO5h','PO3h','PO1h','PO2h','PO4h','PO6h','PO8h','PO10h','O1h',... + 'O2h','I1h','I2h','AFp9','AFp7','AFp5','AFp3','AFp1','AFpz','AFp2',... + 'AFp4','AFp6','AFp8','AFp10','AFF9','AFF7','AFF5','AFF3','AFF1',... + 'AFFz','AFF2','AFF4','AFF6','AFF8','AFF10','FFT9','FFT7','FFC5',... + 'FFC3','FFC1','FFCz','FFC2','FFC4','FFC6','FFT8','FFT10','FTT9',... + 'FTT7','FCC5','FCC3','FCC1','FCCz','FCC2','FCC4','FCC6','FTT8',... + 'FTT10','TTP9','TTP7','CCP5','CCP3','CCP1','CCPz','CCP2','CCP4',... + 'CCP6','TTP8','TTP10','TPP9','TPP7','CPP5','CPP3','CPP1','CPPz',... + 'CPP2','CPP4','CPP6','TPP8','TPP10','PPO9','PPO7','PPO5','PPO3',... + 'PPO1','PPOz','PPO2','PPO4','PPO6','PPO8','PPO10','POO9','POO7',... + 'POO5','POO3','POO1','POOz','POO2','POO4','POO6','POO8','POO10',... + 'OI1','OIz','OI2','T3','T5','T4','T6'}; + +xyz = [ ... +0.0000 0.9237 -0.3826 ; +0.0000 -0.9237 -0.3826 ; +0.9230 0.0000 -0.3824 ; +0.9511 0.3090 0.0001 ; +1.0000 0.0000 0.0001 ; +0.9511 -0.3091 0.0000 ; +0.7467 0.5425 -0.3825 ; +0.8090 0.5878 0.0000 ; +0.8553 0.4926 0.1552 ; +0.8920 0.3554 0.2782 ; +0.9150 0.1857 0.3558 ; +0.9230 0.0000 0.3824 ; +0.9150 -0.1857 0.3558 ; +0.8919 -0.3553 0.2783 ; +0.8553 -0.4926 0.1552 ; +0.8090 -0.5878 0.0000 ; +0.7467 -0.5425 -0.3825 ; +0.5430 0.7472 -0.3826 ; +0.5878 0.8090 0.0000 ; +0.6343 0.7210 0.2764 ; +0.6726 0.5399 0.5043 ; +0.6979 0.2888 0.6542 ; +0.7067 0.0000 0.7067 ; +0.6979 -0.2888 0.6542 ; +0.6726 -0.5399 0.5043 ; +0.6343 -0.7210 0.2764 ; +0.5878 -0.8090 0.0000 ; +0.5429 -0.7472 -0.3826 ; +0.2852 0.8777 -0.3826 ; +0.3090 0.9511 0.0000 ; +0.3373 0.8709 0.3549 ; +0.3612 0.6638 0.6545 ; +0.3770 0.3581 0.8532 ; +0.3826 0.0000 0.9233 ; +0.3770 -0.3581 0.8532 ; +0.3612 -0.6638 0.6545 ; +0.3373 -0.8709 0.3549 ; +0.3090 -0.9511 0.0000 ; +0.2852 -0.8777 -0.3826 ; +-0.0001 0.9237 -0.3826 ; +0.0000 1.0000 0.0000 ; +0.0001 0.9237 0.3826 ; +0.0001 0.7066 0.7066 ; +0.0002 0.3824 0.9231 ; +0.0002 0.0000 1.0000 ; +0.0001 -0.3824 0.9231 ; +0.0001 -0.7066 0.7066 ; +0.0001 -0.9237 0.3826 ; +0.0000 -1.0000 0.0000 ; +0.0000 -0.9237 -0.3826 ; +-0.2852 0.8777 -0.3826 ; +-0.3090 0.9511 -0.0001 ; +-0.3372 0.8712 0.3552 ; +-0.3609 0.6635 0.6543 ; +-0.3767 0.3580 0.8534 ; +-0.3822 0.0000 0.9231 ; +-0.3767 -0.3580 0.8534 ; +-0.3608 -0.6635 0.6543 ; +-0.3372 -0.8712 0.3552 ; +-0.3090 -0.9511 -0.0001 ; +-0.2853 -0.8777 -0.3826 ; +-0.5429 0.7472 -0.3826 ; +-0.5878 0.8090 -0.0001 ; +-0.6342 0.7211 0.2764 ; +-0.6724 0.5401 0.5045 ; +-0.6975 0.2889 0.6545 ; +-0.7063 0.0000 0.7065 ; +-0.6975 -0.2889 0.6545 ; +-0.6724 -0.5401 0.5045 ; +-0.6342 -0.7211 0.2764 ; +-0.5878 -0.8090 -0.0001 ; +-0.5429 -0.7472 -0.3826 ; +-0.7467 0.5425 -0.3825 ; +-0.8090 0.5878 0.0000 ; +-0.8553 0.4929 0.1555 ; +-0.8918 0.3549 0.2776 ; +-0.9151 0.1858 0.3559 ; +-0.9230 0.0000 0.3824 ; +-0.9151 -0.1859 0.3559 ; +-0.8918 -0.3549 0.2776 ; +-0.8553 -0.4929 0.1555 ; +-0.8090 -0.5878 0.0000 ; +-0.7467 -0.5425 -0.3825 ; +-0.9511 0.3090 0.0000 ; +-1.0000 0.0000 0.0000 ; +-0.9511 -0.3090 0.0000 ; +-0.8785 0.2854 -0.3824 ; +-0.9230 0.0000 -0.3823 ; +-0.8785 -0.2854 -0.3824 ; +0.8732 0.4449 -0.1949 ; +0.9105 0.4093 0.0428 ; +0.9438 0.3079 0.1159 ; +0.9669 0.1910 0.1666 ; +0.9785 0.0647 0.1919 ; +0.9785 -0.0647 0.1919 ; +0.9669 -0.1910 0.1666 ; +0.9438 -0.3079 0.1159 ; +0.9105 -0.4093 0.0428 ; +0.8732 -0.4449 -0.1949 ; +0.6929 0.6929 -0.1949 ; +0.7325 0.6697 0.1137 ; +0.7777 0.5417 0.3163 ; +0.8111 0.3520 0.4658 ; +0.8289 0.1220 0.5452 ; +0.8289 -0.1220 0.5452 ; +0.8111 -0.3520 0.4658 ; +0.7777 -0.5417 0.3163 ; +0.7325 -0.6697 0.1138 ; +0.6929 -0.6929 -0.1949 ; +0.4448 0.8730 -0.1950 ; +0.4741 0.8642 0.1647 ; +0.5107 0.7218 0.4651 ; +0.5384 0.4782 0.6925 ; +0.5533 0.1672 0.8148 ; +0.5533 -0.1672 0.8148 ; +0.5384 -0.4782 0.6925 ; +0.5107 -0.7218 0.4651 ; +0.4741 -0.8642 0.1647 ; +0.4448 -0.8730 -0.1950 ; +0.1533 0.9678 -0.1950 ; +0.1640 0.9669 0.1915 ; +0.1779 0.8184 0.5448 ; +0.1887 0.5466 0.8154 ; +0.1944 0.1919 0.9615 ; +0.1944 -0.1919 0.9615 ; +0.1887 -0.5466 0.8154 ; +0.1779 -0.8184 0.5448 ; +0.1640 -0.9669 0.1915 ; +0.1533 -0.9678 -0.1950 ; +-0.1532 0.9678 -0.1950 ; +-0.1639 0.9669 0.1915 ; +-0.1778 0.8185 0.5449 ; +-0.1883 0.5465 0.8153 ; +-0.1940 0.1918 0.9611 ; +-0.1940 -0.1918 0.9611 ; +-0.1884 -0.5465 0.8153 ; +-0.1778 -0.8185 0.5449 ; +-0.1639 -0.9669 0.1915 ; +-0.1533 -0.9678 -0.1950 ; +-0.4448 0.8731 -0.1950 ; +-0.4740 0.8639 0.1646 ; +-0.5106 0.7220 0.4653 ; +-0.5384 0.4786 0.6933 ; +-0.5532 0.1673 0.8155 ; +-0.5532 -0.1673 0.8155 ; +-0.5384 -0.4786 0.6933 ; +-0.5106 -0.7220 0.4653 ; +-0.4740 -0.8638 0.1646 ; +-0.4449 -0.8731 -0.1950 ; +-0.6928 0.6928 -0.1950 ; +-0.7324 0.6700 0.1139 ; +-0.7776 0.5420 0.3167 ; +-0.8108 0.3520 0.4659 ; +-0.8284 0.1220 0.5453 ; +-0.8284 -0.1220 0.5453 ; +-0.8108 -0.3519 0.4659 ; +-0.7775 -0.5421 0.3167 ; +-0.7324 -0.6700 0.1139 ; +-0.6928 -0.6928 -0.1950 ; +-0.8730 0.4448 -0.1950 ; +-0.9106 0.4097 0.0430 ; +-0.9438 0.3080 0.1160 ; +-0.9665 0.1908 0.1657 ; +-0.9783 0.0647 0.1918 ; +-0.9783 -0.0647 0.1918 ; +-0.9665 -0.1908 0.1657 ; +-0.9438 -0.3080 0.1160 ; +-0.9106 -0.4097 0.0430 ; +-0.8730 -0.4448 -0.1950 ; +-0.9679 0.1533 -0.1950 ; +-0.9679 -0.1533 -0.1950 ; +0.9877 0.1564 0.0001 ; +0.9877 -0.1564 0.0001 ; +0.7928 0.5759 -0.1949 ; +0.8332 0.5463 0.0810 ; +0.8750 0.4284 0.2213 ; +0.9053 0.2735 0.3231 ; +0.9211 0.0939 0.3758 ; +0.9210 -0.0939 0.3758 ; +0.9053 -0.2735 0.3231 ; +0.8750 -0.4284 0.2212 ; +0.8332 -0.5463 0.0810 ; +0.7927 -0.5759 -0.1949 ; +0.5761 0.7929 -0.1949 ; +0.6117 0.7772 0.1420 ; +0.6549 0.6412 0.3987 ; +0.6872 0.4214 0.5906 ; +0.7045 0.1468 0.6933 ; +0.7045 -0.1468 0.6933 ; +0.6872 -0.4214 0.5906 ; +0.6549 -0.6412 0.3987 ; +0.6117 -0.7772 0.1420 ; +0.5761 -0.7929 -0.1949 ; +0.3027 0.9317 -0.1950 ; +0.3235 0.9280 0.1813 ; +0.3500 0.7817 0.5146 ; +0.3703 0.5207 0.7687 ; +0.3811 0.1824 0.9054 ; +0.3811 -0.1824 0.9054 ; +0.3703 -0.5207 0.7687 ; +0.3500 -0.7817 0.5146 ; +0.3235 -0.9280 0.1813 ; +0.3028 -0.9317 -0.1950 ; +0.0000 0.9801 -0.1950 ; +0.0000 0.9801 0.1949 ; +0.0001 0.8311 0.5552 ; +0.0002 0.5550 0.8306 ; +0.0001 0.1950 0.9801 ; +0.0002 -0.1950 0.9801 ; +0.0002 -0.5550 0.8306 ; +0.0001 -0.8311 0.5552 ; +0.0000 -0.9801 0.1949 ; +0.0000 -0.9801 -0.1950 ; +-0.3028 0.9319 -0.1949 ; +-0.3234 0.9278 0.1813 ; +-0.3498 0.7818 0.5148 ; +-0.3699 0.5206 0.7688 ; +-0.3808 0.1825 0.9059 ; +-0.3808 -0.1825 0.9059 ; +-0.3699 -0.5206 0.7688 ; +-0.3498 -0.7818 0.5148 ; +-0.3234 -0.9278 0.1813 ; +-0.3028 -0.9319 -0.1949 ; +-0.5761 0.7929 -0.1950 ; +-0.6116 0.7771 0.1420 ; +-0.6546 0.6411 0.3985 ; +-0.6869 0.4217 0.5912 ; +-0.7041 0.1469 0.6934 ; +-0.7041 -0.1469 0.6934 ; +-0.6870 -0.4216 0.5912 ; +-0.6546 -0.6411 0.3985 ; +-0.6116 -0.7771 0.1420 ; +-0.5761 -0.7929 -0.1950 ; +-0.7926 0.5759 -0.1950 ; +-0.8331 0.5459 0.0809 ; +-0.8752 0.4292 0.2219 ; +-0.9054 0.2737 0.3233 ; +-0.9210 0.0939 0.3757 ; +-0.9210 -0.0940 0.3757 ; +-0.9054 -0.2737 0.3233 ; +-0.8752 -0.4292 0.2219 ; +-0.8331 -0.5459 0.0809 ; +-0.7926 -0.5758 -0.1950 ; +-0.9877 0.1564 0.0000 ; +-0.9877 -0.1564 0.0000 ; +-0.9118 0.1444 -0.3824 ; +-0.9118 -0.1444 -0.3824 ; +0.8225 0.4190 -0.3825 ; +0.8910 0.4540 0.0000 ; +0.9282 0.3606 0.0817 ; +0.9565 0.2508 0.1438 ; +0.9743 0.1287 0.1828 ; +0.9799 0.0000 0.1949 ; +0.9743 -0.1287 0.1828 ; +0.9565 -0.2508 0.1437 ; +0.9282 -0.3606 0.0817 ; +0.8910 -0.4540 0.0000 ; +0.8225 -0.4191 -0.3825 ; +0.6527 0.6527 -0.3825 ; +0.7071 0.7071 0.0000 ; +0.7564 0.6149 0.2206 ; +0.7962 0.4535 0.3990 ; +0.8221 0.2404 0.5148 ; +0.8312 0.0000 0.5554 ; +0.8221 -0.2404 0.5148 ; +0.7962 -0.4535 0.3990 ; +0.7564 -0.6149 0.2206 ; +0.7071 -0.7071 0.0000 ; +0.6527 -0.6527 -0.3825 ; +0.4192 0.8226 -0.3826 ; +0.4540 0.8910 0.0000 ; +0.4932 0.8072 0.3215 ; +0.5260 0.6110 0.5905 ; +0.5477 0.3286 0.7685 ; +0.5553 0.0000 0.8310 ; +0.5477 -0.3286 0.7685 ; +0.5260 -0.6110 0.5905 ; +0.4932 -0.8072 0.3216 ; +0.4540 -0.8910 0.0000 ; +0.4192 -0.8226 -0.3826 ; +0.1444 0.9119 -0.3826 ; +0.1565 0.9877 0.0000 ; +0.1713 0.9099 0.3754 ; +0.1838 0.6957 0.6933 ; +0.1922 0.3764 0.9059 ; +0.1951 0.0000 0.9804 ; +0.1922 -0.3764 0.9059 ; +0.1838 -0.6957 0.6933 ; +0.1713 -0.9099 0.3754 ; +0.1564 -0.9877 0.0000 ; +0.1444 -0.9119 -0.3826 ; +-0.1444 0.9117 -0.3826 ; +-0.1564 0.9877 -0.0001 ; +-0.1711 0.9100 0.3754 ; +-0.1836 0.6959 0.6936 ; +-0.1918 0.3763 0.9056 ; +-0.1948 0.0000 0.9800 ; +-0.1919 -0.3763 0.9056 ; +-0.1836 -0.6959 0.6936 ; +-0.1711 -0.9100 0.3754 ; +-0.1564 -0.9877 -0.0001 ; +-0.1444 -0.9117 -0.3826 ; +-0.4191 0.8225 -0.3826 ; +-0.4540 0.8910 -0.0001 ; +-0.4931 0.8073 0.3216 ; +-0.5259 0.6109 0.5904 ; +-0.5476 0.3285 0.7685 ; +-0.5551 0.0000 0.8311 ; +-0.5475 -0.3286 0.7685 ; +-0.5258 -0.6109 0.5904 ; +-0.4931 -0.8073 0.3216 ; +-0.4540 -0.8910 -0.0001 ; +-0.4191 -0.8225 -0.3826 ; +-0.6529 0.6529 -0.3825 ; +-0.7071 0.7071 0.0000 ; +-0.7561 0.6147 0.2205 ; +-0.7960 0.4537 0.3995 ; +-0.8218 0.2405 0.5152 ; +-0.8306 0.0000 0.5551 ; +-0.8218 -0.2405 0.5152 ; +-0.7960 -0.4537 0.3995 ; +-0.7562 -0.6147 0.2205 ; +-0.7071 -0.7071 0.0000 ; +-0.6529 -0.6529 -0.3825 ; +-0.8228 0.4191 -0.3824 ; +-0.8910 0.4540 0.0000 ; +-0.9283 0.3608 0.0818 ; +-0.9567 0.2511 0.1442 ; +-0.9739 0.1285 0.1822 ; +-0.9797 0.0000 0.1949 ; +-0.9739 -0.1286 0.1822 ; +-0.9567 -0.2511 0.1442 ; +-0.9283 -0.3608 0.0818 ; +-0.8910 -0.4540 0.0000 ; +-0.8228 -0.4191 -0.3824 ; +-0.9322 0.3029 -0.1949 ; +-0.9799 0.0000 -0.1949 ; +-0.9322 -0.3029 -0.1949 ; +0.0000 1.0000 0.0000 ; +-0.5878 0.8090 -0.0001 ; +0.0000 -1.0000 0.0000 ; +-0.5878 -0.8090 -0.0001 ]'; + + +elec = struct(... + 'labels',names,... + 'X',xyz(1,:),... + 'Y',xyz(2,:),... + 'Z',xyz(3,:)); + + +return + +% LPA 0.0000 0.9237 -0.3826 +% RPA 0.0000 -0.9237 -0.3826 +% Nz 0.9230 0.0000 -0.3824 +% Fp1 0.9511 0.3090 0.0001 +% Fpz 1.0000 -0.0000 0.0001 +% Fp2 0.9511 -0.3091 0.0000 +% AF9 0.7467 0.5425 -0.3825 +% AF7 0.8090 0.5878 0.0000 +% AF5 0.8553 0.4926 0.1552 +% AF3 0.8920 0.3554 0.2782 +% AF1 0.9150 0.1857 0.3558 +% AFz 0.9230 0.0000 0.3824 +% AF2 0.9150 -0.1857 0.3558 +% AF4 0.8919 -0.3553 0.2783 +% AF6 0.8553 -0.4926 0.1552 +% AF8 0.8090 -0.5878 0.0000 +% AF10 0.7467 -0.5425 -0.3825 +% F9 0.5430 0.7472 -0.3826 +% F7 0.5878 0.8090 0.0000 +% F5 0.6343 0.7210 0.2764 +% F3 0.6726 0.5399 0.5043 +% F1 0.6979 0.2888 0.6542 +% Fz 0.7067 0.0000 0.7067 +% F2 0.6979 -0.2888 0.6542 +% F4 0.6726 -0.5399 0.5043 +% F6 0.6343 -0.7210 0.2764 +% F8 0.5878 -0.8090 0.0000 +% F10 0.5429 -0.7472 -0.3826 +% FT9 0.2852 0.8777 -0.3826 +% FT7 0.3090 0.9511 0.0000 +% FC5 0.3373 0.8709 0.3549 +% FC3 0.3612 0.6638 0.6545 +% FC1 0.3770 0.3581 0.8532 +% FCz 0.3826 0.0000 0.9233 +% FC2 0.3770 -0.3581 0.8532 +% FC4 0.3612 -0.6638 0.6545 +% FC6 0.3373 -0.8709 0.3549 +% FT8 0.3090 -0.9511 0.0000 +% FT10 0.2852 -0.8777 -0.3826 +% T9 -0.0001 0.9237 -0.3826 +% T7 0.0000 1.0000 0.0000 +% C5 0.0001 0.9237 0.3826 +% C3 0.0001 0.7066 0.7066 +% C1 0.0002 0.3824 0.9231 +% Cz 0.0002 0.0000 1.0000 +% C2 0.0001 -0.3824 0.9231 +% C4 0.0001 -0.7066 0.7066 +% C6 0.0001 -0.9237 0.3826 +% T8 0.0000 -1.0000 0.0000 +% T10 0.0000 -0.9237 -0.3826 +% TP9 -0.2852 0.8777 -0.3826 +% TP7 -0.3090 0.9511 -0.0001 +% CP5 -0.3372 0.8712 0.3552 +% CP3 -0.3609 0.6635 0.6543 +% CP1 -0.3767 0.3580 0.8534 +% CPz -0.3822 0.0000 0.9231 +% CP2 -0.3767 -0.3580 0.8534 +% CP4 -0.3608 -0.6635 0.6543 +% CP6 -0.3372 -0.8712 0.3552 +% TP8 -0.3090 -0.9511 -0.0001 +% TP10 -0.2853 -0.8777 -0.3826 +% P9 -0.5429 0.7472 -0.3826 +% P7 -0.5878 0.8090 -0.0001 +% P5 -0.6342 0.7211 0.2764 +% P3 -0.6724 0.5401 0.5045 +% P1 -0.6975 0.2889 0.6545 +% Pz -0.7063 0.0000 0.7065 +% P2 -0.6975 -0.2889 0.6545 +% P4 -0.6724 -0.5401 0.5045 +% P6 -0.6342 -0.7211 0.2764 +% P8 -0.5878 -0.8090 -0.0001 +% P10 -0.5429 -0.7472 -0.3826 +% PO9 -0.7467 0.5425 -0.3825 +% PO7 -0.8090 0.5878 0.0000 +% PO5 -0.8553 0.4929 0.1555 +% PO3 -0.8918 0.3549 0.2776 +% PO1 -0.9151 0.1858 0.3559 +% POz -0.9230 -0.0000 0.3824 +% PO2 -0.9151 -0.1859 0.3559 +% PO4 -0.8918 -0.3549 0.2776 +% PO6 -0.8553 -0.4929 0.1555 +% PO8 -0.8090 -0.5878 0.0000 +% PO10 -0.7467 -0.5425 -0.3825 +% O1 -0.9511 0.3090 0.0000 +% Oz -1.0000 0.0000 0.0000 +% O2 -0.9511 -0.3090 0.0000 +% I1 -0.8785 0.2854 -0.3824 +% Iz -0.9230 0.0000 -0.3823 +% I2 -0.8785 -0.2854 -0.3824 +% AFp9h 0.8732 0.4449 -0.1949 +% AFp7h 0.9105 0.4093 0.0428 +% AFp5h 0.9438 0.3079 0.1159 +% AFp3h 0.9669 0.1910 0.1666 +% AFp1h 0.9785 0.0647 0.1919 +% AFp2h 0.9785 -0.0647 0.1919 +% AFp4h 0.9669 -0.1910 0.1666 +% AFp6h 0.9438 -0.3079 0.1159 +% AFp8h 0.9105 -0.4093 0.0428 +% AFp10h 0.8732 -0.4449 -0.1949 +% AFF9h 0.6929 0.6929 -0.1949 +% AFF7h 0.7325 0.6697 0.1137 +% AFF5h 0.7777 0.5417 0.3163 +% AFF3h 0.8111 0.3520 0.4658 +% AFF1h 0.8289 0.1220 0.5452 +% AFF2h 0.8289 -0.1220 0.5452 +% AFF4h 0.8111 -0.3520 0.4658 +% AFF6h 0.7777 -0.5417 0.3163 +% AFF8h 0.7325 -0.6697 0.1138 +% AFF10h 0.6929 -0.6929 -0.1949 +% FFT9h 0.4448 0.8730 -0.1950 +% FFT7h 0.4741 0.8642 0.1647 +% FFC5h 0.5107 0.7218 0.4651 +% FFC3h 0.5384 0.4782 0.6925 +% FFC1h 0.5533 0.1672 0.8148 +% FFC2h 0.5533 -0.1672 0.8148 +% FFC4h 0.5384 -0.4782 0.6925 +% FFC6h 0.5107 -0.7218 0.4651 +% FFT8h 0.4741 -0.8642 0.1647 +% FFT10h 0.4448 -0.8730 -0.1950 +% FTT9h 0.1533 0.9678 -0.1950 +% FTT7h 0.1640 0.9669 0.1915 +% FCC5h 0.1779 0.8184 0.5448 +% FCC3h 0.1887 0.5466 0.8154 +% FCC1h 0.1944 0.1919 0.9615 +% FCC2h 0.1944 -0.1919 0.9615 +% FCC4h 0.1887 -0.5466 0.8154 +% FCC6h 0.1779 -0.8184 0.5448 +% FTT8h 0.1640 -0.9669 0.1915 +% FTT10h 0.1533 -0.9678 -0.1950 +% TTP9h -0.1532 0.9678 -0.1950 +% TTP7h -0.1639 0.9669 0.1915 +% CCP5h -0.1778 0.8185 0.5449 +% CCP3h -0.1883 0.5465 0.8153 +% CCP1h -0.1940 0.1918 0.9611 +% CCP2h -0.1940 -0.1918 0.9611 +% CCP4h -0.1884 -0.5465 0.8153 +% CCP6h -0.1778 -0.8185 0.5449 +% TTP8h -0.1639 -0.9669 0.1915 +% TTP10h -0.1533 -0.9678 -0.1950 +% TPP9h -0.4448 0.8731 -0.1950 +% TPP7h -0.4740 0.8639 0.1646 +% CPP5h -0.5106 0.7220 0.4653 +% CPP3h -0.5384 0.4786 0.6933 +% CPP1h -0.5532 0.1673 0.8155 +% CPP2h -0.5532 -0.1673 0.8155 +% CPP4h -0.5384 -0.4786 0.6933 +% CPP6h -0.5106 -0.7220 0.4653 +% TPP8h -0.4740 -0.8638 0.1646 +% TPP10h -0.4449 -0.8731 -0.1950 +% PPO9h -0.6928 0.6928 -0.1950 +% PPO7h -0.7324 0.6700 0.1139 +% PPO5h -0.7776 0.5420 0.3167 +% PPO3h -0.8108 0.3520 0.4659 +% PPO1h -0.8284 0.1220 0.5453 +% PPO2h -0.8284 -0.1220 0.5453 +% PPO4h -0.8108 -0.3519 0.4659 +% PPO6h -0.7775 -0.5421 0.3167 +% PPO8h -0.7324 -0.6700 0.1139 +% PPO10h -0.6928 -0.6928 -0.1950 +% POO9h -0.8730 0.4448 -0.1950 +% POO7h -0.9106 0.4097 0.0430 +% POO5h -0.9438 0.3080 0.1160 +% POO3h -0.9665 0.1908 0.1657 +% POO1h -0.9783 0.0647 0.1918 +% POO2h -0.9783 -0.0647 0.1918 +% POO4h -0.9665 -0.1908 0.1657 +% POO6h -0.9438 -0.3080 0.1160 +% POO8h -0.9106 -0.4097 0.0430 +% POO10h -0.8730 -0.4448 -0.1950 +% OI1h -0.9679 0.1533 -0.1950 +% OI2h -0.9679 -0.1533 -0.1950 +% Fp1h 0.9877 0.1564 0.0001 +% Fp2h 0.9877 -0.1564 0.0001 +% AF9h 0.7928 0.5759 -0.1949 +% AF7h 0.8332 0.5463 0.0810 +% AF5h 0.8750 0.4284 0.2213 +% AF3h 0.9053 0.2735 0.3231 +% AF1h 0.9211 0.0939 0.3758 +% AF2h 0.9210 -0.0939 0.3758 +% AF4h 0.9053 -0.2735 0.3231 +% AF6h 0.8750 -0.4284 0.2212 +% AF8h 0.8332 -0.5463 0.0810 +% AF10h 0.7927 -0.5759 -0.1949 +% F9h 0.5761 0.7929 -0.1949 +% F7h 0.6117 0.7772 0.1420 +% F5h 0.6549 0.6412 0.3987 +% F3h 0.6872 0.4214 0.5906 +% F1h 0.7045 0.1468 0.6933 +% F2h 0.7045 -0.1468 0.6933 +% F4h 0.6872 -0.4214 0.5906 +% F6h 0.6549 -0.6412 0.3987 +% F8h 0.6117 -0.7772 0.1420 +% F10h 0.5761 -0.7929 -0.1949 +% FT9h 0.3027 0.9317 -0.1950 +% FT7h 0.3235 0.9280 0.1813 +% FC5h 0.3500 0.7817 0.5146 +% FC3h 0.3703 0.5207 0.7687 +% FC1h 0.3811 0.1824 0.9054 +% FC2h 0.3811 -0.1824 0.9054 +% FC4h 0.3703 -0.5207 0.7687 +% FC6h 0.3500 -0.7817 0.5146 +% FT8h 0.3235 -0.9280 0.1813 +% FT10h 0.3028 -0.9317 -0.1950 +% T9h 0.0000 0.9801 -0.1950 +% T7h 0.0000 0.9801 0.1949 +% C5h 0.0001 0.8311 0.5552 +% C3h 0.0002 0.5550 0.8306 +% C1h 0.0001 0.1950 0.9801 +% C2h 0.0002 -0.1950 0.9801 +% C4h 0.0002 -0.5550 0.8306 +% C6h 0.0001 -0.8311 0.5552 +% T8h 0.0000 -0.9801 0.1949 +% T10h 0.0000 -0.9801 -0.1950 +% TP9h -0.3028 0.9319 -0.1949 +% TP7h -0.3234 0.9278 0.1813 +% CP5h -0.3498 0.7818 0.5148 +% CP3h -0.3699 0.5206 0.7688 +% CP1h -0.3808 0.1825 0.9059 +% CP2h -0.3808 -0.1825 0.9059 +% CP4h -0.3699 -0.5206 0.7688 +% CP6h -0.3498 -0.7818 0.5148 +% TP8h -0.3234 -0.9278 0.1813 +% TP10h -0.3028 -0.9319 -0.1949 +% P9h -0.5761 0.7929 -0.1950 +% P7h -0.6116 0.7771 0.1420 +% P5h -0.6546 0.6411 0.3985 +% P3h -0.6869 0.4217 0.5912 +% P1h -0.7041 0.1469 0.6934 +% P2h -0.7041 -0.1469 0.6934 +% P4h -0.6870 -0.4216 0.5912 +% P6h -0.6546 -0.6411 0.3985 +% P8h -0.6116 -0.7771 0.1420 +% P10h -0.5761 -0.7929 -0.1950 +% PO9h -0.7926 0.5759 -0.1950 +% PO7h -0.8331 0.5459 0.0809 +% PO5h -0.8752 0.4292 0.2219 +% PO3h -0.9054 0.2737 0.3233 +% PO1h -0.9210 0.0939 0.3757 +% PO2h -0.9210 -0.0940 0.3757 +% PO4h -0.9054 -0.2737 0.3233 +% PO6h -0.8752 -0.4292 0.2219 +% PO8h -0.8331 -0.5459 0.0809 +% PO10h -0.7926 -0.5758 -0.1950 +% O1h -0.9877 0.1564 0.0000 +% O2h -0.9877 -0.1564 0.0000 +% I1h -0.9118 0.1444 -0.3824 +% I2h -0.9118 -0.1444 -0.3824 +% AFp9 0.8225 0.4190 -0.3825 +% AFp7 0.8910 0.4540 0.0000 +% AFp5 0.9282 0.3606 0.0817 +% AFp3 0.9565 0.2508 0.1438 +% AFp1 0.9743 0.1287 0.1828 +% AFpz 0.9799 -0.0000 0.1949 +% AFp2 0.9743 -0.1287 0.1828 +% AFp4 0.9565 -0.2508 0.1437 +% AFp6 0.9282 -0.3606 0.0817 +% AFp8 0.8910 -0.4540 0.0000 +% AFp10 0.8225 -0.4191 -0.3825 +% AFF9 0.6527 0.6527 -0.3825 +% AFF7 0.7071 0.7071 0.0000 +% AFF5 0.7564 0.6149 0.2206 +% AFF3 0.7962 0.4535 0.3990 +% AFF1 0.8221 0.2404 0.5148 +% AFFz 0.8312 0.0000 0.5554 +% AFF2 0.8221 -0.2404 0.5148 +% AFF4 0.7962 -0.4535 0.3990 +% AFF6 0.7564 -0.6149 0.2206 +% AFF8 0.7071 -0.7071 0.0000 +% AFF10 0.6527 -0.6527 -0.3825 +% FFT9 0.4192 0.8226 -0.3826 +% FFT7 0.4540 0.8910 0.0000 +% FFC5 0.4932 0.8072 0.3215 +% FFC3 0.5260 0.6110 0.5905 +% FFC1 0.5477 0.3286 0.7685 +% FFCz 0.5553 0.0000 0.8310 +% FFC2 0.5477 -0.3286 0.7685 +% FFC4 0.5260 -0.6110 0.5905 +% FFC6 0.4932 -0.8072 0.3216 +% FFT8 0.4540 -0.8910 0.0000 +% FFT10 0.4192 -0.8226 -0.3826 +% FTT9 0.1444 0.9119 -0.3826 +% FTT7 0.1565 0.9877 0.0000 +% FCC5 0.1713 0.9099 0.3754 +% FCC3 0.1838 0.6957 0.6933 +% FCC1 0.1922 0.3764 0.9059 +% FCCz 0.1951 0.0000 0.9804 +% FCC2 0.1922 -0.3764 0.9059 +% FCC4 0.1838 -0.6957 0.6933 +% FCC6 0.1713 -0.9099 0.3754 +% FTT8 0.1564 -0.9877 0.0000 +% FTT10 0.1444 -0.9119 -0.3826 +% TTP9 -0.1444 0.9117 -0.3826 +% TTP7 -0.1564 0.9877 -0.0001 +% CCP5 -0.1711 0.9100 0.3754 +% CCP3 -0.1836 0.6959 0.6936 +% CCP1 -0.1918 0.3763 0.9056 +% CCPz -0.1948 0.0000 0.9800 +% CCP2 -0.1919 -0.3763 0.9056 +% CCP4 -0.1836 -0.6959 0.6936 +% CCP6 -0.1711 -0.9100 0.3754 +% TTP8 -0.1564 -0.9877 -0.0001 +% TTP10 -0.1444 -0.9117 -0.3826 +% TPP9 -0.4191 0.8225 -0.3826 +% TPP7 -0.4540 0.8910 -0.0001 +% CPP5 -0.4931 0.8073 0.3216 +% CPP3 -0.5259 0.6109 0.5904 +% CPP1 -0.5476 0.3285 0.7685 +% CPPz -0.5551 0.0000 0.8311 +% CPP2 -0.5475 -0.3286 0.7685 +% CPP4 -0.5258 -0.6109 0.5904 +% CPP6 -0.4931 -0.8073 0.3216 +% TPP8 -0.4540 -0.8910 -0.0001 +% TPP10 -0.4191 -0.8225 -0.3826 +% PPO9 -0.6529 0.6529 -0.3825 +% PPO7 -0.7071 0.7071 0.0000 +% PPO5 -0.7561 0.6147 0.2205 +% PPO3 -0.7960 0.4537 0.3995 +% PPO1 -0.8218 0.2405 0.5152 +% PPOz -0.8306 0.0000 0.5551 +% PPO2 -0.8218 -0.2405 0.5152 +% PPO4 -0.7960 -0.4537 0.3995 +% PPO6 -0.7562 -0.6147 0.2205 +% PPO8 -0.7071 -0.7071 0.0000 +% PPO10 -0.6529 -0.6529 -0.3825 +% POO9 -0.8228 0.4191 -0.3824 +% POO7 -0.8910 0.4540 0.0000 +% POO5 -0.9283 0.3608 0.0818 +% POO3 -0.9567 0.2511 0.1442 +% POO1 -0.9739 0.1285 0.1822 +% POOz -0.9797 -0.0000 0.1949 +% POO2 -0.9739 -0.1286 0.1822 +% POO4 -0.9567 -0.2511 0.1442 +% POO6 -0.9283 -0.3608 0.0818 +% POO8 -0.8910 -0.4540 0.0000 +% POO10 -0.8228 -0.4191 -0.3824 +% OI1 -0.9322 0.3029 -0.1949 +% OIz -0.9799 0.0000 -0.1949 +% OI2 -0.9322 -0.3029 -0.1949 +% T3 0.0000 1.0000 0.0000 +% T5 -0.5878 0.8090 -0.0001 +% T4 0.0000 -1.0000 0.0000 +% T6 -0.5878 -0.8090 -0.0001 diff --git a/elec_1020all_cart.txt b/elec_1020all_cart.txt new file mode 100644 index 0000000..2217c70 --- /dev/null +++ b/elec_1020all_cart.txt @@ -0,0 +1,342 @@ +LPA 0.0000 0.9237 -0.3826 +RPA 0.0000 -0.9237 -0.3826 +Nz 0.9230 0.0000 -0.3824 +Fp1 0.9511 0.3090 0.0001 +Fpz 1.0000 -0.0000 0.0001 +Fp2 0.9511 -0.3091 0.0000 +AF9 0.7467 0.5425 -0.3825 +AF7 0.8090 0.5878 0.0000 +AF5 0.8553 0.4926 0.1552 +AF3 0.8920 0.3554 0.2782 +AF1 0.9150 0.1857 0.3558 +AFz 0.9230 0.0000 0.3824 +AF2 0.9150 -0.1857 0.3558 +AF4 0.8919 -0.3553 0.2783 +AF6 0.8553 -0.4926 0.1552 +AF8 0.8090 -0.5878 0.0000 +AF10 0.7467 -0.5425 -0.3825 +F9 0.5430 0.7472 -0.3826 +F7 0.5878 0.8090 0.0000 +F5 0.6343 0.7210 0.2764 +F3 0.6726 0.5399 0.5043 +F1 0.6979 0.2888 0.6542 +Fz 0.7067 0.0000 0.7067 +F2 0.6979 -0.2888 0.6542 +F4 0.6726 -0.5399 0.5043 +F6 0.6343 -0.7210 0.2764 +F8 0.5878 -0.8090 0.0000 +F10 0.5429 -0.7472 -0.3826 +FT9 0.2852 0.8777 -0.3826 +FT7 0.3090 0.9511 0.0000 +FC5 0.3373 0.8709 0.3549 +FC3 0.3612 0.6638 0.6545 +FC1 0.3770 0.3581 0.8532 +FCz 0.3826 0.0000 0.9233 +FC2 0.3770 -0.3581 0.8532 +FC4 0.3612 -0.6638 0.6545 +FC6 0.3373 -0.8709 0.3549 +FT8 0.3090 -0.9511 0.0000 +FT10 0.2852 -0.8777 -0.3826 +T9 -0.0001 0.9237 -0.3826 +T7 0.0000 1.0000 0.0000 +C5 0.0001 0.9237 0.3826 +C3 0.0001 0.7066 0.7066 +C1 0.0002 0.3824 0.9231 +Cz 0.0002 0.0000 1.0000 +C2 0.0001 -0.3824 0.9231 +C4 0.0001 -0.7066 0.7066 +C6 0.0001 -0.9237 0.3826 +T8 0.0000 -1.0000 0.0000 +T10 0.0000 -0.9237 -0.3826 +TP9 -0.2852 0.8777 -0.3826 +TP7 -0.3090 0.9511 -0.0001 +CP5 -0.3372 0.8712 0.3552 +CP3 -0.3609 0.6635 0.6543 +CP1 -0.3767 0.3580 0.8534 +CPz -0.3822 0.0000 0.9231 +CP2 -0.3767 -0.3580 0.8534 +CP4 -0.3608 -0.6635 0.6543 +CP6 -0.3372 -0.8712 0.3552 +TP8 -0.3090 -0.9511 -0.0001 +TP10 -0.2853 -0.8777 -0.3826 +P9 -0.5429 0.7472 -0.3826 +P7 -0.5878 0.8090 -0.0001 +P5 -0.6342 0.7211 0.2764 +P3 -0.6724 0.5401 0.5045 +P1 -0.6975 0.2889 0.6545 +Pz -0.7063 0.0000 0.7065 +P2 -0.6975 -0.2889 0.6545 +P4 -0.6724 -0.5401 0.5045 +P6 -0.6342 -0.7211 0.2764 +P8 -0.5878 -0.8090 -0.0001 +P10 -0.5429 -0.7472 -0.3826 +PO9 -0.7467 0.5425 -0.3825 +PO7 -0.8090 0.5878 0.0000 +PO5 -0.8553 0.4929 0.1555 +PO3 -0.8918 0.3549 0.2776 +PO1 -0.9151 0.1858 0.3559 +POz -0.9230 -0.0000 0.3824 +PO2 -0.9151 -0.1859 0.3559 +PO4 -0.8918 -0.3549 0.2776 +PO6 -0.8553 -0.4929 0.1555 +PO8 -0.8090 -0.5878 0.0000 +PO10 -0.7467 -0.5425 -0.3825 +O1 -0.9511 0.3090 0.0000 +Oz -1.0000 0.0000 0.0000 +O2 -0.9511 -0.3090 0.0000 +I1 -0.8785 0.2854 -0.3824 +Iz -0.9230 0.0000 -0.3823 +I2 -0.8785 -0.2854 -0.3824 +AFp9h 0.8732 0.4449 -0.1949 +AFp7h 0.9105 0.4093 0.0428 +AFp5h 0.9438 0.3079 0.1159 +AFp3h 0.9669 0.1910 0.1666 +AFp1h 0.9785 0.0647 0.1919 +AFp2h 0.9785 -0.0647 0.1919 +AFp4h 0.9669 -0.1910 0.1666 +AFp6h 0.9438 -0.3079 0.1159 +AFp8h 0.9105 -0.4093 0.0428 +AFp10h 0.8732 -0.4449 -0.1949 +AFF9h 0.6929 0.6929 -0.1949 +AFF7h 0.7325 0.6697 0.1137 +AFF5h 0.7777 0.5417 0.3163 +AFF3h 0.8111 0.3520 0.4658 +AFF1h 0.8289 0.1220 0.5452 +AFF2h 0.8289 -0.1220 0.5452 +AFF4h 0.8111 -0.3520 0.4658 +AFF6h 0.7777 -0.5417 0.3163 +AFF8h 0.7325 -0.6697 0.1138 +AFF10h 0.6929 -0.6929 -0.1949 +FFT9h 0.4448 0.8730 -0.1950 +FFT7h 0.4741 0.8642 0.1647 +FFC5h 0.5107 0.7218 0.4651 +FFC3h 0.5384 0.4782 0.6925 +FFC1h 0.5533 0.1672 0.8148 +FFC2h 0.5533 -0.1672 0.8148 +FFC4h 0.5384 -0.4782 0.6925 +FFC6h 0.5107 -0.7218 0.4651 +FFT8h 0.4741 -0.8642 0.1647 +FFT10h 0.4448 -0.8730 -0.1950 +FTT9h 0.1533 0.9678 -0.1950 +FTT7h 0.1640 0.9669 0.1915 +FCC5h 0.1779 0.8184 0.5448 +FCC3h 0.1887 0.5466 0.8154 +FCC1h 0.1944 0.1919 0.9615 +FCC2h 0.1944 -0.1919 0.9615 +FCC4h 0.1887 -0.5466 0.8154 +FCC6h 0.1779 -0.8184 0.5448 +FTT8h 0.1640 -0.9669 0.1915 +FTT10h 0.1533 -0.9678 -0.1950 +TTP9h -0.1532 0.9678 -0.1950 +TTP7h -0.1639 0.9669 0.1915 +CCP5h -0.1778 0.8185 0.5449 +CCP3h -0.1883 0.5465 0.8153 +CCP1h -0.1940 0.1918 0.9611 +CCP2h -0.1940 -0.1918 0.9611 +CCP4h -0.1884 -0.5465 0.8153 +CCP6h -0.1778 -0.8185 0.5449 +TTP8h -0.1639 -0.9669 0.1915 +TTP10h -0.1533 -0.9678 -0.1950 +TPP9h -0.4448 0.8731 -0.1950 +TPP7h -0.4740 0.8639 0.1646 +CPP5h -0.5106 0.7220 0.4653 +CPP3h -0.5384 0.4786 0.6933 +CPP1h -0.5532 0.1673 0.8155 +CPP2h -0.5532 -0.1673 0.8155 +CPP4h -0.5384 -0.4786 0.6933 +CPP6h -0.5106 -0.7220 0.4653 +TPP8h -0.4740 -0.8638 0.1646 +TPP10h -0.4449 -0.8731 -0.1950 +PPO9h -0.6928 0.6928 -0.1950 +PPO7h -0.7324 0.6700 0.1139 +PPO5h -0.7776 0.5420 0.3167 +PPO3h -0.8108 0.3520 0.4659 +PPO1h -0.8284 0.1220 0.5453 +PPO2h -0.8284 -0.1220 0.5453 +PPO4h -0.8108 -0.3519 0.4659 +PPO6h -0.7775 -0.5421 0.3167 +PPO8h -0.7324 -0.6700 0.1139 +PPO10h -0.6928 -0.6928 -0.1950 +POO9h -0.8730 0.4448 -0.1950 +POO7h -0.9106 0.4097 0.0430 +POO5h -0.9438 0.3080 0.1160 +POO3h -0.9665 0.1908 0.1657 +POO1h -0.9783 0.0647 0.1918 +POO2h -0.9783 -0.0647 0.1918 +POO4h -0.9665 -0.1908 0.1657 +POO6h -0.9438 -0.3080 0.1160 +POO8h -0.9106 -0.4097 0.0430 +POO10h -0.8730 -0.4448 -0.1950 +OI1h -0.9679 0.1533 -0.1950 +OI2h -0.9679 -0.1533 -0.1950 +Fp1h 0.9877 0.1564 0.0001 +Fp2h 0.9877 -0.1564 0.0001 +AF9h 0.7928 0.5759 -0.1949 +AF7h 0.8332 0.5463 0.0810 +AF5h 0.8750 0.4284 0.2213 +AF3h 0.9053 0.2735 0.3231 +AF1h 0.9211 0.0939 0.3758 +AF2h 0.9210 -0.0939 0.3758 +AF4h 0.9053 -0.2735 0.3231 +AF6h 0.8750 -0.4284 0.2212 +AF8h 0.8332 -0.5463 0.0810 +AF10h 0.7927 -0.5759 -0.1949 +F9h 0.5761 0.7929 -0.1949 +F7h 0.6117 0.7772 0.1420 +F5h 0.6549 0.6412 0.3987 +F3h 0.6872 0.4214 0.5906 +F1h 0.7045 0.1468 0.6933 +F2h 0.7045 -0.1468 0.6933 +F4h 0.6872 -0.4214 0.5906 +F6h 0.6549 -0.6412 0.3987 +F8h 0.6117 -0.7772 0.1420 +F10h 0.5761 -0.7929 -0.1949 +FT9h 0.3027 0.9317 -0.1950 +FT7h 0.3235 0.9280 0.1813 +FC5h 0.3500 0.7817 0.5146 +FC3h 0.3703 0.5207 0.7687 +FC1h 0.3811 0.1824 0.9054 +FC2h 0.3811 -0.1824 0.9054 +FC4h 0.3703 -0.5207 0.7687 +FC6h 0.3500 -0.7817 0.5146 +FT8h 0.3235 -0.9280 0.1813 +FT10h 0.3028 -0.9317 -0.1950 +T9h 0.0000 0.9801 -0.1950 +T7h 0.0000 0.9801 0.1949 +C5h 0.0001 0.8311 0.5552 +C3h 0.0002 0.5550 0.8306 +C1h 0.0001 0.1950 0.9801 +C2h 0.0002 -0.1950 0.9801 +C4h 0.0002 -0.5550 0.8306 +C6h 0.0001 -0.8311 0.5552 +T8h 0.0000 -0.9801 0.1949 +T10h 0.0000 -0.9801 -0.1950 +TP9h -0.3028 0.9319 -0.1949 +TP7h -0.3234 0.9278 0.1813 +CP5h -0.3498 0.7818 0.5148 +CP3h -0.3699 0.5206 0.7688 +CP1h -0.3808 0.1825 0.9059 +CP2h -0.3808 -0.1825 0.9059 +CP4h -0.3699 -0.5206 0.7688 +CP6h -0.3498 -0.7818 0.5148 +TP8h -0.3234 -0.9278 0.1813 +TP10h -0.3028 -0.9319 -0.1949 +P9h -0.5761 0.7929 -0.1950 +P7h -0.6116 0.7771 0.1420 +P5h -0.6546 0.6411 0.3985 +P3h -0.6869 0.4217 0.5912 +P1h -0.7041 0.1469 0.6934 +P2h -0.7041 -0.1469 0.6934 +P4h -0.6870 -0.4216 0.5912 +P6h -0.6546 -0.6411 0.3985 +P8h -0.6116 -0.7771 0.1420 +P10h -0.5761 -0.7929 -0.1950 +PO9h -0.7926 0.5759 -0.1950 +PO7h -0.8331 0.5459 0.0809 +PO5h -0.8752 0.4292 0.2219 +PO3h -0.9054 0.2737 0.3233 +PO1h -0.9210 0.0939 0.3757 +PO2h -0.9210 -0.0940 0.3757 +PO4h -0.9054 -0.2737 0.3233 +PO6h -0.8752 -0.4292 0.2219 +PO8h -0.8331 -0.5459 0.0809 +PO10h -0.7926 -0.5758 -0.1950 +O1h -0.9877 0.1564 0.0000 +O2h -0.9877 -0.1564 0.0000 +I1h -0.9118 0.1444 -0.3824 +I2h -0.9118 -0.1444 -0.3824 +AFp9 0.8225 0.4190 -0.3825 +AFp7 0.8910 0.4540 0.0000 +AFp5 0.9282 0.3606 0.0817 +AFp3 0.9565 0.2508 0.1438 +AFp1 0.9743 0.1287 0.1828 +AFpz 0.9799 -0.0000 0.1949 +AFp2 0.9743 -0.1287 0.1828 +AFp4 0.9565 -0.2508 0.1437 +AFp6 0.9282 -0.3606 0.0817 +AFp8 0.8910 -0.4540 0.0000 +AFp10 0.8225 -0.4191 -0.3825 +AFF9 0.6527 0.6527 -0.3825 +AFF7 0.7071 0.7071 0.0000 +AFF5 0.7564 0.6149 0.2206 +AFF3 0.7962 0.4535 0.3990 +AFF1 0.8221 0.2404 0.5148 +AFFz 0.8312 0.0000 0.5554 +AFF2 0.8221 -0.2404 0.5148 +AFF4 0.7962 -0.4535 0.3990 +AFF6 0.7564 -0.6149 0.2206 +AFF8 0.7071 -0.7071 0.0000 +AFF10 0.6527 -0.6527 -0.3825 +FFT9 0.4192 0.8226 -0.3826 +FFT7 0.4540 0.8910 0.0000 +FFC5 0.4932 0.8072 0.3215 +FFC3 0.5260 0.6110 0.5905 +FFC1 0.5477 0.3286 0.7685 +FFCz 0.5553 0.0000 0.8310 +FFC2 0.5477 -0.3286 0.7685 +FFC4 0.5260 -0.6110 0.5905 +FFC6 0.4932 -0.8072 0.3216 +FFT8 0.4540 -0.8910 0.0000 +FFT10 0.4192 -0.8226 -0.3826 +FTT9 0.1444 0.9119 -0.3826 +FTT7 0.1565 0.9877 0.0000 +FCC5 0.1713 0.9099 0.3754 +FCC3 0.1838 0.6957 0.6933 +FCC1 0.1922 0.3764 0.9059 +FCCz 0.1951 0.0000 0.9804 +FCC2 0.1922 -0.3764 0.9059 +FCC4 0.1838 -0.6957 0.6933 +FCC6 0.1713 -0.9099 0.3754 +FTT8 0.1564 -0.9877 0.0000 +FTT10 0.1444 -0.9119 -0.3826 +TTP9 -0.1444 0.9117 -0.3826 +TTP7 -0.1564 0.9877 -0.0001 +CCP5 -0.1711 0.9100 0.3754 +CCP3 -0.1836 0.6959 0.6936 +CCP1 -0.1918 0.3763 0.9056 +CCPz -0.1948 0.0000 0.9800 +CCP2 -0.1919 -0.3763 0.9056 +CCP4 -0.1836 -0.6959 0.6936 +CCP6 -0.1711 -0.9100 0.3754 +TTP8 -0.1564 -0.9877 -0.0001 +TTP10 -0.1444 -0.9117 -0.3826 +TPP9 -0.4191 0.8225 -0.3826 +TPP7 -0.4540 0.8910 -0.0001 +CPP5 -0.4931 0.8073 0.3216 +CPP3 -0.5259 0.6109 0.5904 +CPP1 -0.5476 0.3285 0.7685 +CPPz -0.5551 0.0000 0.8311 +CPP2 -0.5475 -0.3286 0.7685 +CPP4 -0.5258 -0.6109 0.5904 +CPP6 -0.4931 -0.8073 0.3216 +TPP8 -0.4540 -0.8910 -0.0001 +TPP10 -0.4191 -0.8225 -0.3826 +PPO9 -0.6529 0.6529 -0.3825 +PPO7 -0.7071 0.7071 0.0000 +PPO5 -0.7561 0.6147 0.2205 +PPO3 -0.7960 0.4537 0.3995 +PPO1 -0.8218 0.2405 0.5152 +PPOz -0.8306 0.0000 0.5551 +PPO2 -0.8218 -0.2405 0.5152 +PPO4 -0.7960 -0.4537 0.3995 +PPO6 -0.7562 -0.6147 0.2205 +PPO8 -0.7071 -0.7071 0.0000 +PPO10 -0.6529 -0.6529 -0.3825 +POO9 -0.8228 0.4191 -0.3824 +POO7 -0.8910 0.4540 0.0000 +POO5 -0.9283 0.3608 0.0818 +POO3 -0.9567 0.2511 0.1442 +POO1 -0.9739 0.1285 0.1822 +POOz -0.9797 -0.0000 0.1949 +POO2 -0.9739 -0.1286 0.1822 +POO4 -0.9567 -0.2511 0.1442 +POO6 -0.9283 -0.3608 0.0818 +POO8 -0.8910 -0.4540 0.0000 +POO10 -0.8228 -0.4191 -0.3824 +OI1 -0.9322 0.3029 -0.1949 +OIz -0.9799 0.0000 -0.1949 +OI2 -0.9322 -0.3029 -0.1949 +T3 0.0000 1.0000 0.0000 +T5 -0.5878 0.8090 -0.0001 +T4 0.0000 -1.0000 0.0000 +T6 -0.5878 -0.8090 -0.0001 \ No newline at end of file diff --git a/elec_1020select.m b/elec_1020select.m new file mode 100644 index 0000000..8af2169 --- /dev/null +++ b/elec_1020select.m @@ -0,0 +1,68 @@ +function [CHAN1020,XYZ1020] = elec_1020select(CHAN) + +% elec_1020select - select 10-20 locations +% +% [labels,xyz] = elec_1020select(CHAN) +% +% where CHAN input is a cell array of channel names from the International +% 10-20 nomenclature for EEG electrode placement. For a list of the 10-20 +% electrode names, see the elec_1020all_cart function, which is based on: +% +% Oostenveld, R. & Praamstra, P. (2001). The five percent electrode system +% for high-resolution EEG and ERP measurements. Clinical Neurophysiology, +% 112:713-719. +% + +% $Revision: 1.1 $ $Date: 2009-01-30 03:49:28 $ + +% Copyright (C) 2005 Darren L. Weber +% +% This program is free software; you can redistribute it and/or +% modify it under the terms of the GNU General Public License +% as published by the Free Software Foundation; either version 2 +% of the License, or (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program; if not, write to the Free Software +% Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +% Modified: 01/2005, Darren.Weber_at_radiology.ucsf.edu +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +ver = '$Revision: 1.1 $ $Date: 2009-01-30 03:49:28 $'; +fprintf('\nELEC_1020SELECT [v %s]\n',ver(11:15)); + +% get the 1020 data +elec = elec_1020all_cart; +elec = struct2cell(elec); +labels = squeeze(elec(1,:,:))'; +x = squeeze(elec(2,:,:)); x = x{1}; +y = squeeze(elec(3,:,:)); y = y{1}; +z = squeeze(elec(4,:,:)); z = z{1}; +clear elec + +% find all the electrode names in elec.labels that match CHAN +CHAN1020 = zeros(1,length(CHAN)); +XYZ1020 = zeros(length(CHAN),3); +for c = 1:length(CHAN), + chan = CHAN{c}; + index = strmatch(lower(chan),lower(labels),'exact'); + if ~isempty(index), + CHAN1020(c) = index; + XYZ1020(c,:) = [ x(index), y(index), z(index) ]; + else + msg = sprintf('No match for channel: %s\n',chan) + error(msg) + end +end + +CHAN1020 = labels(CHAN1020); + +return diff --git a/gpl.txt b/gpl.txt new file mode 100644 index 0000000..5b6e7c6 --- /dev/null +++ b/gpl.txt @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/gpl_include.txt b/gpl_include.txt new file mode 100644 index 0000000..5c28d9c --- /dev/null +++ b/gpl_include.txt @@ -0,0 +1,15 @@ +Copyright (C) 2004 Darren L. Weber + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. diff --git a/plot_3Dsensor.m b/plot_3Dsensor.m new file mode 100644 index 0000000..8ed2062 --- /dev/null +++ b/plot_3Dsensor.m @@ -0,0 +1,78 @@ +function hf = plot_3Dsensor(channelfile,M,mesh,flat) +%function hf = plot_3Dsensor(channelfile,M,mesh,flat) +% +%Plots the channels, including the topography of measurements M, with or +%without a mesh +% +%inputs: +%channelfile: a file that contains a Channel structure, produced by BrainStorm +%M: a (nSensors x 1) vector with the measurements on the sensors. Use zeros +% if you only want to see the sensors +%mesh: 'y' or 'n', plots a mesh around the sensors +%flat: 'y' or 'n', to get a flat mesh +% +%eg, use: +%plot_3Dsensor('GA_HiN_CueLInvNT-fEOG_channel.mat',zeros(275,1),'y') +% +% Author: Dimitrios Pantazis, PhD Student, USC, February 2005 + +%load channel file +load(channelfile) + +%get channel locations +ndx = 1; +for i=1:size(Channel,2) %for all channels + if strfind(Channel(i).Type,'MEG') & isempty(strfind(Channel(i).Type,'REF')) %if MEG + MEGndx(ndx) = i; + chanlocs(:,ndx) = Channel(i).Loc(:,1); + ndx = ndx+1; + end +end +chanlocs = chanlocs'; + +%if M does not exist, assign zeros +if(~exist('M')) + M = zeros(size(MEGndx,2),1); +end + +if(~exist('mesh','var')) + mesh = 'y'; +end + +%create patch (Sylvain's code) +chanlocs(:,3)=chanlocs(:,3)-max(chanlocs(:,3)); +[TH,PHI,R]=cart2sph(chanlocs(:,1),chanlocs(:,2),chanlocs(:,3)); +%PHI2=zeros(size(PHI)); +R2=R./cos(PHI).^.2; +[Y,X]=pol2cart(TH,R2); +%Y et X sont les coordonnées projetees dans le plan 'tangent superieur' pour chaque capteur +bord = convhull(Y,X); +ncapt = size(chanlocs,1); +[center,R] = bestfitsph(chanlocs); +coordC = chanlocs-(ones(ncapt,1)*center'); +tri = convhulln(coordC./(norlig(coordC)'*ones(1,3))); +keep = find(~(ismember(tri(:,1),bord) & ismember(tri(:,2),bord) & ismember(tri(:,3),bord))); +tri = tri(keep,:); + +%plot patch +hf = figure; +if exist('flat') & strcmp(flat,'y') + h =trisurf(tri,X,Y,zeros(273,1),M); %flat + view(90,270) +else + h =trisurf(tri,chanlocs(:,1),chanlocs(:,2),chanlocs(:,3),M); + view(0,90); +end +set(h,'edgecolor','none','facecolor','interp') +axis equal +axis off +axis vis3d + + + +if(strcmp(mesh,'y')) + set(h,'edgecolor','black'); + set(h,'marker','*'); +end + +set(gcf,'color','white'); diff --git a/pop_ctf_read.m b/pop_ctf_read.m new file mode 100644 index 0000000..7eb18f1 --- /dev/null +++ b/pop_ctf_read.m @@ -0,0 +1,252 @@ +% pop_ctf_read() - read CTF file as EEGLAB dataset +% +% Usage: +% >> EEGOUT = pop_ctf_read; % pop up graphic interface +% >> EEGOUT = pop_ctf_read(folder); +% >> EEGOUT = pop_ctf_read(folder, chans, time, trials); +% +% Inputs: +% folder - [string] EEGLAB figure +% chans - [integer array or string] see ctf_read() +% time - [float array or string] see ctf_read() +% trials - [integer array or string] see ctf_read() +% +% +% Author: Arnaud Delorme (SCCN, UCSD) and Daren Weber (DNL, UCSF) +% +% See also: ctf_read(), ctf_readmarkerfile() + +% Copyright (C) 2003 Arnaud Delorme, SCCN, UCSD, arno@salk.edu +% +% This program is free software; you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation; either version 2 of the License, or +% (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program; if not, write to the Free Software +% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +% from ctf2eeglab - script to convert and save ctf .ds into eeglab .set data +% +% The script uses a ctf struct in the matlab workspace or a GUI prompt to +% load a CTF .ds folder, then converts the ctf data into an EEGLAB EEG +% struct, saving the resulting dataset into an EEEGLAB .set file, located +% in the same path as the ctf .ds folder. The GUI prompt for the CTF .ds +% folder also provides access to definition of the channels, time and +% trials to load. +% +% Licence: GNU GPL, no express or implied warranties +% Modified: 01/2004, Darren.Weber_at_radiology.ucsf.edu +% - developed in collaboration with Fredrick Carver of +% the NIH, USA. +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function [EEG, com] = pop_ctf_read(orifolder, varargin) + + EEG = []; + com = ''; + if nargin < 1 + ctf = ctf_folder; + %tmp = ctf_folder(tmp, []); + %tmp = tmp.folder; + %tmp = uigetfile('*.*','Select .res4 file'); + %if tmp == 0 return; end; + + % read info and prompt + % -------------------- + listchan = { 'all' 'eeg' 'meg' 'ref' 'other' 'megeeg'}; + disp('Reading file info...'); + ctf = ctf_read_res4(ctf.folder, 0); + uigeom = { [2 1] [2 1] [2 1] [2 1] }; + uilist = { { 'style' 'text' 'string' 'Channels group subset' } ... + { 'style' 'list' 'string' strvcat(listchan{:}) } ... + { 'style' 'text' 'string' 'or channel indices (overwrite above)' } ... + { 'style' 'edit' 'string' '' } ... + { 'style' 'text' 'string' 'Time range (default all)' } ... + { 'style' 'edit' 'string' '' } ... + { 'style' 'text' 'string' sprintf('Trial range (default all [1:%d])', ctf.setup.number_trials) } ... + { 'style' 'edit' 'string' '' } }; + result = inputgui( uigeom, uilist, 'pophelp(''pop_ctf_read'')', 'Load a CTF dataset'); + if length( result ) == 0 return; end; + + % decode inputs + % ------------- + options{1} = [1:ctf.setup.number_channels]; + if result{1} > 1 + options{1} = listchan{result{1}}; + end; + if ~isempty(result{2}) + options{1} = eval( [ '[' result{2} ']' ] ); + end; + if ~isempty(result{3}) + options{2} = eval( [ '[' result{3} ']' ] ); + end; + if ~isempty(result{4}) + options{3} = eval( [ '[' result{4} ']' ] ); + end; + else + ctf.folder = orifolder; % *** JRI *** + options = varargin; + end; + + alltrials = []; + if length(options) == 3 + alltrials = options{3}; + end; + if length(options) > 1 & isempty(options{2}) + options{2} = 'all'; + end; + + % read the data + % ------------- + ctf = ctf_read(ctf.folder,options{:}); + + % check if the data is averaged + % ----------------------------- + if ctf.setup.number_trials_averaged > 0, + warning('this .ds folder is averaged, removing stdev'); + end + + % check if the data is greater than 500 Mb + data_size = ctf.setup.number_samples * ctf.setup.number_channels * ctf.setup.number_trials; + data_bytes = data_size * 8; + if data_bytes > 5e9, warning('data is greater than 500 Mb'); end + clear data_size data_bytes; + + % ctf.data is a 3D matrix of samples(time) x channels x trials + % whereas EEGLAB has a 3D data matrix with channels X samples X trials + if ndims(ctf.data) < 3 + data = ctf.data'; + else + try, + data = permute(ctf.data, [2 1 3]); + catch, + disp('Not enough memory, trying to transpose data by saving it'); + fid = fopen('tmpmeg.raw', 'w') + if fid == -1, + error('Cannot create file in current folder'); + end; + for index = i:size(ctf.data,2) + fwrite(fid,squeeze(ctf.data(:,index,:)),'float'); + end; + fclose(fid); + ctf.data = []; + EEG.data = floatread('tmpmeg.raw'); + delete('tmpmeg.raw'); + end; + end; + + % import the data into the EEGLAB EEG struct + + [DSpath,DSfile,DSext] = fileparts(ctf.folder); + + EEG = eeg_emptyset; + EEG.setname = DSfile; + + % --- + % These fields now contain the name of the dataset *once* + % it has been saved (so reamin empty before the dataset + % has been saved). + %EEG.filename = [DSfile,'.set']; + %EEG.filepath = DSpath; + % --- + + EEG.comments = [ 'Original folder: ' ctf.folder ]; + %EEG.comments = ctf.setup.run_description'; + EEG.pnts = ctf.setup.number_samples; + EEG.nbchan = ctf.setup.number_channels; + EEG.trials = ctf.setup.number_trials; + EEG.srate = ctf.setup.sample_rate; + EEG.xmin = ctf.setup.start_sec; + EEG.xmax = ctf.setup.end_sec; + EEG.data = data; + EEG.ref = 'common'; + + try, + for index=1:ctf.setup.number_channels, + EEG.chanlocs(index).labels = ctf.sensor.label{index}; + EEG.chanlocs(index).X = ctf.sensor.location(1,index); + EEG.chanlocs(index).Y = ctf.sensor.location(2,index); + EEG.chanlocs(index).Z = ctf.sensor.location(3,index); + end + catch, + for index=1:length(ctf.sensor.info), + EEG.chanlocs(index).labels = ctf.sensor.info(index).label; + if ~isempty(ctf.sensor.info(index).location) + EEG.chanlocs(index).X = ctf.sensor.info(index).location(1); + EEG.chanlocs(index).Y = ctf.sensor.info(index).location(2); + EEG.chanlocs(index).Z = ctf.sensor.info(index).location(3); + end; + end + end; + EEG.chanlocs = convertlocs(EEG.chanlocs, 'cart2all'); + + % now clear the workspace of the input data + % ----------------------------------------- + clear data + clear DSpath DSfile DSext i + + % import event information + % ------------------------ + %try + eventarray = []; + allfields = {}; + timefields = {}; + otherfields = {}; + + eventstruct = ctf_read_markerfile(ctf); + if isfield(eventstruct, 'markers') + eventstruct = eventstruct.markers; + end; + + if isfield(eventstruct,'trial_times'), + + for index = 1:length(eventstruct) + trialtimes = eventstruct(index).trial_times(:,2)*EEG.srate; + if EEG.trials > 1 + trialtimes = trialtimes+(eventstruct(index).trial_times(:,1)-1)*EEG.pnts - ctf.setup.start_msec/1000*EEG.srate; + end; + + for numev = 1:length(trialtimes) + EEG.event(end+1).latency = trialtimes(numev); + EEG.event(end).type = eventstruct(index).marker_names; + if EEG.trials > 1 + EEG.event(end).epoch = floor(trialtimes(numev)/EEG.pnts)+1; + end; + end; + end; + + EEG = eeg_checkset(EEG, 'eventconsistency'); + end + + + %catch + % disp(lasterr); + % disp('error (see above) while importing events: events not imported'); + %end; + + % command + com = sprintf('EEG = pop_ctf_read(''%s'', %s)', ctf.folder, vararg2str(options)); + +% format folder +% ------------- +function [folder,parentfolder] = formatfolder( orifolder ) + delims = [ find(orifolder == '/') find(orifolder == '\') ]; + if ~isempty(delims) + if delims(end) == length(orifolder) + folder = orifolder(delims(end-1)+1:end-1); + parentfolder = orifolder(1:delims(end-1)-1); + else + folder = orifolder(delims(end)+1:end-1); + parentfolder = orifolder(1:delims(end)-1); + end; + else + folder = orifolder; + parentfolder = '.'; + end; diff --git a/read_ctf_ascii.m b/read_ctf_ascii.m new file mode 100644 index 0000000..3b31a8a --- /dev/null +++ b/read_ctf_ascii.m @@ -0,0 +1,68 @@ +function [file] = read_ctf_ascii(filename); + +% READ_CTF_ASCII reads general data from an CTF configuration file +% +% The file should be formatted like +% Group +% { +% item1 : value1a value1b value1c +% item2 : value2a value2b value2c +% item3 : value3a value3b value3c +% item4 : value4a value4b value4c +% } +% +% This fileformat structure is used in +% params.avg +% default.hdm +% multiSphere.hdm +% processing.cfg +% and maybe for other files as well. + +% Copyright (C) 2003, Robert Oostenveld +% +fid = fopen(filename, 'r'); +if fid==-1 + error(sprintf('could not open file %s', filename)); +end + +line = ''; +while ischar(line) + line = cleanline(fgetl(fid)); + if isempty(line) | line==-1 + continue + end + + % the line is not empty, which means that we have encountered a chunck of information + subline = cleanline(fgetl(fid)); % read the { + subline = cleanline(fgetl(fid)); % read the first item + while isempty(findstr(subline, '}')) + if ~isempty(subline) + [item, value] = strtok(subline, ':'); + value(1) = ' '; % remove the : + value = deblank2(value); + item = deblank2(item); + warning off + if isempty(str2num(value)) + % the value appears to be a string + eval(sprintf('file.%s.%s = [ ''%s'' ];', line, item, value)); + else + % the value appears to be a number or a list of numbers + eval(sprintf('file.%s.%s = [ %s ];', line, item, value)); + end + warning on + end + subline = cleanline(fgetl(fid)); % read the first item + end +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function line = cleanline(line) + if isempty(line) | line==-1 + return + end + comment = findstr(line, '//'); + if ~isempty(comment) + line(min(comment):end) = ' '; + end + line = deblank2(line); + diff --git a/read_ctf_coef.m b/read_ctf_coef.m new file mode 100644 index 0000000..256bc21 --- /dev/null +++ b/read_ctf_coef.m @@ -0,0 +1,864 @@ +function [coef] = read_ctf_coef + +% READ_CTF_COEF returns the spatial filter coefficients for the CTF MEG system +% that has been installed at the F.C. Donders Centre (id 1706) +% +% This function actually does not read the coefficients from a file, but the +% coefficients themselves are included in this function. +% +% The original location of the coefficients included in this file is +% odin:/opt/ctf/hardware/M016/M017_1706.coef + +% Copyright (C) 2003, Robert Oostenveld +% +if nargin~=0 + error('this function does not accept input parameters') +end + +% start with an empty coefficient list +coef = []; + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +coef(end+1).name = 'G1BR'; +coef(end).reference = {'BP1-1706', 'BP2-1706', 'BP3-1706', 'P11-1706', 'P12-1706', 'P13-1706', 'P22-1706', 'P23-1706'}; +temp = { +'BG1-1706' 0 0 0 0 0 0 0 0 +'BG2-1706' 0 0 0 0 0 0 0 0 +'BG3-1706' 0 0 0 0 0 0 0 0 +'BP1-1706' 0 0 0 0 0 0 0 0 +'BP2-1706' 0 0 0 0 0 0 0 0 +'BP3-1706' 0 0 0 0 0 0 0 0 +'BQ1-1706' 0 0 0 0 0 0 0 0 +'BQ2-1706' 0 0 0 0 0 0 0 0 +'BQ3-1706' 0 0 0 0 0 0 0 0 +'BR1-1706' 0 0 0 0 0 0 0 0 +'BR2-1706' 0 0 0 0 0 0 0 0 +'BR3-1706' 0 0 0 0 0 0 0 0 +'G11-1706' -0.0264191384733462771 -0.09393714520816329183 0.03472106287087559084 0.003506626350611835238 -0.005880847048019656638 -0.001459855517849013157 -0.007353073326519059955 -0.003743057534581884557 +'G12-1706' -0.15631635645912062 -0.02014141111638220738 0.1436481856661243617 0.004600874792404144493 -0.004611259697450509169 0.0004752228341851168409 0.0007640003853063520676 -0.00277532679348740409 +'G13-1706' 0.04110897336270846747 -0.03452679329560731647 -0.06393676172944513791 0.001028131731276316465 0.00186284243649349735 -0.001451816271089236216 -0.001358597755574905176 0.0006910884467223846368 +'G22-1706' 0.04331969312007057094 -0.06062950945022867882 0.08408422096536792567 0.003680940988756525607 -0.001070296228248003275 0.001825104713254158345 -0.004107276586287685917 -0.006349581432787697148 +'G23-1706' -0.05915572966201160937 0.03876223332726273785 0.06908504192232067798 -0.002644022948828536352 0.002055794217374205552 0.003456284601839287179 0.004962421184143010582 -0.001541088857505202182 +'P11-1706' 0.1013730157232110296 -0.003842563929868799376 0.1390088421251277351 0.00127245842882615901 0.001513541569498277504 -0.01203161286911904118 -0.002039665399731243299 -0.0001118461525465887501 +'P12-1706' -0.02230063857995695509 -0.08339752179219198092 0.05167979193789769277 -0.001901666430778932914 -1.112991324090676032e-05 0.0009289665129036059083 0.001596662183431015163 -0.006763350544924771543 +'P13-1706' 0.01953618217372175142 -0.00841684891003604066 0.04062399459219920989 0.003293303481822240121 -0.0008279888787800854721 -4.805932113300294287e-05 -0.0001369132452980285615 0.0002111599101189122701 +'P22-1706' -0.06162852648212610585 0.002014404545876338944 -0.05876248274342443095 -0.004574372345416573976 0.003033074270561343915 0.002749808529324927059 0.002733472711775690282 -0.00184592004765981926 +'P23-1706' -0.06926180620722945103 0.07765435121154141973 0.005943320067624360305 -0.001485322407569247957 0.002372893729645904077 -8.393517856784981257e-05 0.00330296967456195599 -0.0001543974363835938306 +'Q11-1706' 0.1559525537865661948 -0.0301179071973083877 0.08454678440973048548 -0.004561199340475460481 -0.0003274266530055112284 0.005332537946052225315 -0.005159675580844180764 -0.001910276003785410168 +'Q12-1706' 0.04519943580039444131 0.01199298670693924214 -0.06012000410506595366 -0.0004658052084824485526 0.0005453884287832038791 -0.004192556702062221786 -0.0006458749810405322884 -0.002403900354036449943 +'Q13-1706' 0.02152223087935774617 0.1185191818257770868 -0.06280260960320684094 -0.001732743570825734684 0.009788679236335286193 -0.00279724962173814309 0.0007139947222094535041 0.0006292178009423591515 +'Q21-1706' 0.03511431540352640684 -0.09324176515284531008 -0.2378508183929713971 0.0001863963556231685496 -0.0047797126202589078 -0.01383469564159488067 -0.003243539629848182435 -0.0007882212657080260847 +'Q22-1706' -0.01325191191768199279 0.01569028060420297327 -0.04503484859083141389 -0.005415702823409083641 0.004773939902877517155 -0.002107258730870098257 0.003592044859670810199 0.002241853893423344235 +'Q23-1706' -0.04034452584000429443 0.03887881319097546279 -0.01411338083056289799 0.005302706624404679783 -0.002464485100338323353 0.002116497861299033566 -0.002876588871398561183 -8.164520627749203077e-05 +'R11-1706' -0.05465494247696155161 0.02699062350395145873 -0.0198390465441167195 -0.002245929791160849315 -0.003468163840904351595 0.004102981500407982748 0.005131791355486700103 -0.0001263427478631306807 +'R12-1706' 0.1739091278560166154 0.07391028779775499213 0.05744677916065434736 0.000176580815800490902 -0.002604670495164311799 -0.002866536244602645687 -0.0001556539881100017883 0.003703473197964752325 +'R13-1706' 0.0957588675733173772 0.08096465545098394112 0.07183655710790715077 -0.0008256035302983351408 -0.0002200289694127210375 0.001790966223527513078 -0.004087592449532656894 -0.001900148179563695017 +'R22-1706' -0.04994986697262312342 -0.09270927263208594837 -0.03263699661542152769 -0.003923601934597151925 0.001253183979806851483 0.001148162523333353313 0.0054274328185575536 -0.009606445303716919584 +'R23-1706' -0.03576965100617419263 -0.03376652789935699617 -0.0365169940808238655 0.001271346843492731629 -0.0005998660778820106339 0.0001397113587351274508 -0.0005725112719108759168 -0.0007844263515726342464 +'MLC11-1706' -0.08169094833952039725 -0.07778761523671674782 -0.03602817837011070001 0.001973157498682633938 -0.0009570852073294326906 -0.001941672919277036627 0.002122549758488780081 0.0001897740511579152007 +'MLC12-1706' -0.1143598681667212513 -0.04464789592974541949 -0.0497273135933348695 0.001792677112180930893 0.001568561833941606743 -0.002775683674789341301 0.002043118558131330666 -3.192655624035087736e-05 +'MLC13-1706' -0.02675515262126364202 -0.05993399388341711514 -0.1240824188186403776 -0.002302474427003269215 0.0003205276383441307852 -0.002874876832128037216 0.004490328235682608006 -0.0009827928235380146028 +'MLC14-1706' -0.01593022948195283589 0.1161792516187972191 0.05128349023491357572 -0.001314836099823023111 0.0004682101500485290942 -0.0005389841182682172157 -0.001621418941626334318 -0.002763764934209912271 +'MLC15-1706' -0.04365891434796476817 -0.005112828275713867353 0.03711797746191328184 0.0009289168132441707982 0.000554282860115148609 -0.001452804120565325333 -0.001144416911372263127 -6.832449990082212465e-06 +'MLC21-1706' 0.02932828982385538366 0.05638773587514809421 -0.05153260851931371761 -0.002663064412076631207 0.001254424973730259478 -0.0006627033082959863427 0.001270449914446846688 -0.002988101930751302805 +'MLC22-1706' -0.1303193811874465702 -0.01551791555834620452 -0.02740006384928243485 0.001966843191339693458 0.002492647514403653099 -0.002865153989623993921 -0.0005534910207995557933 0.0004929628996566032305 +'MLC23-1706' 0.06264549991388240757 0.05891663467177794822 0.0877364920707897622 0.003658963071312066381 -0.001576273532511551344 0.002127799386718442955 -0.004384102939197958952 8.593959831221818833e-05 +'MLC24-1706' 0.0886490694282748154 -0.06008059716139022705 0.0894572210640846438 0.00333470302853348206 -0.003196455331682110552 0.003946856845293355599 -0.003083204887401702881 0.002704361887335607513 +'MLC31-1706' -0.004188032385454836838 -0.009438367638259297435 0.02772370501803808271 0.0003764062181060639448 0.000529860243414346458 -0.0001969268532747479959 0.000545944359708026958 -0.000337202737926062257 +'MLC32-1706' -0.02892555588501214206 0.01816094057448786395 0.1427226447881204674 0.004033674089350164534 -0.0004173658358086427276 0.000206722794864947168 -0.003280813869518356234 0.0009126403465631925758 +'MLC33-1706' -0.03760957250429839555 0.1330770886630250061 -0.1109134405160249887 -0.002911674501802634981 0.0001662039590296551361 -0.0009504583043188576021 0.002268194506639244733 -0.002411707490049654415 +'MLC41-1706' 0.004484038158600188624 0.03207114254079498211 -0.145540551211527508 -0.001413807995355089581 -0.0004928656017118796407 -0.001659366168101239752 0.001695958091025974316 0.0008531778609591880507 +'MLC42-1706' 0.03081856381159134295 0.06951500880368327584 -0.1203999073440922829 -0.00296489572291142988 -0.0002134452125507216389 6.624333005537298854e-05 0.001781280265482826581 -0.0007521350260563572886 +'MLC43-1706' 0.0321920808795027949 0.04281961220683999647 -0.1436538778853285736 -0.002409441977414472288 0.0002222236100169890604 -0.0007767938994046890864 0.002834769034894948914 0.0001321676835478797129 +'MLF11-1706' 0.0486845482046923822 -0.05634815909642976878 0.03605598118424856863 -0.001391817542817647656 -0.002927758763471970463 0.004912599036272874593 0.002422008102513675733 0.0008733812980664337365 +'MLF12-1706' 0.03641949670982108644 0.01565833525682581995 -0.03015848431759602169 -0.002524202973409718411 -0.001239068139467321876 0.00090620191538810129 0.001138356456189477343 -0.00221020780040241541 +'MLF21-1706' -0.08437362559607890222 0.03675168392572165238 0.1267087488804320428 0.007197828423764823444 0.005312923466261385182 0.001718012609777189777 -0.004145187006278239911 0.005145921122402897195 +'MLF22-1706' 0.003666449426546053263 0.06878420312064491282 0.06485373056897690558 0.00115840366206490606 0.002957863791410553656 0.002266983421226344796 -0.003559978383786141856 0.00290003870868536448 +'MLF23-1706' -0.001766104283337611297 0.002191620637104321149 0.07503871470169515279 -0.0001397438849889657165 -0.000980983709857669332 0.0003121188549579255911 -0.0008650284150994518809 0.00103497768738134246 +'MLF31-1706' 0.05862127215467319991 -0.04720680136460211895 -0.05315630240811205359 -0.00534592739062208621 -0.004342439212181393136 -0.0005416426992542979673 0.004299323821839680371 0.0009008307410594766206 +'MLF32-1706' 0.04170433995433825425 0.03577403397096552001 0.03442132344435087227 0.0006274239791459252551 0.0001146220781466724027 0.003207747872516627033 -0.002500579466886360472 0.0005162823742417331583 +'MLF33-1706' 0.07224144575709082194 -0.05799248697109807976 0.1193261626801749853 -0.0008386642658422710809 -0.00345628328411052687 0.005766293522296093987 -0.0007209900800219163058 0.007480349471250150734 +'MLF34-1706' -0.04623778586970897497 0.02651913381776007175 -0.1211211264001189059 -0.001901332217566160769 0.003405230063653887258 -0.0006642837924313488339 0.001986179146561393039 -0.007277908574261159926 +'MLF41-1706' -0.005952984108760345054 -0.0300002530868771107 -0.104517977065195028 -0.002779416187950886456 -0.001952051692240219577 -0.003213457278739185671 0.005053509821421920366 -0.002161729698395222984 +'MLF42-1706' 0.01938890309157847644 0.0972611201679080134 0.08224929721602226851 0.003910687120174407248 0.002562919478749034214 0.002965603937278296891 -0.007749814833394774033 -0.0003513692943487557946 +'MLF43-1706' -0.05523509547259997793 -0.01212834526674348712 -0.06683058435081275228 -0.00162060294950301274 0.0007094265108195284752 -0.004344416977020417077 0.004779069704465808109 -0.0008087881775315204722 +'MLF44-1706' -0.06149572398636771881 0.008654051646542509912 -0.06884525165364401011 -0.001989818251993153743 0.002845720221727946267 -0.003118398960983834699 0.001651189326422665329 -0.002560476316490174244 +'MLF45-1706' -0.07455239819444736682 -0.04312643887730381598 0.01570213489960134087 1.15731867135759197e-05 0.0001594891684185467586 -0.001829440166051054953 0.002530474279609825749 -3.510000676300471995e-05 +'MLF51-1706' 0.1104599032276762094 0.1023363109639326696 0.2434784393728419427 0.0007421300460333978216 0.0004699027730810729142 0.008034059594279932201 -0.007750718594812190144 0.003007665055409218958 +'MLF52-1706' 0.0315025401549877751 0.04207995779152934324 0.03602312351826288117 0.002236467567895387629 0.0001019471475048513016 0.00320331235249392797 -0.00624960718857017674 0.0006667885597981402157 +'MLO11-1706' 0.02314122268608936883 -0.08361990527001375573 0.1270911413084725161 0.005143302599188393116 0.0005145727833603718285 -0.0008371162079795993081 -0.006247019539966511964 -0.0001945087097456884651 +'MLO12-1706' -0.1174636777315953284 0.1019435450856824438 -0.07472174090096674048 -0.002799574059898726156 -0.002713258320886116799 -0.003517947128114793948 0.00234264710666397041 -0.002224427175212217739 +'MLO21-1706' -0.03447047688806180454 0.04500620522302665322 0.002138697203099019541 -0.0004338134055141773201 -0.0003640155912981522367 0.0005511483414477360817 -0.0007040415156798425543 -0.0002694382562125265004 +'MLO22-1706' 0.07281409188120534226 0.004173418721493943502 0.1365910222816845432 0.007459290090986435764 -0.000589805622887046516 9.722846236602031961e-05 -0.006004115400561333207 -0.00122646357454577826 +'MLO31-1706' -0.002357501371323334621 -0.1123805701947582364 -0.08216080167334305351 -0.005093116624289911396 0.0006597203424861065651 0.001344129095256043401 0.002514485089694316108 0.01133942555914089351 +'MLO32-1706' -0.0334560583782100851 -0.07311456282523082217 0.1636041895649194 0.008086372320052081716 -0.0005989395114369598866 -0.004234944143885506843 -0.007930486259201464591 0.001588027840800883229 +'MLO33-1706' 0.08065690416624418657 0.08129573318855765063 0.1095079882767951707 0.007645175349801078442 -0.002135024888823164064 0.003910597195522389977 -0.006440567658631740633 -0.005752498015854643973 +'MLO41-1706' 0.0626825670717182093 -0.03925604868915193169 0.07864228172199665134 0.005837815341852983092 0.0006908949329460713652 0.004226961089515340886 -0.003543907457279057722 0.002720203614981867978 +'MLO42-1706' 0.03150489107474273992 -0.005192130363646422532 0.06789940483885768818 0.006442137779951049616 -0.002051857356090561364 0.002959343398706090842 -0.005841434473312411349 -0.001865818098152014284 +'MLO43-1706' -0.105017444393681908 -0.03879118782735690996 0.05267434148790881704 -0.0002048930333194926099 -0.0002766798434827620959 -0.01204192572666521778 -0.0009104394104636268211 0.003526212006333630158 +'MLP11-1706' -0.01665683945522817427 -0.01458082955110009959 -0.001717118410571721702 -0.0008058382407195099906 -0.0003952112063049105679 -0.000265328884316369377 0.0002772382041650639961 0.0002674196615851753378 +'MLP12-1706' 0.08334674643181358422 0.1462031775683859391 -0.03759622085453590001 -0.004419246049768943245 -0.0004848435753358127298 0.002215313654544366195 0.003772826635950356569 -0.003453052202966981187 +'MLP13-1706' -0.1413978500480226885 0.1162061410570211506 -0.1431007518787011934 -0.004250190066254892242 0.001124484842748748638 -0.003283929031137248263 0.002343406143426495208 -0.003137041034065265934 +'MLP21-1706' 0.0310521781998556283 0.01715180039719564273 0.1488184129943469769 0.007281852350803847893 0.001947879159909643053 0.001662601233256877451 -0.006083270462598984289 -0.002605696887711325682 +'MLP22-1706' -0.07229855724346374857 -0.002555363737419081259 -0.003438598478491566423 -0.005512381047732611491 -0.0009443738122476391357 -0.002964420858213685176 0.00316842969160179835 -0.001099456227804870845 +'MLP31-1706' 0.01973400859938471974 -0.08293197660109212499 0.1644500223297546138 0.006807980745524295878 0.0002338667421802310097 -0.0005797875849454812774 -0.00789221550859022826 0.0006403819587172882629 +'MLP32-1706' 0.08073799498754855031 -0.06003975620547930686 0.009228449346786226151 0.002994834586953030921 0.001489471388944963934 0.004021223273314469132 -0.002564271811308516807 0.001384448368804964578 +'MLP33-1706' -0.04856319683161220563 0.0141345464612201259 0.01356816981008760435 0.002516500519507202088 -0.0006689698230333984306 -0.0004843248254058340747 -0.003667588625343277432 8.147322887774581415e-05 +'MLP34-1706' 4.338742305103973233e-05 -0.02220759823796741514 0.06807469498132442953 0.001205513384094533159 0.0002079994603228527779 -0.001293848123360223082 1.256253441546337235e-05 0.0009161645481515392608 +'MLT11-1706' -0.07119135147717041423 -0.05764704672273533032 -0.08728968968067148115 0.0007050945318952128466 0.001474554514320723696 -0.003961243065413599593 0.004562958194916142025 -0.001234582376461780063 +'MLT12-1706' -0.1131044318276106936 -0.05634271214959760826 -0.09412831582017650023 -0.00117458971689575432 0.003918556622871823686 -0.002052558714322601403 0.004427591691441123793 -0.004042430364576622866 +'MLT13-1706' -0.07436579021423332658 -0.04723163126907089365 -0.01948968242544554808 -0.002375777053119673948 0.000990975693939571663 -0.002370644120056819397 0.004234419169750066117 -0.0001061545369819668678 +'MLT14-1706' 0.05794205774340786819 0.1270499567655195838 0.1374594193211001458 0.004129831578295194323 -0.002952530329313013575 -0.001215989310713602419 -0.005028798681107788347 -0.00158130994677367848 +'MLT15-1706' 0.1326511965250666836 -0.03381652123913944652 0.06779784282069752088 0.002806242428225305067 -0.0016524526660064993 0.004432219259263953451 -0.0008377102596376339574 0.001687073790903483852 +'MLT16-1706' -0.04875426598541725276 0.03389287478206472887 0.05350224143467714744 0.0004654454495571575998 -0.0007356571395929717514 -0.002440628202642887087 -0.0003349232651082225298 -0.0005072977169438921442 +'MLT21-1706' -0.1501717797510344343 -0.01043889896880097375 0.02243968818810324409 0.002569750102552477346 0.003852297018191960278 -0.009174577728081610359 0.001676096652902918762 0.0006436174186517940867 +'MLT22-1706' 0.001991509699583361107 0.06761637317345421672 0.002648187471900352325 -0.001025153177916804338 0.001578599412250763882 -0.0006893423928120410472 -0.002696316037159098965 -0.001826750479865601713 +'MLT23-1706' -0.01794186865101339221 -0.06859440818349024638 0.01008800095080463963 -0.002347713002170558408 -0.0005415664270881071201 0.0002651125668366013845 0.003499309941100396757 0.00239153471711374627 +'MLT24-1706' 0.04693035075192095174 0.05899796693030478351 -0.003378271376477684062 0.002580714528480798631 -0.0003527947059254335298 0.001243299159284090051 -0.002405588759071313788 -0.001276035870958701877 +'MLT25-1706' 0.09916325960215900681 0.0152808410209484876 0.04155238518362013717 0.002981292595810487289 -0.001769973001534464385 0.001898658697853405171 -0.001589526894059696896 0.0002384428863824039223 +'MLT26-1706' 0.1215786588670737384 -0.03147435425247940843 -0.03803587133465206882 0.001452680151748617391 0.0006815245731913477682 0.007494668280355921974 -0.0005195227264274136824 -0.0009845825491643031297 +'MLT31-1706' 0.0277145770495155 0.08508615708089016516 0.0737625545970785057 -0.0002232388156622773371 0.001330887911399056918 0.00220513339677778572 -0.006166671234359989186 -0.001623079340617667029 +'MLT32-1706' -0.06576210263306202231 -0.1042723949972844261 -0.08173267636174512407 -0.005258471527102252276 0.0003894854010517451604 -0.003411973568032630917 0.009816266375972833302 0.00237127284610463146 +'MLT33-1706' 0.05247701532802057089 0.1025483019053009537 0.02154734523881653846 0.001927605329932429454 -0.001775332314277266663 0.001723311512882435247 -0.003463121231166730284 -0.00561993043810803377 +'MLT34-1706' 0.03430466991650319569 0.06327278809233097268 0.006755227857269980631 0.002697067481351988691 -0.0003993427962760715141 0.0008996038898930002305 -0.001049023723620778155 -0.003268916470090367423 +'MLT35-1706' 0.08961015988181658676 0.03587109863180910213 0.18318100239945595 0.01103931854924236101 -0.0009129008593952861808 0.003683617138389610676 -0.008911821707427115477 -0.001087860716498573101 +'MLT41-1706' 0.1121900794750923247 0.03501854649282737375 0.0555803354178334777 -0.0007588274198073101211 -0.00327244229595591166 0.006515251659190389455 -0.003816077694025338252 0.002139163643736591291 +'MLT42-1706' 0.0003771634197455116981 -0.07576882101058936281 -0.08206390643651423344 -0.007016106621470171584 -0.0002634107999376103472 -0.000181541646441572786 0.00844110623251771372 0.002835783392186372494 +'MLT43-1706' 0.08589727633060219303 0.04754776854846856637 0.05396015690086911065 0.003816218495162844015 -0.002865759494469760985 0.004841391883276729112 -0.002594262814933909374 -0.002374908586833878159 +'MLT44-1706' -0.03880614531269225426 0.01168086900390651398 -0.08035085640332936818 -0.008125791889615803162 -0.001255245122555012248 -0.004336833616457717346 0.005279578553331631431 -0.0007364185322912057642 +'MRC11-1706' 0.04905825153194179333 0.05021553215442244728 -0.1161873431783372324 -0.005283411844977561889 0.004190274243753211968 -0.006489463089603761045 0.002134827421827209179 0.001088646833990697003 +'MRC12-1706' 0.038765513319149493 -0.06028831091843185608 -0.01683800007477901858 -0.004015554489408797514 -0.00117469770939427026 -0.001358937607160284455 0.001647334429817644665 0.002068934508305220101 +'MRC13-1706' 0.01449403421996967901 0.01266919604325178299 -0.04528591473060563505 -0.005630487298552830887 0.003674791001803843268 -0.00131273425897167101 0.004840227163619238715 0.001209112022495565991 +'MRC14-1706' -0.1309257608810071305 0.07948374963692056427 0.109917585339755472 0.01232417333508195427 0.000257771915422067802 0.0006982015370585765036 -0.004852008483657222447 -0.002323079066554080852 +'MRC15-1706' -0.1455614998216883393 -0.05126645011277587011 0.03295470527381598458 0.008847436352862067879 -0.005648358483434529412 -0.003513780630661109908 -0.003816921740647256228 0.002029066444882624606 +'MRC21-1706' -0.1181262950946457696 -0.05776720096259697207 -0.1314170306161213664 0.001022110117168670068 -0.001859368538163123355 -0.007711482513466389604 0.002682874244183034926 0.002435347213165651829 +'MRC22-1706' 0.03004418418700032997 -0.02160229914730798714 -0.1215452966207518776 -0.004795334252637433597 0.001435138509880688751 -0.004622433913632447051 0.003710077909880159924 0.00225101600599322783 +'MRC23-1706' 0.1326933601962281273 -0.001799686029024137905 -0.004594922880254277003 -0.009839516690303723445 0.005259402711640813813 0.001834948417114939468 0.004259923055308295799 -0.0008544581475162210237 +'MRC24-1706' -0.1030444064379932717 -0.1229694292493842545 0.1440635615401658076 0.007484031274591061191 -0.008862040632252196626 0.0005350760240263389674 -0.007021909707641223186 -0.000411628591045229723 +'MRC31-1706' -0.001335090457241287082 -0.02091655342978157583 -0.0903712961347432342 -0.0005962869644783134202 -0.0006111606907601909323 -0.001881149945461462738 0.001524379007802776622 0.002713905994343594839 +'MRC32-1706' 0.09932995406713381048 0.1077439435820987251 0.04774401161753110551 -0.004481345381639550984 0.007672543929189098479 0.003015247573588319616 0.004681080360663899577 -0.002440951108030150595 +'MRC33-1706' -0.04143616505395392169 -0.02061407332365062031 0.0595403742138041342 0.002437038054817142457 -0.002243296022937215153 0.001373102667297474832 -0.003021827048105957952 -0.00104075099145226036 +'MRC41-1706' 0.05340153596053777429 0.01235192694892472097 -0.1521502927781260561 -0.00250222580921827557 0.0002184060632382003571 -0.0007764978088582583831 0.001346388234322260392 0.004022353641659032544 +'MRC42-1706' -0.1308251678875679558 -0.06121244703380408769 0.01621668870635739265 0.003857724856966076969 -0.003229309708774994077 -0.0003559183806644752456 -0.001895358420277294285 0.0003408015670166281001 +'MRC43-1706' -0.008820247830537628064 -0.01410409010443540098 0.004978901877824444197 0.0003257003865880967147 -0.0001055912814816655849 0.0005820141162282079948 -0.0006839780404464143549 -0.0004314270984197458381 +'MRF11-1706' -0.05927180624303287487 0.1698647403831448355 0.02349070388399385548 0.005174611933079595327 0.01066759352216164851 0.001624143995984451364 -0.002857301605767159115 -0.006952567109497205348 +'MRF12-1706' -0.1156961786695336891 0.03139903126417253887 0.01030336632029419698 0.008384614606784839691 0.0008993967787351204481 -0.004420081528940797595 -0.0007430514111727649961 -0.001400375235163405386 +'MRF21-1706' 0.07536482991616295923 -0.05095617741978673149 0.0300090052436431283 -0.003790137430286858941 -0.003385386874246742051 0.002378283424642998849 -0.0002265281329216957689 0.001165314637045623694 +'MRF22-1706' -0.09497410800327661662 0.1514611719541867074 -0.07313452737114113644 0.00164891767321490414 0.01024679739526251562 -0.005968414744568563933 0.002447748697249224094 -0.007008070951553715087 +'MRF23-1706' 0.06750415506240187158 -0.04810977815045710398 0.07000768562149536911 -0.003497732142617483719 -0.002901560356745745868 0.005042332304732799822 0.00116697253454212395 0.001540567143372666668 +'MRF31-1706' 0.03755041253144317942 0.05042251936021212994 0.0003918437442440177144 -0.001378490605474496722 0.001982906272060441007 0.001284623507700979059 -0.001704301729835097819 -0.001758231312330221221 +'MRF32-1706' -0.08921740135827620211 0.0255206941200210799 0.03375029688523754207 0.007122396832095226511 0.0005851826770174807686 -0.0009541123811495143096 -0.002261617883304014621 -0.0008908450396267382238 +'MRF33-1706' 0.01388357405685359744 -0.006911773932703257906 -0.08195124606123098399 -0.002081204245761677629 0.0001895407612800169761 -0.00409108487776416261 0.000417171201991288639 0.002767172285945048056 +'MRF34-1706' -0.1591741172499583357 0.02643972890461294273 -0.0418869261070791421 0.008533571437607417529 -0.0004425887773276770509 -0.008400364021072373455 -0.0009472442618778351446 -0.0006326585123341227444 +'MRF41-1706' 0.008934226636687043338 -0.1246821349510704585 0.0539355831986764872 -0.00210835905638084159 -0.008108795465159924706 0.00217714790307930962 0.002404859883105429138 0.005299630618631053988 +'MRF42-1706' 0.02219229715764200334 -0.02386008771660289365 -0.1207300526725543499 -0.004029417922900853377 -0.0001965364257043537702 -0.005705865724320029371 0.0021085872967686165 0.001823024669664702726 +'MRF43-1706' -0.1199734016582196111 -0.005524728023895125045 -0.01528967679157985059 0.009073302104067249713 -0.0009730378375928919101 -0.005513288873390123114 -0.001441347067386034193 0.001915372552622523084 +'MRF44-1706' 0.01911049286834281755 0.08625057435879517065 -0.0348336447430629137 -0.003193841199669685948 0.007213966774171157344 0.0004416997950282252066 0.004097167454934042344 -0.00217954837490737241 +'MRF45-1706' 0.03267429006525768981 -0.0123880122742903772 -0.08559274144003650719 -0.003397272545011727381 0.0007521833043020785623 -0.002705146870133031886 0.0004395196201568037629 0.002829012658065854519 +'MRF51-1706' -0.04486963828819867661 0.03263503416404628377 0.1417765381672110303 0.006420450680982054022 0.001053881903977611735 0.006862393908655901008 -0.003461165306832853818 -0.002843001205936236328 +'MRF52-1706' 0.0840161711866430766 -0.05056896176359865908 -0.1363333502479064929 -0.01046921658184522992 -0.001417564895243629943 -0.004430650194079593061 0.004443712756929127719 0.001394260784154460362 +'MRO11-1706' 0.0489268523418150969 0.07043529233620775265 -0.05875944298932979371 -0.001706116523312542748 0.001483607951952967043 0.003289763667354275375 0.003582036680922548628 -0.0009428245285377184585 +'MRO12-1706' -0.1098868283857271089 0.01031943943541243844 -0.156055338186844722 -0.003441384322028810758 -0.003737846836239794822 -0.005919596439685380178 0.005507461837499515872 0.006451515186175109731 +'MRO21-1706' 0.06124648629334391442 -0.1344152643233897659 0.1157083655140577899 0.004495273242447866621 0.001458244197427900233 0.003095620997526333986 -0.009987577509252004368 -0.001043636905061555995 +'MRO22-1706' 0.02035942451991331476 0.07306095749210204937 -0.1025338157335537598 -0.007602469546580188815 0.002970999315757878387 -0.001478616739937645315 0.009556609659277712915 0.0001498316600219531979 +'MRO31-1706' -0.01842520934869511934 -0.05897768794678836385 -0.0176618050312796239 -0.0007268350708921553216 -0.0004381571913522227493 -0.0008142566825747265223 -0.001129510346025942077 0.003697154697330076734 +'MRO32-1706' -0.108015119699060802 0.04992775934758275636 -0.00766620980323388674 0.001333973175836866568 -0.003343014713466150797 -0.007254840704327543584 0.002474534892554944038 -0.00467167985526563672 +'MRO33-1706' -0.04604995813830589646 -0.08181317800527922179 -0.07971201856678399034 -0.002444308052713499435 -0.003747723289008821762 -0.005311673540943672063 0.0003173246244727370973 0.01008590777313568727 +'MRO41-1706' -0.1396447267673452675 0.01956462198692184365 -0.07442927854132301568 -0.0027880158103816533 -0.004183359022666682109 -0.008861860678774294633 0.006359551938724348 0.001481230065256445476 +'MRO42-1706' -0.08731436244733133123 -0.1898859586254274534 -0.1061605608345139312 -0.004347882126933712635 -0.008673396879751630803 -0.004599885172080419096 -0.002088211173904723494 0.0183974821236261403 +'MRO43-1706' -0.01015844501632899056 0.09080703786872038052 0.02754974753961466488 0.0008742615752022631906 0.001786074076516968234 0.001883520317054157957 0.003029565798177593586 -0.01090131499734971546 +'MRP11-1706' 0.08568603364928094324 -0.05172293645489798447 0.0381520593088977289 -0.0004589506864935068587 0.001590958599182141359 0.0006352943985494967968 -0.0006108614358327026962 0.001377458387293534941 +'MRP12-1706' -0.05401520174951638525 -0.1649083483779936188 0.1375705327125132937 0.008141710511508014683 -0.005827597171975091618 0.0008055673321375186402 -0.01333094063522897305 0.001063807059849061418 +'MRP13-1706' -0.05170672468111960768 -0.04546398718793677463 -0.03026097969430951301 0.004627665264566305919 -0.004382106746662349332 -0.00259724309315358115 -0.005712202655835688266 0.002826830100591210936 +'MRP21-1706' -0.02358425510825486876 -0.1655003835229378606 0.04263621208603748242 0.003571196378993595193 4.24043403787814036e-05 0.0002463783544003374779 -0.007653379675732863846 0.004647381567297975864 +'MRP22-1706' -0.0152693644505065302 0.1064396750856890644 -0.04915748879273994926 -0.004506612092503519719 0.001117647624786547627 -0.00238976361274184472 0.009440357167682645462 -0.002213030850561107168 +'MRP31-1706' 0.02605718797169995563 0.1008159057564364386 -0.03176540201688388826 -0.00263611762654228669 0.002021634576953478066 0.0002898946841780580797 0.005696263206697630387 -0.002858881996858541209 +'MRP32-1706' -0.04562033778394036787 -0.0191764976511411174 0.1100151740356888203 0.006057706133151600364 -0.003141236716978187266 0.0001241584817513247314 -0.005692454998138657234 -0.003046031637971305817 +'MRP33-1706' -0.05359105529443427413 -0.108030777055477395 -0.03641341663242660814 0.00235350143162603052 -0.005088681913204950308 -0.003043802832686251948 -0.003631635296101508575 0.004700500334008261838 +'MRP34-1706' 0.07383963570145232747 0.05789326739102877706 -0.04300724157919594282 -0.004382654381244953726 0.005450544115452076593 0.001879083840005240855 0.002792466282195058512 -0.001201345824202150903 +'MRT11-1706' -0.05985921631980969937 -0.009016481778594797811 -0.04346444678682877955 0.004120295390647475686 6.076521551743360294e-05 -0.004973651394235749888 -0.001545776790683258458 0.0008635627930405878529 +'MRT12-1706' -0.01759763376596451198 -0.04828758555665632612 -0.02470731770203738603 0.002671822733217408142 -0.001569204228173147735 -0.0004365625264122458644 -0.002887496094355171492 0.001314498135731895657 +'MRT13-1706' 0.08128708406894420702 0.03189288086681602713 -0.02693551162288163395 -0.003967154719136415861 0.00442724447554997385 0.001991286101900421358 0.0002609542149035969615 0.00148015053412317815 +'MRT14-1706' -0.1162962964384676168 -0.03621731485049613231 -0.1682955862496358923 -0.000535230337944536433 -0.003960393348884780861 -0.01206056499581117068 0.003538970641713494198 0.005178749704418062795 +'MRT15-1706' 0.08932965824522876019 -0.05166579748786509496 0.01161631208494163896 -0.004005325134839899347 0.0009617133710911995436 0.004230366249620202274 -0.000924770385257994449 0.002463093784220889149 +'MRT16-1706' -0.00399850202197785283 0.08835741140573125096 -0.05147703854561432729 -0.0004925097395915996844 0.002359309014294077612 -0.001081153130429976126 0.004235431494727366283 -0.00037244107846327965 +'MRT21-1706' 0.1113956198550619947 -0.03392461199470167554 0.05705166046623318804 -0.005175794672244536133 -0.001471057943205783666 0.01218851836144587558 -0.0007043289034428030409 0.0009564854292477372637 +'MRT22-1706' 0.04711068650423857335 0.05952896272395349214 -0.03096674808938605639 -0.004352989414070788758 0.004320607126882290878 0.002364897744390333147 0.002222375895663792223 -0.001883949592848320779 +'MRT23-1706' -0.08340999993678881175 -0.06747303878644381192 -0.01504468196754400397 0.002958614061142303495 -0.006189050101080968008 -0.005640230797651546793 0.0002591916738018565738 0.002917317441589548782 +'MRT24-1706' 0.03171168279119977035 0.04365824586675463165 0.04667283211934530884 0.000216492168100109177 0.00274607520382899508 0.003346553492217337576 9.575290406123761601e-05 -0.002637571559936767104 +'MRT25-1706' -0.09910903306266298507 -0.01001841365376395995 -0.07960848962092809122 0.002469112155534166145 -0.003822984385791183912 -0.008347447632039494553 0.001898502888129895627 0.003940294515481054978 +'MRT26-1706' 0.0007734276721666665444 -0.06700129664722917489 -0.04038920592138294657 0.0003854113951465349048 -0.001563770739720348911 8.564504304294472126e-05 -0.00232512996713209099 0.00269018265925205155 +'MRT31-1706' 0.04050681318299218653 0.03125316201216151585 0.001506916185139704854 -0.003533473004486763474 0.001414057153773838746 0.004750884268308786136 0.0005100418475276040104 -0.002746408068342049997 +'MRT32-1706' 0.08217026326770715539 0.02448282558704611978 -0.07416495503046548199 -0.007868065332407993967 0.003291684021555728572 0.002770759820770513863 0.002439647833194805767 9.25362291549575519e-05 +'MRT33-1706' 0.007427308952660549059 -0.01154170313289417348 0.01369371728950028247 -0.0001564389549000813249 -0.0009190814209578675002 0.0001141384526413533919 -0.0007738174915289131603 -7.83291616818462713e-05 +'MRT34-1706' 0.03811942565064375954 0.09709976587065491382 -0.1165401771927899177 -0.007682893268070568882 0.005641741760780463397 -0.001578302192996052476 0.0101381861130977538 -0.002297401560141792889 +'MRT35-1706' -0.03387641660861703125 -0.07724995311540595877 -0.01147930860206294 0.0003949886581202345583 -0.003508316223875716615 -0.003308568367685030005 -0.002868273518264801477 0.006596507278721489183 +'MRT41-1706' -0.1758567692921810532 -0.03515977917188119889 -0.01519512535015960994 0.01134698594789500248 -0.00276902816365899888 -0.01341278181279694642 6.535853401789164057e-05 0.002465644192952843282 +'MRT42-1706' -0.02152130408445456292 -0.03205011379447719744 0.0009744124587214717447 0.0006857491666887961584 -0.002992507465501631752 -0.002249384464828016027 0.0002026534437485450564 0.001707255060233871247 +'MRT43-1706' 0.09889795875194561103 0.003888088698199017312 0.01979261571006893025 -0.005854555830175177736 0.002550630691211766554 0.007814062754916960632 0.001534605528027466453 -0.001740738529028019663 +'MRT44-1706' -0.05691008159632153507 -0.1645107481226831536 -0.04779496534737437408 -0.004393966613594979531 -0.008692954536789214773 -0.00741345907509721215 -0.001635450184394400455 0.01400487427236647882 +'MZC01-1706' -0.01494286518344861876 0.09399604291418038604 0.001514042424394920847 -0.0002662129026606222925 0.00272306583656161446 -0.001462974992030099041 0.000286755318048692229 -0.002427846703108969481 +'MZC02-1706' 0.01048523110613878463 0.0009020160280337854216 -0.05016703820507201206 -0.0002998510518858664388 -0.000515313659549525337 -0.003264881453735892902 0.00102562807721430743 0.0008618217559544430603 +'MZF01-1706' 0.01968281285050175675 -0.06023107763614371502 0.06121508202898146705 0.0001622292073713806819 -0.003467093553142917405 0.00172970768133278211 0.0002289916838627152932 0.0003681591649551428712 +'MZF02-1706' 0.06678984472783246196 -0.182440558735761621 -0.09178606635743639941 -0.007584419234038608168 -0.01038819388683161551 -0.002998489417295726635 0.007930818537335527704 0.004545979240750585605 +'MZF03-1706' 0.05325156675761270192 0.1174738411772354302 0.02751730704591508897 -0.001211262822488221903 0.003903677346005184935 0.002496012419996640041 -0.003155274508161381476 -0.001828277363740007846 +'MZO01-1706' -0.02439720069461531055 0.06592929524778615158 -0.07484527118930360545 -0.001991400967305742824 -0.002043057608432549601 0.0009466362350490286834 0.002905927484150935911 0.0003895711563017285189 +'MZO02-1706' -0.004193409439129229879 -0.03588347742750992719 -0.01056765234081206463 0.000828269113155421957 6.357854193919900885e-05 0.0005194924160432156995 -0.0005895915780497043351 0.002171980319106391489 +'MZP01-1706' 0.03381324548225054377 -0.0969433821121011563 0.08366330975129604441 0.002633418695614468154 0.0001724388743565483367 0.001263530525531823259 -0.004448313057072220827 0.0004818693201072772776 +'MZP02-1706' 0.002633998031293571709 0.1230252286459674327 -0.1066414172307003361 -0.005316138877684267912 0.0008464339200343246094 0.0006126163070335105586 0.007819364143145711085 -0.001852859759265136543 +}; +coef(end).label = temp(:,1); +coef(end).value = cell2mat(temp(:,2:end)); + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +coef(end+1).name = 'G2BR'; +coef(end).reference = {'BP1-1706', 'BP2-1706', 'BP3-1706', 'P11-1706', 'P12-1706', 'P13-1706', 'P22-1706', 'P23-1706'}; +temp = { +'MLC11-1706' -0.1382228139973263881 -0.0662533451338533641 -0.08514893299283234074 0.2886713463945499991 -0.03145826574391359653 -0.1032094036312776741 -0.2677078788695917422 -0.1726664652951542811 +'MLC12-1706' -0.1725242892252873694 -0.02316799131720484115 -0.09864268844080101295 0.2708002617960945102 0.004966079429890845123 0.006366494614789523429 -0.2078166773781876531 -0.2548113407111339268 +'MLC13-1706' -0.06433513939400752057 -0.02469987208653662281 -0.1547419125782673044 0.1418973878845695979 0.1154807762403902011 0.1188750122484098504 -0.02036827737249559053 -0.3102419760200211818 +'MLC14-1706' -0.0101725826309732939 0.07652184257691851954 0.06285597934187520108 0.02169242670745954657 -0.2582685301006519274 -0.1754755617201763096 -0.0770185861151197193 0.2127978003944720475 +'MLC15-1706' -0.0234806731320204784 0.02967070404938945694 0.04419021236823218041 -0.1472778785094536191 0.3208338160851761933 0.1096039676317745737 0.1155024694090843046 -0.0999885415781458925 +'MLC21-1706' 0.08743625635265907248 0.04198538522939099238 0.002595763142494787734 -0.2948187247460258842 0.008232970318121625442 0.02056178412134233163 0.2672628912666229484 0.1725954757795352679 +'MLC22-1706' -0.1860618882723089618 0.01115782510601683909 -0.07663727931105152047 0.2479503631283714593 0.04773637890704240938 0.08225074763523326782 -0.1824246449791908642 -0.2695854761088272711 +'MLC23-1706' 0.09932052461823512313 0.02459404557479431819 0.1243893787964647085 -0.1214521353695743461 -0.1467888516667933962 -0.1954673507175130331 0.0827014306951008582 0.2565056823171180667 +'MLC24-1706' 0.09542051075649532477 -0.09846890209426244212 0.1029865957655926867 0.04568292306962887933 -0.2578532484170544814 -0.212186495553021659 -0.026742951757970361 0.20175432492741463 +'MLC31-1706' 0.05360363065430327062 -0.0290658497723569817 0.08444762605308975267 -0.2746546031050620673 -0.02850152883999820461 -0.08464483138426905084 0.2478561306001653697 0.1935575302880424842 +'MLC32-1706' 0.01417751084994100727 -0.009609644382386633293 0.1893266810670302669 -0.1537872939301765385 -0.1114998313699658156 -0.2384590696179459679 0.1708144723346288196 0.2018385584725512771 +'MLC33-1706' -0.07741406054111449331 0.140602962564341849 -0.1613843832943822887 0.1657525588942669881 0.01936887116091059666 0.2843437265599630948 -0.2427637099503201223 -0.03446355440781331131 +'MLC41-1706' -0.05205615869574087978 0.04122180525868625323 -0.2040984775909389648 0.306050945666863472 -0.004845563660082926466 -0.02656975327913183027 -0.2965742741062059595 -0.1030378866416584993 +'MLC42-1706' -0.02389402919451669161 0.07844658973459740781 -0.1838052010794586355 0.2877669212562368739 0.01362667991036912302 0.1231018548508429622 -0.2956834717016642577 -0.06702306755529127691 +'MLC43-1706' -0.005209111846768275933 0.03384509470499676154 -0.198775722190652343 0.233533809231346895 -0.04116800311516879973 0.204014512418244004 -0.257621450547025066 0.1104885236548849847 +'MLF11-1706' 0.06358350010679529596 -0.0784445226147908875 0.07465856520074432012 -0.06599042869640468767 -0.2771210257315528946 -0.006568449735539011285 0.2547869704665173263 -0.02066346292026897263 +'MLF12-1706' 0.05193664472756427675 0.007433386036594913024 -0.004354256429245254717 -0.0104594934129525613 -0.1185032398077054266 -0.004922107449456929358 0.3094693534941974078 -0.03052891107477028951 +'MLF21-1706' -0.094404553516449774 0.05713796765517231008 0.08266203354542170367 0.09905781386387088605 0.3179322781523764574 0.06462239355808441221 -0.2089744688446816823 0.09630895339785545961 +'MLF22-1706' -0.005401466460099793067 0.07799861220626723435 0.03423511561012176907 0.02010940732427979327 0.1913544074894210911 0.03221201176237215025 -0.2826473303848106022 0.09805244526818387985 +'MLF23-1706' 0.01742441361442586059 0.008819523871757835309 0.09118678122227265315 -0.00035833527450891895 0.05733828285980938771 0.001937081080728298614 0.3197619531956262806 -0.02787631604312304501 +'MLF31-1706' 0.04654583340223795995 -0.047033385721240481 -0.03064091442360981216 0.01509156098077189812 -0.2121415682595462204 -0.1112084492731538476 0.1523790428804583652 -0.240462429525251653 +'MLF32-1706' 0.04746952247722049933 0.02258704023958208601 0.02194903989996015853 -0.0414873715701736534 0.0450056070330318303 0.02014421752427554557 -0.239552750474094106 0.2240642801760762137 +'MLF33-1706' 0.05869476665463646547 -0.08361178423739487608 0.1122550523316090815 0.01652918328603633635 -0.2009617190249260721 -0.03349511899062078413 -0.2660305009062145509 0.1264355272430096322 +'MLF34-1706' -0.0218949579017706196 0.04946250378941413617 -0.1116108859354522365 -0.0491185333376887856 0.2506667734195127117 0.01359099838777923404 0.2722985984247927593 -0.04207272814955062556 +'MLF41-1706' -0.03942545908135971361 -0.02407661327905865484 -0.1064493759388815408 0.1087447642448455681 -0.1595908287940409898 -0.2032976679415572085 -0.06620409544320542128 -0.2639041423904764372 +'MLF42-1706' 0.05363422328221816027 0.07967140221233734443 0.08951534003717770416 -0.128937214577220377 0.08810343302557513412 0.07615585441940531108 -0.04098182085352847226 0.3213350654240125781 +'MLF43-1706' -0.06803485675123928378 0.02096578177021040518 -0.07395732983967347185 0.05434491795285490562 0.1411017643030943458 0.07179673034290874611 0.1643525586201984023 -0.2682898473340409873 +'MLF44-1706' -0.06260930679826015588 0.04295959449824775928 -0.07156891208540423766 0.006612428169781000946 0.2081223075433809855 0.08387857375424689899 0.1932466340951884409 -0.2172583991596181707 +'MLF45-1706' -0.05273449228516488563 -0.008524618559531807471 0.02247780394187684841 -0.1073240959812722661 0.3276726083020715108 0.07029252766680937903 0.1898373308456635378 -0.09345150444010934254 +'MLF51-1706' 0.1624317912595521218 0.08610496267367034884 0.2761220436858867755 -0.2291957786065656477 0.06302140921111969163 0.1150472021390444161 0.1585149441735389519 0.2768588909419009703 +'MLF52-1706' 0.07813537475270850019 0.01258956549997311894 0.0704459322986105696 -0.1925680107901989457 -0.04418983798888989623 -0.05323237435557155728 0.0706631643303960999 0.315963044331685039 +'MLO11-1706' 0.001623072866654050317 -0.0505657566297947822 0.08349523534917566159 0.1933396783320261991 0.3210745787150182107 -0.10751155424449374 -0.1046291748235521901 -0.07963442963719634393 +'MLO12-1706' -0.0932543347501357256 0.0816296319231611528 -0.03166616724170764202 -0.270890689883850011 -0.204853914567168699 0.1259003486000364325 0.01927732627214839151 0.04117169739736232376 +'MLO21-1706' -0.01017560646354364814 0.01985941627204387133 0.05514742758507345383 -0.2571367677595031709 -0.2793730885099177663 0.02122191927113283028 0.06579356396974349319 0.01006261887051268511 +'MLO22-1706' 0.04228339699326733037 0.01212366091993068162 0.08879376494519121421 0.3260521580611809855 0.07925669214609561142 -0.01819740163416505921 -0.009591517815856168139 -0.003271903174406161872 +'MLO31-1706' 0.01883014372343630102 -0.1412157130247556902 -0.03076257068120249322 -0.2120135195069595135 -0.3234457946035887432 0.01496756686803598843 0.114501508697362378 0.0212206696608342113 +'MLO32-1706' -0.06075735201504169763 -0.05558799106456796535 0.1118396305158921855 0.3025245377843828187 0.1916345478112770895 -0.0186420866884403659 -0.03524606438421783866 -0.002627656002018843341 +'MLO33-1706' 0.04693372383741226117 0.08044034771046811028 0.0653618770327214077 0.3384757636250301793 -0.0258698388823904446 -0.009578034291444910767 -0.005871694612373942572 -0.005290584850912462972 +'MLO41-1706' 0.03923384480471365371 -0.01525029131105908736 0.02714999417571031803 0.2546115164329926239 0.2690482753680357164 -0.009767390421729766486 -0.06730807681393313757 -0.004156501435087131199 +'MLO42-1706' 0.001428077299708022108 0.003844081474509456094 0.01959334188366524537 0.3214212593155210129 0.09069845192517340948 -0.009534190431742349883 -0.01124799407868778967 -0.003469786724388063733 +'MLO43-1706' -0.07099233623833486884 -0.02880924754568231147 0.08856351332414597044 -0.3060528484596556353 0.128839616138026275 0.003165219732926745702 0.00994938826448356177 0.0006090051591933717291 +'MLP11-1706' -0.03249607645747909501 -0.03205139619401013718 -0.02829538554438305181 0.07148907765356921074 -0.1146178887559892168 0.2960008321297108447 -0.1589520302232046711 0.140935032443428615 +'MLP12-1706' 0.07426184295142532199 0.1492185896179328841 -0.05111344519783470042 -0.06136746941840764275 0.001724787166957722582 0.3282088611462577465 -0.130134171293704165 -0.004936585729251252545 +'MLP13-1706' -0.1550668393682321788 0.1438313884956307909 -0.1629892686117093148 -0.0394500456953563311 0.1701208339783343848 0.2852099729622109003 -0.08313554870547654185 -0.14560583845332567 +'MLP21-1706' 0.02654843949261885203 0.04836841501601622101 0.1462326737279008859 0.03725154422432774837 0.2241878770131820464 -0.2473136379978512212 0.02254832068650799645 -0.1907638261900793664 +'MLP22-1706' -0.0686176390587671936 -0.02320309969255752308 0.001400987193962166446 -0.09754388151307355481 -0.1665353760105017233 0.2813326097644027191 -0.06635495897286450284 0.1135272370178197487 +'MLP31-1706' 0.00410461651847717629 -0.05408423003028114961 0.1377390235016080489 0.1692504652513706909 0.2497298125801123425 -0.2136456344231150439 -0.02055520016833128211 -0.1160272495532611442 +'MLP32-1706' 0.06336749823488235789 -0.05042684966902965388 -0.01654673930951551519 0.236575211873756186 0.09534624686072780408 -0.2177310220670032048 0.03421893273639377286 -0.03397234014568384364 +'MLP33-1706' -0.03323736611209159725 0.03002182472506493074 0.02689757791333211023 -0.2207079389025662641 0.128711273619539962 0.2266871851504149993 -0.03736291801907636045 -0.05088352815167572485 +'MLP34-1706' 0.01804484165856728647 0.01031036791405627942 0.07549176520119624256 -0.1699046426367207818 0.2899420145878607857 0.1446179218179321768 0.06650532942325219909 -0.0992577900696323262 +'MLT11-1706' -0.04704491941066894084 -0.03797941156058894097 -0.07737316306722230586 -0.0371319234728271913 0.2231138592719367209 0.003212535244369423872 0.277973060208098588 -0.02185444193729014356 +'MLT12-1706' -0.08447872404705902838 -0.03003933274360280972 -0.08427636400014384965 -0.08897256645086894233 0.309660363262441618 0.007748120488902505119 0.2347308524974138499 -0.02053834692366506356 +'MLT13-1706' -0.04155250655432526918 -0.01767708282357837238 -0.005058913529922428806 -0.1744857916782741325 0.3460584289539624936 0.01625148968725365073 0.1543297160145147839 -0.01757610927126036088 +'MLT14-1706' 0.02473601543887470749 0.09954298179551401837 0.12087844240992629 0.1964107424914252886 -0.3303216413858801603 -0.01522956155732175729 -0.126241152957685121 0.009533979930416870002 +'MLT15-1706' 0.09975884082223460125 -0.05496818271985834392 0.04251169561728222746 0.2673987405566053965 -0.2452043039081176767 -0.03954824050132876162 -0.04696591748658365123 0.02039530731989156603 +'MLT16-1706' -0.01809030105728349699 0.03788238383809146292 0.0911475289757280871 -0.3155033569353283829 0.04735155161616331349 0.08297294674179991891 -0.005384807996269442947 -0.006461459956578846642 +'MLT21-1706' -0.1288538542114405494 0.002481952925272324847 0.03485703117358385922 -0.009551033352974021978 0.1422676410576970696 -0.004939041608370217835 0.3031750340360210294 -0.02265133277841845094 +'MLT22-1706' -0.0237058575720274084 0.04512844725750929376 -0.006987253626539095472 0.05103612862324776595 -0.2530604354950670154 -0.009800139935999267055 -0.2678564659799040348 0.01978457309890234092 +'MLT23-1706' 0.01363484305779106079 -0.03864465828962739685 0.02261442090285450263 -0.1509838934441197489 0.3446303859724349494 0.0201338703042538876 0.1770152141325894435 -0.01924419428211009142 +'MLT24-1706' 0.01393201296458278921 0.0305976414413392378 -0.01880820659807747042 0.1839983223451140404 -0.3361884590426196251 -0.01389905054059030476 -0.1375696812691714344 0.01182448961353790157 +'MLT25-1706' 0.06463614949607772442 -0.009091585275117273698 0.01958275607012524913 0.2400990650349234534 -0.2953646988618118252 -0.01301339264680832254 -0.08030090445001912547 0.008743103831794342071 +'MLT26-1706' 0.08681852359305899935 -0.04323256250900678332 -0.07327380800820051943 0.3092413470854838975 -0.1484321325726151719 -0.01074461506969169935 -0.0151504182588766325 0.003048914048373080506 +'MLT31-1706' 0.003035953703011757404 0.0646580228454244621 0.06415362135829164036 0.04362663534979851349 -0.2322643812263140428 -0.004476755280500705793 -0.2705967667099912766 0.01602903942775381341 +'MLT32-1706' -0.03739804724905297639 -0.07804379670670040514 -0.07195296403668691165 -0.09604611440909098519 0.3052418652000546406 0.006742533954966011857 0.2313814044002251435 -0.01405236708920687763 +'MLT33-1706' 0.01828050731997953038 0.07289809325464820244 0.00657024311860331979 0.1769381056866486668 -0.3549014141525700383 -0.009858498387001077279 -0.1586977712752264957 0.00536515252067098266 +'MLT34-1706' -0.0006301953427265624685 0.03576772048592252035 -0.01198610988375524086 0.2152738178167998007 -0.3307915708951239542 -0.01134930826208157238 -0.1127700732372116377 0.005556709078458120163 +'MLT35-1706' 0.05334568942542123465 0.01680234893714786792 0.1533550635366545123 0.2992700536244244369 -0.2357057131142628326 -0.0111909195602401014 -0.04976395803997243211 0.004429677610622913264 +'MLT41-1706' 0.08651884553088011465 0.01301954871435762398 0.0461874236875364913 0.05370947177516879889 -0.2573876221729367031 -0.0004022934679234792255 -0.2578139585112749765 0.0181297648629859115 +'MLT42-1706' 0.03185784436153658861 -0.04740810871268212601 -0.0697960927546261295 -0.1473082410533657349 0.3355281876026416366 0.01029525218719577404 0.1834483212803902363 -0.009071629251501650559 +'MLT43-1706' 0.05372747600040422844 0.02026929145742300403 0.03885607146340949031 0.1801580011202781884 -0.3276590704776112251 -0.007393763903438013881 -0.132827908291525465 0.008161154239529398377 +'MLT44-1706' -0.004786981027231705654 0.0351094683864824203 -0.05814207825039392069 -0.2452282195270626131 0.281805606880582149 0.009707600877972163977 0.07841898469102287494 -0.008444893768065512424 +'MRC11-1706' -0.0007879057259526575652 0.0562766694771630327 -0.1606509791041782764 0.2625214587867037985 -0.02943882930227824379 -0.1765816276048170208 -0.2781150695457602628 -0.1126389196907389145 +'MRC12-1706' 0.005041312833811165128 -0.06072117216660291583 -0.05206699265535509602 0.2086495590651812615 -0.003767579200974270279 -0.2391770468357752033 -0.2618243726129056981 -0.004602653674354887856 +'MRC13-1706' 0.0210067559732514085 0.01087679324347014254 -0.05049581465957574122 0.01484813121440720085 0.121673549590438107 -0.3081245755028024225 -0.1336690921949419963 0.1230624412539903928 +'MRC14-1706' -0.1626377966401037489 0.0734525194434082207 0.1031786964687588237 0.08959637570570466725 -0.2602790116005987975 0.218979276625638819 -0.02874054868554443143 -0.1788435128919033945 +'MRC15-1706' -0.1843432827081813996 -0.06793325587954066047 0.0206622197920528633 0.1270255143763397709 -0.3312232160428612571 0.1019088645291856693 -0.1542841425969307123 -0.1151075077535118479 +'MRC21-1706' -0.1624387619387309689 -0.05665387335815671999 -0.1797641205371675044 0.275760674553589713 -0.006878584310087037731 -0.180999150896493266 -0.2951779406261597072 -0.01604416014587845343 +'MRC22-1706' 0.008115207652171683994 -0.02539517701411761474 -0.1537991189617910759 0.1807428031374978261 0.04658037739398068755 -0.2681088102671762563 -0.240935352738834152 0.08616231667606881472 +'MRC23-1706' 0.1373696362710403462 -0.006754250254273726044 -0.02322382248563889875 0.08395796000441761719 0.1489590287865106 -0.2543618894601860636 -0.1241346125955813534 0.1985899454334250913 +'MRC24-1706' -0.1322683152887810243 -0.1253515894290049559 0.1446953244022337604 0.02769056553012722716 -0.2584609775592148773 0.1966702959277972507 -0.04996274691785355243 -0.2170447783805828645 +'MRC31-1706' -0.03351178862986126106 -0.02502474764367358315 -0.1354577267289230336 0.2487483637503605793 0.02800565614940635217 -0.1888168006782719177 -0.2715657568930669452 0.08482959003495658956 +'MRC32-1706' 0.09422505621642351947 0.0974268035931084575 0.01434750330881125191 0.1759475490781015061 0.1147891059968733918 -0.1882355818634162681 -0.1525823291225343881 0.2385474019058428652 +'MRC33-1706' -0.02743513551602546133 -0.001346386555345108205 0.1040961934368644787 -0.2389427230023080662 -0.0210474394704532955 0.03072307783726403035 0.160168753914748635 -0.2825274975756738027 +'MRC41-1706' 0.004069615769342165013 0.01524889356876139163 -0.2066967427690987735 0.2944317960398715739 -0.005128244934604534074 -0.1038586236046362271 -0.3021520579721332367 -0.02904603565774256657 +'MRC42-1706' -0.09261069535108770734 -0.05391463190176774833 0.07393599397715618082 -0.2967904418944345424 -0.01839631920055650668 0.0676362606430673946 0.2893330539464480933 -0.1241483698974569644 +'MRC43-1706' 0.02121592901906437303 0.002736008405995041248 0.05867749995983034123 -0.2599204191479295711 0.04181595136570286086 -0.1132943588742273827 0.2334756974634588367 -0.2026394493973507904 +'MRF11-1706' -0.08237912727941071322 0.1930170658866355027 -0.02999511644876571778 0.2560554149778885846 0.2816132118458873901 0.02238669585085677899 -0.06731832491388607675 0.003857697094186068008 +'MRF12-1706' -0.1452633744918867542 0.0413703610092215554 -0.03966250163167530512 0.3163134685732207907 0.1070690457748723207 0.02720564582295028136 -0.007841875063684807315 0.00389592610458493584 +'MRF21-1706' 0.09178898921567094082 -0.07326030686495163535 0.08279190922802177888 -0.2031894200380436055 -0.3079692909353750618 -0.0900654060700137038 0.08916715451558471228 -0.06269989707734738293 +'MRF22-1706' -0.1201093945905412491 0.1666597350767906605 -0.1266918845073792821 0.2800702632171455653 0.1963824608020995344 0.09204699582438576055 -0.01677482812683377122 0.02336377569770818619 +'MRF23-1706' 0.1020462997170876462 -0.04476148723999442275 0.1125374056494373165 -0.3225737173313791839 0.0573288654152874777 -0.02539360876236581438 0.002355324897689480695 0.004255860165688138755 +'MRF31-1706' 0.04460755158466561676 0.03889906756587595271 0.04177857900706357513 -0.1552087321145515231 -0.2052526905362134779 -0.2388507361215514435 -0.02003904756496036055 -0.110713764729872155 +'MRF32-1706' -0.1130533484546892981 0.03040892813732698485 -0.007850927498421034212 0.2429085798779209715 0.04094478195904468348 0.2200857368082461407 0.03784565422790188427 0.01452989250527078439 +'MRF33-1706' 0.05205094682228531 0.004683024081423316914 -0.04904272170391472258 -0.2709531288968970997 0.2013610811022400471 -0.1260709754696639762 0.01923096933089796581 0.04400575957673252131 +'MRF34-1706' -0.1976976839368163597 0.008096467905396718956 -0.07168205328873483717 0.2845413282209070527 -0.2524060671096146069 0.03109573688763932892 -0.0492872162319630755 -0.01768523987644998047 +'MRF41-1706' -0.01709039766296914162 -0.1242241645463833533 0.05760983901736607682 0.06728767597205795314 -0.1646797689443417756 -0.260967487800225495 -0.1096413467969140909 -0.1927757931200057839 +'MRF42-1706' 0.01785010709892954212 -0.02780013680753913585 -0.1056340188579661943 -0.04193121114594819399 -0.07854366550232408373 -0.3264883544679060834 -0.1283969803927337838 -0.06592678160634457551 +'MRF43-1706' -0.1460013779933039824 -0.008416346706667056365 -0.03687283923864802943 0.163355218596175078 -0.1412543970141160177 0.2692111348867542997 0.05720260391292623925 -0.07662781704671199623 +'MRF44-1706' 0.05257004161810163723 0.09384741603594291826 -0.011268845423295204 -0.190943968764359373 0.2101659028426117737 -0.2186085251700451426 -0.005747623259752606892 0.08681586790408382659 +'MRF45-1706' 0.07199443390726908976 0.007034553280036182424 -0.06714184252894038474 -0.1840608704768749992 0.3227559652076311125 -0.09959805645941838259 0.107333823150499913 0.07921069084164619745 +'MRF51-1706' -0.00913693632605947631 0.03027867128393653406 0.1652189968253011398 -0.168070378189555808 0.06081735921405818923 0.2681085377762136845 0.2261921790313926039 0.1069252315962646721 +'MRF52-1706' 0.07649395040977598204 -0.05309537920131012639 -0.147506915141427275 0.06143852183256792721 0.04835541207699078914 -0.3203646898990325509 -0.1854305377398010046 0.06147484919150039695 +'MRO11-1706' 0.06910029908177262037 0.03545983650013832811 -0.02158888727785019529 -0.1020278751344255996 -0.3175560286413296462 0.08403824520574382229 0.1853070260950459291 0.1048268365378309114 +'MRO12-1706' -0.08793773769676554997 -0.0171440733558369876 -0.1298907460213891141 -0.02076220236820512655 -0.2090988154049477077 0.038203607832962512 0.2714144291478555182 0.1368635910393601052 +'MRO21-1706' 0.0438694744555706076 -0.1092273371107565227 0.07793492706636623302 0.06955358762672385342 0.2774552828328116227 -0.005840745098776823144 -0.2636923358538589834 -0.01961517797204404695 +'MRO22-1706' 0.03997476187009500748 0.06355656022146444206 -0.07888175138367259365 -0.01117412174041480799 -0.08469174072528504182 0.0003682080590293678422 0.3274628421764786967 0.02126712273219566809 +'MRO31-1706' -0.03620589722182501746 -0.02987930659140425327 -0.06213334914691368005 0.118407085133361456 0.3259932373850928933 -0.01070798936638819171 -0.1976188461788445094 -0.009302204064925326948 +'MRO32-1706' -0.09094560252909791864 0.03158194181827086999 0.0230778135580117158 -0.02822735310259225777 -0.2018575532181628718 -0.003045371570343902157 0.2842089016990146377 0.01019822220958127579 +'MRO33-1706' -0.06683738042582462735 -0.08101546494756467487 -0.09737747036912622334 -0.004012321966511324216 -0.01612191771294267661 -0.004108697475914506285 -0.3127554768216350145 -0.007036500232096088228 +'MRO41-1706' -0.1225363074102404359 -0.006166923769823740714 -0.03533575305960776763 -0.07596378520017350866 -0.2911935506207178892 -0.00211488118868098391 0.2517530950482770313 0.01466944197950798695 +'MRO42-1706' -0.1056737531664330432 -0.1792631923173793884 -0.1301742665729932191 0.001986541658350563823 0.09561490736448920169 -0.0066325803334242317 -0.3050403144744178174 0.0006606828106451717586 +'MRO43-1706' 0.01417578775829909064 0.09833592717382419468 0.04164056376765437606 -0.006287842766885024318 0.1151264732907840288 -0.002040487800555591986 0.320971392498041852 0.007277238339984764409 +'MRP11-1706' 0.07937136737516901908 -0.08194471897082386547 0.00911682031052066591 0.1623852560418392044 -0.111313111170271109 0.1443868143757177369 -0.07907093939012151129 0.2945295122235159768 +'MRP12-1706' -0.06666497082207931135 -0.1396905727416886678 0.1547207712218562903 -0.1268877644416627481 -0.002864878921118730291 -0.002126475673897641316 -0.07116602560667395494 -0.3271894550938625468 +'MRP13-1706' -0.07270631909909819335 -0.03602690840902320751 -0.0164057944139923105 -0.08076570241445495124 -0.173085186979941491 0.1360476641012798305 -0.0500671400106301942 -0.290216626621441931 +'MRP21-1706' -0.0313210310086282015 -0.1285000062876426319 0.04184803149379558856 -0.01984220168867284473 0.2310851181898425089 -0.1972613619388189354 -0.03632270041376398084 -0.2445844123905571987 +'MRP22-1706' -0.002997104464619428435 0.07090456386015700496 -0.05100851650664366133 0.06356271010231347163 -0.1725637712268349444 0.1194692718967358541 0.09891304721593767446 0.2830716257311182149 +'MRP31-1706' 0.04405419856043098215 0.0641848636923310345 -0.01402512920915510719 -0.01486844389148727144 -0.2464546592395191749 0.1185010264911498246 0.1632689096493861458 0.2096961493572045143 +'MRP32-1706' -0.06877166500509926395 0.006233115323576100819 0.09947401374409642338 -0.03169758388264812266 0.0937861738658565397 -0.03664328933815391709 -0.2348250697569170542 -0.2271607089027971038 +'MRP33-1706' -0.08348282514167326696 -0.1002621734012028726 -0.03903049761368913156 -0.03219885497932736124 -0.1309134925510340997 0.04797249600258152169 -0.2240468287700749517 -0.2235606873069985734 +'MRP34-1706' 0.1102335224006878445 0.0674893320915589956 -0.0362946234611954896 -0.06044850207409657034 0.2918716097737355519 -0.1104362190697510127 0.1708385718994873403 0.166809603947957602 +'MRT11-1706' -0.09724202022874177398 -0.0266421507343533176 -0.07346252924992914546 0.2814838508913077297 -0.2369801585956532453 0.02309369494145910653 -0.04459200365448148795 -0.01055945544159708413 +'MRT12-1706' -0.05477609482914039263 -0.07194231399418909989 -0.04692024281487688908 0.2324165281391495363 -0.3111608025536575783 0.02185111493173206437 -0.09323331910843153658 -0.01289847086245934048 +'MRT13-1706' 0.1162633777079926378 0.05780624699812348527 -0.01320501685296877371 -0.150016634394035453 0.3453118415347369297 -0.01812276141472254562 0.1728871060513144653 0.02315320445571670063 +'MRT14-1706' -0.1496256195776213826 -0.06140460254194054363 -0.1801318994229649251 0.1172643247767564817 -0.3332825172831100358 0.003537356988004568964 -0.1962557573038295755 -0.01467816124316543083 +'MRT15-1706' 0.119490999552530161 -0.03599166467948063108 0.02183327665572958043 -0.04806332050793390293 0.2414056247054576221 -0.01658593971100207759 0.2664400348178166955 0.05057478668619069806 +'MRT16-1706' 0.02175309419387837923 0.084375275879240208 -0.03613428540213743656 0.005626728858434142458 0.04146685838633926147 -0.007051845557262325856 0.315299000799203144 0.08658389162536425654 +'MRT21-1706' 0.1463749447859550301 -0.0235627441911108633 0.09262713635230909737 -0.3023789453526899984 0.1428117279667904249 -0.009330073693726185363 0.01357467794683290575 0.005972394680508323096 +'MRT22-1706' 0.08422035136889689799 0.0789029994625845138 -0.003252530594576027306 -0.2693273626473119409 0.2611653767122183445 -0.02174595929537247521 0.05562229119176472641 0.009254512600153278964 +'MRT23-1706' -0.1183053200091673529 -0.09302657996608576507 -0.02983563402352337052 0.163010356482950175 -0.3414084521263605621 0.01478154579731901126 -0.152166811190382778 -0.01694922609353283899 +'MRT24-1706' 0.06583217289102817615 0.06941352606434744721 0.05945343675901655633 -0.1332480194203361223 0.3392049016656066285 -0.01362908105734855421 0.1843278244557821632 0.01700873787986762614 +'MRT25-1706' -0.1304404148548278242 -0.03214403094818506224 -0.09001738513111527673 0.07935870145132037368 -0.2986573684359518643 0.005418417012691698412 -0.241396878132969589 -0.01942165439417802356 +'MRT26-1706' -0.02448222236607095967 -0.07643637496156417688 -0.05322533974201267004 0.0127777153965803348 -0.142747401947125957 0.005982426083731508595 -0.3100952414431430437 -0.02078201285639674073 +'MRT31-1706' 0.07692244832144835842 0.04967357141473870141 0.02972370623778024593 -0.2705460344428185504 0.2444622817749315391 -0.01571775585169138401 0.04798050829488970798 0.006170086987540743598 +'MRT32-1706' 0.1183911930836422099 0.0482654932379635096 -0.05341813265657303911 -0.225417551116335324 0.3133116461414766629 -0.01760852795563047288 0.09827031357259446986 0.01382081992302661155 +'MRT33-1706' -0.02815371106508243737 -0.03849285530039202319 -0.0003594739829390451724 0.1507070338960555256 -0.3507640005420725737 0.01694738408302787561 -0.1772428377477041628 -0.01809253676490350446 +'MRT34-1706' 0.07085697799770632188 0.1218407577082802618 -0.1052834832714291263 -0.1135059758618555958 0.3284512121353261871 -0.01542467793972079546 0.2237094080081143965 0.01676752280198122794 +'MRT35-1706' -0.06178363145406416679 -0.09394381670895736447 -0.02218072427506302333 0.03809605516504455114 -0.2284367959451374108 0.004675721833080008494 -0.2860160016107772263 -0.01291155128013030118 +'MRT41-1706' -0.2115151356661075233 -0.05501128622833940246 -0.04057452668981493399 0.2597146532565894339 -0.2630025835447360461 0.006269429510887616908 -0.05873148654871722385 -0.007377544951544463651 +'MRT42-1706' -0.05579057156662327321 -0.0573997182103033049 -0.01397743666484975444 0.1638150765639064532 -0.3321591429085127833 0.01508810360484356614 -0.1442835524886325327 -0.01457792992863648704 +'MRT43-1706' 0.1319017205133816983 0.02875515346517001566 0.03197787686309716548 -0.1317679035492529682 0.3280014936254582736 -0.008766336198923136216 0.1841597090282735549 0.01790151717898413875 +'MRT44-1706' -0.08602043061594286111 -0.1848864273626642518 -0.05769059101293678299 0.05803921456863097433 -0.2768930705704691353 0.002361448403676739971 -0.2493503123000496147 -0.004156293039720317453 +'MZC01-1706' 0.03943130371279519875 0.08608602734225456743 0.05402486926618242646 -0.2954478994888347088 0.02211216073609953078 0.1005233510682451009 0.2926037510085774396 0.1107799483911513505 +'MZC02-1706' -0.04036240227242930689 0.002172785467835445725 -0.1131188116266274996 0.311275923761081208 -0.0004225813884387379874 0.02581225323545671343 -0.309727525633242462 0.009804524900259885961 +'MZF01-1706' 0.03765554150652822285 -0.08861191470414692128 0.1111432717536282172 -0.1621163164884525387 -0.3429098817724575143 -0.01286304891926058971 0.1568681701625642688 -0.01396450435145797642 +'MZF02-1706' 0.05863624296178021611 -0.1907854574863376285 -0.05986171585472097045 -0.05458698607002626657 -0.2710081004089226475 -0.2046524437756771786 0.0520159679047374271 -0.1950831797372347409 +'MZF03-1706' 0.09979508375523039876 0.1091106033374151796 0.05708088071825111187 -0.2160648488740414819 0.0803112193013833936 0.1939613448658862593 0.2095335402733197738 0.1943378312758658188 +'MZO01-1706' -0.004544257897588159512 0.03445429291455819748 -0.02651131545871721062 -0.1612147099583010612 -0.3466180529484072514 0.02485264483338892397 0.1657024739150892989 0.02461630109363294877 +'MZO02-1706' -0.02343082248434896764 -0.005805140700950898319 -0.05924557023038063558 0.1639879674010855104 0.3386338264572117396 -0.011107079871270251 -0.1554351678562210792 -0.009174248706972676012 +'MZP01-1706' 0.04525024184794872173 -0.06876050086032142739 0.1110612069001668256 -0.1171632509903119262 0.1505173826221477273 -0.2401965713993839402 0.1174918637724963466 -0.2350542652438107893 +'MZP02-1706' 0.01764883535911147827 0.08550704121382816936 -0.08569212950392161854 -0.08000835648493688501 -0.2886321565610597828 0.1867370105823364379 0.08216087195490533179 0.183650843327438501 +}; +coef(end).label = temp(:,1); +coef(end).value = cell2mat(temp(:,2:end)); + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +coef(end+1).name = 'G3BR'; +coef(end).reference = {'BP1-1706', 'BP2-1706', 'BP3-1706', 'G11-1706', 'G12-1706', 'G13-1706', 'G22-1706', 'G23-1706', 'P11-1706', 'P12-1706', 'P13-1706', 'P22-1706', 'P23-1706', 'Q11-1706', 'Q13-1706', 'R11-1706', 'R12-1706', 'R13-1706', 'R22-1706', 'R23-1706'}; +temp = { +'MLC11-1706' -0.1419916047814387405 -0.0910501741939442194 -0.06916984619594829242 0.01582197324380207881 -0.1271590546758249451 -0.1267036205378564429 0.0004875643762199514692 0.1553849119195069017 0.1435702075034691605 -0.0336545736392792616 0.0870987680252153923 -0.2676172006473142018 -0.171702271802850831 0.1427442097545613131 0.194025562705910537 0.01614314639917840272 -0.1260325976584864283 0.1239975004790138113 0.0005000413491736438888 0.1596441791706937618 +'MLC12-1706' -0.1710040203261259384 -0.03600161613011888112 -0.08999022050706914633 0.01248884642270277345 -0.1124402655492882236 -0.1271574666406136978 0.03411953294031517397 0.1797227863480370669 0.1305723839664658381 0.003445429309680184127 0.1238958021446532332 -0.2078687428941256299 -0.2532174183538100642 0.1380636427649603593 0.1213546868160432501 0.01274235982149208267 -0.1114441970704661833 0.1244416533935489566 0.03499266582379075008 0.1846491808655484623 +'MLC13-1706' -0.05358832450198318387 -0.004511719082704659933 -0.1492087599811351417 0.0605016286586212565 -0.1257631569930391935 -0.1001503692237943749 0.1508299742012967071 0.1586186551447117676 0.03236862394435705004 0.1149075250070351883 0.1586322492085609215 -0.02050671303987481459 -0.306666075158129825 0.108100461701926373 0.04345065941277753002 0.06172976238646130792 -0.1246490657387545331 0.09801137018093723785 0.1546897752870647624 0.1629665627693281937 +'MLC14-1706' -0.01904650765169212112 0.03684135059771824483 0.03963929835186085632 -0.1093487419732767779 0.2181662787531701564 0.1067048750363892295 -0.1676036493778315928 -0.0481491788574822388 0.1296004142123039216 -0.2583946281296123915 -0.1329322708903828698 -0.07755973011868458333 0.2088539259955674854 -0.1068856331367264989 0.0387953152374361579 -0.1115684322707398701 0.216233620978427632 -0.1044258856792855683 -0.171892695711446053 -0.04946899954113682246 +'MLC15-1706' -0.02253020830426025189 0.06300694102370001104 0.05740826149007852153 0.1346899799479751025 -0.2169096668428487362 -0.1940277075253118433 0.1246164447953080345 -0.04906055242947692657 -0.2353330290626789167 0.322216306979711653 -0.01222330019337251536 0.1168019034866430994 -0.09661732693310091935 0.08755307115862445699 -0.1185054479409324152 0.1374240767127013485 -0.2149881409478459071 0.1898836880483890655 0.1278054308802857031 -0.05040535484115674092 +'MLC21-1706' 0.08809312315815749639 0.05424853717534677128 -0.01594022930885971578 -0.0101728981277198257 0.121266213840355408 0.08462345590423571429 -0.01073948352851232524 -0.1363452150992110479 -0.1610517699377295442 0.009949352057560777174 -0.1060700303199139383 0.2672276857395401994 0.171610521194374338 -0.131629156049414997 -0.1299899412343137883 -0.01037939966457974636 0.1201919594123496138 -0.08281607873143725929 -0.01101431132983924852 -0.1400825838202419682 +'MLC22-1706' -0.1803744424431386051 0.0103978920890233674 -0.06414299749090723868 0.01940502285778583982 -0.1162944664886920859 -0.08547578161779832706 0.05382627575887366511 0.1671455589692090737 0.1255163524403446751 0.04647349342576399811 0.1637931766816881629 -0.1825759964145527714 -0.2677786353594247548 0.1206264359005969761 0.08498991565678053195 0.01979892899865396544 -0.1152642550091573931 0.08365020057915650842 0.05520371229771226657 0.1717271981818223603 +'MLC23-1706' 0.0886981247646397436 0.003810366734521404564 0.1006580651479679622 -0.05766598589922657114 0.1607503620136247202 0.04714625615989979229 -0.09376239570743730156 -0.1282642176407829959 -0.003717136064622409645 -0.1460160007894806544 -0.2223084582313918922 0.08271621711579957292 0.2540149566740921294 -0.1161658681181572395 -0.0303098903389482574 -0.05883655839127627935 0.1593263315048136786 -0.04613931232552433842 -0.09616181398402456892 -0.1317800775460195029 +'MLC24-1706' 0.08560719286123144589 -0.1348770430057112113 0.07474551100477312693 -0.125233410786655841 0.2120418375627758645 0.08324353993831334897 -0.1262273232795047551 -0.04913717269595265641 0.1733942591603040151 -0.2581087394698355908 -0.1760874504885056036 -0.0273632921371572066 0.198453280299255741 -0.1261577865683032318 0.03218116579810925693 -0.1277755469084348727 0.2101634340428624459 -0.08146563483789175109 -0.1294575324075498135 -0.05048407535139323027 +'MLC31-1706' 0.0500987482419861796 -0.02735769807223535632 0.06579849163392478828 -0.01553865660360322608 0.1140093769461364148 0.05282887866757261103 -0.02696041553437809185 -0.1289073638937637267 -0.1592266946371354297 -0.02719249023135991705 -0.1673192911137738603 0.2479186246518885473 0.1923890980860657185 -0.1136436427442296393 -0.08565909110774679036 -0.01585407866220412548 0.1129994082653313775 -0.05170056609338087583 -0.02765034365843565406 -0.132440853128252406 +'MLC32-1706' 0.006252652104452267184 -0.02362177951341700236 0.1626513132858952715 -0.04564982324737449498 0.1440814812824977309 0.02415936296382304935 -0.05359854357986789525 -0.1113929367632070927 -0.03338708715194392551 -0.1105946824200700895 -0.2799598368290855954 0.1707939858527597332 0.2001659157595109539 -0.1186123350970336582 -0.04467681649317097048 -0.04657647743574978155 0.1428051144828784702 -0.02364337031540675316 -0.05497015235856500537 -0.1144463367472083742 +'MLC33-1706' -0.07366143465773603016 0.1469378697671210876 -0.1316998446411595525 0.01412209615379935931 -0.1333086727189825293 -0.01022295353684249224 0.01504935849746135909 0.09825060065910384832 0.0397152344821374223 0.01818839221103402473 0.3332490428679334427 -0.2427271022110076837 -0.03360985538528847572 0.124051248411041995 0.05185402936493111598 0.0144087631903537499 -0.1321277384139956657 0.01000461297554494991 0.01543447777216925415 0.1009437551013674661 +'MLC41-1706' -0.05197450335552159656 0.0359772116367608058 -0.1795926903567076627 0.01988244371992369322 -0.1252833604830689007 -0.0457079603558257358 0.01728923381336941109 0.1068298941780081585 0.1786148324828609746 -0.006489327604167107431 0.09346221358780322508 -0.2965146011277054461 -0.1020796597069024286 0.1253435150610543447 0.1231077883842362913 0.02028604111499712412 -0.12417351957609081 0.04473173546309879012 0.01773167241881449738 0.1097582162660360044 +'MLC42-1706' -0.02061507166623353232 0.08109286737385959509 -0.1580192733327846488 0.01656068058139405913 -0.1215043242229561782 -0.01901559856324408146 0.01871173732427364872 0.1030471261115278869 0.1703261759821826649 0.01234098306900308431 0.1953109368458957329 -0.2956913735010814892 -0.06611217107531766612 0.1155664856423573444 0.07502857484974280455 0.01689684889337052937 -0.1204279604594251651 0.01860946579068042256 0.01919057837972890784 0.1058717584658140781 +'MLC43-1706' 0.0004019166858968969969 0.03953790619182215998 -0.1680299932043710642 0.009868029794529609156 -0.1330787707995961244 0.0004339782093814935999 0.00624652000196958615 0.1126341307409509801 0.1139697241451518572 -0.04243691560689288877 0.2527325199116586263 -0.2576914403619168237 0.1111783942231928113 0.1177161183973081254 0.05153387254232009995 0.0100683427528199497 -0.1318998731142669023 -0.0004247093571377890168 0.006406371018410765214 0.1157215531843819867 +'MLF11-1706' 0.07735723608690792119 -0.01738528699295514846 0.01418397496548772993 0.2835141285434452096 0.4184122988313058733 0.2571801644327982306 0.1858120765438741329 -0.2505768541680257755 0.001888430616810009722 -0.2712103652738331871 -0.0681329012255057348 0.2551021571535910248 -0.01824458000799288049 -0.06936688782446175094 -0.06413765564584567036 0.2892692341712300164 0.4147057325048982834 -0.2516873426905806288 0.1905670840189512549 -0.2574454347507799112 +'MLF12-1706' 0.03442545171886030042 0.05057023427038630919 -0.05813373524098031792 0.1105977752493197269 0.3096723046656408851 0.1019871710196863235 0.2502963502036379406 -0.3123802107775209835 0.001336988275444510842 -0.1150147235061758783 -0.01036637455374727138 0.3102086813901137052 -0.02733471002058017463 -0.01362416918904570985 -0.006812063723213105867 0.1128428199038061519 0.3069290274247453709 -0.09980894179411715916 0.2567015367681494964 -0.3209428877147308401 +'MLF21-1706' -0.1268772685834627656 0.005949649736367107478 0.1736001171741426985 -0.4110326234407283841 -0.4450615448755212977 -0.1463656539008464652 -0.2004790816535191311 0.1277117342909525888 -0.04934315916644556321 0.3110554671937837967 0.08922805689597516909 -0.2090147071938114332 0.09278378168400806814 0.1481529484599651836 0.02746944518282542699 -0.419376250534446271 -0.4411189023193098913 0.1432395945959478722 -0.2056094238228236559 0.1312124500344445666 +'MLF22-1706' -0.008419324885348912837 0.0329059449847334401 0.1146971455533823125 -0.2306318545931332065 -0.3804860976050700172 -0.07221948264325320221 -0.2749268136987981226 0.1863336475619819244 -0.0229345591946356446 0.1865212757573262992 0.02534075093689022035 -0.2829871771889512777 0.0937519868574891585 0.04447681283733782159 -0.005732640550630002316 -0.2353134931807213392 -0.3771155060593904818 0.07067702797786537539 -0.2819623039562264011 0.1914412528825427395 +'MLF23-1706' -0.01363383436795023024 0.03511401238972383654 0.04905378375186592033 0.0009736977464505454025 0.14445770423352014 -0.06723844698678364817 0.2593321980587697251 -0.2848539139949683996 -0.001522812844420897262 0.05888140632615337239 0.002269152846466814151 0.3207221265656609588 -0.0242967123290697383 0.0002983252188515594884 -3.302288126234842469e-05 0.0009934630167358329735 0.1431780046080605717 0.06580237665711220763 0.2659686156869127682 -0.2926620655861580378 +'MLF31-1706' 0.06559105680007558392 -0.03063318850084134279 -0.1336171515548172373 0.3150584212980804821 0.3345864905540749112 -0.1160809081942632687 0.258151635303991156 0.03705162056756188677 0.0812891278797745892 -0.2077243533413940524 -0.003731753894028506154 0.1523439322089215342 -0.2351863727509601321 -0.06655607189077279717 0.1075807538994045243 0.3214538503470978914 0.3316225073666239642 0.1136016666952461424 0.264757841845599029 0.03806724526456315566 +'MLF32-1706' 0.04618489658673670395 -0.01020751890350296565 0.0936547318547089197 -0.1628208334954506509 -0.19843913476606026 0.1168558808876774685 -0.3248879520424387546 0.03007725148907827717 -0.03016259178434937613 0.04222910542151396551 -0.02534733042481529877 -0.2397468141885754356 0.2181413518056453393 -0.01017241039146943304 -0.04685888874544928695 -0.166125963648873276 -0.196681232771258041 -0.1143600876189334592 -0.3332019683822730061 0.03090170124221458536 +'MLF33-1706' 0.07630712987970246497 -0.1153179660474652202 0.13724466800154142 -0.03537269696642592054 0.04850038357309409409 0.1880516789263814992 -0.2803942145860950919 0.1416521462217149308 0.0410139041089336992 -0.2017949111510445315 -0.001950976326601244412 -0.2669344303698421572 0.1214960006026231665 -0.02444369317934020139 0.029947401589785521 -0.03609073387141992911 0.0480707358570207216 -0.1840352947198254374 -0.2875696178813185733 0.1455349836221378479 +'MLF34-1706' -0.04946549482269909509 0.06799469901144057637 -0.127779459208252677 0.001629783068830295729 -0.088943096646320427 -0.2191691520426225226 0.2068347099188549698 -0.2218835546124507396 -0.04870524820451053311 0.2512222555874852881 -0.03728025575272300718 0.2736337588545251776 -0.0385548765257871795 0.0002582800956461522943 -0.0500963708036415295 0.001662866336178139403 -0.0881551812625793324 0.2144881647424619064 0.2121276952299434027 -0.2279656210503254454 +'MLF41-1706' -0.02787383191243573977 -0.05226992725105554516 -0.1734064800299444098 0.2204933157085144091 0.1313506730949790535 -0.228026764928527137 0.1147121469351524287 0.1599282354340805234 0.1312692650119849924 -0.1585523657340339732 0.03627260666290946928 -0.0662904046036192629 -0.2605955023139146509 -0.02263297759094701211 0.2409629395527505269 0.2249691502238604923 0.130187084015010085 0.2231565978416937823 0.1176476779636214526 0.1643120400603453601 +'MLF42-1706' 0.04336561691321157153 0.08059668561405861076 0.1537679854761040132 -0.165354670914493268 -0.1208521787274865478 0.2045569633173106583 -0.2066159360308264803 -0.1601086322888763125 -0.08721385312678198165 0.08665433275240777555 -0.05555372412110218261 -0.04084335158716150688 0.3165980275222728957 -0.04052167173961532254 -0.1343611760383786879 -0.1687112359013936691 -0.1197815920898674114 -0.2001880613138866671 -0.2119033228281246295 -0.1644973817865984789 +'MLF43-1706' -0.06523554126838097822 0.0548510196592606053 -0.09604484617076336495 0.08426680218549760515 -0.06022131270992513163 -0.1617574179793801747 0.2742141521611269339 0.05552786011046897952 -0.019019120057566688 0.1417248160803924739 0.07654789248214588504 0.1645693699669397714 -0.2628005795767917596 0.07243710950524909209 0.00794187675569257151 0.08597734955745646446 -0.05968783343494646343 0.1583026233049865117 0.281231405116643185 0.05704993836874622942 +'MLF44-1706' -0.06261808353219436296 0.08275240888914309201 -0.07787720845941836778 0.09210766383238704058 -0.1246791214505762607 -0.151907310774808707 0.2615725997192988039 -0.0115668764637563426 -0.05682994331870962895 0.2086433283692236684 0.06361540820889420578 0.1937907870910379471 -0.2120642607603696328 0.06294595618971338125 -0.01736201366289939763 0.09397737430222227739 -0.1235746332831260674 0.1486628934564438731 0.2682663501475544554 -0.01188393696539708638 +'MLF45-1706' -0.0607371648991964011 0.02282404098053832098 0.02643764264989164128 0.09623809236747336848 -0.207882110391500452 -0.2322574879775848589 0.1782620223955120042 -0.1049212834076801021 -0.1541754446311173476 0.3286568099542159782 -0.03141747563205062044 0.1911821347090726375 -0.08949037728639576417 0.04720843316522807531 -0.09915765928942074647 0.0981916471685578135 -0.206040556420950649 0.2272969616377337743 0.1828238208791152786 -0.1077972884254795594 +'MLF51-1706' 0.1609591777651071809 0.1126299177296107706 0.2968988897071070387 -0.07281123413888339335 0.03232580924570688935 0.2033577841285824084 -0.06040591379007709955 -0.1910903584045522685 -0.1263495135440656503 0.06396991961816667072 -0.07414161571549546248 0.1585294164298887698 0.2745824900030534588 -0.1010786546019470516 -0.192654886879311954 -0.07428924282053694927 0.03203944635351016479 -0.1990144940440837229 -0.06195172597275758891 -0.1963283502759360089 +'MLF52-1706' 0.07081954892655731304 0.009071022276967530273 0.07767398954548544732 -0.04774801063907743726 0.08606836170813929321 0.1507367801952299302 -0.1258970579119070288 -0.1943506271689609821 -0.06882832497242824532 -0.04351760466414032053 -0.1316686120697501128 0.07081928798816240767 0.312671084149176437 -0.1219104814058515063 -0.08243724407450131464 -0.04871725632061100347 0.08530591258279682232 -0.1475173629223842375 -0.1291188154133360855 -0.1996779865072808302 +'MLO11-1706' 0.007022250688877448854 -0.0795926653998906275 -0.01027016298806482375 0.1878562755191815759 0.2548295426621260962 -0.2166783789925806059 0.117388835449233217 0.05435550840015292151 0.3128053875747224266 0.3233135538776563678 0.05954731289904383745 -0.104681209538808731 -0.07690453605260665071 -0.1181060813637083845 0.1660187319921619942 0.1916696047314133677 0.2525720980209348876 0.2120505893112736295 0.1203928640378697096 0.0558454512394571459 +'MLO12-1706' -0.09619806710825690166 0.1182677218979499567 0.02992458665593146494 -0.1438962338233842897 -0.1721878315302234619 0.1309354582884898199 -0.04183219727899264995 -0.006016333608517805166 -0.4446028371306636751 -0.2054136149191853888 -0.09613533608693748678 0.01947003916081320105 0.04023431708417059272 0.1710905365142074142 -0.2194251980145262293 -0.146817210034864698 -0.1706624805308629422 -0.1281389551689726403 -0.04290270041560414332 -0.006181247771639700878 +'MLO21-1706' -0.005577215601228074221 0.07442041047134057008 0.1241585583074960586 -0.1545886028960309633 -0.1416011796979842197 0.2691976267730566974 -0.03734795811754333672 -0.0642653468547197404 -0.3340926389582788425 -0.279701993322102771 -0.2536483781048549657 0.0655685606380514846 0.008515416778202312964 0.07601111135127988638 -0.2746490752453900064 -0.157726625480968996 -0.1403467850114175353 -0.2634481375752656951 -0.03830370772936070312 -0.06602692900489831596 +'MLO22-1706' 0.03574124278436890956 -0.03351124200854807555 0.07065428381431673732 0.07376064313098742997 0.03977678648937582606 -0.07578681872217876703 0.005045205805280114815 0.006742940211901614529 0.4322932474242985323 0.07710937925826136241 0.3268960193534011793 -0.009815171494333538652 -0.003207357303087278889 -0.1046431256795483794 0.3434199736797098335 0.07525792404101842858 0.03942441802939977008 0.07416817333959727088 0.005174314697251110318 0.006927771442080139092 +'MLO31-1706' 0.02335027695706177672 -0.08184121978709980871 0.06297953295131275553 -0.1571978205858913513 -0.1892721686426063199 0.3622236681314214835 -0.07510702038737752939 -0.1265939267982662819 -0.2610489784066898356 -0.3244345342798212739 -0.2426640726539950887 0.1142887483528743503 0.0186479229051942294 0.04862104026539474516 -0.2584352257722497548 -0.1603888081623384421 -0.1875954735531542017 -0.3544873403930586253 -0.07702903993538265381 -0.1300640022383471317 +'MLO32-1706' -0.06917102755867893249 -0.1160203877977356857 0.06499745363772395368 0.1293377696994272297 0.08590209897514125559 -0.2123922803917337732 0.0146880595173055923 0.03608521283023888304 0.3970715913069901015 0.1904263073945612061 0.3454274162777479229 -0.03513815240054251471 -0.001811790343358681736 -0.09322105136653607849 0.363200742477256755 0.1319632209603800455 0.0851411227124493214 0.2078560326675444325 0.01506393300248606675 0.03707434725366065553 +'MLO33-1706' 0.03906514855758928123 0.03715943036126497651 0.06784612276801420261 0.02173853060394633288 0.0194594592231374236 0.02998984578603465165 0.003445603318812817065 0.003474766925558448686 0.4448646287160821777 -0.02944331019303483843 0.400131504261086457 -0.006493778708088468465 -0.005767022449763669137 -0.1049233347731324539 0.4075424213113187366 0.02217980504928450738 0.0192870747676899025 -0.0293493264157224272 0.003533777725136923262 0.003570014017368785923 +'MLO41-1706' 0.02968258526596665586 -0.08528502534192591855 -0.04805625349816969316 0.1530178477015080862 0.134723723402018547 -0.3368410507075745297 0.03484338371611422208 0.08407067512638699558 0.3243979555234395851 0.2688077505120701205 0.3351456381247909788 -0.06700542119285950171 -0.002477196440968285843 -0.06891968780570872921 0.3450665330949023724 0.1561239852368144776 0.1335302536643340476 0.329646841733182594 0.03573504023870834045 0.08637514258675720036 +'MLO42-1706' -0.009813525708051419605 -0.05517041548606339829 -0.001480731269012075524 0.08369318087936838957 0.03908314554066603941 -0.1130734023650762504 0.005927871711646718472 0.01040278567924651787 0.424016138424608946 0.08790051950661811886 0.4266355306707683703 -0.01141097276075207605 -0.003318531062898421279 -0.1011492292646147678 0.4346660429824507621 0.08539208420655218512 0.03873692180012171943 0.1106583947988930977 0.006079568387258236367 0.0106879372027591929 +'MLO43-1706' -0.06497367018937913463 0.005357698822009322737 0.06721619353052157853 0.03814081452870590749 -0.02366229325607518627 -0.1631022490844800943 0.002705093792193812279 -0.0137182102065099322 -0.3991597116636950715 0.133307710411953162 -0.4174923294867435852 0.01105514837010679492 0.0017220870395755056 0.09211466454468868192 -0.4181292144614614514 0.03891504196304988034 -0.02345267738284792514 0.159618731675772868 0.002774318255113093854 -0.01409424107563159341 +'MLP11-1706' -0.03254907887140537359 -0.031343189015960643 0.01162562349697794477 -0.04481489544758975735 -0.1637221261562841756 -0.003644449989792582657 -0.0313657533939791025 0.09920318384683535218 -0.06585969536860916684 -0.1163234330464612276 0.3189788093004055081 -0.1589258747295231866 0.14086329016737692 0.1353490369514508129 0.02589680587528723002 -0.04572460128244197619 -0.1622717698417261156 0.003566612283348509407 -0.03216841592605935302 0.1019224496169326144 +'MLP12-1706' 0.07420168669935493788 0.1626135653591918029 -0.01161357581151663612 0.0006503848446864165687 -0.1650560746376732446 -0.009740636855120811399 0.006052426588323464238 0.06994411533537923942 -0.2411069308675658773 0.0008280259812821844437 0.3206804543421148401 -0.1297772789069849275 -0.004178645054211406126 0.1768255167663430605 -0.003703793444594739425 0.0006635871267000516965 -0.1635939013460901426 0.009532597553105218169 0.006207310674466478065 0.07186135862612773317 +'MLP13-1706' -0.1472537393590042654 0.1698745075867932885 -0.1289722917829971005 0.08954636501127397064 -0.1815010951972302888 -0.03446370320538457571 0.06322647055022191653 0.06917967305637177933 -0.197444497143178993 0.1699705841858713262 0.2744847843162597778 -0.08265853485686419644 -0.1435369710122164078 0.1555788231247704212 -0.006745237965122670432 0.09136408320356184665 -0.1798932412944094228 0.03372763174862437874 0.06484446194066885438 0.07107596216357581209 +'MLP21-1706' 0.03065305428369943103 0.04998678184158267951 0.08347290655773205448 0.1215210239110993823 0.2281643782632242767 -0.03553814460919221124 0.09987713047746586692 -0.08087828976564592764 0.1839552744870874557 0.2266761617423720399 -0.2230459482949261885 0.02251211022933336664 -0.1892567775181508427 -0.144853423111896501 0.02160539624538475659 0.1239878016064401289 0.2261431508669016766 0.03477912536749458439 0.1024330273321973211 -0.08309525051605176627 +'MLP22-1706' -0.07457784830778133034 -0.01685430435273760699 0.05613896592371505484 -0.1008948889056937026 -0.1990878771411294379 0.02379315990121987773 -0.05209375562562000572 0.06321294330035755193 -0.2756225730534200835 -0.1684282363993371556 0.2458283783038056891 -0.06615441853850734244 0.1129004881214447087 0.1754344441912255859 -0.03218934493916735667 -0.102942972879282682 -0.1973242281674533194 -0.02328498857195069466 -0.05342685626155296852 0.06494567793928966715 +'MLP31-1706' 0.01240951581111496629 -0.06797052655871625715 0.06226620494947669726 0.1665491062541684109 0.2445198134613952301 -0.09081177834893650047 0.09002874174319693001 -0.02516855560792082697 0.3486075340535446654 0.2520251052602807129 -0.1098374529835711572 -0.02073335737228252512 -0.114372507474338414 -0.1768978117412787487 0.1009622619911235142 0.1699299173045038802 0.2423536990588144313 0.08887223176040152939 0.09233261427895005091 -0.02585845273716091963 +'MLP32-1706' 0.06730412417434690486 -0.07499711696366041791 -0.06492806293250759364 0.07172379999208475243 0.1691686145398393626 -0.03211099887297767796 0.02094649814523389872 -0.02989385536553905431 0.4450973378894834132 0.09576057813882125902 -0.08030536293800243086 0.03374692119732352474 -0.03397550516256678255 -0.2051654323689691695 0.1335667039921200894 0.07317973464726831856 0.1676700097141929913 0.03142517618069180785 0.02148252764939672169 -0.03071327803404187706 +'MLP33-1706' -0.0301997206769226631 0.0599716611456580645 0.05736201770451674481 0.06991588837645240639 -0.165524104091330948 -0.05922745143604712936 0.03169309247090957432 0.02788423815925609311 -0.4195211203525940902 0.1297071527555289372 0.1012943008122802191 -0.03645650359655178141 -0.04928184303175944109 0.1956362613135718409 -0.120889271280105709 0.07133512390003669823 -0.1640577846926244698 0.05796247894603584472 0.03250413174462386118 0.02864857506268425613 +'MLP34-1706' 0.02142708564677759872 0.04222148761828281582 0.09213146860173419828 0.1420231637408337633 -0.1928328936320904408 -0.1554264662092531002 0.08993872846965687839 -0.02230082821303797092 -0.2961103254223054204 0.2914856764061067307 0.02674171626503536736 0.06774850378097202475 -0.09641422921272820024 0.1247227021563254851 -0.1140678707053414398 0.1449061181569676893 -0.1911246553413975813 0.1521068872098651215 0.09224029752871192034 -0.02291211785569865003 +'MLT11-1706' -0.08233530045752376902 -0.02447828727219286682 -0.1014393526359933517 -0.02958229687602973584 -0.04527773462767654966 -0.2230494963104258377 0.2111870063729225366 -0.2675319784798846356 -0.0288329727485090101 0.2236778367940650547 -0.03943624108943055012 0.2793902637327433935 -0.01854404305117749938 -0.007690732417338416033 -0.0423465413057005774 -0.03018279338076725743 -0.04487663521693806973 0.218285633103375204 0.216591368740646828 -0.27486531722241897 +'MLT12-1706' -0.1114444708120039818 -0.01849487989224751772 -0.09792452961550676682 0.02583722051321851038 -0.1458246707812212439 -0.2931978717395675726 0.1560182061764308903 -0.2214425097855136082 -0.0848403927824512849 0.3105837944274463802 -0.08700575886028404093 0.2364350428229961554 -0.0174784414767892686 -0.002961941039041637597 -0.09372235346856495897 0.02636169502158206002 -0.1445328616833843338 0.2869357883156186673 0.1600107762526922217 -0.2275124867111925353 +'MLT13-1706' -0.05383329550375999528 -0.00380981021998805236 -0.01632765315264699327 0.0908144486053477501 -0.1717561243681703931 -0.3085807255201218902 0.08954527229144168543 -0.1360471724394358428 -0.1917812092621452025 0.3480644017516279498 -0.1567186628871949927 0.156061174564948113 -0.01497555806176901864 0.01829121545937899621 -0.1711193688961214765 0.09265790786058103468 -0.1702345977096196561 0.3019900970317062061 0.09183677264504268301 -0.1397763714911947064 +'MLT14-1706' 0.03334052127485961914 0.08727846851640211345 0.1337573540696984642 -0.1055074212258858696 0.1400925198914803327 0.2849956143401081166 -0.05395499469257002828 0.1109506775354029418 0.2330972961545163535 -0.3327796299227183119 0.1722295147687499806 -0.1279301503386968963 0.007437001995765885054 -0.03710694895270723326 0.1853935350794390924 -0.1076491358444471719 0.1388514898876737069 -0.2789087137024304774 -0.05533572520187218097 0.1139919547191769883 +'MLT15-1706' 0.09871839735438511787 -0.07714045463308322192 0.05219836140068744718 -0.1042273170158462409 0.09197801163002736202 0.198300305442292879 -0.02672396356482748328 0.03877652626137417097 0.3613035029548977706 -0.2482918958501107443 0.2010145982418926336 -0.04831902000297656763 0.01869519582748750339 -0.09290063791491030842 0.2376949885519369365 -0.1063430465627597798 0.09116321100961051471 -0.1940650323541676658 -0.02740784078571651197 0.03983943247523755865 +'MLT16-1706' -0.015137694284533737 0.07209707496102379931 0.1038206332590150549 0.003874088488978161271 -0.07852820718152854484 -0.0415903061725510087 0.00528007797795675398 0.004592155608955979067 -0.4719628478113992998 0.04960774435547862793 -0.189838959624057807 -0.004619140748259872344 -0.005670844111562792396 0.1540051832598874626 -0.2695591179257623149 0.003952729326314908566 -0.07783255361392255045 0.04070202562216752862 0.005415197345444400581 0.004718031524165252136 +'MLT21-1706' -0.1695220056619411442 0.01938514843339033539 -0.0007782423507863810153 -0.02659917894251488321 0.05609075520668714565 -0.1653810029292919481 0.2439709046622440536 -0.3296950813646306044 -0.003400926890683688558 0.1432800487499681641 -0.01647650673444727917 0.304595137741725086 -0.01920512994132781218 -0.006285297594146315066 -0.01177099016291409915 -0.02713912058568088842 0.05559386707731669985 0.1618488161813626536 0.2502142204732934472 -0.3387323774932354259 +'MLT22-1706' 0.01253719985686441163 0.03293244308938413079 0.01255531523583442582 0.005052397400462312754 0.09561464443966852245 0.2713505700295311129 -0.1949733212451122133 0.2842238004776054261 0.0487393815794826199 -0.2538105484288438185 0.05302185428441363174 -0.2696109120444568075 0.01648506921534850789 0.001519694326976172303 0.06216639915200549565 0.005154956947891538299 0.09476762817752369672 -0.2655550985393071439 -0.1999627687406963783 0.2920146799808179261 +'MLT23-1706' -0.004754430361167108834 -0.02378388530037454929 0.01028461857033133482 0.09196490667031650967 -0.1966179352201750663 -0.3542016182441959926 0.1185664188260945745 -0.1809617825397288327 -0.1707138964970726092 0.3466278676514039647 -0.1531833728266965566 0.1790467592506942707 -0.01613109864795101225 0.02082234402610015633 -0.1712879613734991646 0.09383171928616804158 -0.1948761665869620796 0.3466366244426276055 0.1216005822577597706 -0.1859221392729948075 +'MLT24-1706' 0.02586678269583084569 0.01710795420096069414 -0.003917041659703515352 -0.1176957007984857084 0.1686647075162490128 0.3383488613902197462 -0.07370318403295750276 0.1396937168091365311 0.2212181269494159774 -0.3388481006657154126 0.1897634867790275182 -0.1395512097724121992 0.009251444612437566967 -0.03783713251572059372 0.2013466407745358455 -0.1200848275538659304 0.1671705666244078792 -0.3311224487841090136 -0.07558927883116588198 0.1435228715568635793 +'MLT25-1706' 0.06825304953278769904 -0.02586006496609506364 0.03872178135421450174 -0.1268721880940744118 0.1120982594992709497 0.2902333077321472832 -0.03271270445964546275 0.08155398098307603538 0.3082687234376009222 -0.2988903686932241621 0.2458178196993102138 -0.08206954564754399828 0.00673555467769808465 -0.06791620918030311094 0.2561261906134915667 -0.1294475900589104611 0.1111052207308852041 -0.2840345410949811633 -0.03354983602358273254 0.08378946315514863852 +'MLT26-1706' 0.08262104215029614229 -0.07113893019464671841 -0.05751161154286840715 -0.04987476942547613284 0.03235102071602020263 0.1472970077251444798 -0.005571973328459640593 0.01502889713360176967 0.4028474180133593818 -0.1521229824971006839 0.3212392533118609284 -0.01619601809869684883 0.00195337153083327119 -0.09246606463987298852 0.3294980051938202759 -0.0508871865761827899 0.03206443448433951571 -0.1441510566819111661 -0.005714562418041769024 0.0154408553384998478 +'MLT31-1706' 0.04536269821446053951 0.05543637710208089431 0.09006923830836613409 0.02296390257423754772 0.0658605352782777459 0.2810548014687349605 -0.2029959020507628165 0.3237891685553785925 0.036543353703195329 -0.2330948026272021412 0.05456119252573662232 -0.2724653032860071544 0.01277527675922108044 0.006359767533228870458 0.0586766135365817329 0.02343005107138606408 0.06527710012834667119 -0.2750520682188090094 -0.2081906506893610176 0.3326645772735130069 +'MLT32-1706' -0.07040737547028194654 -0.07010868790391346084 -0.0919325801047311264 0.03295694794073949357 -0.1505221903652836923 -0.354879798883719455 0.153931473965670973 -0.2668958203861421241 -0.09406606299642095159 0.3066220431621312636 -0.1132565363247583362 0.2334896233478791772 -0.01091877318015843298 -0.0007529988673511585091 -0.1188547122644263987 0.03362594711034984363 -0.1491887676056194711 0.3473003205849888864 0.1578706437062533385 -0.2742117213523712627 +'MLT33-1706' 0.03759154420645592631 0.06293433604215277477 0.02785939330557466592 -0.1061371672066710875 0.1865440063790075598 0.410383837180749389 -0.08840482736597141122 0.1877449635833288721 0.2002981087374888503 -0.3577055301325957615 0.2150493937769878683 -0.1610161405018594449 0.002517759247609677176 -0.02447174925164136844 0.2227025717381491965 -0.1082916651551381199 0.1848914791125554902 -0.4016189105835031858 -0.0906671432647921105 0.1928912545911712906 +'MLT34-1706' 0.01010830937860377615 0.02300220144635611863 0.01175418885146892189 -0.1309931439552913801 0.1478078965860212812 0.3750463712044744269 -0.05026462681219697609 0.1313665713175116156 0.2687998819186505628 -0.3343907771078135083 0.2557206487946995233 -0.1149472042471736399 0.003135771625174524433 -0.05384999391382537526 0.2643678739438211078 -0.1336521979638213564 0.1464985187933675881 -0.3670361777798173963 -0.05155091928935751772 0.1349674700675989047 +'MLT35-1706' 0.05302704195493749412 -0.007555412711386787217 0.1787448755649659327 -0.0992282311351058155 0.06627001854908867728 0.2644343474922813964 -0.01438336069692540235 0.05340909162285857603 0.3906858811735310355 -0.2401727388401060093 0.3504831715207544773 -0.05141044200545939052 0.002739962210585126026 -0.0906296722238528335 0.3587242843285467497 -0.1012424833149695308 0.0656829559319271894 -0.2587865918168069657 -0.01475143681395034261 0.05487309216225923908 +'MLT41-1706' 0.1293857880350949563 0.00637571676035968149 0.07136577695359848372 -0.005179597420609745144 0.1028952934831743327 0.3343091811333139263 -0.1875372043946663403 0.3359978703363776242 0.04801916603187286747 -0.2585108773865401055 0.07671975522743527953 -0.259996493698508746 0.01485932153584340262 0.004754998426423406865 0.07647673598986186316 -0.005284739024727168333 0.1019837805304340955 -0.3271690475121927788 -0.1923363586011000437 0.345207932677138507 +'MLT42-1706' 0.004773705767403838007 -0.03956184197923247325 -0.09336372858720129453 0.08206218110972902935 -0.1878686369052043892 -0.4316469045532592141 0.115278634680994016 -0.2363962694522231123 -0.1589447350970379091 0.3379995109937863895 -0.1938551071848978458 0.1858992914826183285 -0.005978616651057470921 0.0129834577410325655 -0.2022497029033333282 0.08372797647153064349 -0.1862043752061913748 0.4224278440260984535 0.1182286623639114964 -0.2428761449841677633 +'MLT43-1706' 0.07119702620511179914 0.01148867339718427638 0.06546062155324658405 -0.1162688954220271603 0.1630026811665273301 0.417495408100176435 -0.06999080869833090857 0.1733134191511145339 0.2142543027499685671 -0.3309780358394447952 0.243641597888815592 -0.1351828999414670385 0.005501391533327266471 -0.03492379500937104614 0.2486377776137869144 -0.1186290591917036341 0.1615586981602591676 -0.4085785934618999526 -0.07178190228459020716 0.1780641260328996167 +'MLT44-1706' -0.01060059760112150307 0.05279261184974405607 -0.08770762262678184762 0.1286489460236365234 -0.108358113107704393 -0.356080161954127894 0.03283024541845395994 -0.09813784237239926711 -0.3191464532929893516 0.2862178580547877771 -0.3243211846736706039 0.08049649684748082235 -0.006229524418852130235 0.07373414556936487563 -0.3310271196235037849 0.1312604147256478115 -0.1073982069711976323 0.348475046451275472 0.03367038490387921218 -0.1008279059889712198 +'MRC11-1706' -0.005660562964780430084 0.03093564647386291139 -0.1366476803393353867 0.03149288472440638087 -0.1428646582377278429 -0.09706565209807684058 0.006744921713188308833 0.1301950389802383479 0.1292700997476396163 -0.03218320200967091094 0.07363530531781213584 -0.2780291827662086934 -0.1117044033296687167 0.131025106735402963 0.2536033537948697569 0.03213216460454412782 -0.1415990708423841005 0.09499253605725488381 0.006917527034443880611 0.1337638247712473472 +'MRC12-1706' 0.001657209719117924696 -0.08621241292836676062 -0.02032110369289632373 0.005415489136256735822 -0.124468946543081882 -0.005139337647525064716 0.001096150089557285795 0.1128702813525614829 0.132144935373970096 -0.007353401404667603107 0.06365797610045072219 -0.2621644187450471453 -0.004295464814762192315 0.07515609803940684341 0.3047129122011199565 0.005525419149852170767 -0.1233663202406795334 0.005029572317709748649 0.001124201021265271898 0.115964176937779273 +'MRC13-1706' 0.01567806134576491331 -0.03576686567425289842 -0.04743607632671517638 -0.1675320574891141501 0.0557961346471095021 0.1082317265516854754 -0.04093260804039606376 0.09301617041409791786 0.167624894580672229 0.1170817167061984354 0.005894582849949414442 -0.135330212382247933 0.121112523485422674 -0.1501655102976734713 0.310447528153994512 -0.1709328216480059948 0.0553018564569024984 -0.1059201268911439675 -0.04198009031833362104 0.0955658435038559545 +'MRC14-1706' -0.1408236532932465035 0.1437399719835189549 0.1440907664891577511 0.3667402996001041249 -0.26068625812285523 -0.08012772140454960113 0.1202107523793718991 -0.04224879299289648754 -0.1334373946045232517 -0.2567361730716835599 0.06242766246245907286 -0.02682478483333718133 -0.1746168437430096476 0.2194568596232674418 -0.1504935965628990402 0.3741848286364785614 -0.2583769309142280313 0.07841636356614101189 0.1232869949830844442 -0.0434068777655675711 +'MRC15-1706' -0.1415466196240769692 0.02020267978190632557 0.105594078560044824 0.4177190730735461099 -0.382816307871402528 0.09738142075264108466 0.1621698710909499352 0.06487558913729139787 -0.06751218407339500127 -0.3300944839791737917 0.1052854051065583024 -0.1533620785578568568 -0.1102796631811167744 0.1916663244901095631 0.009215365861497617703 0.4261984296425794794 -0.3794250738184858918 -0.09530156056444240298 0.1663198648029446669 0.06665389868356871861 +'MRC21-1706' -0.1645483263218346925 -0.06940489131530748479 -0.1424274970759405179 0.01872577238450523832 -0.148397797041877777 -0.005538765983709789155 0.01377114050098533771 0.1100361958312194022 0.1458221056487790102 -0.009818289542760873581 0.05470974035509937328 -0.2952812683540666505 -0.01531456261076340544 0.1276575891519702022 0.2386784095436131348 0.01910589029463673205 -0.1470831935300668802 0.005420469713515407156 0.01412354965135108852 0.1130524060897281774 +'MRC22-1706' 0.007350299927600816713 -0.04662536045993592726 -0.1190910105663929713 -0.04209156594515547217 -0.08279258821657893563 0.09074295641062139761 0.0003863620856409030724 0.1152965948957720699 0.1429817115580201692 0.04255942258065224804 0.03736489202088946054 -0.2417822316490968737 0.08592803084441706651 0.03692211334232609055 0.3061453894366336637 -0.04294599041175175408 -0.08205915800810550942 -0.0888048797124255801 0.0003962492503477413374 0.1184569983400094034 +'MRC23-1706' 0.1340046642764439744 -0.04144836320494377224 -0.008996463796811753413 -0.1788124872672437748 0.06725340995093564977 0.1743462871326501851 -0.05619907952350092217 0.1204575310739445793 0.1371456339256297008 0.144819087650337297 0.006131711438593132925 -0.125770465034433454 0.1964531086529643367 -0.05273188814522869472 0.2584612031979672819 -0.1824422349524009723 0.06665763581772661539 -0.1706226209675350824 -0.05763723708676137675 0.1237594013194150827 +'MRC24-1706' -0.1138176828966930565 -0.0599252702223835032 0.1795681998662090328 0.3263463036260727534 -0.2772457583260635183 -0.1163327608533506752 0.1470652409259930737 -0.06757398049154753061 -0.1119816947438452004 -0.2555540976094763383 0.05145665452761891828 -0.04821044840374194562 -0.2126462493436306611 0.138009767366694569 -0.1405683727414873407 0.3329708674820410219 -0.2747897363715914865 0.1138481403167832945 0.1508287009385719524 -0.06942625584173779674 +'MRC31-1706' -0.03030764062539810511 -0.02895209766741612539 -0.09569436626421892744 0.00184434773831949287 -0.1129043021380233547 0.08292197523586969377 0.02234935690276347933 0.1161350076765614442 0.1483247473883449463 0.02501205533002289969 0.03670024877906322841 -0.2720823248176128528 0.08534663745625559184 0.09848974457835335539 0.2276114894841698433 0.001881786493498736976 -0.1119041229234537665 -0.08115093807408949034 0.02292128613961647021 0.1193183929152090289 +'MRC32-1706' 0.09912685369841618688 0.08132927740746792589 0.04133291048937849654 -0.1027786634329944243 0.01874258259204315824 0.1865765162199978233 -0.04378564074318946897 0.1531800457235129032 0.1374387834159497834 0.1115522076961573544 0.02093102885570796712 -0.1539170044932215986 0.2371980743126564095 0.03726142830899034641 0.2091948521718647591 -0.1048649864934298181 0.0185765486927060193 -0.1825916383537725118 -0.04490613330162523953 0.1573788752252050782 +'MRC33-1706' -0.04089369243021736405 -0.00161308383295192051 0.06755710509737210268 0.02058540768048557762 0.05924720742842816412 -0.1424802279592479737 0.04461174001234675252 -0.1791885335444835803 -0.1330153948348522519 -0.01903961338319410876 -0.08326488125491482428 0.1610202673483977776 -0.2819241620903628065 -0.1037757855673080154 -0.1158915693951795833 0.02100327467075113058 0.05872235740704664919 0.1394371530949919114 0.04575337279090742337 -0.1841002836190956393 +'MRC41-1706' 0.004808495888703870347 0.01280792054287886207 -0.1740545572962289289 0.03244070404921673562 -0.1387476241065075111 -0.009913414231561785972 0.028590827599259825 0.1005579916418899017 0.1627993359508683735 -0.007193955936396094486 0.05891867588529264843 -0.3021535635152705623 -0.02797872926364249058 0.1293653642299854578 0.1658607538920409408 0.03309922388878212829 -0.1375185080580100805 0.009701684771979133745 0.02932247863874982985 0.1033143941481210332 +'MRC42-1706' -0.1001818712659820615 -0.06157689018310366635 0.03385256424823168686 -0.02143174127961211539 0.1243777597910707133 -0.0752531838929455521 -0.02630914246999125142 -0.1272866685687265853 -0.16598485506785432 -0.01630864584944390072 -0.07361937969056429887 0.2896955373257253941 -0.1249853015552933461 -0.1284161673178949303 -0.1440881176063019964 -0.02186678815182689986 0.123275941279800183 0.07364593581621334262 -0.02698240424842112892 -0.1307757328044375222 +'MRC43-1706' 0.01051572342516605106 -0.005573886465091043921 0.02231890046566168198 -0.01700595089220478112 0.1306546549002026714 -0.04593449857095479455 0.003256521167696147401 -0.144430709314943867 -0.1345610541412786132 0.04324527501680675706 -0.1750576421336568211 0.2337679031398093299 -0.2031584325166854443 -0.1233057730234948107 -0.06462385529311368004 -0.01735115782841065504 0.129497231598846213 0.04495343530340120686 0.003339856883991669349 -0.1483897101127143736 +'MRF11-1706' -0.1460610777701848162 0.1225370377843743586 0.003292974800558338966 -0.3914759656339776295 -0.1993117264089305785 -0.2666611432810869764 -0.02958525882224877224 0.06581447692863147403 -0.06374779841188568663 0.2752635410150005568 0.2717012586028726417 -0.06674925331413927854 0.003226199356359232828 0.3146042658840567663 0.2551314180783957331 -0.3994226085210087485 -0.197546094433893038 0.2609658279800435854 -0.03034235776580785152 0.06761852239722450364 +'MRF12-1706' -0.1978666252348947607 -0.004246940324839718756 -0.008404965065261033041 -0.1777551380750957699 -0.05615897247615009302 -0.1006349131576794037 -0.004967777846480942242 0.007194231535034661257 -0.1003539970723780761 0.1030919117036809135 0.3400687939021461714 -0.006876828688666960891 0.003914930140392529692 0.4080310672392012394 0.3198682354164517072 -0.1813634224338307455 -0.05566148003415649637 0.09848556528616757288 -0.005094905325135224566 0.007391433144869870644 +'MRF21-1706' 0.1468485575525668163 -0.02660898146923014809 0.01082298439571230744 0.4489556698662187095 0.3172484424707289197 0.1544123396890724198 0.0921297269988990003 -0.04898630155053217833 0.1018950793831793072 -0.3015256224154518883 -0.1707156859987638553 0.08872398706265811896 -0.06072974909297342017 -0.3008291650378063231 -0.08584168000493415385 0.4580691038793566205 0.3144380509089804154 -0.1511144202768913147 0.09448736461161434674 -0.05032906866590711875 +'MRF22-1706' -0.1753734699537965458 0.1319961639025657996 -0.07758587017575943601 -0.3031220334089506641 -0.1553476163683171207 -0.1115559371568244779 -0.02654041212715628831 0.009159656794319161188 -0.1411408338101635129 0.1920495516064696928 0.2370308326963556922 -0.01584976674019302964 0.02281963895626976102 0.4133614984690955341 0.1520565620048316413 -0.3092751635169273539 -0.1539714468691728011 0.1091733394225089387 -0.0272195921912489272 0.009410732820518952907 +'MRF23-1706' 0.1277627716319828799 -0.03506348061873196947 0.07049036255540865048 -0.05095919589964797991 0.02584686254273198258 -0.05359056888835258409 -0.003287907748599090338 -0.002309859197859597674 0.1019585901104455711 0.05896635622042942226 -0.3080083839977790783 0.001283698699669189123 0.003611616205129146093 -0.4150806889987312398 -0.2898279082339914048 -0.051993626023522789 0.02561789434411121391 0.05244598822982095288 -0.003372046660411215369 -0.002373174918252017422 +'MRF31-1706' 0.08258377870033484225 0.02882409598080180879 -0.03478561157289992295 0.3345237250523870887 0.2153588278531803901 -0.05186325543676745947 0.0693964612798855518 0.04843043705848610464 0.191818203958879413 -0.2025251240757260651 -0.0826636353268593721 -0.0207706622106353482 -0.1089803201412488931 -0.3411415075314344625 0.1510093116030930271 0.341314283895318038 0.2134510402913788185 0.05075556652260274776 0.07117234527121399368 0.04975796733137858446 +'MRF32-1706' -0.140292069230588623 0.0518084379845978743 0.04625992645041328982 -0.08223499388170910085 -0.1259187845971654895 0.01472054522641652423 -0.005661619525129373692 -0.03129152352533937087 -0.2112104070428087454 0.04073682600412430188 0.1432569673872305105 0.03925861477650859771 0.01497882477466179647 0.4452362640532511184 -0.06901112308688432673 -0.08390429720186784457 -0.1248033146930692949 -0.01440614566510008826 -0.005806502697761463036 -0.03214925777858698014 +'MRF33-1706' 0.04581512633311696225 -0.03851916734220987848 -0.1121433021056573304 -0.2704492552298836117 0.1416339165348300955 -0.1072501162247365691 -0.03457846331288893377 -0.01401686321925640216 0.1539189910460826427 0.2001699628286556787 -0.2149691214471755041 0.01774882660361733894 0.04184702532194709002 -0.4159159851214078163 -0.09708104383185747754 -0.2759391545826957448 0.1403792318442233233 0.1049594816746192844 -0.03546334041338593257 -0.01440108048808023435 +'MRF34-1706' -0.1804816263940929866 0.0482547197334161071 0.00149114393265449563 0.3353531235492367979 -0.1432900075491073399 0.1985818351149147842 0.02560302013500279431 0.04157311037525023706 -0.06898630043424712477 -0.2521540703680296147 0.2528825855342297091 -0.04830650884366950726 -0.01582398468404331085 0.3456799574124652663 0.2286065383861655143 0.3421605185053499532 -0.1420206521349005879 -0.1943405491513010563 0.02625821195240731626 0.04271267396198386024 +'MRF41-1706' -0.004460773861003406934 -0.1604055877951704456 0.003142378096630205064 0.2310292917860298223 0.09826412580379421946 -0.1892634406097830069 0.07086692188108359436 0.1301887207711014127 0.1540796045597042363 -0.1644560006901570337 0.03904030390114558019 -0.1098205675145439569 -0.1904384299867170061 -0.08561206781191804671 0.2999938520169375678 0.2357189980245574801 0.09739363872486382634 0.1852211757489562183 0.07268043556409059525 0.133757333373214965 +'MRF42-1706' 0.03004480325200908908 -0.07122999434194551838 -0.1404816604715563577 0.1235229175863819667 0.06321053702925003015 -0.07769921687174238811 0.01805435270065995287 0.08657730690902729065 0.1948044818285250279 -0.08024469733894981638 0.002226204493076584627 -0.1292736570153762976 -0.06550159751628488458 -0.2324064146017385812 0.3252043815005539185 0.1260303320909570424 0.06265057727500479567 0.07603972672899494967 0.01851637101317284151 0.08895048383758648314 +'MRF43-1706' -0.142053850856965036 0.04882004860033850591 0.0002093252162574856662 0.201628475797231338 -0.1266298560996375056 -0.006719513938002405658 0.04694529932042386389 -0.04190293870243258501 -0.2008881807115901474 -0.1378154184197052379 0.070668880323283223 0.05904396586246443007 -0.0742525001907780452 0.3571554136700185733 -0.1912439638530392949 0.2057213694450500674 -0.1255080870650088221 0.006575999400879384282 0.04814664884161949654 -0.04305154323770573471 +'MRF44-1706' 0.04052347657870172815 0.03395938511220548267 -0.06296226606685161042 -0.3049314232960364524 0.1936938430041473258 -0.00547853199430812024 -0.05892261881081731212 0.02198968854998612291 0.173888331141278607 0.2071834799580361819 -0.1191120092087274984 -0.007656235063676544023 0.08385329629100289617 -0.3577793987619313776 0.09173947367047886881 -0.3111212825433174456 0.1919779778679718274 0.005361522194115560941 -0.06043047286480504598 0.02259244952045455501 +'MRF45-1706' 0.03333028018806128562 -0.07061627546691667812 -0.1533342211569757585 -0.4316641322479654597 0.3130181039474156379 -0.1472042904251516238 -0.1003939048455900207 -0.06245609999890650021 0.08833489617920510517 0.3214055386254895397 -0.1542982360874382008 0.1062539354665490848 0.07543292546338328797 -0.267342037806401811 -0.06136503392626676406 -0.4404265621472305825 0.3102451874559831735 0.1440603196263994523 -0.1029630261689838955 -0.06416808875042699645 +'MRF51-1706' -0.007265128715334814857 0.06919684443253426576 0.161788688768056077 -0.07484133460293593276 0.07707841074468414766 0.1163096828009216877 -0.01217654667726364437 -0.1264042630085773222 -0.1366166716280267646 0.06355798626457344336 -0.0657555576099347755 0.2263490905229616768 0.1060020400426279347 -0.0309284095129038622 -0.3354558912991432718 -0.07636055266863557567 0.07639560041009968439 -0.1138255551625077661 -0.012488149515722545 -0.1298691395605668097 +'MRF52-1706' 0.07238836968977092889 -0.09904856959499559743 -0.1362848755353477936 -0.07217592118370531884 -0.02348616596768675346 0.03670057000230018268 -0.02822063658828575031 0.09589625669184358159 0.1626096663820633115 0.04392102620374231658 0.0375767947370768754 -0.1865541340379883173 0.06041334171735435882 -0.09932675507893340416 0.3559667699362377147 -0.07364103353041243083 -0.0232781103437115465 -0.03591672382464094343 -0.02894281428752183694 0.09852487603842831343 +'MRO11-1706' 0.06209961816336936197 0.0469618832994443125 0.07743497040960828359 -0.1439377423882668983 -0.2549757463148236147 0.2261121631683401523 -0.2008059047286922527 -0.1024485944130896081 -0.1750551121584435488 -0.320013918835879152 -0.01343605646839339703 0.1855797110827041574 0.1006391428739244198 0.07238630623524415497 -0.0976189532015430822 -0.1468595611897677566 -0.2527170065072678051 -0.2212828879061124465 -0.2059446104349335893 -0.1052568203709602496 +'MRO12-1706' -0.1006215789754773271 -0.03889078837013267703 -0.06130458970919448747 -0.08525198542510474542 -0.1130534545083538428 0.176148990736793909 -0.3008410647741507349 -0.1452357138483714172 -0.0536640376157460422 -0.210479749195360194 0.009796322209887506349 0.2720278502013791511 0.1310533180979747692 0.0322733233593751126 -0.02977349187045847181 -0.08698253121349452943 -0.112051954005774973 -0.1723868226538754489 -0.3085397113767760491 -0.1492167806846262379 +'MRO21-1706' 0.05299930883992316072 -0.1253943442984888634 -0.008060704348819155984 0.03797736748939538332 0.1608819553919366152 -0.2740428237563288238 0.1952426672348398506 0.2545954870257767233 0.07201616767469194713 0.2784536500571362927 0.06723888940824945815 -0.2644354197546802676 -0.01521978793965386018 -0.002430446545962240863 0.07509430126772151382 0.03874827708211848326 0.1594567591440060605 0.2681898514481907969 0.200239007405100311 0.2615742226494168765 +'MRO22-1706' 0.01136950260910647714 0.03276013849721078758 -0.05313899731148753053 -0.006430042846686685569 0.04714505400198649998 0.09102279698813997566 -0.2597015444726570865 -0.3180763230458197866 -0.01028332816728782378 -0.08401308036534056722 -0.006060076790239271767 0.3289500340605445161 0.01601793786951182311 -0.001738658626476179657 -0.008799210965516061217 -0.006560567473321627339 0.04672741267043737518 -0.08907874348993724545 -0.2663474138274672942 -0.3267951365354385129 +'MRO31-1706' -0.03431694508912453562 -0.07370029867745292451 -0.1664149331400278931 0.08602719904402476858 0.2093333318024645784 -0.3682588126828165165 0.1355740691343928772 0.226981895933509592 0.1335850593161744815 0.3273626812000050013 0.1356215035999679686 -0.1979141672076910607 -0.005639567486516952437 -0.01515844377503166446 0.1481137795908643584 0.08777348103675787494 0.2074789219755522607 0.3603935870829781396 0.1390434653337753179 0.2332037133803844531 +'MRO32-1706' -0.1087741636176016158 0.03333519879229727978 0.09020687306929475735 -0.0002436270116799254225 -0.08081828468970840562 0.2290552876885150746 -0.216981546773290207 -0.324944769024212432 -0.0240884604532793957 -0.2020856418585134651 -0.0369592344382079982 0.2853976405614884193 0.005429632116573002328 -0.004528067678526469589 -0.03633638412096942827 -0.000248572441359931097 -0.08010234413675237919 -0.2241631535413881327 -0.2225341938135226294 -0.3338518539918073347 +'MRO33-1706' -0.02533887649724315613 -0.03334882922997218363 -0.08998682364949989188 0.01988763421954067162 -0.1467871015991251138 0.0155571339412026409 0.2444654391110442637 0.3613000654319142302 -0.002185657294263091896 -0.01758022063736399895 -0.008301246034923645545 -0.3146028371800014822 -0.002058524571889519192 -0.0005954442418589613387 -0.001815652475860966364 0.02029133697752391954 -0.1454867666676281923 -0.01522486662289178165 0.2507214102620719531 0.3712036881037409364 +'MRO41-1706' -0.1318835467722205557 0.02509851316335850319 0.06601022801180113364 -0.04406543436568154115 -0.1707656107408329349 0.3669737316865546162 -0.1878796017412906194 -0.3190554244422296182 -0.07454240134044072541 -0.2921773931478982012 -0.1027944273095854483 0.2525191788905997714 0.01000684716213734969 -0.001524081956684707195 -0.1032478323597157965 -0.04495992675169276087 -0.169252858691602226 -0.359135952685688542 -0.1926875180366742213 -0.3278010761522508476 +'MRO42-1706' -0.07318938945963861242 -0.1590908096926428317 -0.1672869050411737168 -0.01193371074095540656 -0.01972110418109116609 -0.1251373047666229921 0.2351644925913276563 0.3960703128377357496 0.006305162994235082724 0.09493145152750688542 -0.002161588196992130818 -0.3068127483431794533 0.005679218381249857839 -0.003308924782297256034 0.006955195658859420968 -0.01217595533807115486 -0.0195464019056528493 0.1224646378838539079 0.2411824486948452029 0.4069270253190029885 +'MRO43-1706' -0.04460931854263572305 0.02719773910218599433 -0.003728426641930664837 -0.07593844347411667084 0.2602400875255623247 -0.1422747006965756622 -0.2471334134969108975 -0.41506257810071151 0.002433305663614115238 0.1172890961571882301 -0.00804006039315415845 0.3231783102257934637 0.002124297435654079469 -0.0100204441153366481 -0.008774519017626986397 -0.077479931955302353 0.2579347127841938314 0.1392360154578551057 -0.2534576592099804238 -0.4264398889622277311 +'MRP11-1706' 0.09091342290745632604 -0.08509583464003678266 0.05410142364072195731 -0.02839194248750643787 -0.1405666560577371882 0.06987850919576898967 -0.09700962574462990151 0.1666413209526842465 0.04793745535868150498 -0.1130568192580671399 0.177015219918323391 -0.07949211126512761849 0.2933596063384565911 0.1127250224886619939 0.0349413940588477398 -0.02896827576878964125 -0.1393214258496036639 -0.06838605274808451373 -0.09949214197366111623 0.1712091384599333521 +'MRP12-1706' -0.07244204547305001241 -0.1090743396722866632 0.1292169644961305153 0.09739089495020634979 -0.03231249842259252547 -0.1466504663197842895 0.2089179425745801288 -0.1469124826604693845 -0.06647132220092623334 -0.001206703358727696795 -0.07039956611653661045 -0.07035579305218907231 -0.3234175762193998716 -0.05885811759713729246 -0.06836217779079099832 0.09936785070370793282 -0.03202625344626221227 0.1435183240269125027 0.2142642386662945986 -0.1509395115299805024 +'MRP13-1706' -0.06685284636917024348 0.01393180430551429344 -0.009030272210802998967 0.2153575925059789953 -0.2012203252896204719 -0.1704584524734704953 0.1825707165983682101 -0.1239009772266408682 -0.1031653192855565698 -0.1707604600172206166 -0.0008085777422766498614 -0.04861434372340728977 -0.2859462141145162062 0.02302053062172365605 -0.134654492496094097 0.2197291760280589423 -0.199437785713249216 0.1668178221940861961 0.1872427763390623612 -0.127297236027912819 +'MRP21-1706' -0.0321846866134685855 -0.1203327754998208265 -0.02494411870797171027 0.1052549201448559901 0.224935908466461415 -0.06439032125882331037 0.1582573289659364169 -0.09703511583425827869 0.09927980543914520506 0.2335898083980518236 -0.1815915229382112084 -0.03624206333944344355 -0.2421006006834806601 -0.1177582487392547922 0.01366474968060247056 0.1073915091973655367 0.2229432809403335269 0.06301508084174492486 0.1623071991154746985 -0.09969495253257348866 +'MRP22-1706' 0.001373885231302659354 0.05190617500167100939 0.006231894938661670935 -0.08424306106916294723 -0.1434806735565201108 0.1051964348668135429 -0.2204480265687690788 0.1038958784299011812 -0.02572005083577275433 -0.17458896117410308 0.1234028916148416644 0.09867831541313423771 0.2794316308720455888 0.08803075237259211372 0.004972999485524236783 -0.08595312651581904495 -0.1422096290996999746 -0.1029496625859317865 -0.226089382252951332 0.1067437759964230126 +'MRP31-1706' 0.03961518347503724391 0.04878567593913155087 0.06472177217925165205 -0.1266902054632001173 -0.2104101275326138165 0.1340896529867566522 -0.2499581906438838041 0.007149305199927877968 -0.100775157535556284 -0.2489673574284274604 0.08792403018124492209 0.1633858409578691495 0.2051967419307717533 0.08495421116759854785 -0.03005737017492284696 -0.1292619133290208999 -0.2085461787537994938 -0.1312257829719112312 -0.2563547235661547963 0.007345275330686571076 +'MRP32-1706' -0.05969335356130192616 0.04884364254600762068 0.06239727238831098421 0.1065206128061736562 0.001712781428890655221 -0.1203525303299126936 0.3166663456728607828 0.01914302189583558939 0.006865863683347846885 0.09497291959942964767 -0.04740770657389491854 -0.2349377722579154282 -0.2213264971115342927 -0.03752001214396780832 -0.009730552787549379828 0.1086828943876432807 0.001697608504991057407 0.1177820560603085737 0.3247699677236279836 0.01966775267723812337 +'MRP33-1706' -0.06236168639862664509 -0.02919609626726288321 -0.01653635510057613334 0.1995734623595420421 -0.2503735742719284674 -0.06969331434919955048 0.2994971187813960656 0.009959877265647461286 -0.04978464791958937818 -0.1302968380902898016 -0.003417567749370875943 -0.2236833875499582569 -0.2174361490145962361 0.01845991482130362668 -0.0487385055858143984 0.2036246409102642485 -0.2481556034761110696 0.06820481326985392001 0.3071613732532165186 0.01023288819405335573 +'MRP34-1706' 0.07451672209536142066 -0.01964245882179521674 -0.1057052840013412154 -0.3537795235039212782 0.385263812209249823 -0.0192444446037038433 -0.2179183359184919122 -0.03017081540125064743 0.06824896892857384989 0.2908878349744518643 -0.07068156199879936652 0.1699446742481623973 0.1612842353955718233 -0.1274869112653244929 0.03490003323420842046 -0.3609609593539532257 0.3818508965824700119 0.01883342416606915981 -0.2234949557783110219 -0.03099782984166633837 +'MRT11-1706' -0.08448217322366359527 0.005330033603299871511 -0.002513868483830547507 0.2970825306806210153 -0.1056530983298611115 0.2210735936133791657 0.01485774315382389077 0.04406581052119701997 -0.07826293556993635381 -0.2372353792300817554 0.2875401013398221073 -0.04377648865668318928 -0.009130838517003542903 0.3515318445110414691 0.2710547978388109791 0.3031130638079131967 -0.1047171549609784702 -0.2163519314886662437 0.01523795891306452439 0.04527370169500138236 +'MRT12-1706' -0.01826875387727217026 -0.01255893231891157258 0.04620318101849359149 0.3932227256378996727 -0.2264713585281721564 0.2811676860222742103 0.04312004367605091343 0.08728678655800681252 -0.0429147367907022001 -0.3112634655187738186 0.2353726864021187526 -0.09275144577236230092 -0.01068737625239260872 0.2693889665745742845 0.2193041172702692443 0.4012048263286764893 -0.2244651289939041949 -0.2751625417981919397 0.04422350333173622611 0.08967941108541550854 +'MRT13-1706' 0.06143658709263687123 -0.02429376303086969863 -0.1189003301768871146 -0.3886853350509835714 0.3494254567756627794 -0.290515730651019044 -0.1010536135958220727 -0.1552934388321740578 0.01229753380494272297 0.3459005945611928201 -0.1461099416469029688 0.173032970577711942 0.01989949574357055551 -0.1595660262461908174 -0.1325471050566982278 -0.3965753304127017098 0.3463300204433851226 0.2843109320605229362 -0.1036396171375145309 -0.159550198707835017 +'MRT14-1706' -0.0934989887112458451 0.02418591090685225098 -0.07546725985374881651 0.3395129292446765756 -0.3763745754767839347 0.2792411365015105007 0.1336135746180418249 0.1721410733107822388 0.005538095603431817358 -0.3343932713005484114 0.1059756921351160952 -0.1967164085420742281 -0.01106121796058463086 0.1103257244265740122 0.1062673592548190604 0.3464047648644394961 -0.3730404064490692728 -0.2732771392808077127 0.1370328009562747362 0.1768596449344968236 +'MRT15-1706' 0.06924189845566677826 -0.1207172340985713938 -0.05564500889705686903 -0.2219000834627985475 0.3618364358044361961 -0.1659958841817762709 -0.2244279148128164036 -0.2045623423771165683 0.001827107526805415386 0.2427992347298212616 -0.04551977761896566776 0.2672749549952029291 0.04563553260761370189 -0.05025887900664510743 -0.03214279317161550242 -0.2264044742164572077 0.3586310550057212887 0.1624505648770653843 -0.2301711174743449051 -0.2101696157922102459 +'MRT16-1706' -0.01144848411101582857 0.02243757269311213998 -0.04890303599169169152 -0.09077905863521555652 0.1840463484126602378 0.006589680063641904784 -0.301780045338034264 -0.216495837863997842 0.009508448440316865508 0.04223656775818457332 0.001287752289909258139 0.3163459238792002415 0.08063946759148558907 -0.004957641380678504822 0.005858728672343345607 -0.09262179950291264674 0.1824159470132986627 -0.006448938502146830606 -0.3095027208395517149 -0.2224302212017447156 +'MRT21-1706' 0.155748628331710659 -0.0267638123030705874 0.03852731274639387138 -0.1693394994845449086 0.03386935837351044004 -0.155725517569714339 -0.005131458567266230716 -0.01704573757168450013 0.08302785032164439194 0.1442048733039289765 -0.3490921117004178176 0.01273554114548543399 0.005175508193981940425 -0.3764298467609032972 -0.3463295461960160804 -0.1727769532421288556 0.03356932172641632905 0.1523995514688234743 -0.005262774702897696222 -0.01751297953819545145 +'MRT22-1706' 0.06279125836471208255 0.03876640877924443507 -0.08552350741298803127 -0.3388887099592233776 0.1449015924992736459 -0.2664522091135295701 -0.02166978958355749232 -0.05981434410406401281 0.06189547170882842009 0.261653031346809839 -0.3058614908554006528 0.05498959288208550567 0.007663555906850926663 -0.3236569477279402363 -0.290357388019215068 -0.3457678744364893753 0.1436179606249219365 0.2607613562022694786 -0.02222432841316276247 -0.06145391949041578705 +'MRT23-1706' -0.06201597286485143606 -0.01078243381468511897 0.081652924768020399 0.4086058485054042122 -0.3334910139132320483 0.3386312097769583751 0.08719325379927823916 0.1606512652001204911 -0.0245114083995646645 -0.3421008265966746231 0.1812531823087500105 -0.1523580383354619927 -0.01395603294111404796 0.183999285272995583 0.1712801867821796553 0.4169002140467635287 -0.3305367351652531704 -0.3313987668093654748 0.08942456503213008778 0.1650548888484903998 +'MRT24-1706' 0.005269852982638222744 -0.02048148614599409889 -0.05510692084162467641 -0.375595922231928725 0.3835455901131707424 -0.3292457244758767443 -0.1247889157694017787 -0.1880223463534416439 0.007076019971924291281 0.3403806789666197763 -0.1469490950926675976 0.184829122919536154 0.01345520678294684011 -0.1381895991579571159 -0.1376085915729550468 -0.3832202131867226136 0.3801478956072335547 0.3222137355278880677 -0.1279823154575548683 -0.193176240720800696 +'MRT25-1706' -0.06844079662230366512 0.06180557438681325011 0.01365980696304658348 0.2828372625993176293 -0.4038339099889616812 0.2823294657081341641 0.1891373649000410717 0.2392063259700661637 0.006722746203060924776 -0.300447124196000559 0.08157507865480070897 -0.2424441340951825619 -0.01499618368305141725 0.07239940577769447827 0.07963964750366377132 0.2885786284003633573 -0.4002564884446917493 -0.2762995083390245576 0.1939774678720549983 0.2457632281679372754 +'MRT26-1706' 0.02532067772175256373 -0.003782853576499475845 -0.001720949951281622314 0.1050888806572391476 -0.2816581855451608662 0.1292270460145213962 0.2446569367688023744 0.3044522565771751177 -0.00191761557639429309 -0.1446153014900228018 0.01474395691265615281 -0.311689257249497087 -0.01575529219852555424 0.01580749954448290931 0.01140360900008644332 0.1072220992435411746 -0.2791630754611246212 -0.1264670309503868884 0.2509178084236673434 0.3127976197785962142 +'MRT31-1706' 0.05976398660378959282 0.01687755761853252517 -0.0510291337793060823 -0.3086746709116662268 0.1125647708475518705 -0.2863311199505572668 -0.01368354888154532482 -0.05950058235337607471 0.06910680008013324327 0.2454203904794841351 -0.3439740680879053158 0.04747178602789680485 0.0049284476555383986 -0.3316876876261776186 -0.3343655254630220064 -0.3149405150332447723 0.111567599420400454 0.2802156957513127211 -0.01403371652633760708 -0.06113155719329852605 +'MRT32-1706' 0.07643614064726578228 -0.01464124375973278186 -0.1569458681881034656 -0.3964372002504353842 0.2342102872439691119 -0.3521369471898071479 -0.04624278513140918367 -0.1152329175635172787 0.03863912532424536306 0.3140767989100335389 -0.2791678693348662588 0.0981529599903037675 0.01171531186390875091 -0.2582227365812956865 -0.2670245992220527942 -0.404484552154716015 0.2321355012818414887 0.3446160503740351433 -0.04742615702551918055 -0.1183915755437158768 +'MRT33-1706' 0.03709670006858418329 0.05456972555440108008 0.1239836536421827645 0.4080911873358347708 -0.3789762305181581525 0.3934450162942331741 0.1115701114680978517 0.2083989110951881552 -0.01772536798665411487 -0.3520856768378927137 0.1918939750879667394 -0.1778581730629515412 -0.01473363111280816783 0.165486470792466589 0.17959808617072201 0.4163751056751141544 -0.375619014350108027 -0.3850418669120306281 0.1144252365164459828 0.2141113489776419465 +'MRT34-1706' 0.00283946414248180401 0.02351879575908732978 -0.2249981390990651309 -0.3397475311866878789 0.415745055615732384 -0.3585738196145702439 -0.1610164625333277144 -0.252088181049104243 -0.002809727236749775744 0.3303191632080401119 -0.1387378769354527253 0.2247596873891006819 0.01270443054485766513 -0.1094406023159156249 -0.1273232583952539909 -0.3466441290345758097 0.4120621174520598951 0.3509154448837162321 -0.1651369400458626568 -0.258998188724173295 +'MRT35-1706' 0.001388028708025478009 -0.005254980931497649221 0.06202308809091870712 0.1793780557049627633 -0.3587292706962945665 0.2494593852504861653 0.2228105507443027544 0.3269661932461752074 0.005131026113919879075 -0.230699748903987728 0.0462183602234476007 -0.2877541982900571615 -0.008131601578235942221 0.03371846888625342625 0.04449635292021266592 0.1830192839682326933 -0.355551415172512042 -0.2441314629430789973 0.2285123643939933891 0.3359286876218201545 +'MRT41-1706' -0.1854172948840371871 -0.01378932618833311752 0.05038116377072511531 0.3444910106824735641 -0.1493508287430190262 0.3315741882651958017 0.02382002289817803514 0.07862309522611271584 -0.04564831431687182278 -0.2642111881338651824 0.3502138905368340493 -0.05845392967163402093 -0.005943530913353980809 0.2981764179373116441 0.3495903171844591539 0.3514838972962219255 -0.1480277826609937286 -0.3244924682792162396 0.02442958708283209102 0.08077823867309683048 +'MRT42-1706' 0.004685209749061006873 0.0270107464450301607 0.1064786175451871431 0.405564569849272305 -0.3238440919547319607 0.414733165560908057 0.08256969496974458922 0.1896153179315436255 -0.02913211360075013828 -0.3334128690584848842 0.2277452671871685597 -0.1448190609690093444 -0.01183572498502765032 0.1890980488950824434 0.217343017245908432 0.4137971999138161383 -0.320975271870814316 -0.4058753465528367466 0.08468268743018497746 0.1948128773600135144 +'MRT43-1706' 0.06428756437833564596 -0.06615687200426181858 -0.09109689871753426371 -0.3701089625246422599 0.3802544157392230284 -0.4061641501277884481 -0.1297730590036710596 -0.2368310715350214479 0.005476788674316687353 0.3297426546219510701 -0.1757437995950493492 0.1851275828213302388 0.01440685151634308464 -0.1350429327878975572 -0.1711112029019075664 -0.3776218726715269147 0.3768858765811160527 0.3974893470781378224 -0.1330940049674840253 -0.2433228654588431294 +'MRT44-1706' -0.01523688774367132348 -0.08891689057968117649 0.04841002088626875782 0.2406435970187885964 -0.3896858672821779668 0.3442578621406999773 0.1862269920188888706 0.3260221425503641579 0.004737099873146293806 -0.2792810289515386124 0.08044012008840235872 -0.2510935518153261659 5.648181728558354653e-05 0.05345759104423266489 0.08118235994736561212 0.2455284658138934539 -0.3862337782360873439 -0.3369052458366149638 0.1909926173516527659 0.3349587594829391279 +'MZC01-1706' 0.04204025588050766538 0.09973611267435579519 0.02751996430813627784 -0.02391931916997655852 0.1417986173777720793 0.07046624507028984019 -0.01114579712558720105 -0.1187209928182630519 -0.1524031334710047869 0.0242711122943844379 -0.07478573253701592538 0.292488297364044858 0.1098190239519626077 -0.1406678154557412797 -0.1787756247308593116 -0.02440486184495763156 0.1405424736607455705 -0.06896123583340652008 -0.0114310226590058836 -0.1219752626858623124 +'MZC02-1706' -0.03607334764599564453 0.008660565657927537381 -0.08199383785160102578 0.0329860961456469523 -0.1319213007654680969 0.002158133791314099763 0.03143593947386275761 0.1017413749458724176 0.1808832834405825762 -0.001855346596270791328 0.1207378287763004043 -0.3097376284771757859 0.01094083326236182027 0.128203204180871666 0.09798964025104563158 0.03365568700004902686 -0.1307526566971197735 -0.002112040640088035885 0.03224039809659923206 0.10453021525890209 +'MZF01-1706' 0.08590626839178756857 -0.01441090509424085286 0.06102063561358359728 0.4241320184700321239 0.3634629310188698392 0.3227551601388116698 0.09622372620780363095 -0.1536188736744157901 0.02391844281582552675 -0.3356654992592253972 -0.1708291472305303871 0.1567508161884614282 -0.01246809356519270641 -0.1848060935747454225 -0.1621384487923093476 0.4327415526014029568 0.3602431416752608917 -0.3158617958510432366 0.0986861309443969742 -0.157829731921351718 +'MZF02-1706' 0.09091109253604076623 -0.1927384347315918567 -0.1619876378899409719 0.3995099705574585713 0.3205411093931799793 -0.1085954633461616997 0.1572927879771929272 0.06087473096350234231 0.1412249934014974395 -0.2666872331735322121 -0.03650186088532945267 0.05176850050408973031 -0.1913419291705447112 -0.1935688156523877324 0.1659936880197643294 0.4076196971933890301 0.3177015492616429015 0.1062760950407188459 0.1613179751260523376 0.06254337269206330929 +'MZF03-1706' 0.1013126457081718335 0.1451283779715137057 0.06648925893965323963 -0.08476145778963735389 0.05880682163312014876 0.1821951059880053125 -0.02572129604377287881 -0.1590329724559112479 -0.1318265732416555869 0.08204214584699960622 -0.07162315054781388801 0.2094715310002542574 0.1927791920019187033 -0.08276685631835581369 -0.2684877993627400317 -0.08648204626701068432 0.05828587283348588 -0.178303805732778653 -0.0263795145903372337 -0.1633922369628234006 +'MZO01-1706' -0.005308725741457413078 0.07783520895170410736 0.07396499431747347031 -0.1322184213759801108 -0.2240929329331750042 0.3304941606069153881 -0.1162130444180013294 -0.1569902555624272666 -0.2003804821685873649 -0.348283595764672993 -0.1475557273861506091 0.1657619163477621615 0.02142630600776433691 0.03896733021231457011 -0.1734157207390877309 -0.134902347517040555 -0.2221077730286595275 -0.3234355077163966752 -0.1191869840304710104 -0.1612935270063039495 +'MZO02-1706' -0.02658155735603297612 -0.06707571527719961846 -0.1683905967408728943 0.1261991479225860746 0.2127925096954688677 -0.4211122313449436882 0.1012264488089415077 0.1966053177788535389 0.1942740074706133802 0.3398634522670653801 0.2108940663187433839 -0.1554142098042013975 -0.005942282051400559276 -0.03008190739925795804 0.2235332349426182585 0.1287608877207480351 0.210907456237068941 0.4121181690487834004 0.1038168752748358376 0.2019944806073426247 +'MZP01-1706' 0.04017854860732768263 -0.06762024079843045876 0.06576559996076289383 0.0435609739308873839 0.1791420077131553323 -0.01508717018906922773 0.06297567838672223084 -0.1336379212849230502 0.009000035625792287761 0.1523863514908494199 -0.259132967100815681 0.117638510210997721 -0.2345061145769041511 -0.1244779544471104477 -0.02167437933398821265 0.04444522618141683729 0.1775550521306131224 0.01476494029771726994 0.06458725190253843118 -0.1373010801760541078 +'MZP02-1706' 0.01113696669382539112 0.08490576745599756614 0.0002751195819735569037 -0.16714673477936276 -0.274570363993646982 0.1076932575458072056 -0.1680748259937583367 0.03143321464885555361 -0.2154572990851696956 -0.2916368649096758303 0.12624924793755124 0.08224191488986806742 0.1806151731626295665 0.1339468366791077003 -0.05862429606164578505 -0.1705396772014445284 -0.272138042409766856 -0.1053931584388543147 -0.1723759299307992821 0.03229483280791303063 +}; +coef(end).label = temp(:,1); +coef(end).value = cell2mat(temp(:,2:end)); + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +coef(end+1).name = 'G2OI'; +coef(end).reference = {'P11-1706', 'P12-1706', 'P13-1706', 'P22-1706', 'P23-1706'}; +temp = { +'MLC11-1706' 0.2882758246354492626 -0.03120999774279694522 -0.1054929283772120807 -0.2717653434718079186 -0.1721714336864499373 +'MLC12-1706' 0.2707115714046856025 0.002556669069641236483 0.00532606715271141673 -0.2118278906254209282 -0.2543955638270479769 +'MLC13-1706' 0.1451419226914006655 0.1144647065373022299 0.1200584513961427402 -0.02608330423637332876 -0.3099282303472095657 +'MLC14-1706' 0.02297076671314541435 -0.258266292113235707 -0.1756697927087090549 -0.07532023803989948418 0.217374120317144176 +'MLC15-1706' -0.1490165849442950108 0.3200698826228612348 0.1134730579149910434 0.1174294116552293543 -0.1023067954490225889 +'MLC21-1706' -0.2939459996674608222 0.007740420184267527044 0.02548910979135213598 0.2679113682477302638 0.1750479156274055703 +'MLC22-1706' 0.2477248366198913088 0.04435263213132555754 0.08169014209414329764 -0.1837107949230099013 -0.270008064801653902 +'MLC23-1706' -0.1264284317559201121 -0.1443622213124367559 -0.1959776700662004267 0.08823032725680611532 0.2571663009859624371 +'MLC24-1706' 0.04197965668630763286 -0.2540058346419358237 -0.2169455027664035085 -0.02352252380137997631 0.2007298166134338646 +'MLC31-1706' -0.2770222792240450982 -0.02816859258104389627 -0.0804682834726284657 0.2491618235131626835 0.1936094136902788143 +'MLC32-1706' -0.1596946199654126763 -0.1101175402019794053 -0.2363698624596247411 0.1754218964993517482 0.2012837385526677625 +'MLC33-1706' 0.1709504486010900992 0.01840543196989581631 0.2825666388593609524 -0.2461674043874238216 -0.03167648659483182638 +'MLC41-1706' 0.3092969582147505059 -0.005015433824104452779 -0.02945142491651119715 -0.3000665835747561294 -0.1033281034840016072 +'MLC42-1706' 0.2929364326540206953 0.01312174951724293104 0.1187006751311367181 -0.299092458347635648 -0.06580511760359740447 +'MLC43-1706' 0.2380185347009860786 -0.04172518187747005503 0.2011510500396395396 -0.2613833180249839905 0.1111197476859226707 +'MLF11-1706' -0.0653212325808427835 -0.2735619830659467566 -0.01025223449824854381 0.2526869886170121648 -0.020144837230313236 +'MLF12-1706' -0.009113275019503310967 -0.1164022572345058404 -0.004974738420955654265 0.3089160198733825191 -0.02809736129861412079 +'MLF21-1706' 0.09239021496591647009 0.3122958158447293742 0.06150928991830794529 -0.2047919666336068256 0.08941774473149002866 +'MLF22-1706' 0.01985237319200582398 0.1877772868271440077 0.02910331337218240513 -0.2792836678639408765 0.09438729015165442382 +'MLF23-1706' -0.001751182885548752165 0.05921801322000715129 0.002587505319376641813 0.3215048164518695128 -0.02989991938723269432 +'MLF31-1706' 0.0201767018301880971 -0.2077977888862391487 -0.1106719877716045575 0.1473312268916143197 -0.2402183497190712169 +'MLF32-1706' -0.04144600962507432457 0.04462630315221136068 0.0168058333577182778 -0.2368072568641025055 0.2236569539676231122 +'MLF33-1706' 0.01867234286082305669 -0.1979617281201427326 -0.04040957588002060813 -0.2659863553008675052 0.1207557861832349727 +'MLF34-1706' -0.04888544195959795141 0.2479072499064756963 0.01582246065609179894 0.2714256504442650875 -0.03695801831738865229 +'MLF41-1706' 0.1120229228313913972 -0.1581394049012047887 -0.2017474727665534984 -0.0727704840724649471 -0.2605534334953005238 +'MLF42-1706' -0.1332659834567252732 0.08594136762138628038 0.07475533610891614555 -0.03185955837584739103 0.3211450999577711851 +'MLF43-1706' 0.0556908724160892557 0.1402574910259281327 0.0760581144898714312 0.1592212392059628445 -0.2686722654885064787 +'MLF44-1706' 0.007955074663295390314 0.2052817685187591501 0.08763306136186609085 0.1917042781632272708 -0.2163891613977388106 +'MLF45-1706' -0.10857089237927392 0.3276269581147815968 0.0742547100966179513 0.1882389165924465146 -0.09593709909227673971 +'MLF51-1706' -0.2311641711304221747 0.06326781060489868047 0.1102874456449588758 0.1681849132640110822 0.2731198417089248376 +'MLF52-1706' -0.1959762162296030952 -0.0435567223805512771 -0.05392624319712389924 0.07850671350398787107 0.3154077620128406534 +'MLO11-1706' 0.188040483148237042 0.3204383247987012684 -0.1088987423746517191 -0.09877820864597226802 -0.08145627098427889179 +'MLO12-1706' -0.2677562350111690748 -0.2024945157288647601 0.1324892651189990278 0.0173346636823901723 0.04478467684938867294 +'MLO21-1706' -0.2567443063286396487 -0.2791827929041414413 0.0236819846256173562 0.06679491816959798323 0.01212881403351893407 +'MLO22-1706' 0.3187958652859171904 0.08032764991436761037 -0.02206570290726060993 -0.004126298369180464443 -0.002621017642216875391 +'MLO31-1706' -0.2070455860673502957 -0.3240599933700139546 0.01612034334958025589 0.1122357733597204726 0.01189052252659221487 +'MLO32-1706' 0.2945227928691284136 0.1925948181501072609 -0.01784666341710804127 -0.02770024787398775099 -0.005502997760545315017 +'MLO33-1706' 0.33123839191812815 -0.0232177786240188172 -0.01749512453759982655 -0.0001398901227021657199 0.0005783700591417944691 +'MLO41-1706' 0.2488297132318827709 0.2685303411983450128 -0.01691329256931119879 -0.06404411479800468932 -0.008604723072321249569 +'MLO42-1706' 0.315179958629739132 0.09321640608876378964 -0.01621437749271109272 -0.005922024598868695644 -0.002261818546464018208 +'MLO43-1706' -0.3064678256674615575 0.128661805661052786 0.01904556413948683274 0.0117072903063823279 -0.003770121458569130127 +'MLP11-1706' 0.07409718857426442207 -0.1145009382414202692 0.2948034262586526899 -0.1595715105173279302 0.1417686534780706609 +'MLP12-1706' -0.05533120166471061641 0.001445878194115893765 0.326275987728952499 -0.1342072209955394724 -0.001170311024293257561 +'MLP13-1706' -0.03400580237496988317 0.1681031817683860397 0.2888211829190402424 -0.08588902376493311175 -0.1433602685633046936 +'MLP21-1706' 0.02891586574946547819 0.2221234152493576086 -0.2490117769257594871 0.02841232236650191936 -0.1897393948560113786 +'MLP22-1706' -0.09074733769460201216 -0.1658980556432302356 0.2850203534834693797 -0.06944912682898449208 0.1159293529040759246 +'MLP31-1706' 0.1617014658541526817 0.2495954579377616112 -0.2147949753743080004 -0.01299138058915705676 -0.1183769167205985379 +'MLP32-1706' 0.2328450886003847198 0.09441878883438181713 -0.2243519347893738469 0.03647010210456870516 -0.03613053527368102064 +'MLP33-1706' -0.2227662276745906722 0.1286275650546016558 0.2298728808384410682 -0.0333288994312119502 -0.05169199561518745406 +'MLP34-1706' -0.1715450793661448814 0.2893093848180111061 0.148430531689724865 0.06713024264392333795 -0.1021882656228587372 +'MLT11-1706' -0.03950391512582699521 0.2223488722060107114 0.008611991530144004481 0.2745201917026739435 -0.02262069580646115102 +'MLT12-1706' -0.08948634643692650326 0.3062504395727334572 0.01179956657469517778 0.2315433758472659476 -0.0189791755608124009 +'MLT13-1706' -0.1735792143005089327 0.3451945807914174602 0.02144806843397334753 0.151345012910839738 -0.02005695760150492599 +'MLT14-1706' 0.1936338582874379544 -0.3273975321723666676 -0.01698438558071153903 -0.1224176624183875295 0.01352823502386997501 +'MLT15-1706' 0.2654214142353523709 -0.2432025609773219021 -0.04752881349927528393 -0.04711279333707184269 0.0203971923338452793 +'MLT16-1706' -0.316138268520930632 0.04750628991843062338 0.08924556488330348536 -0.00437391060919731841 -0.006212226955779655453 +'MLT21-1706' -0.01373229354245368225 0.1392472333064813106 0.00536373590988593104 0.3024935248571345991 -0.02478861110195732659 +'MLT22-1706' 0.05376274425761890657 -0.2552972057567962638 -0.01072863969528590859 -0.2663252863892679456 0.02381764726141846755 +'MLT23-1706' -0.1501734759342365499 0.3453946997867533564 0.02247798273796644541 0.1747681729769871017 -0.02426907264751922491 +'MLT24-1706' 0.1828304180809965929 -0.3359169521261648472 -0.01802964520583870411 -0.1363921888619753497 0.01559755442196450806 +'MLT25-1706' 0.2382682952782238794 -0.2934327202072343765 -0.01827096728895463706 -0.07984660874488416771 0.01060449495459777312 +'MLT26-1706' 0.308454512523014035 -0.1486619637226493096 -0.02213062658403951513 -0.0155201903306658711 0.005027649793544570686 +'MLT31-1706' 0.04551183456170396907 -0.2342756726072209861 -0.008178595482797779495 -0.2655566310817074061 0.01971694201508631186 +'MLT32-1706' -0.09243689882928650403 0.3053299196854436515 0.01216393342110120949 0.2227861278406501888 -0.01888411568809355429 +'MLT33-1706' 0.1765551656062118446 -0.3532853830266671213 -0.01446514738924366793 -0.1565397098266445852 0.01363852840618042656 +'MLT34-1706' 0.2139263630818607487 -0.3303679088139176989 -0.01544049635173570453 -0.1129543933409746376 0.01123960168364337465 +'MLT35-1706' 0.2891640624776887214 -0.2344472189545973861 -0.0186863716695061452 -0.04190466050340616727 0.007143149121790612864 +'MLT41-1706' 0.05613626424617368382 -0.2547510963067269318 -0.008532354001643182792 -0.2551553964542446762 0.01817368236061459377 +'MLT42-1706' -0.1418537546936807225 0.3360626631820053389 0.01298100207607117557 0.1762653239482036283 -0.01448485064730739569 +'MLT43-1706' 0.1777181766462496426 -0.3248761645591489167 -0.01503696086576308821 -0.1314292718158479589 0.01295087025989425343 +'MLT44-1706' -0.2382114437009178187 0.2828848830097625555 0.01737743484274609576 0.07424539005954737536 -0.00972696164839428716 +'MRC11-1706' 0.2690966272697508654 -0.03420070890509311484 -0.1741191208968008997 -0.2819736177038322245 -0.1130251679918460456 +'MRC12-1706' 0.2133678258301035802 -0.002887697478237460751 -0.2411035011349615398 -0.2646224466039233114 -0.006237398518784461471 +'MRC13-1706' 0.01971951050431900582 0.1181499308935818199 -0.3073150357727655324 -0.1382964508755176458 0.1212237092265487509 +'MRC14-1706' 0.07895830497971247086 -0.2610847331555283812 0.2170236341866025875 -0.02514173518480369504 -0.1746442564861342694 +'MRC15-1706' 0.1201571272919262634 -0.3262080053496420051 0.1032604981649825338 -0.1520414824112646113 -0.1146235957327424032 +'MRC21-1706' 0.2759113263172232045 -0.005405008568720096399 -0.1774252909518069243 -0.2992853162801875078 -0.01795604698726411749 +'MRC22-1706' 0.1858090498041023164 0.04510170942281802736 -0.2663488615075146337 -0.2453091385220129705 0.08396909421387847849 +'MRC23-1706' 0.09308424905259089777 0.1441351570512157121 -0.2575391990423077093 -0.1280129163411886095 0.1986104105891146332 +'MRC24-1706' 0.02187582370436531518 -0.2503687890967836727 0.195526407500792393 -0.04424234848579100543 -0.2147861470229526781 +'MRC31-1706' 0.2501118354072580652 0.02851724921224238138 -0.1906696193935734085 -0.2740056378769517575 0.08234765429483695276 +'MRC32-1706' 0.1801766832188144152 0.1076426705923665406 -0.1937614253997617386 -0.1570676463715844073 0.2404520703191420639 +'MRC33-1706' -0.2418711014848120844 -0.01937036393100139905 0.03271281352133925679 0.1631644674327529243 -0.2815794914457797615 +'MRC41-1706' 0.298414406084870909 -0.005808284948225599098 -0.1075088415339297693 -0.3050428955851984258 -0.03251707854280969784 +'MRC42-1706' -0.3019162954950597721 -0.0150937896165679649 0.07242118132738999126 0.292196514100403093 -0.1248581198776768791 +'MRC43-1706' -0.2617936158721271833 0.04184651262947680639 -0.1100198732120620804 0.2347470699234750491 -0.202886995201335546 +'MRF11-1706' 0.25102572866124645 0.2711331029081969213 0.01781468002146481544 -0.06468943111857271278 0.009070192571966010503 +'MRF12-1706' 0.3082383890721727693 0.1065996856314965074 0.0279936146303054155 -0.007566777779953144829 0.004560029759003688191 +'MRF21-1706' -0.1996873630900226348 -0.3046841333305525534 -0.09006890012770327192 0.08936647206025714885 -0.06195660821367301313 +'MRF22-1706' 0.2787793278732061952 0.1864871505715646749 0.09477396545008080764 -0.01946339661596619905 0.02913083089301551909 +'MRF23-1706' -0.3196962319866564206 0.05977931950319602394 -0.0265274988882367134 0.001952561942505099367 0.00233717465142020079 +'MRF31-1706' -0.1541717564570690979 -0.2075811142308803536 -0.2385042638051590169 -0.01872543504763774305 -0.1075335400377467332 +'MRF32-1706' 0.2365242339435248975 0.04069293930925910185 0.2183296177913348068 0.03981860515693522867 0.01508933335264873651 +'MRF33-1706' -0.2701382869909204065 0.2010134035111192929 -0.1184859183491530077 0.01988792064427201758 0.03984139471017113243 +'MRF34-1706' 0.277206234547004271 -0.251757135213100891 0.03579044121206432366 -0.04949802068967154578 -0.01527957803454208473 +'MRF41-1706' 0.06972356545337310418 -0.1570556779483562593 -0.2644119196520327564 -0.1133630047160334997 -0.1968371824439046069 +'MRF42-1706' -0.03815776628745096155 -0.07869509603263664943 -0.3207359241581183018 -0.1310891975871425197 -0.06702869328867649967 +'MRF43-1706' 0.1554953745709938828 -0.1402788213248585825 0.2728760518895503862 0.05796743358818410435 -0.07764922024070908257 +'MRF44-1706' -0.1891799642161861583 0.2030237471847192166 -0.2166067335230297819 -0.008839932107464349917 0.0876005084145633911 +'MRF45-1706' -0.1824240138889976492 0.3223061630363367458 -0.09410243191841580201 0.1083344043824291947 0.07399094072273164346 +'MRF51-1706' -0.1751776341806619286 0.06023851728731902111 0.2640233128343442703 0.2310622827687529302 0.1089928119661103117 +'MRF52-1706' 0.07164052372835255644 0.04970899560140586149 -0.3172626690705966923 -0.1902193112258701579 0.06001124722854464522 +'MRO11-1706' -0.1005671589023337253 -0.3184481836135348298 0.08215085066904470601 0.1822640209356397312 0.1075989749624769037 +'MRO12-1706' -0.01822304838708951533 -0.2043027395691204284 0.04487306914637103489 0.266774666951497097 0.1312926445156141209 +'MRO21-1706' 0.06577730604637746503 0.2752836806532742431 -0.01016876665559485887 -0.2541586930458559213 -0.01997064522979013004 +'MRO22-1706' -0.004893496022736055877 -0.0866546221016496615 0.002699715000534955861 0.3187184292095230354 0.02111289553308321604 +'MRO31-1706' 0.1195503184311552947 0.325986138347081289 -0.01156863996579928985 -0.1967981106213541331 -0.01485436431130437301 +'MRO32-1706' -0.03052190796262438735 -0.1976693397106427663 0.005167784966038890294 0.2823037885580250705 0.01568778171216827014 +'MRO33-1706' -8.079764946757514422e-05 -0.01336587985263110352 0.0003294383584753273701 -0.314006684307413908 -0.01644976023889444319 +'MRO41-1706' -0.07384492280286379662 -0.2863450522051803615 0.00804374953325440005 0.245806252801942321 0.01467881660550873942 +'MRO42-1706' 0.007553845574269186895 0.1033374251872434119 -0.002861038265026958922 -0.3036912924450048124 -0.01787380603422548259 +'MRO43-1706' -0.008884695967864262439 0.1143356893380604589 -0.002834788868179920294 0.3190705992750625386 0.01681408124898283937 +'MRP11-1706' 0.1636529644916352444 -0.1123118378097654191 0.141431568998499485 -0.07823527060214552353 0.2940222386631903273 +'MRP12-1706' -0.1344524497036454491 0.0018035190138875883 -0.001446774556747544831 -0.05880217978628444336 -0.3280915268834389553 +'MRP13-1706' -0.08407671474045583238 -0.1697742884644727057 0.1393912721874492333 -0.04556171358429891849 -0.2917272309729673219 +'MRP21-1706' -0.02402554041685992306 0.2304836081772463074 -0.1970541573577784256 -0.0291331444751189092 -0.2507370675528401982 +'MRP22-1706' 0.06804523203505868922 -0.1727238249174085916 0.1210981651810198456 0.09023369860717134205 0.2862600468267264553 +'MRP31-1706' -0.0124288852830982139 -0.2476026524321700562 0.1185423690638573307 0.1583258156037012365 0.2139307892448033266 +'MRP32-1706' -0.03671879484985802328 0.09567060089618774354 -0.03684938766839854218 -0.2302702342721110185 -0.2243057126641644639 +'MRP33-1706' -0.03283321225777938862 -0.1271266615553836299 0.05069962887499877141 -0.2219143248827675496 -0.2269423320523189236 +'MRP34-1706' -0.05807352504376002422 0.2873295648216210862 -0.1108917410117932212 0.1696495810992718067 0.1657119735469045063 +'MRT11-1706' 0.2784649242756098708 -0.2367940784368867124 0.02437523846682844442 -0.04414855025894403456 -0.009764492725799666512 +'MRT12-1706' 0.2311267612627858348 -0.3095602837305387878 0.0189674781959776502 -0.09160403874322066431 -0.01197020785157400409 +'MRT13-1706' -0.1477685147366601393 0.3412446774503195002 -0.01754140179891962303 0.1740133991651602874 0.01905376317115334284 +'MRT14-1706' 0.1195685582727329943 -0.3297996325490215042 0.01330056652603126693 -0.2011739297334531607 -0.01726290882101528049 +'MRT15-1706' -0.04593648998548987422 0.2413118683090362537 -0.01930341272777367362 0.2687328730280011402 0.04597751964976206501 +'MRT16-1706' 0.004475184478593583273 0.04026951520908507443 -0.005135458558074823196 0.3122573498599781061 0.08609269632732095834 +'MRT21-1706' -0.2979898783734901135 0.1439004855539918193 -0.01775737532988330356 0.01517383133724756021 0.004043605197747838532 +'MRT22-1706' -0.2661319616205501948 0.2566436408767915345 -0.02052028221081921358 0.05453519215382589963 0.009326016542110255464 +'MRT23-1706' 0.1616830465609692125 -0.335493155927043929 0.01774256636529579143 -0.1537714355642708919 -0.01732529806686393392 +'MRT24-1706' -0.1351993507670538053 0.3368658695943041459 -0.01452636730990351094 0.1856113116134285312 0.01703476785224634568 +'MRT25-1706' 0.07874111593583162094 -0.2955134698020839834 0.01187235652530052761 -0.2446673193495453591 -0.02091472215848995397 +'MRT26-1706' 0.01414206746639621107 -0.1421536790300834963 0.004746650830635270463 -0.3089435259932729605 -0.02193766761872376417 +'MRT31-1706' -0.2681039327266906969 0.2428181212324489191 -0.01688359986468553758 0.04856388096721252212 0.007209894006635116613 +'MRT32-1706' -0.2189353503320036753 0.3100210419010489549 -0.01719033450530795329 0.09707782229058130319 0.01147139082660934145 +'MRT33-1706' 0.1526067775490485279 -0.3501976804696779189 0.01418329196903104009 -0.177878232995817176 -0.01532905570521735095 +'MRT34-1706' -0.1076210753115257046 0.3233437238561964744 -0.01166089561883905563 0.2149506220699262948 0.01648828468929573743 +'MRT35-1706' 0.03952917498144791625 -0.2257756384973783337 0.006517990512011123151 -0.2844248597018838032 -0.01745638284769740131 +'MRT41-1706' 0.249519269584947051 -0.2600671751594011427 0.01627363702258671774 -0.05991343367436408746 -0.007996904994250479681 +'MRT42-1706' 0.1647009743847969443 -0.3294007709211726476 0.01464941567343870654 -0.1457941983477845371 -0.01380140457132374848 +'MRT43-1706' -0.1276092416581545153 0.3258644619749146987 -0.01423721443306406875 0.1839670022425759222 0.01710735668576828655 +'MRT44-1706' 0.06421548015713664237 -0.2688995707705105209 0.008068710371388123151 -0.2490094177243531437 -0.01588587950451505679 +'MZC01-1706' -0.2967596404124023257 0.02001082669780943762 0.10636961324527755 0.2941154377800699882 0.1125678135158421633 +'MZC02-1706' 0.3134699820933341541 -0.0003775164637455381681 0.02444472186528674068 -0.3122185721876272191 0.00949022300987163378 +'MZF01-1706' -0.1625806153583159719 -0.3392282875688631405 -0.01251892450806297609 0.1568188688576882539 -0.01231037757463507819 +'MZF02-1706' -0.04713288292349182562 -0.2608602793145025633 -0.2011839686279725259 0.04325673744016556022 -0.1979513651183880396 +'MZF03-1706' -0.2159046698706476586 0.07703254794835286134 0.194698541218714688 0.2144567561892637697 0.1952843497189999944 +'MZO01-1706' -0.1594711784599919802 -0.3442769741360834357 0.02594992692061309086 0.1631011801756426238 0.02627338333863271647 +'MZO02-1706' 0.1634084852976976643 0.3383229901496460634 -0.01370307753403180243 -0.1551049378954044433 -0.01336722097785999694 +'MZP01-1706' -0.1212316631637880143 0.1501663046130006784 -0.2394950979633920229 0.1220114500346160119 -0.2367774399422623577 +'MZP02-1706' -0.07424190874691369291 -0.2890710184374202241 0.1869301645091102082 0.07482911456239958736 0.1873395142419100046 +}; +coef(end).label = temp(:,1); +coef(end).value = cell2mat(temp(:,2:end)); + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +coef(end+1).name = 'G3OI'; +coef(end).reference = {'G11-1706', 'G12-1706', 'G13-1706', 'G22-1706', 'G23-1706', 'P11-1706', 'P12-1706', 'P13-1706', 'P22-1706', 'P23-1706', 'Q11-1706', 'Q13-1706', 'R11-1706', 'R12-1706', 'R13-1706', 'R22-1706', 'R23-1706'}; +temp = { +'MLC11-1706' .01260050981901611987 -0.1278459799016925802 -0.1273419567487086013 -0.001923917025805598575 0.1587476838819164571 0.1436449445971240968 -0.03120999774279694522 0.0885395806894111459 -0.2717653434718079186 -0.1721714336864499373 0.1407632721782391405 0.1944662709505341758 0.01285628989369859247 -0.1267134376571318888 0.1246222031850210132 -0.001973150853925342233 0.1630991283227401223 +'MLC12-1706' .01055826230456967038 -0.11322357173668679 -0.1282203404228567101 0.03212822970716164295 0.1829662612023769952 0.1297597069912169443 0.002556669069641236483 0.1257031869077913644 -0.2118278906254209282 -0.2543955638270479769 0.1371826379622788916 0.1206462241773023497 0.01077258641998794786 -0.1122205642258487651 0.1254818264506671333 0.03295040432175121853 0.1879815628477200518 +'MLC13-1706' .05921228577804626969 -0.1286519791350161368 -0.1007485269384171822 0.1495548896960138818 0.1622167906772100932 0.03284560202762086545 0.1144647065373022299 0.163254184545968295 -0.02608330423637332876 -0.3099282303472095657 0.1092933787447173954 0.0432922977032507289 0.060414246896760046 -0.1275122968287849823 0.09859675251800555096 0.1533820608447684086 0.1666633270595970495 +'MLC14-1706' 0.1119402956200304944 0.2206365821810303274 0.1086716672526212291 -0.1689384254721353062 -0.05078101078293766751 0.1330209732947825185 -0.258266292113235707 -0.1359838144337361943 -0.07532023803989948418 0.217374120317144176 -0.1071073285194525798 0.03977469673140165973 -0.114212592343331254 0.2186820408633632085 -0.1063506713936881454 -0.1732616292750812637 -0.05217297280510605623 +'MLC15-1706' .136498338519072504 -0.2180032216898858122 -0.196098622699952152 0.1244876814808927451 -0.05086439510188196095 -0.2381035631101456884 0.3200698826228612348 -0.007569655402967806479 0.1174294116552293543 -0.1023067954490225889 0.08670468264988440144 -0.1213133056821717043 0.1392691434882295243 -0.21607200837990162 0.1919103728760948591 0.1276733724596860187 -0.05225864277775092021 +'MLC21-1706' 0.00644849813660345033 0.1193763834788681144 0.08614039908742214535 -0.008233430513488340305 -0.1393722730317872305 -0.1621366268976746905 0.007740420184267527044 -0.1034934932271945884 0.2679113682477302638 0.1750479156274055703 -0.1282846278050708 -0.1292709450966149642 -0.006579397390574985398 0.1183188703885335175 -0.08430062323210207875 -0.008444127387261886677 -0.143192616660487021 +'MLC22-1706' .01783256803114304997 -0.1162043681310968302 -0.08547394078432954401 0.05277688115309989852 0.1694951047295970847 0.1246356159641417716 0.04435263213132555754 0.1652785288357867532 -0.1837107949230099013 -0.270008064801653902 0.1197976632983312056 0.08377524953221679449 0.01819455462123343442 -0.1151749548009933233 0.0836483990619784068 0.05412746325229404049 0.1741411475138877341 +'MLC23-1706' 0.05610480564046715218 0.161683702347664382 0.04725551282667648373 -0.09239386774295313409 -0.129923801200800465 -0.00691276075561228498 -0.1443622213124367559 -0.2257138314563914283 0.08823032725680611532 0.2571663009859624371 -0.1163196747618713556 -0.02980263691765253076 -0.05724368744627370692 0.1602514037074841413 -0.04624623550209554929 -0.09475826482596669265 -0.1334851520730843122 +'MLC24-1706' 0.1247315711938176003 0.2142376263357548549 0.08195209366089853398 -0.124781891153038102 -0.0508745651513948377 0.1729265076011892721 -0.2540058346419358237 -0.1854399077991417399 -0.02352252380137997631 0.2007298166134338646 -0.1274451708468511968 0.03157602608363744429 -0.1272635203810694449 0.2123397711009933075 -0.08020177110832672762 -0.1279751110783687307 -0.05226909159923913417 +'MLC31-1706' 0.01242564087697576106 0.1128891670124982927 0.05362610946249397881 -0.02509412338657093441 -0.1305142353997465476 -0.1620827474007076607 -0.02816859258104389627 -0.1653864006610325232 0.2491618235131626835 0.1936094136902788143 -0.1118659071824810169 -0.08510795260653579442 -0.0126778712547255569 0.1118891218746438931 -0.05248076973283101465 -0.0257362923268414992 -0.1340917707072917242 +'MLC32-1706' 0.0436283364929993811 0.1445307537538864928 0.02537821400513018757 -0.05235003780328865985 -0.1134205983061229023 -0.03802966780833552662 -0.1101175402019794053 -0.2813820829963721848 0.1754218964993517482 0.2012837385526677625 -0.1184114814934470183 -0.04511284586841459582 -0.04451395614861127642 0.1432504070086048353 -0.0248361892888248996 -0.05368969680557332536 -0.1165295786698376385 +'MLC33-1706' .01171994421282923637 -0.1344973255356535502 -0.01034359154494013389 0.01316467304196127473 0.1011396051066888874 0.04293055998529879402 0.01840543196989581631 0.3354585767030787147 -0.2461674043874238216 -0.03167648659483182638 0.1245964791244947995 0.05301017837316902154 0.01195784952373243892 -0.1333058613764622757 0.01012267441217458257 0.01350156244057197988 0.1039119502623887248 +'MLC41-1706' .01661015058844571984 -0.1247465094591370671 -0.04577701157520800562 0.0151580878299151043 0.110258386268105274 0.1818975616105177884 -0.005015433824104452779 0.09429487595104601994 -0.3000665835747561294 -0.1033281034840016072 0.1239925798335252544 0.1240229371325291541 0.01694732310122675292 -0.1236414243251923173 0.0447993118951855937 0.01554598953296777372 0.1132806870050244857 +'MLC42-1706' .0140064507186234994 -0.1204301362490788757 -0.01927618234868750183 0.01702585007088754099 0.1055428126855424836 0.1757475496849503216 0.01312174951724293104 0.1938709340158550065 -0.299092458347635648 -0.06580511760359740447 0.1140551079082688934 0.07533830285459094944 0.01429077024714283349 -0.1193632883362609753 0.01886448406027034855 0.01746154857801604163 0.1084358544880989067 +'MLC43-1706' .008250857535456065234 -0.1333882985563539514 0.0007097149462618483531 0.005258400434502867593 0.1163558393118957618 0.1175496877973721127 -0.04172518187747005503 0.2542180805315235048 -0.2613833180249839905 0.1111197476859226707 0.1172473615675885539 0.05318566244294434947 0.008418343215553585404 -0.1322066588742825677 -0.0006945569433256512442 0.005392965064736176921 0.1195452777827445134 +'MLF11-1706' .2832149360101232083 0.4173482122493002988 0.256636966806000788 0.1859337979185545497 -0.2552991230447017035 0.00397432793753006719 -0.2735619830659467566 -0.07292230323593781871 0.2526869886170121648 -0.020144837230313236 -0.06744251188547435716 -0.06281016839011996367 0.2889639682734477244 0.4136510722889537583 -0.2511557466106650316 0.1906919202936814828 -0.262297146087018207 +'MLF12-1706' .1092948886274156123 0.3079131141982029973 0.09973094735410283074 0.2510571899889197378 -0.316852701330905151 0.002699082846878799943 -0.1164022572345058404 -0.01177476842161623988 0.3089160198733825191 -0.02809736129861412079 -0.01149648086889677213 -0.006815231545174577077 0.1115134857458705969 0.3051854210024384506 -0.09760090627100936889 0.2574818467565184732 -0.3255379740356830753 +'MLF21-1706' 0.405481851054968867 -0.4414248382406332771 -0.1478743345008416143 -0.1983162996063415895 0.131177545697185538 -0.05298740532629662991 0.3122958158447293742 0.08744022080571989264 -0.2047919666336068256 0.08941774473149002866 0.1414900436780504034 0.0259888997787456541 -0.4137128019954384173 -0.4375144119801415155 0.144716052984638438 -0.2033912952933691065 0.1347732630520888375 +'MLF22-1706' 0.2284737597543823329 -0.3764371321716458718 -0.07207459479402492097 -0.2739562584986123817 0.1903929634360497503 -0.02226328168202757266 0.1877772868271440077 0.02501636505550764236 -0.2792836678639408765 0.09438729015165442382 0.0409894303929245335 -0.004096084736184129986 -0.2331115907764864936 -0.373102408976333122 0.07053523462517487241 -0.2809669118492167383 0.195611838962649609 +'MLF23-1706' 0.001689639930778544024 0.1420180902410613233 -0.07064400490299874158 0.2591319035498976242 -0.2902381852719592703 -0.003252664361894135481 0.05921801322000715129 -0.0006521967611630608182 0.3215048164518695128 -0.02989991938723269432 0.001461330012438449193 -0.003246944471438655347 -0.001723938243615759673 0.1407600022916904448 0.06913519909387139117 0.2657631955591647777 -0.2981939255192050942 +'MLF31-1706' .3114384843575664918 0.3308012286508820732 -0.1207446355907550173 0.2573997376335220855 0.03793516019367754177 0.08401391357990173336 -0.2077977888862391487 -0.003019779669880581774 0.1473312268916143197 -0.2402183497190712169 -0.06213012608540914583 0.107892865839017596 0.3177604316384419758 0.3278707777576448934 0.1181657867860978206 0.263986702804439255 0.03897500366036598524 +'MLF32-1706' 0.1618416422571992697 -0.1948444550110768614 0.1186658136801942293 -0.3250403304524918657 0.03127266602232983 -0.0281308263781561152 0.04462630315221136068 -0.02686026193625825481 -0.2368072568641025055 0.2236569539676231122 -0.01295911884787272032 -0.04376371134733203494 -0.1651268956269325849 -0.193118397010753895 -0.1161313640935471431 -0.3333582462185222806 0.03212988337117522047 +'MLF33-1706' 0.03422249862027276768 0.05156836215563662812 0.1862296524499829076 -0.2778443508635660697 0.1450296727305530609 0.04503163341165733469 -0.1979617281201427326 -0.006699125056417287727 -0.2659863553008675052 0.1207557861832349727 -0.02565441065731719275 0.03378581092035758821 -0.03491718743672873881 0.05111153630417870908 -0.1822521828567156554 -0.284954502097209128 0.1490050917585703238 +'MLF34-1706' 0.00107550521843275391 -0.09019233962539885407 -0.2201413766859628696 0.2029366710639383675 -0.2255037992522271606 -0.04941047961680940931 0.2479072499064756963 -0.03505635944310626917 0.2714256504442650875 -0.03695801831738865229 0.0005109975036195397481 -0.05099256028100346283 -0.001097337097383950175 -0.08939335764066946854 0.2154396247336330672 0.2081299039572183096 -0.2316851004822383653 +'MLF41-1706' .2160581206354072192 0.1272567074518235475 -0.2294781029899453095 0.1116128295114007241 0.1630707284143859404 0.1327388966443867613 -0.1581394049012047887 0.03969111617520743041 -0.0727704840724649471 -0.2605534334953005238 -0.02016200315937529547 0.241978327657154324 0.2204439243072934262 0.1261293853631375306 0.2245769384065645913 0.1144690477320496197 0.16754067214690474 +'MLF42-1706' 0.1621740171854678947 -0.1156570550353058641 0.2078227827865649635 -0.2040972430566403428 -0.1632763262637005053 -0.08857170497916681817 0.08594136762138628038 -0.05900644459931643493 -0.03185955837584739103 0.3211450999577711851 -0.04349909842545013339 -0.1340608066924575403 -0.165466017495221579 -0.1146324901580239586 -0.2033841298199341452 -0.2093201754646305535 -0.167751905653991229 +'MLF43-1706' .08218561513582908762 -0.06480838331372384964 -0.1625579492363286582 0.2714671056111329639 0.05778111047295791947 -0.0204068509157986841 0.1402574910259281327 0.08089928502225260387 0.1592212392059628445 -0.2686722654885064787 0.07406277648779024947 0.004851993024243806372 0.08385391610771061877 -0.06423426880530587468 0.1590860569156090365 0.2784140605153998527 0.05936495274267693245 +'MLF44-1706' .0912936654616337967 -0.1263487289661000823 -0.1518809199292650014 0.260816941315607953 -0.01237232342513022373 -0.05732897397337718276 0.2052817685187591501 0.06860391527432835312 0.1917042781632272708 -0.2163891613977388106 0.06353827277208179414 -0.01907168596034488836 0.09314685242828914247 -0.1252294503371538525 0.1486370662632739981 0.2674913541344627887 -0.01271146209268018273 +'MLF45-1706' .09709402458949725756 -0.2112482170941605009 -0.2358345403009498298 0.1767461833888918366 -0.1061403192317468408 -0.1570723631987329116 0.3276269581147815968 -0.02866194725896517581 0.1882389165924465146 -0.09593709909227673971 0.04720448175517780176 -0.1031467287152491863 0.09906495411674891283 -0.2093768439768264322 0.2307976157255730854 0.1812691909287547642 -0.109049739330195572 +'MLF51-1706' 0.06996854093294238575 0.03662902547438628975 0.2028029198859360172 -0.05689258295535458421 -0.1956690485599958118 -0.1264130302031062358 0.06326781060489868047 -0.08147619874835063114 0.1681849132640110822 0.2731198417089248376 -0.1019499664070744049 -0.1921923342044024874 -0.07138884526048974721 0.03630454191409968057 -0.1984714805224395417 -0.05834848755671821069 -0.2010325472440521455 +'MLF52-1706' 0.04221800773222808556 0.08962559708554490578 0.1504836753331121324 -0.1198991000498791926 -0.1976688893934382407 -0.06996904624856850607 -0.0435567223805512771 -0.1336979720408882355 0.07850671350398787107 0.3154077620128406534 -0.1226375830649022586 -0.07995005945213791432 -0.04307499886399942385 0.0888316356721988859 -0.1472696638422121562 -0.1229673673422775754 -0.2030872058616941256 +'MLO11-1706' .1861799120317299827 0.2535620425213156448 -0.2190945988025922719 0.1149661634001307581 0.05183351123819172901 0.3065324340622725963 0.3204383247987012684 0.05398471083210759636 -0.09877820864597226802 -0.08145627098427889179 -0.1153233302115229536 0.1632475810215299195 0.1899592124320982345 0.2513158262148404987 0.2144152038011949979 0.117908194814431655 0.05325432342776405259 +'MLO12-1706' 0.1438844856289933638 -0.1723963022502312259 0.1303356181537212721 -0.04242604550398709068 -0.004193976882799839608 -0.4433961928709581057 -0.2024945157288647601 -0.08475733604489762985 0.0173346636823901723 0.04478467684938867294 0.1709431290678761761 -0.2177322584150830909 -0.1468052233617073155 -0.1708691044826160521 -0.1275519263446773521 -0.04351174546096370915 -0.004308938291655273721 +'MLO21-1706' 0.1534645184633245119 -0.1387016611195459881 0.272535826613681087 -0.03649574258560613765 -0.06570907301419000313 -0.331454588536091721 -0.2791827929041414413 -0.2506927966626872339 0.06679491816959798323 0.01212881403351893407 0.07271243724779878626 -0.2749881492368085878 -0.1565797230508738092 -0.1374729522408670024 -0.2667150405617766951 -0.03742968365139080072 -0.06751022924833045835 +'MLO22-1706' .07031806801288296993 0.03674257854049649968 -0.07731739734900225369 0.003274607210591818848 0.003917316203801275883 0.4236023825456401992 0.08032764991436761037 0.3181712690071258343 -0.004126298369180464443 -0.002621017642216875391 -0.1020038619081512221 0.3409975755401586373 0.0717454674551435273 0.03641708905382512462 0.07566606205980166977 0.003358405756164980095 0.004024694046432725388 +'MLO31-1706' 0.1486056070595172807 -0.1860956154444221577 0.3673530722307644103 -0.06680087649187285703 -0.1291518241755400254 -0.2533167993801668239 -0.3240599933700139546 -0.2391346552867524566 0.1122357733597204726 0.01189052252659221487 0.04503386408105534283 -0.2558256240929574488 -0.1516221797075980593 -0.1844470603144103271 -0.3595071913220643234 -0.0685103384007469951 -0.1326920143287955989 +'MLO32-1706' .1277388769672969659 0.08069504723258087708 -0.2154131143382879421 0.013929798833946282 0.03142668021599177158 0.3851157925547521454 0.1925948181501072609 0.3405554408090999963 -0.02770024787398775099 -0.005502997760545315017 -0.08817043129939775015 0.3592033162121512357 0.1303318720095484884 0.07998019839659877006 0.2108123480210030987 0.01428626811631876319 0.03228811925922935033 +'MLO33-1706' .0150435247737256677 0.01954013225976638027 0.0277966515985706257 -0.0006511827497863130476 0.0002041167332333240823 0.4396096570935431602 -0.0232177786240188172 0.3864511737469091823 -0.0001398901227021657199 0.0005783700591417944691 -0.105473284074222573 0.4048493248349855911 0.01534889605991792902 0.01936703315046700916 -0.02720297419503440658 -0.0006678467842262062609 0.0002097117920233969931 +'MLO41-1706' .1521201211852270807 0.1362084970758885016 -0.3383503102636729043 0.03524532989688156093 0.08213602096174497935 0.3206148896844249752 0.2685303411983450128 0.3231577290096785959 -0.06404411479800468932 -0.008604723072321249569 -0.06986555242334493987 0.3408312542208970508 0.1552080356042725429 0.135001874254230908 0.3311238667127043289 0.03614727238758753958 0.08438745747448943291 +'MLO42-1706' .08022918042986069975 0.03971726164992910729 -0.1169980304730939835 0.003942374694141351395 0.007510006939329620657 0.4198514502740613996 0.09321640608876378964 0.4152765353445951324 -0.005922024598868695644 -0.002261818546464018208 -0.1018724470440043328 0.4324555156873291506 0.08185776737251708457 0.03936542049941813698 0.114499201191307784 0.004043261684313762157 0.007715864292001307044 +'MLO43-1706' .0444546059681233327 -0.03284245308838265598 -0.1648903255862971817 0.005210751308679780966 -0.01552507240412293911 -0.4104443775580652876 0.128661805661052786 -0.4000908876289550609 0.0117072903063823279 -0.003770121458569130127 0.1011960908351902944 -0.4200734360800368328 0.04535699822032780021 -0.03255151343141262504 0.1613686186636062447 0.005344096578182164041 -0.01595063130586135344 +'MLP11-1706' 0.04596132649404464227 -0.1649185633370018056 -0.003790106214033653765 -0.03214946980248429426 0.1021414181560006823 -0.06515756863128974175 -0.1145009382414202692 0.3227808658807878039 -0.1595715105173279302 0.1417686534780706609 0.1355309134912667801 0.02803998350705355636 -0.04689430394432293758 -0.1634576082093158744 0.003709157600194507194 -0.03297218795985057405 0.1049412240828914572 +'MLP12-1706' 0.0008592274242542254515 -0.1655300352077557213 -0.01033290015474596507 0.004483834573653531705 0.07265767050976255914 -0.2367787204002267387 0.001445878194115893765 0.3249031524020167261 -0.1342072209955394724 -0.001170311024293257561 0.1765953886131755579 -0.001375904315944748504 -0.0008766690403397350839 -0.1640636632673899975 0.01011221136735316987 0.004598577744879529111 0.0746492952610129934 +'MLP13-1706' .08867883724308185667 -0.1836460093553235196 -0.03441823811114610998 0.0619300753246413635 0.07090030737045935338 -0.195185041816601762 0.1681031817683860397 0.2838561084891378927 -0.08588902376493311175 -0.1433602685633046936 0.1568691080700883034 -0.004976173910339043265 0.09047894532907051202 -0.1820191544178446919 0.03368313769217452791 0.06351489142797589471 0.07284376091142165388 +'MLP21-1706' .1198467967095010606 0.2289743371574221864 -0.0343122230836385364 0.0982016719213779643 -0.08556036512411803463 0.1775040410377459743 0.2221234152493576086 -0.2330851078030575507 0.02841232236650191936 -0.1897393948560113786 -0.1446147444793930148 0.01596227337291918416 0.1222795889578392192 0.2269459346221960605 0.03357938692034693334 0.1007146931024364978 -0.08790566658660189936 +'MLP22-1706' 0.1008083000688739239 -0.2005495173042529944 0.02265567886485072083 -0.05205300628041349686 0.06646758001153829643 -0.2712141221055427431 -0.1658980556432302356 0.2574129736527093759 -0.06944912682898449208 0.1159293529040759246 0.1756408803323148693 -0.02766909644280012362 -0.1028546263596813309 -0.1987729201781801291 -0.02217180171309598991 -0.05338506412383983712 0.06828952773678102772 +'MLP31-1706' .16581050962173563 0.2443761049925057549 -0.09136194201552376437 0.08859815972496630498 -0.02957360698583187675 0.3418264799460875025 0.2495954579377616112 -0.1179504917908447414 -0.01299138058915705676 -0.1183769167205985379 -0.1753082493725646174 0.09706098052950398736 0.1691763277626954221 0.242211263652339831 0.08941064510030136137 0.09086542307838357813 -0.03038425130244014685 +'MLP32-1706' .07083546623669863262 0.1695314527542970684 -0.03119865250907051177 0.02082508165766782521 -0.03117101574078156093 0.4435770974238671949 0.09441878883438181713 -0.09294125277860057488 0.03647010210456870516 -0.03613053527368102064 -0.2050967753693166695 0.1317044520870827296 0.07227336844100842872 0.168029633673449752 0.03053231559616096866 0.02135800406396750825 -0.03202544674628174382 +'MLP33-1706' .07228231375196787767 -0.1666962067082004006 -0.06051632896586048999 0.0323353420534630287 0.02741834725624891361 -0.4242720235401877815 0.1286275650546016558 0.1085980695426739112 -0.0333288994312119502 -0.05169199561518745406 0.1961172827089589787 -0.1215459225176528379 0.07374958578105660079 -0.1652195040676462945 0.05922382879098895408 0.03316281675819292979 0.02816991358986247612 +'MLP34-1706' .1449206920916428776 -0.1940479600912682068 -0.1571050011387674916 0.09052326573032641599 -0.02288000989830266466 -0.2998389350387301588 0.2893093848180111061 0.03217017999936495898 0.06713024264392333795 -0.1021882656228587372 0.1248631199647714102 -0.1165202530306865547 0.1478624639706104249 -0.192328957957269342 0.1537495722005778886 0.09283979333833934644 -0.0235071755327444093 +'MLT11-1706' 0.02941061710430426315 -0.04953292467771624324 -0.2246542970572873443 0.2083775617487515497 -0.2676898346580280919 -0.03296335039524216082 0.2223488722060107114 -0.03690080689561065636 0.2745201917026739435 -0.02262069580646115102 -0.006365661974308251154 -0.04561454280499389197 -0.03000762864966599955 -0.04909413004579045448 0.219856158716873612 0.2137100292728400519 -0.2750275004078738261 +'MLT12-1706' .02406653693109491593 -0.1476152289496073522 -0.2953007851043348841 0.1512078266795950088 -0.2227774201197675608 -0.08678040706142246818 0.3062504395727334572 -0.08359867304333283566 0.2315433758472659476 -0.0189791755608124009 -0.002633579223959338963 -0.09561150346921233611 0.02455506800658314309 -0.1463075579312892172 0.288993787920114209 0.1550772971657174149 -0.2288839883708186085 +'MLT13-1706' .09141707171244942143 -0.1727783077629869157 -0.3119253971339939757 0.08681890703404496201 -0.1365912028533433631 -0.1916503702946605048 0.3451945807914174602 -0.1517632776229305425 0.151345012910839738 -0.02005695760150492599 0.01758791102637360243 -0.17359856199376833 0.09327276372536902338 -0.1712477259438655308 0.3052633335681422255 0.0890406385791818189 -0.140335314362798308 +'MLT14-1706' 0.1079860546418236339 0.1384966246830776626 0.2872585880018046489 -0.05339696190071521048 0.1092075127277415125 0.2299118865433914805 -0.3273975321723666676 0.1674945779970780646 -0.1224176624183875295 0.01352823502386997501 -0.03530790910025199264 0.1848913684019521664 -0.110178083497613849 0.1372697321495520706 -0.2811233550560796046 -0.05476341212131945191 0.1122010078927405397 +'MLT15-1706' 0.1058068957446395841 0.09301823583701179787 0.1990832945251175545 -0.02545237949609771219 0.03887179631788453826 0.3615968643281262662 -0.2432025609773219021 0.1895132377488270015 -0.04711279333707184269 0.0203971923338452793 -0.09360360010729668057 0.2375719614534080593 -0.1079546894517356137 0.09219422023886056361 -0.1948312984542243942 -0.02610371635758457903 0.03993731398627527185 +'MLT16-1706' .006420570751482670806 -0.07800153269754098173 -0.04246600458637435349 0.005465358113195416603 0.003731525648345963581 -0.4741744781430483613 0.04750628991843062338 -0.181917944434745793 -0.00437391060919731841 -0.006212226955779655453 0.1538101267389136995 -0.2717696984314896258 0.006550903102308660089 -0.07731054475260618064 0.04155902097894257491 0.005605218875561319113 0.003833810772394539382 +'MLT21-1706' 0.0254339337657134186 0.04815597458099193928 -0.164766311671775495 0.2437658469651044768 -0.3333786386016404646 -0.0130998952064865469 0.1392472333064813106 -0.01380817708549701706 0.3024935248571345991 -0.02478861110195732659 -0.0006154872255995307668 -0.01921477202523860436 -0.02595022188194863813 0.04772937786216745193 0.1612472534227391563 0.2500039152653308339 -0.342516904988642068 +'MLT22-1706' .003637203781615106282 0.09824284691276874426 0.2779104357506039791 -0.1942274733398270392 0.2849747264372969324 0.05113473093761433663 -0.2552972057567962638 0.05489714164889791803 -0.2663252863892679456 0.02381764726141846755 0.002557737007157911448 0.06577248852580981631 0.003711036052551706065 0.09737254833599555404 -0.2719748594698795374 -0.1991978342807002866 0.2927861896272306308 +'MLT23-1706' .09297609498469261435 -0.19775263310112981 -0.3601833830603863307 0.1170863219702488883 -0.1814798374515853296 -0.1701171040457079009 0.3453946997867533564 -0.1509446833069279237 0.1747681729769871017 -0.02426907264751922491 0.01941031093313349762 -0.1738103543899987835 0.09486343389878792998 -0.1960008125813735014 0.3524906314750415603 0.1200826091145150987 -0.1864543946261497942 +'MLT24-1706' 0.1186715130442681371 0.1684293196815434546 0.3426153154995126293 -0.07181657155393512959 0.1411217154724233591 0.2196587690382618696 -0.3359169521261648472 0.1848936018071437593 -0.1363921888619753497 0.01559755442196450806 -0.03584351549475146143 0.2033768842428316792 -0.1210804479925458865 0.1669372640071402347 -0.3352977805008744427 -0.07365438716272168507 0.1449900131965574379 +'MLT25-1706' 0.1289296693053584852 0.1128593268904711372 0.292613136161860854 -0.03166624192055746828 0.08148159987594860709 0.3083379404836946724 -0.2934327202072343765 0.2381010044417077032 -0.07984660874488416771 0.01060449495459777312 -0.06819589659467406584 0.2569450941933609234 -0.1315468364610828389 0.1118595460956864629 -0.2863635414471472074 -0.03247659407764289657 0.08371509800416919445 +'MLT26-1706' 0.05372182546018941518 0.03503963177046312549 0.1487859548076093108 -0.005884589770561178199 0.01603850536345583985 0.406421369773121377 -0.1486619637226493096 0.3079434959490638946 -0.0155201903306658711 0.005027649793544570686 -0.09534710283094016692 0.3308120069933360718 -0.05481233471145389308 0.03472922808593260913 -0.1456082030190672394 -0.006035178843495702522 0.01647813801381213528 +'MLT31-1706' .02055273293205340038 0.07099233538185675818 0.2871463182699538486 -0.2020034866671847895 0.3215253353419816884 0.03975120206712119686 -0.2342756726072209861 0.05408961777373167551 -0.2655566310817074061 0.01971694201508631186 0.005606586086863958075 0.06240741455645516106 0.02096993665156924799 0.07036343943282653834 -0.281013483167100786 -0.2071728389878737253 0.3303386899613696692 +'MLT32-1706' .03299708863869348086 -0.1547248836231362445 -0.3600742513428886737 0.1505898304783163666 -0.2638001098705970993 -0.09334107510393213625 0.3053299196854436515 -0.1076501292093403617 0.2227861278406501888 -0.01888411568809355429 0.0008799974874751702401 -0.1200819083320490283 0.03366690263174096365 -0.1533542306927689336 0.3523838305790983338 0.1544434861874269538 -0.2710311540881552572 +'MLT33-1706' 0.1099997440199430854 0.187268982771912007 0.4142738853881993699 -0.08913507492947406186 0.1866698172998873806 0.2012696447471735151 -0.3532853830266671213 0.2103196686264926507 -0.1565397098266445852 0.01363852840618042656 -0.02405358353029963397 0.2252873250320789611 -0.112232649128116771 0.1856100331964292138 -0.4054258756285356036 -0.09141607816384204888 0.1917866373938635349 +'MLT34-1706' 0.135000755116522958 0.1489074201976655631 0.3796215613536432221 -0.05128349622819194931 0.1328296703181114924 0.2687351078038757723 -0.3303679088139176989 0.2498071932638179782 -0.1129543933409746376 0.01123960168364337465 -0.05334309138552047885 0.2658406538466721036 -0.137741160363760079 0.1475883021148593488 -0.3715136515907858095 -0.05259586199283353136 0.1364706741825340297 +'MLT35-1706' 0.1032074790357673938 0.0675393359422463424 0.2666475478061224869 -0.01440748404018138244 0.04902123790123995989 0.3833512633744912135 -0.2344472189545973861 0.3343947542043311238 -0.04190466050340616727 0.007143149121790612864 -0.09166851914355969577 0.353870442752071579 -0.105302506703276455 0.06694102889197391104 -0.2609525228755305015 -0.01477617748348371285 0.05036496265949417378 +'MLT41-1706' 0.004339327789664010858 0.1082769594768177718 0.3358928511631726344 -0.1831110523055304584 0.3374513073356221193 0.05456897001241389766 -0.2547510963067269318 0.07290608262066095024 -0.2551553964542446762 0.01817368236061459377 0.001525382855664386608 0.08162049317489925016 -0.004427412605441619943 0.1073177722515770843 -0.3287188937158956326 -0.1877969394592453878 0.3467012099448880669 +'MLT42-1706' .08289736379339353312 -0.1891539828210876406 -0.437786186032757485 0.1131852689211517715 -0.2330278938556159252 -0.1543954744205159046 0.3360626631820053389 -0.1880551626002880394 0.1762653239482036283 -0.01448485064730739569 0.01220633869491688159 -0.2014855833121523832 0.08458011268265315519 -0.1874783346979592147 0.4284360035006529177 0.1160817265131404707 -0.2394154385962946607 +'MLT43-1706' 0.1195810197362568023 0.1668278052319297211 0.4197158897090380592 -0.07099760113938126393 0.1732764219830687513 0.2165440840064302153 -0.3248761645591489167 0.2333942807058506097 -0.1314292718158479589 0.01295087025989425343 -0.03778765477925585814 0.2489866124416025006 -0.1220084169287566078 0.1653499368066746744 -0.4107516503026569232 -0.07281445895836478888 0.1780261147327588944 +'MLT44-1706' .1307442290410151253 -0.111985768181042139 -0.3613517170509017995 0.0314233495385638148 -0.09731985505301764261 -0.3159787758927056767 0.2828848830097625555 -0.3100734037957798006 0.07424539005954737536 -0.00972696164839428716 0.07568773795048078235 -0.3281828587177348933 0.1333982302797542541 -0.110993725933392795 0.3536340123345119713 0.03222748597967695083 -0.0999874967590044933 +'MRC11-1706' .03057431121130314844 -0.1430035554237890083 -0.09863892347482025591 0.004684366149590397932 0.1344493424118867464 0.1335871575944615197 -0.03420070890509311484 0.077411435627397579 -0.2819736177038322245 -0.1130251679918460456 0.1318857795622695173 0.252092855948062744 0.03119494479814343899 -0.1417367375874803992 0.09653220570097334474 0.004804241006336004531 0.1381347432272195253 +'MRC12-1706' .003497019502994293001 -0.1259043748687618813 -0.005750283493578489842 0.000902736791224480477 0.1165895711168080939 0.1342061630712123588 -0.002887697478237460751 0.06541078890143686708 -0.2646224466039233114 -0.006237398518784461471 0.07704478240095771757 0.3071995062227549367 0.003568006147383240897 -0.1247890326153447416 0.005627469658899193414 0.0009258381970649453164 0.1197854164273552818 +'MRC13-1706' 0.1656846953418930068 0.05149173519367507279 0.1116820670537876647 -0.03954847718963529213 0.0972599342165118147 0.1687617422748686757 0.1181499308935818199 0.008728751680269819513 -0.1382964508755176458 0.1212237092265487509 -0.1450566589321088673 0.3167503069394009274 -0.1690479595555628156 0.05103558815332689957 -0.109296775452929526 -0.04056053898972086791 0.09992593342804124978 +'MRC14-1706' .3636747657300390957 -0.2571269623579317543 -0.08285637539531157114 0.1171409741987591707 -0.0451344322454187083 -0.1379300216658054246 -0.2610847331555283812 0.05922638433937921221 -0.02514173518480369504 -0.1746442564861342694 0.2110884656706498441 -0.1581500073964554609 0.3710570669285332412 -0.2548491656895512381 0.08108673930671016217 0.1201386599160349095 -0.04637161548791660093 +'MRC15-1706' .4123706533164807064 -0.3793033815167258238 0.09304703903705804913 0.1601034970567334903 0.06401025148435419976 -0.07075990482867222653 -0.3262080053496420051 0.1066564946557981286 -0.1520414824112646113 -0.1146235957327424032 0.1858116755476573734 0.003403588279648795366 0.4207414413256269081 -0.3759432672338775538 -0.09105975203069449631 0.1642006114071616341 0.06576484119657012573 +'MRC21-1706' .01596540809033131225 -0.1494953587583078281 -0.006840851951792977122 0.01306503188608057475 0.1145948091914549688 0.1457281130939310221 -0.005405008568720096399 0.0597713216937120484 -0.2992853162801875078 -0.01795604698726411749 0.1267019537676334628 0.2377268683745890343 0.01628949285613327108 -0.1481710323360790615 0.006694745892568024909 0.01339937142652355105 0.117735975936125864 +'MRC22-1706' 0.04241520406883505373 -0.08510884897049819653 0.09101557479661256944 0.0006435740043285814943 0.1200691726388278813 0.1461303999689518851 0.04510170942281802736 0.04245863239927688548 -0.2453091385220129705 0.08396909421387847849 0.03861759387020459455 0.3094978365765182482 -0.04327619812544267891 -0.0843548998285764684 -0.08907167554907198526 0.0006600433278422506572 0.1233603975626646476 +'MRC23-1706' 0.1749051174651098384 0.0637066317942764776 0.1801363709554188453 -0.05428455943657647942 0.1257883722260832171 0.1419859402424387129 0.1441351570512157121 0.008074694845674967869 -0.1280129163411886095 0.1986104105891146332 -0.04759399973994973138 0.2662076767729228965 -0.1784555487294113008 0.06314227731225702245 -0.1762890409051782181 -0.05567372364324870565 0.129236366550527032 +'MRC24-1706' .3229435721425160666 -0.2722164008237961674 -0.1225303115396950832 0.1459966507936349411 -0.07238352715167904738 -0.1154162338419092576 -0.2503687890967836727 0.04637932958573351416 -0.04424234848579100543 -0.2147861470229526781 0.1336206988381435923 -0.14948049790641732 0.3294990633240059696 -0.2698049321657102761 0.1199133244917619245 0.1497327651451477171 -0.0743676373391742862 +'MRC31-1706' 0.0002015592274662599112 -0.1129674974829350809 0.08331198511425862152 0.02244996115923489702 0.1203431034753908307 0.1502163137972551132 0.02851724921224238138 0.03965614790932375788 -0.2740056378769517575 0.08234765429483695276 0.09722419233050288989 0.2308406631789497454 -0.0002056507154294260806 -0.1119667584431928431 -0.08153261817034136716 0.02302446490039591551 0.1236418371375397618 +'MRC32-1706' 0.10033146968031742 0.01605425853277189785 0.1921915433182271316 -0.04223352577446042033 0.1586271222133333325 0.1413229106131536073 0.1076426705923665406 0.02091224582853301595 -0.1570676463715844073 0.2404520703191420639 0.03781477487375302371 0.2151535766653063231 -0.1023681167030517369 0.0159120395438960352 -0.1880867404064746062 -0.04331429907236285237 0.1629752619293906024 +'MRC33-1706' .01979455986725166261 0.06027299581073901347 -0.1441811383131844093 0.04337358539616040926 -0.1840072500933647437 -0.1357269453402529247 -0.01937036393100139905 -0.08659556111370171616 0.1631644674327529243 -0.2815794914457797615 -0.1033057306817664889 -0.1195750898653752808 0.02019637329177765769 0.05973905869347978514 0.1411017356186141936 0.04448353328876114565 -0.1890510863617767823 +'MRC41-1706' .03018628867388630996 -0.137955618317214479 -0.01012663822241948938 0.02781968947274519877 0.1037583814758227668 0.1666134520555595244 -0.005808284948225599098 0.06026175429401210704 -0.3050428955851984258 -0.03251707854280969784 0.1282764341920848983 0.1681456489057032155 0.03079904571961640178 -0.1367335183674243115 0.009910354751544682081 0.02853160677035956189 0.1066025101032216649 +'MRC42-1706' 0.02140418101093491052 0.1240464576224376975 -0.07621935890969942784 -0.02666822430130585606 -0.1312854698877474746 -0.1712307868744430694 -0.0150937896165679649 -0.07414781835223806239 0.292196514100403093 -0.1248581198776768791 -0.1271908171674049071 -0.1468966563477286935 -0.0218386684321685981 0.1229475739997102218 0.07459147538796501165 -0.02735067513151226079 -0.1348841455605774842 +'MRC43-1706' 0.01680441244167842768 0.1296604565921741503 -0.04595174941600873447 0.00284215659716115579 -0.1473910554431897835 -0.1371354967257686353 0.04184651262947680639 -0.1756806022421203428 0.2347470699234750491 -0.202886995201335546 -0.1213246075110408356 -0.06580751433763405711 -0.017145528311676074 0.1285118405414185372 0.04497031770706700488 0.002914888553642197219 -0.1514312025064532274 +'MRF11-1706' 0.3909624068298494515 -0.1966629436094969596 -0.2616276690293469764 -0.0333362237260401012 0.06540429879971824956 -0.06501668898923340656 0.2711331029081969213 0.2729975682736562881 -0.06468943111857271278 0.009070192571966010503 0.3075910541636388551 0.2557533525052311796 -0.3988986248919204058 -0.1949207762629079077 0.2560398580409701252 -0.03418931140449750494 0.06719710084544576467 +'MRF12-1706' 0.1810151985130786234 -0.05990966650042391789 -0.1017034550152422639 -0.006173838949915151815 0.00741538186797176431 -0.1061526123317638182 0.1065996856314965074 0.3414651553147626251 -0.007566777779953144829 0.004560029759003688191 0.4033096756610932698 0.3141723098838756223 -0.1846896594404026648 -0.05937894798880982705 0.09953128536056284059 -0.006331830028335919645 0.007618645445851566882 +'MRF21-1706' .4494660512473251934 0.3188347727628673689 0.1548909176139302013 0.0936471831896307505 -0.05248414846159161345 0.1046688669347286271 -0.3046841333305525534 -0.1751613558566728623 0.08936647206025714885 -0.06195660821367301313 -0.2962173695877688417 -0.08528268088289434057 0.4585898455863270384 0.3160103284630425557 -0.1515827767943679905 0.09604365313049310904 -0.05392279531595729758 +'MRF22-1706' 0.3027428147593829166 -0.1603343142667683074 -0.1041321552298076353 -0.03069864475769192372 0.01004639714197603888 -0.1459342732771093942 0.1864871505715646749 0.2436404045537557406 -0.01946339661596619905 0.02913083089301551909 0.4133562363769067716 0.1491992317237742227 -0.308888247037993946 -0.1589139693775554196 0.101908113700120595 -0.03148423570534539945 0.0103217796730766271 +'MRF23-1706' 0.04942536722689590267 0.02470043930056848788 -0.05498403098691546226 -0.002051437466676938985 -0.002040322834149596847 0.103348738191039069 0.05977931950319602394 -0.3147225681344787973 0.001952561942505099367 0.00233717465142020079 -0.4117322266515858198 -0.2888393326058792954 -0.05042866187942061929 0.02448162685931213126 0.05380968893940260567 -0.002103934595335844437 -0.002096250273448490437 +'MRF31-1706' .3348559522644288244 0.2186712504024280745 -0.05061241474803721691 0.06948873460858513706 0.0474252247707601382 0.1947144537019051547 -0.2075811142308803536 -0.08500770620575032188 -0.01872543504763774305 -0.1075335400377467332 -0.3395565632099347142 0.1538397009021389983 0.3416532550488612374 0.2167341192627388335 0.04953144113264470322 0.071266979912352868 0.04872520109568744678 +'MRF32-1706' 0.08316329737541253153 -0.1259721001332885504 0.01439651290995311306 -0.006389550750947605232 -0.03253252650443295979 -0.2157666023689230883 0.04069293930925910185 0.1450268481992543212 0.03981860515693522867 0.01508933335264873651 0.4401960223065913835 -0.07346663876837009055 -0.08485144449954092061 -0.12485615792574567 -0.0140890339902692719 -0.006553061983092769299 -0.03342427798163223607 +'MRF33-1706' 0.2692017745492568115 0.140979940040355578 -0.1094033752311791008 -0.03405185195410588561 -0.0139078964682223874 0.1533716596449277714 0.2010134035111192929 -0.2152800158308411649 0.01988792064427201758 0.03984139471017113243 -0.4121847690665810249 -0.09701048178902450803 -0.2746663510614665293 0.139731048695832194 0.1070667516448804979 -0.03492325285330288159 -0.0142891268414177177 +'MRF34-1706' .3320356914539314697 -0.1436364267235446524 0.198415710073604562 0.02395681540492492281 0.0421650391261524024 -0.07363952629181191867 -0.251757135213100891 0.2579755010672394322 -0.04949802068967154578 -0.01527957803454208473 0.3414637130912087093 0.222681757087011406 0.3387757452435934402 -0.1423640025045958268 -0.194177972187817266 0.02456988016609809242 0.04332082811542097706 +'MRF41-1706' .2252989132717254372 0.09477020999282342872 -0.1966920575781135327 0.07106450127687112539 0.1332280996496958969 0.1546532987066245868 -0.1570556779483562593 0.03847132013309478848 -0.1133630047160334997 -0.1968371824439046069 -0.08265860758632444238 0.3035603387172922107 0.2298722974990488055 0.09393067427628942756 0.1924911332464513958 0.0728830710978932983 0.1368800248898361105 +'MRF42-1706' .122220576130128239 0.06287795152105045415 -0.07912379477149947271 0.01792023612989282824 0.09012258455386137901 0.1974821243929711645 -0.07869509603263664943 0.005740464068836104161 -0.1310891975871425197 -0.06702869328867649967 -0.2293385897887736113 0.3272062299111700434 0.1247015541650900033 0.06232093802399887861 0.07743387867238586686 0.0183788223441891177 0.09259294134874393456 +'MRF43-1706' .2023056450853150945 -0.1269884779896983951 -0.0114691936659614916 0.046997348837595182 -0.04361861875008592876 -0.2052037349053756898 -0.1402788213248585825 0.07198649532141201957 0.05796743358818410435 -0.07764922024070908257 0.3510535710507777241 -0.2013386474598358455 0.2064122847175079989 -0.1258635320507929534 0.01122423606406773577 0.04820003032734650195 -0.04481425191735564917 +'MRF44-1706' 0.3016461262471071825 0.1904893894750705752 0.001049389085828675077 -0.05872263746143031177 0.02504658074139399365 0.1752508817344972658 0.2030237471847192166 -0.1195740731936100892 -0.008839932107464349917 0.0876005084145633911 -0.3546855162957496255 0.09724957794671922062 -0.3077692966431751498 0.1888019114574826796 -0.001026976365161051544 -0.06022537391042216692 0.02573313440859489876 +'MRF45-1706' 0.429087921409202766 0.3112612550713563242 -0.1486566217366131204 -0.0990480169215538081 -0.06341326118471525553 0.08692149687532574331 0.3223061630363367458 -0.1535279624963728218 0.1083344043824291947 0.07399094072273164346 -0.2621428800796802849 -0.05955837702837864234 -0.4377980563291216098 0.3085039018817264389 0.1454816322276034635 -0.101582696419322327 -0.06515148675191145822 +'MRF51-1706' 0.07165648892676913795 0.07960048013116406695 0.1193507755665426384 -0.01115464410125674953 -0.1313315593441189422 -0.1395678309768154102 0.06023851728731902111 -0.07161652265399121031 0.2310622827687529302 0.1089928119661103117 -0.03465755320902647735 -0.3363901621632690575 -0.07311105722221321324 0.07889532767736631702 -0.1168016966497128772 -0.01144009603242214339 -0.134931498378428022 +'MRF52-1706' 0.07512822170158524326 -0.02672216954749038684 0.03762477103156019326 -0.02881561283473826202 0.1009683479162923753 0.1661857043206552698 0.04970899560140586149 0.04410357375813644953 -0.1902193112258701579 0.06001124722854464522 -0.09201692602111330443 0.3621740811802816595 -0.07665326334145543263 -0.02648544731420532719 -0.03682118588406674276 -0.0295530162208726202 0.1037359987285480928 +'MRO11-1706' 0.143276100144351215 -0.2541123251126914395 0.2304375354588815983 -0.1992797827550804868 -0.1009715781098459025 -0.1717904391127985653 -0.3184481836135348298 -0.01347342214091126755 0.1822640209356397312 0.1075989749624769037 0.06931868197881396743 -0.09583804196091520733 -0.1461844881478135127 -0.2518612340476852895 -0.2255158794369905018 -0.2043794343722261098 -0.1037393174651747435 +'MRO12-1706' 0.08030627094740680483 -0.1159084996680348062 0.1744209751266761754 -0.2954909636016306851 -0.1465166558028980492 -0.05372111750999448987 -0.2043027395691204284 0.01758580874190161444 0.266774666951497097 0.1312926445156141209 0.03454880703502136857 -0.02734826138588613426 -0.08193642276470862462 -0.1148817073318296467 -0.1706957137847386619 -0.3030526989144144978 -0.1505328346332981126 +'MRO21-1706' .0342732027805162931 0.1620929087787638667 -0.275090865364903181 0.1894644805054137848 0.2534779263145584549 0.06871914308472523714 0.2752836806532742431 0.06249021887556825 -0.2541586930458559213 -0.01997064522979013004 -0.002863168692766314503 0.07282141552085227842 0.03496892085008027756 0.1606569851237781288 0.2692155091153480839 0.1943129545003326464 0.2604260283993324876 +'MRO22-1706' .001357964157832736163 0.04225486884667223331 0.09290471355455792724 -0.2531492933423769576 -0.3188393176441711163 -0.006091288204190485091 -0.0866546221016496615 -0.003509691524755090622 0.3187184292095230354 0.02111289553308321604 0.001165761743317600364 -0.006223287724298064323 0.001385529722932521716 0.04188054793299136186 -0.09092046631802450096 -0.2596274878954057952 -0.3275790456348531832 +'MRO31-1706' .08711715795998192791 0.2076837804847151692 -0.3719424387026276646 0.1357571408978750782 0.2274215193331486085 0.1329200637795422135 0.325986138347081289 0.1371108348814457922 -0.1967981106213541331 -0.01485436431130437301 -0.01301222189154930056 0.1490118495066197757 0.08888556522994020548 0.2058439834485481235 0.3639985386796026345 0.1392312219789940131 0.2336553873293709671 +'MRO32-1706' 0.002204780672650812155 -0.08513386090556848695 0.2271558161996131142 -0.2174581476603746899 -0.3248048539011507696 -0.03033060034554384277 -0.1976693397106427663 -0.03349391549637302512 0.2823037885580250705 0.01568778171216827014 -0.0001861918157847285539 -0.03874812913412495341 -0.002249535922494594591 -0.08437969019177483931 -0.2223042507266526358 -0.2230229911133639054 -0.333708103645014964 +'MRO33-1706' .02376605782231675651 -0.1458503121580901341 0.00822758814107140031 0.2497384068779923139 0.3622341776944859038 -0.0004383955360670803263 -0.01336587985263110352 8.929494625889891732e-05 -0.314006684307413908 -0.01644976023889444319 0.0003480352786931168807 -0.0002406802555495012443 0.0242484894169119336 -0.1445582759123793526 -0.008051864343993343082 0.2561293154432830455 0.3721634053862579727 +'MRO41-1706' 0.04152203387525037204 -0.1752611798897343032 0.3656618629005881638 -0.1832182112847341449 -0.3180248248375751596 -0.07710392238485595795 -0.2863450522051803615 -0.09471444922521680965 0.245806252801942321 0.01467881660550873942 0.00317184991937523135 -0.1029879158821386947 -0.0423648973052325184 -0.1737086031860373692 -0.3578521026289516738 -0.187906840680808207 -0.326742226706019212 +'MRO42-1706' 0.0006186237104445340427 -0.01642587448840864342 -0.1369535374081572721 0.2461103410469845931 0.3925103219146011679 0.009027117582519181629 0.1033374251872434119 0.008469699455115612535 -0.3036912924450048124 -0.01787380603422548259 -0.00143387490026280367 0.01135606771336500689 -0.0006311812673315621335 -0.0162803634854324121 0.1340285009085180057 0.2524084059152057469 0.4032694512227910644 +'MRO43-1706' 0.08221783114419019267 0.2570286385302366083 -0.1371119582080091992 -0.254144306543879539 -0.4144548760409454968 -0.0004114704945558465138 0.1143356893380604589 -0.01363770164907001509 0.3190705992750625386 0.01681408124898283937 -0.008246640988500159725 -0.01082706281544928116 -0.08388678607477202676 0.254751712877812897 0.1341835381767676194 -0.2606479638940469301 -0.4258155291365972039 +'MRP11-1706' 0.02748283000027591794 -0.1405072101460464185 0.07048084432354789763 -0.09606075786900664104 0.1702560820585738155 0.04947278815567629495 -0.1123118378097654191 0.1789795646800260709 -0.07823527060214552353 0.2940222386631903273 0.1111268577960597137 0.03763193465351765549 -0.02804070903937222123 -0.13926250654818495 -0.06897552327764193414 -0.09851899217877094217 0.1749229840484087251 +'MRP12-1706' .0931295139803695049 -0.02595720028830306864 -0.1514900343153851581 0.2040307770766470741 -0.1547671122997557325 -0.07105573619661578744 0.0018035190138875883 -0.07628787395845018637 -0.05880217978628444336 -0.3280915268834389553 -0.06170140730825360992 -0.07500840753180212928 0.09501996717497693257 -0.02572725464668311826 0.1482545291353801198 0.2092520085928675777 -0.1590094450001184878 +'MRP13-1706' .2115313331810317055 -0.1979795999163342646 -0.1773300089107257282 0.1791671793914443034 -0.129942997425514073 -0.1053042416643629742 -0.1697742884644727057 -0.001526718480467759154 -0.04556171358429891849 -0.2917272309729673219 0.02065987671007081874 -0.1412330144410109678 0.2158252467588040735 -0.1962257687779685178 0.1735426167895614824 0.1837521412149221434 -0.1335048744869256621 +'MRP21-1706' .1059050275956029408 0.2259068501607105761 -0.06482051915468850511 0.157586233001309084 -0.1045439499578527526 0.09633096497930783431 0.2304836081772463074 -0.1880002055480553824 -0.0291331444751189092 -0.2507370675528401982 -0.1171380242104116121 0.009074192022111760361 0.1080548132992553423 0.2239056214060842764 0.06343609062482903627 0.1616189295290481609 -0.1074096118607012484 +'MRP22-1706' 0.08275366367863590256 -0.147092236625264855 0.1068427140129646902 -0.2173906904690626196 0.1108255042931935441 -0.0235029569255204851 -0.1727238249174085916 0.1302747969075241929 0.09023369860717134205 0.2862600468267264553 0.08910007763672668502 0.009197146191244270214 -0.08443349557274115735 -0.145789198610670051 -0.1045607807082625795 -0.2229538076647767098 0.1138633503440172889 +'MRP31-1706' 0.125147999725753245 -0.2120791308262151287 0.1368472811359962016 -0.2477252155177564197 0.01115434696923150656 -0.09848861390551283401 -0.2476026524321700562 0.09103067709860200585 0.1583258156037012365 0.2139307892448033266 0.08375838548761022073 -0.02757319466598229241 -0.1276884020726413715 -0.2102003969384926285 -0.1339245140445100291 -0.2540646056879851677 0.01146009959455097406 +'MRP32-1706' .100696815012841473 0.005598418676739944436 -0.123708774023335924 0.3127519655012597211 0.01777961042714985493 0.00368555345856103056 0.09567060089618774354 -0.05123250450519883925 -0.2302702342721110185 -0.2243057126641644639 -0.03932388627252543511 -0.01441527045830245587 0.1027408782479179994 0.005548824269007913979 0.1210666175212700563 0.3207554169532023658 0.01826696863648776675 +'MRP33-1706' .1969155068701943512 -0.2475704509676388276 -0.07645127230875255198 0.2986525259336447191 0.007838380115800350906 -0.04965970364450122965 -0.1271266615553836299 -0.002355145126734140004 -0.2219143248827675496 -0.2269423320523189236 0.01637653028347950748 -0.05317337855326999263 0.2009127310918193687 -0.2453773120481249626 0.0748184356096864428 0.3062951669270563282 0.008053238529768351472 +'MRP34-1706' 0.3502081335909552062 0.3820078347044149059 -0.01367046051229097586 -0.2174682698343872178 -0.02899932134096130931 0.06885687531330923761 0.2873295648216210862 -0.07029144813375601264 0.1696495810992718067 0.1657119735469045063 -0.123536125123628257 0.04069105529517456216 -0.357317073137918606 0.3786237626288707081 0.01337848852878420654 -0.2230333723179732941 -0.02979422387151192675 +'MRT11-1706' .2957980748847682251 -0.1050610691674800645 0.2222351434762992461 0.01458100867459895256 0.04447924162409928883 -0.07998024115311103133 -0.2367940784368867124 0.2927056643141205949 -0.04414855025894403456 -0.009764492725799666512 0.3488599002429279561 0.2689302815703668026 0.3018025346067689796 -0.1041303703752115978 -0.2174886731150887931 0.01495414268467773998 0.04569846538827848637 +'MRT12-1706' .390826910040320219 -0.2213572815071022659 0.2833093884197113721 0.04173974353899975731 0.08857216672439705007 -0.03985187575672158311 -0.3095602837305387878 0.239905408234199008 -0.09160403874322066431 -0.01197020785157400409 0.2637323345274371067 0.2214318392971479643 0.3987603776280498336 -0.2193963557694242061 -0.2772585019840553278 0.04280788074637272705 0.09100002490210296058 +'MRT13-1706' 0.3827902272225388591 0.3463004073510678182 -0.2913687386737445206 -0.09965066348789816675 -0.1585554442495373806 0.01147712910421835875 0.3412446774503195002 -0.1479004267071167833 0.1740133991651602874 0.01905376317115334284 -0.1549872191971216617 -0.1306504439930761541 -0.3905605567022985003 0.3432326547245461712 0.2851457216447313425 -0.1022007649592062972 -0.162901619195656211 +'MRT14-1706' .3371102895502340879 -0.3780659255710286382 0.2742499285884065774 0.1341557923905827565 0.1768366880577554034 0.005868339126459232169 -0.3297996325490215042 0.1170846569859600173 -0.2011739297334531607 -0.01726290882101528049 0.1106597352527435296 0.1040161009761790128 0.3439533535433480504 -0.3747167734720156518 -0.2683925329612034116 0.1375888943046636448 0.1816839715227221985 +'MRT15-1706' 0.2152357650663302702 0.3607972877972185355 -0.1660859801752261333 -0.2213257558393851576 -0.2103821977358218132 0.002030419543749620304 0.2413118683090362537 -0.0491439480729107675 0.2687328730280011402 0.04597751964976206501 -0.04668421529222619576 -0.0299072442017636643 -0.2196048755907252237 0.3576011124425654275 0.162538736611570922 -0.2269895729766683579 -0.2161489996342783049 +'MRT16-1706' 0.08716223182764745725 0.1797849274874827596 0.008304484644820366371 -0.298885496265823003 -0.2179973766508081778 0.007001523163325838045 0.04026951520908507443 0.001393035515824442121 0.3122573498599781061 0.08609269632732095834 -0.002458781276855592432 0.00654308859675637941 -0.08893155406036545862 0.1781922765064239689 -0.008127118501845905993 -0.3065340990658705356 -0.2239729187786978215 +'MRT21-1706' 0.1673890899765069495 0.04098873387037455657 -0.1566486630026843463 -0.00462520483834651195 -0.01758499894174973821 0.09126110276667848131 0.1439004855539918193 -0.3539446394773650417 0.01517383133724756021 0.004043605197747838532 -0.3788419305017089456 -0.3369388146054176358 -0.1707869520114706219 0.04062562919790108085 0.1533029804772525484 -0.004743565732800578832 -0.0180670226413451665 +'MRT22-1706' 0.3354920127807168306 0.143916804298337031 -0.2647445266487256643 -0.02229538671280962073 -0.05939535000483622817 0.06354365791657073936 0.2566436408767915345 -0.3074563998201390036 0.05453519215382589963 0.009326016542110255464 -0.320859687441135466 -0.2875775665682340776 -0.342302227074976595 0.142641896313781158 0.2590901462056753868 -0.02286593483030031904 -0.06102344031311165984 +'MRT23-1706' .4048004375153635981 -0.332811047923227743 0.3349981367351722028 0.088510549348795306 0.163077185729994939 -0.0256787243159148082 -0.335493155927043929 0.185413849509261569 -0.1537714355642708919 -0.01732529806686393392 0.1823514863682711429 0.1680461142070909797 0.4130175563166139652 -0.3298627927530659587 -0.327843288486592721 0.09077557071664665855 0.1675473064644668886 +'MRT24-1706' 0.3734840052083489015 0.3810734620099462955 -0.3287594468202453823 -0.1248391293708276811 -0.191007202675304355 0.004587655768895609887 0.3368658695943041459 -0.1526173738218654374 0.1856113116134285312 0.01703476785224634568 -0.1360489298190472318 -0.1383997105297779251 -0.3810654259696526491 0.3776976672110866629 0.321737843729523354 -0.1280338140456972473 -0.1962429151588765963 +'MRT25-1706' .2785672768022660617 -0.4040038823157319769 0.2776109728124044884 0.1897332765842290325 0.2437716367452433808 0.005967384230719477434 -0.2955134698020839834 0.08878916553368973452 -0.2446673193495453591 -0.02091472215848995397 0.07082767249095331397 0.07708875741095530532 0.2842219653734416873 -0.4004249550468345076 -0.2716817924236087922 0.1945886291813776758 0.2504536790126103418 +'MRT26-1706' .1022983664920729674 -0.2776884350535903656 0.1292094029207832562 0.2434004965123313935 0.3089813607156164932 0.001401847574857818801 -0.1421536790300834963 0.01752630158418001793 -0.3089435259932729605 -0.02193766761872376417 0.01239953072074249409 0.01280821980835544598 0.1043749399162489516 -0.2752284915828143164 -0.1264497646756350402 0.2496292153441794226 0.3174508715237502887 +'MRT31-1706' 0.3083285689478249547 0.1154818900634395906 -0.285500189410889893 -0.01586863740012325885 -0.06020566400364342485 0.07240343938744431274 0.2428181212324489191 -0.3468885592541476881 0.04856388096721252212 0.007209894006635116613 -0.3314017856138185558 -0.3307426892346994607 -0.3145873874817540772 0.1144588769105885917 0.2794025121220443664 -0.01627472235897176392 -0.06185596588854919142 +'MRT32-1706' 0.3920952672749096202 0.2330505338991125386 -0.3518439179137804462 -0.04654402162162415979 -0.1158635653696272749 0.04122362595902062665 0.3100210419010489549 -0.2779933243432904932 0.09707782229058130319 0.01147139082660934145 -0.2532020048523628275 -0.2613860178921262323 -0.4000544814802640126 0.2309860217810066618 0.3443292795805862339 -0.04773510228143647283 -0.119039510083231409 +'MRT33-1706' .4058669528527497627 -0.3753771279781216719 0.3955700004671601766 0.1111433744794785711 0.2113314665185665464 -0.01420040483235926465 -0.3501976804696779189 0.1950894183850811203 -0.177878232995817176 -0.01532905570521735095 0.1623465528842618355 0.1813105441220455027 0.4141057210456965398 -0.3720517949844367456 -0.3871214659391294943 0.1139875791527438786 0.2171242888934578064 +'MRT34-1706' 0.3342535360160707181 0.4057218011024366078 -0.3572932696566119559 -0.1584105486746239522 -0.2494793797665892932 -0.00259887151166174335 0.3233437238561964744 -0.1366350186115352361 0.2149506220699262948 0.01648828468929573743 -0.1022137807245685898 -0.1252535040680128886 -0.3410386102418806464 0.4021276553996066538 0.3496622447513816345 -0.1624643397795365873 -0.2563178773977923819 +'MRT35-1706' .1798462919634778168 -0.3556237791433183304 0.2452662005443273785 0.2249706917303061771 0.327444391677241764 0.006152157510481079394 -0.2257756384973783337 0.05121100587044737085 -0.2844248597018838032 -0.01745638284769740131 0.03248447491655015451 0.04479292710329174643 0.1834970250409888037 -0.352473434069035807 -0.240027835750711821 0.2307277842764318965 0.3364199939852583476 +'MRT41-1706' .342503416282284423 -0.1588478603759111152 0.3309627483116839852 0.02608350887476881472 0.07986763368342182645 -0.05776620403283341809 -0.2600671751594011427 0.3509531804746297556 -0.05991343367436408746 -0.007996904994250479681 0.2990682815994545329 0.3354277233831924887 0.349455956350423147 -0.1574406834551183854 -0.3238940873836535506 0.02675099659667950699 0.08205689126561106772 +'MRT42-1706' .4032976705291579367 -0.3228098410385641381 0.4144854629966301385 0.08403390349082605348 0.1929331992972388721 -0.0281426537395409182 -0.3294007709211726476 0.2321754364208655219 -0.1457941983477845371 -0.01380140457132374848 0.1876867520014548762 0.2180123026442746248 0.411484284385966903 -0.3199501830171135319 -0.4056329343889039096 0.08618436564964293556 0.1982217054158968428 +'MRT43-1706' 0.3666394628932131416 0.3803014490187239804 -0.4046003228983229283 -0.1301149689142950538 -0.2400269054143220893 0.009227176221504845843 0.3258644619749146987 -0.1806605924666062069 0.1839670022425759222 0.01710735668576828655 -0.1331772435373809738 -0.1667954193905802629 -0.3740819450266614776 0.3769324932094561542 0.3959589198747823779 -0.1334446644933701409 -0.2466063005757039572 +'MRT44-1706' .2476818659884404694 -0.3881425512609436579 0.3323773856539967708 0.1953330602348201106 0.3237058073324557972 0.004972444866466287083 -0.2688995707705105209 0.09137048577531849125 -0.2490094177243531437 -0.01588587950451505679 0.05765880356308331761 0.08348799747159392493 0.2527096059045198517 -0.3847041339047420627 -0.3252785110787811407 0.2003317135991344033 0.3325789310299764323 +'MZC01-1706' 0.02019300889983394881 0.1402188357850339961 0.07248058238809959586 -0.009326939965943793071 -0.1218544587159723636 -0.1549945219448504163 0.02001082669780943762 -0.07356499216768871974 0.2941154377800699882 0.1125678135158421633 -0.1379741446013496298 -0.1803368512726943595 -0.02060291051482008445 0.1389766867934757177 -0.07093255118706195961 -0.009565620196435626818 -0.1251946202478005365 +'MZC02-1706' .03095008230892063936 -0.1304917884832104136 0.001017510605822849251 0.03101869907137164151 0.1043926022158073591 0.1842814355617958533 -0.0003775164637455381681 0.1224178420661012068 -0.3122185721876272191 0.00949022300987163378 0.1257338856882518341 0.09819214022686766075 0.0315783437426332067 -0.1293358079577441311 -0.0009957787417386679968 0.03181248034057086727 0.1072541155145650821 +'MZF01-1706' .4238778184828426721 0.362626384987233874 0.3258691643671041138 0.09661617574480141357 -0.1584945773865845675 0.02348538437289832137 -0.3392282875688631405 -0.1763786227422756425 0.1568188688576882539 -0.01231037757463507819 -0.1810903657389125454 -0.1642260084558608835 0.4324821925617519658 0.359414006308560019 -0.3189092915670317385 0.09908862342648597221 -0.1628390839066454487 +'MZF02-1706' .3951791165152739316 0.3144966655877023953 -0.1150899148085675616 0.157488025794488673 0.06408943612263484635 0.1450594286368126484 -0.2608602793145025633 -0.03372832036102280107 0.04325673744016556022 -0.1979513651183880396 -0.1870528524445073393 0.1678299972758514336 0.4032009303455910687 0.3117106510425017296 0.1126318388221682343 0.1615182091594063729 0.06584619637079573706 +'MZF03-1706' 0.08092322409149305118 0.06162665343583644678 0.1844695886683845043 -0.02406535815245120294 -0.1622746504127902945 -0.1314510816205053945 0.07703254794835286134 -0.07238598479369670602 0.2144567561892637697 0.1952843497189999944 -0.08219519528702012856 -0.2676815965122152363 -0.08256589955454703145 0.06108072474523034562 -0.1805297102969308787 -0.02468120056718410213 -0.1667227727926455516 +'MZO01-1706' 0.1307758399349754908 -0.2212168536876731595 0.3329480808214752563 -0.1141536834264475775 -0.1566273955788392569 -0.1966640449024798232 -0.3442769741360834357 -0.1452304777154629079 0.1631011801756426238 0.02627338333863271647 0.03619828338696071124 -0.1715630803802632165 -0.1334304828490860129 -0.2192571719502987293 -0.3258370174103475403 -0.1170749231439972421 -0.16092072064101276 +'MZO02-1706' .1265628459513608028 0.2119313183642511644 -0.4246825760479908674 0.1015195125529895909 0.1979067463883590894 0.1930384919643478026 0.3383229901496460634 0.2090938523144613426 -0.1551049378954044433 -0.01336722097785999694 -0.02883766379597153817 0.2232949949226682995 0.1291319685229420366 0.210053893894764393 0.4156122587768196763 0.1041174386406498176 0.2033315827722001756 +'MZP01-1706' .0441301273643714756 0.1801505816427972639 -0.01524715863803512497 0.06289124448329069805 -0.1380465225571813059 0.006365989883024572582 0.1501663046130006784 -0.2640751640578292148 0.1220114500346160119 -0.2367774399422623577 -0.1241855346546572453 -0.02463501511214079981 0.04502593296550447266 0.1785546914611151059 0.01492151173342741444 0.06450065730078503867 -0.1418305259420956643 +'MZP02-1706' 0.1668301397608515091 -0.2756146240200646469 0.1095081489823545168 -0.1666520773266773614 0.03611928595975111983 -0.2103212184787807693 -0.2890710184374202241 0.1321399295104344895 0.07482911456239958736 0.1873395142419100046 0.1324403813939175056 -0.05491271919303714055 -0.1702166555622137145 -0.2731730517065553698 -0.1071692876514003662 -0.170916772540060713 0.03710935436423247469 +}; +coef(end).label = temp(:,1); +coef(end).value = cell2mat(temp(:,2:end)); + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +% remove the '-1706' part from all channel labels +for i=1:5 + for j=1:length(coef(i).reference) + coef(i).reference{j} = coef(i).reference{j}(1:(end-5)); + end + for j=1:length(coef(i).label) + coef(i).label{j} = coef(i).label{j}(1:(end-5)); + end +end diff --git a/read_ctf_dat.m b/read_ctf_dat.m new file mode 100644 index 0000000..4f1b5e2 --- /dev/null +++ b/read_ctf_dat.m @@ -0,0 +1,66 @@ +function [meg] = read_ctf_dat(filename); + +% READ_CTF_DAT reads MEG data from an ascii format CTF file +% +% meg = read_ctf_dat(filename) +% +% returns a structure with the following fields: +% meg.data Nchans x Ntime +% meg.time 1xNtime in miliseconds +% meg.trigger 1xNtime with trigger values +% meg.label 1xNchans cell array with channel labels (string) + +% Copyright (C) 2002, Robert Oostenveld +% +fid = fopen(filename, 'r'); +if fid==-1 + error(sprintf('could not open file %s', filename)); +end + +% read the sample number +line = fgetl(fid); +[tok, rem] = strtok(line, ':'); +meg.sample = str2num(rem(2:end)); + +% read the time of each sample and convert to miliseconds +line = fgetl(fid); +[tok, rem] = strtok(line, ':'); +meg.time = 1000*str2num(rem(2:end)); + +% read the trigger channel +line = fgetl(fid); +[tok, rem] = strtok(line, ':'); +meg.trigger = str2num(rem(2:end)); + +% read the rest of the data +meg.data = []; +meg.label = {}; +chan = 0; +while (1) + line = fgetl(fid); + if ~isempty(line) & line==-1 + % reached end of file + break + end + [tok, rem] = strtok(line, ':'); + if ~isempty(rem) + chan = chan + 1; + meg.data(chan, :) = str2num(rem(2:end)); + meg.label{chan} = fliplr(deblank(fliplr(deblank(tok)))); + end +end + +% convert to fT (?) +meg.data = meg.data * 1e15; + +% apparently multiple copies of the data can be stored in the file +% representing the average, the standard deviation, etc. +% keep only the first part of the data -> average +tmp = find(diff(meg.time)<0); +if ~isempty(tmp) + meg.data = meg.data(:,1:tmp(1)); + meg.time = meg.time(1:tmp(1)); + meg.trigger = meg.trigger(1:tmp(1)); + meg.sample = meg.sample(1:tmp(1)); +end + diff --git a/read_ctf_ds.m b/read_ctf_ds.m new file mode 100644 index 0000000..2e4b1c7 --- /dev/null +++ b/read_ctf_ds.m @@ -0,0 +1,73 @@ +function [meg, hdr, hc] = read_ctf_ds(fname, trial) + +% READ_CTF_DS reads specified trials from a CTF dataset +% +% [meg, hdr, hc] = read_ctf_ds(filename, trial) +% +% Where +% filename name of the dataset directory +% trial number of trials to read (can be multiple) +% and +% meg raw channel data +% hdr header information +% hc head coordinate system information +% +% Due to a non-dislosure agreement between CTF and the F.C. Donders Centre, +% the allowed use of this function is limited. Do not distribute this function. + +% This program is provided to users of CTF MEG systems as a courtesy only. Please +% do not redistribute it without permission from CTF Systems Inc. +% This program has no warranty whatsoever. + +% Original author: Jim McKay November 1999 +% Copyright (C) 1999-2000 CTF Systems Inc. All Rights Reserved. +% +% modifications Copyright (C) 2002, Ole Jensen +% modifications Copyright (C) 2003, Robert Oostenveld +% +% construct the filenames for this dataset +[path, name, ext] = fileparts(fname); +fnameRes = fullfile(path, [name '.ds' filesep name '.res4']); +fnameMeg = fullfile(path, [name '.ds' filesep name '.meg4']); +fnameHc = fullfile(path, [name '.ds' filesep name '.hc']); + +% read header information +hdr = read_ctf_res4(fnameRes); + +% read head location information +hc = read_ctf_hc(fnameHc); + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% read the actual data +% this is from Ole's getTrialCTF +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +fid = fopen(fnameMeg,'r','ieee-be'); + +if fid == -1 + errMsg = strcat('Could not open data file:',fnameMeg); + error(errMsg); +end + +CTFformat =setstr(fread(fid,8,'char'))'; +if (strcmp(CTFformat(1,1:7),'MEG41CP')==0), + fclose(fid) + error('datafile is not in CTF MEG4 format') +end + +% assign trial information to output +meg.Trial = trial; + +for i=1:length(trial) + Trial = trial(i); + fseek(fid, hdr.nSamples*hdr.nChans*4*(Trial-1)+8, 'bof'); + B = fread(fid,[hdr.nSamples,hdr.nChans],'int32'); + for j=1:hdr.nChans + B(:,j) = hdr.gainV(j)*B(:,j); + end + % assign channel data to output + meg.data(i,:,:) = B'; +end + +fclose(fid); + diff --git a/read_ctf_hc.m b/read_ctf_hc.m new file mode 100644 index 0000000..008d264 --- /dev/null +++ b/read_ctf_hc.m @@ -0,0 +1,185 @@ +function [hc] = read_ctf_hc(filename); + +% READ_CTF_HC reads the MEG headcoil marker positions from an ascii file +% and computes the coordinate transformation required to get from from +% dewar to head-coordinates +% +% the definition of head coordinates is according to CTF standard: +% - the origin is exactly between LPA and RPA +% - the positive x-axis goes throught NAS +% - the positive y-axis goes (approximately) through LPA +% - the positive z-axis goes up, orthogonal to the x- and y-axes +% +% hc = read_ctf_hc(filename) +% +% returns a structure with the following fields +% hc.dewar.nas marker positions relative to dewar +% hc.dewar.lpa +% hc.dewar.rpa +% hc.head.nas marker positions relative to head (measured) +% hc.head.lpa +% hc.head.rpa +% hc.standard.nas marker positions relative to head (expected) +% hc.standard.lpa +% hc.standard.rpa +% and +% hc.affine parameter for affine transformation (1x12) +% hc.homogenous homogenous transformation matrix (4x4, see warp3d) +% hc.translation translation vector (1x3) +% hc.rotation rotation matrix (3x3) +% +% Gradiometer positions can be transformed into head coordinates using the +% homogeneous transformation matrix, or using the affine parameters and +% the warp3d function from the WARPING toolbox +% +% WARNING: all returned positions are in mm, and the transformation matrices +% also should be applied on channel positions that are in mm. + +% Copyright (C) 2002, Robert Oostenveld +% +global fb + +hc.standard.nas = [0 0 0]; +hc.standard.lpa = [0 0 0]; +hc.standard.rpa = [0 0 0]; +hc.dewar.nas = [0 0 0]; +hc.dewar.lpa = [0 0 0]; +hc.dewar.rpa = [0 0 0]; +hc.head.nas = [0 0 0]; +hc.head.lpa = [0 0 0]; +hc.head.rpa = [0 0 0]; + +fid = fopen(filename, 'r'); +if fid==-1 + error(sprintf('could not open file %s', filename)); +end + +fseek(fid, 0, 'bof'); +line = []; + +if fb + fprintf('reading standard coil positions with respect to the dewar\n'); +end +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% standard coil positions with respect to the dewar +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +while ~strcmp(line, 'standard nasion coil position relative to dewar (cm):') + line = fgetl(fid); + if ~ischar(line) & line==-1, error('premature end of file'), end +end +line = fgetl(fid); [t, r] = strtok(line, '='); hc.standard.nas(1) = str2num(r(2:end)); +line = fgetl(fid); [t, r] = strtok(line, '='); hc.standard.nas(2) = str2num(r(2:end)); +line = fgetl(fid); [t, r] = strtok(line, '='); hc.standard.nas(3) = str2num(r(2:end)); +% NOTE THAT THERE IS AN TYPING ERROR IN SOME CTF FILES WHICH I HAVE TO REPRODUCE HERE (staNdard) +while ~(strcmp(line, 'stadard left ear coil position relative to dewar (cm):') | ... + strcmp(line, 'standard left ear coil position relative to dewar (cm):')) + line = fgetl(fid); + if ~ischar(line) & line==-1, error('premature end of file'), end +end +line = fgetl(fid); [t, r] = strtok(line, '='); hc.standard.lpa(1) = str2num(r(2:end)); +line = fgetl(fid); [t, r] = strtok(line, '='); hc.standard.lpa(2) = str2num(r(2:end)); +line = fgetl(fid); [t, r] = strtok(line, '='); hc.standard.lpa(3) = str2num(r(2:end)); +while ~strcmp(line, 'standard right ear coil position relative to dewar (cm):') + line = fgetl(fid); + if ~ischar(line) & line==-1, error('premature end of file'), end +end +line = fgetl(fid); [t, r] = strtok(line, '='); hc.standard.rpa(1) = str2num(r(2:end)); +line = fgetl(fid); [t, r] = strtok(line, '='); hc.standard.rpa(2) = str2num(r(2:end)); +line = fgetl(fid); [t, r] = strtok(line, '='); hc.standard.rpa(3) = str2num(r(2:end)); + +if fb + fprintf('reading measured coil positions with respect to the dewar\n'); +end +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% measured coil positions with respect to the dewar +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +while ~strcmp(line, 'measured nasion coil position relative to dewar (cm):') + line = fgetl(fid); + if ~ischar(line) & line==-1, error('premature end of file'), end +end +line = fgetl(fid); [t, r] = strtok(line, '='); hc.dewar.nas(1) = str2num(r(2:end)); +line = fgetl(fid); [t, r] = strtok(line, '='); hc.dewar.nas(2) = str2num(r(2:end)); +line = fgetl(fid); [t, r] = strtok(line, '='); hc.dewar.nas(3) = str2num(r(2:end)); +while ~strcmp(line, 'measured left ear coil position relative to dewar (cm):') + line = fgetl(fid); + if ~ischar(line) & line==-1, error('premature end of file'), end +end +line = fgetl(fid); [t, r] = strtok(line, '='); hc.dewar.lpa(1) = str2num(r(2:end)); +line = fgetl(fid); [t, r] = strtok(line, '='); hc.dewar.lpa(2) = str2num(r(2:end)); +line = fgetl(fid); [t, r] = strtok(line, '='); hc.dewar.lpa(3) = str2num(r(2:end)); +while ~strcmp(line, 'measured right ear coil position relative to dewar (cm):') + line = fgetl(fid); + if ~ischar(line) & line==-1, error('premature end of file'), end +end +line = fgetl(fid); [t, r] = strtok(line, '='); hc.dewar.rpa(1) = str2num(r(2:end)); +line = fgetl(fid); [t, r] = strtok(line, '='); hc.dewar.rpa(2) = str2num(r(2:end)); +line = fgetl(fid); [t, r] = strtok(line, '='); hc.dewar.rpa(3) = str2num(r(2:end)); + +if fb + fprintf('reading measured coil positions with respect to the head\n'); +end +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% measured coil positions with respect to the head +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +while ~strcmp(line, 'measured nasion coil position relative to head (cm):') + line = fgetl(fid); + if ~ischar(line) & line==-1, error('premature end of file'), end +end +line = fgetl(fid); [t, r] = strtok(line, '='); hc.head.nas(1) = str2num(r(2:end)); +line = fgetl(fid); [t, r] = strtok(line, '='); hc.head.nas(2) = str2num(r(2:end)); +line = fgetl(fid); [t, r] = strtok(line, '='); hc.head.nas(3) = str2num(r(2:end)); +while ~strcmp(line, 'measured left ear coil position relative to head (cm):') + line = fgetl(fid); + if ~ischar(line) & line==-1, error('premature end of file'), end +end +line = fgetl(fid); [t, r] = strtok(line, '='); hc.head.lpa(1) = str2num(r(2:end)); +line = fgetl(fid); [t, r] = strtok(line, '='); hc.head.lpa(2) = str2num(r(2:end)); +line = fgetl(fid); [t, r] = strtok(line, '='); hc.head.lpa(3) = str2num(r(2:end)); +while ~strcmp(line, 'measured right ear coil position relative to head (cm):') + line = fgetl(fid); + if ~ischar(line) & line==-1, error('premature end of file'), end +end +line = fgetl(fid); [t, r] = strtok(line, '='); hc.head.rpa(1) = str2num(r(2:end)); +line = fgetl(fid); [t, r] = strtok(line, '='); hc.head.rpa(2) = str2num(r(2:end)); +line = fgetl(fid); [t, r] = strtok(line, '='); hc.head.rpa(3) = str2num(r(2:end)); + +fclose(fid); + +if fb + fprintf('computing transformation matrix\n'); +end + +% change the marker positions from cm to mm +hc.standard.nas = 10*hc.standard.nas; +hc.standard.lpa = 10*hc.standard.lpa; +hc.standard.rpa = 10*hc.standard.rpa; +hc.dewar.nas = 10*hc.dewar.nas; +hc.dewar.lpa = 10*hc.dewar.lpa; +hc.dewar.rpa = 10*hc.dewar.rpa; +hc.head.nas = 10*hc.head.nas; +hc.head.lpa = 10*hc.head.lpa; +hc.head.rpa = 10*hc.head.rpa; + +% compute the direction of the head coordinate axes in dewar coordinates +d_x = hc.dewar.nas - (hc.dewar.lpa + hc.dewar.rpa)/2; +d_z = cross(d_x, hc.dewar.lpa - hc.dewar.rpa); +d_y = cross(d_z, d_x); +d_x = d_x / norm(d_x); +d_y = d_y / norm(d_y); +d_z = d_z / norm(d_z); + +% compute the translation and rotation which are neccessary to transform +% any given location from the dewar to the head coordinate system +hc.translation = -(hc.dewar.lpa + hc.dewar.rpa)/2; +hc.rotation = inv([d_x' d_y' d_z']); + +% construct the homogenous coordinate transformation matrix +% from the subsequent translation and rotation +hc.homogenous = eye(4,4); +hc.homogenous(1:3,4) = hc.rotation * hc.translation'; +hc.homogenous(1:3,1:3) = hc.rotation; + +% construct a vector with the 12 parameters for an affine warp +hc.affine = hc.homogenous'; +hc.affine = hc.affine(1:12); + diff --git a/read_ctf_hdm.m b/read_ctf_hdm.m new file mode 100644 index 0000000..e41a143 --- /dev/null +++ b/read_ctf_hdm.m @@ -0,0 +1,40 @@ +function [vol] = read_ctf_hdm(filename); + +% READ_CTF_HDM reads the head volume conductor model from a *.hdm file +% +% vol = read_ctf_hdm(filename) + +% Copyright (C) 2003, Robert Oostenveld +% +ascii = read_ctf_ascii(filename); + +if isfield(ascii, 'MultiSphere_Data') + chans = fieldnames(ascii.MultiSphere_Data); + % remove the first two fields: SEARCH_RADIUS and HEADSHAPE_FILE + chans = chans(3:end); + for i=1:length(chans) + tmp = getfield(ascii.MultiSphere_Data, chans{i}); + vol.label{i} = chans{i}; + vol.r(i) = tmp(4); + vol.o(i, :) = tmp(1:3); + end + vol.r = vol.r(:); % ensure column vector +elseif isfield(ascii, 'MEG_Sphere') + vol.r = ascii.MEG_Sphere.RADIUS; + vol.o(1) = ascii.MEG_Sphere.ORIGIN_X; + vol.o(2) = ascii.MEG_Sphere.ORIGIN_Y; + vol.o(3) = ascii.MEG_Sphere.ORIGIN_Z; +else + error('no headmodel information found'); +end + +% add the fiducials, these are in raw MRI coordinates +if isfield(ascii, 'Fid_Points') + vol.mri.nas = ascii.Fid_Points.NASION; + vol.mri.lpa = ascii.Fid_Points.LEFT_EAR; + vol.mri.rpa = ascii.Fid_Points.RIGHT_EAR; +end + +% add the units in which the volume conductor is defined +vol.unit = 'cm'; + diff --git a/read_ctf_meg4.m b/read_ctf_meg4.m new file mode 100644 index 0000000..7bcfdbd --- /dev/null +++ b/read_ctf_meg4.m @@ -0,0 +1,175 @@ +function [meg] = read_ctf_meg4(fname, hdr, begsample, endsample, chanindx) + +% READ_CTF_MEG4 reads specified samples from a CTF continous datafile +% It neglects all trial boundaries as if the data was acquired in +% non-continous mode. +% +% [meg] = read_ctf_meg4(filename, hdr, begsample, endsample) +% +% Where +% filename name of the datafile, including the .meg4 extension +% header with all data information (from read_ctf_meg4) +% begsample index of the first sample to read +% endsample index of the last sample to read +% chanindx index of channels to read (optional, default is all) +% +% Due to a non-dislosure agreement between CTF and the F.C. Donders Centre, +% the allowed use of this function is limited. Do not distribute this function. + +% This program is provided to users of CTF MEG systems as a courtesy only. Please +% do not redistribute it without permission from CTF Systems Inc. +% This program has no warranty whatsoever. + +% Copyright (C) 2003, Robert Oostenveld +% +% use global flag for feedback +global fb +if isempty(fb) + fb = 0; +end + +if begsample<1 + error('cannot read before the start of the data'); +end + +if endsample>hdr.nSamples*hdr.nChans*hdr.nTrials + error('cannot read beyond the end of the data'); +end + +if begsample>endsample + error('cannot read a negative number of samples'); +end + +if nargin<5 + % select all channels + chanindx = 1:hdr.nChans; +end + +if isempty(chanindx) + error('no channels were specified for reading CTF data') +end + +fid = fopen(fname,'r','ieee-be'); + +if fid == -1 + error('could not open datafile'); +end + +CTFformat = setstr(fread(fid,8,'char'))'; +if (strcmp(CTFformat(1,1:7),'MEG41CP')==0), + error('datafile is not in CTF MEG4 format') +end + +% the data is not channel multiplexed, but stored in trials +% in each trial first all samples for channel 1 are given, then all samples of channel 2 ... +% this means that we have to read each channel for each trial + +begtrial = ceil(begsample/hdr.nSamples); +endtrial = ceil(endsample/hdr.nSamples); + +% this counts the files and offset if the 2GB file size boundary is encountered +multifilecount = 0; +multifileoffset = 0; +fseek(fid, 0, 'eof'); +multifilelength = ftell(fid); + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% read only the selected data, channel-wise +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +if endtrial==begtrial + rawbegsample = begsample - (begtrial-1)*hdr.nSamples; + rawendsample = endsample - (begtrial-1)*hdr.nSamples; + for chan=1:length(chanindx) + % jump to the begin of this channel in this trial + channeloffset = 8*(multifilecount+1)+(begtrial-1)*hdr.nSamples*4*hdr.nChans+(chanindx(chan)-1)*hdr.nSamples*4-multifileoffset; + if channeloffset>=multifilelength + % data goes beyond 2GB file boundary, jump to the next file + channeloffset = channeloffset - multifilelength+8; % change the current offset, keep the header + multifileoffset = multifileoffset + multifilelength; % remember for the next trial + multifilecount = multifilecount + 1; % increase the file counter + nextname = sprintf('%s.%d_meg4', fname(1:(end-5)), multifilecount); + fprintf('data goes beyond 2GB file boundary, continuing with %s\n', nextname); + fclose(fid); + fid = fopen(nextname,'r','ieee-be'); + fseek(fid, 0, 'eof'); + multifilelength = ftell(fid); % determine the length of the current file + end + fseek(fid, channeloffset, 'bof'); + % jump to the first sample of interest + fseek(fid, 4*(rawbegsample-1), 'cof'); + % read the data from this channel + [tmp, count] = fread(fid,[(endsample-begsample+1),1],'int32'); + raw(:,chan) = tmp; + end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% read and concatenate the raw data of all trials +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +else + raw = zeros((endtrial-begtrial+1)*hdr.nSamples, length(chanindx)); + for trial=begtrial:endtrial + + if length(chanindx)==hdr.nChans & all(chanindx(:)'==1:hdr.nChans) + % read the data from all channels + rawbegsample = (trial-begtrial)*hdr.nSamples + 1; + rawendsample = (trial-begtrial)*hdr.nSamples + hdr.nSamples; + % jump to the begin of this trial + trialoffset = 8*(multifilecount+1)+(trial-1)*hdr.nSamples*4*hdr.nChans-multifileoffset; + if trialoffset>=multifilelength + % data goes beyond 2GB file boundary, jump to the next file + trialoffset = trialoffset - multifilelength+8; % change the current offset, keep the header + multifileoffset = multifileoffset + multifilelength; % remember for the next trial + multifilecount = multifilecount + 1; % increase the file counter + nextname = sprintf('%s.%d_meg4', fname(1:(end-5)), multifilecount); + fprintf('data goes beyond 2GB file boundary, continuing with %s\n', nextname); + fclose(fid); + fid = fopen(nextname,'r','ieee-be'); + fseek(fid, 0, 'eof'); + multifilelength = ftell(fid); % determine the length of the current file + end + fseek(fid, trialoffset, 'bof'); + [tmp, count] = fread(fid,[hdr.nSamples,hdr.nChans],'int32'); + raw(rawbegsample:rawendsample,:) = tmp; + + else + % read the data from the selected channels + rawbegsample = (trial-begtrial)*hdr.nSamples + 1; + rawendsample = (trial-begtrial)*hdr.nSamples + hdr.nSamples; + for chan=1:length(chanindx) + % jump to the begin of this channel in this trial + channeloffset = 8*(multifilecount+1)+(trial-1)*hdr.nSamples*4*hdr.nChans+(chanindx(chan)-1)*hdr.nSamples*4-multifileoffset; + if channeloffset>=multifilelength + % data goes beyond 2GB file boundary, jump to the next file + channeloffset = channeloffset - multifilelength+8; % change the current offset, keep the header + multifileoffset = multifileoffset + multifilelength; % remember for the next trial + multifilecount = multifilecount + 1; % increase the file counter + nextname = sprintf('%s.%d_meg4', fname(1:(end-5)), multifilecount); + fprintf('data goes beyond 2GB file boundary, continuing with %s\n', nextname); + fclose(fid); + fid = fopen(nextname,'r','ieee-be'); + fseek(fid, 0, 'eof'); + multifilelength = ftell(fid); % determine the length of the current file + end + fseek(fid, channeloffset, 'bof'); + [tmp, count] = fread(fid,[hdr.nSamples,1],'int32'); + raw(rawbegsample:rawendsample,chan) = tmp; + end %chan + + end %read all channels + end %trial + + % select the raw data corresponding to the samples of interest + rawoffset = (begtrial-1)*hdr.nSamples; + rawbegsample = begsample - rawoffset; + rawendsample = endsample - rawoffset; + raw = raw(rawbegsample:rawendsample, :); +end +fclose(fid); + +% multiply the dimensionless values with the calibration value +gain = hdr.gainV(chanindx); % only for selected channels +meg = raw'; % transpose the raw data +for i=1:size(meg,1) + meg(i,:) = gain(i)*meg(i,:); +end + diff --git a/read_ctf_mri.m b/read_ctf_mri.m new file mode 100644 index 0000000..b3b8133 --- /dev/null +++ b/read_ctf_mri.m @@ -0,0 +1,134 @@ +function [mri, hdr] = read_ctf_mri(filename); + +% READ_CTF_MRI reads header and image data from CTF format MRI file +% +% [mri, hdr] = read_ctf_mri(filename) +% +% See also READ_CTF_MEG4, READ_CTF_RES4 + +% Copyright (C) 2003 Robert Oostenveld +% +fid = fopen(filename,'rb', 'ieee-be'); + +if fid<=0 + error(sprintf('could not open MRI file: %s\n', filename)); +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% READ THE IMAGE HEADER +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +warning off +% general header information +hdr.identifierString = setstr(fread(fid,32,'char'))'; % CTF_MRI_FORMAT VER 2.2 +hdr.imageSize = fread(fid,1,'int16'); % always = 256 +hdr.dataSize = fread(fid,1,'int16'); % 1 or 2(bytes) +hdr.clippingRange = fread(fid,1,'int16'); % max.integer value of data +hdr.imageOrientation = fread(fid,1,'int16'); % eg., 0 = left on left, 1 = left on right +hdr.mmPerPixel_sagittal = fread(fid,1,'float'); % voxel dimensions in mm +hdr.mmPerPixel_coronal = fread(fid,1,'float'); % voxel dimensions in mm +hdr.mmPerPixel_axial = fread(fid,1,'float'); % voxel dimensions in mm + +% HeadModel_Info specific header items +hdr.HeadModel.Nasion_Sag = fread(fid,1,'int16'); % fid.point coordinate(in voxels) for nasion - sagittal +hdr.HeadModel.Nasion_Cor = fread(fid,1,'int16'); % nasion - coronal +hdr.HeadModel.Nasion_Axi = fread(fid,1,'int16'); % nasion - axial +hdr.HeadModel.LeftEar_Sag = fread(fid,1,'int16'); % left ear - sagittal +hdr.HeadModel.LeftEar_Cor = fread(fid,1,'int16'); % left ear - coronal +hdr.HeadModel.LeftEar_Axi = fread(fid,1,'int16'); % left ear - axial +hdr.HeadModel.RightEar_Sag = fread(fid,1,'int16'); % right ear - sagittal +hdr.HeadModel.RightEar_Cor = fread(fid,1,'int16'); % right ear - coronal +hdr.HeadModel.RightEar_Axi = fread(fid,1,'int16'); % right ear - axial +fread(fid,2,'char'); % padding to 4 byte boundary +hdr.HeadModel.defaultSphereX = fread(fid,1,'float'); % sphere origin x coordinate(in mm) +hdr.HeadModel.defaultSphereY = fread(fid,1,'float'); % sphere origin y coordinate(in mm) +hdr.HeadModel.defaultSphereZ = fread(fid,1,'float'); % sphere origin z coordinate(in mm) +hdr.HeadModel.defaultSphereRadius = fread(fid,1,'float'); % default sphere radius(in mm) + +% Image_Info specific header items +hdr.Image.modality = fread(fid,1,'int16'); % 0 = MRI, 1 = CT, 2 = PET, 3 = SPECT, 4 = OTHER +hdr.Image.manufacturerName = setstr(fread(fid,64,'char'))'; +hdr.Image.instituteName = setstr(fread(fid,64,'char'))'; +hdr.Image.patientID = setstr(fread(fid,32,'char'))'; +hdr.Image.dateAndTime = setstr(fread(fid,32,'char'))'; +hdr.Image.scanType = setstr(fread(fid,32,'char'))'; +hdr.Image.contrastAgent = setstr(fread(fid,32,'char'))'; +hdr.Image.imagedNucleus = setstr(fread(fid,32,'char'))'; + +fread(fid,2,'char'); % padding to 4 byte boundary + +hdr.Image.Frequency = fread(fid,1,'float'); +hdr.Image.FieldStrength = fread(fid,1,'float'); +hdr.Image.EchoTime = fread(fid,1,'float'); +hdr.Image.RepetitionTime = fread(fid,1,'float'); +hdr.Image.InversionTime = fread(fid,1,'float'); +hdr.Image.FlipAngle = fread(fid,1,'float'); +hdr.Image.NoExcitations = fread(fid,1,'int16'); +hdr.Image.NoAcquisitions = fread(fid,1,'int16'); +hdr.Image.commentString = setstr(fread(fid,256,'char'))'; +hdr.Image.forFutureUse = setstr(fread(fid,64,'char'))'; + +% continuation general header +hdr.headOrigin_sagittal = fread(fid,1,'float'); % voxel location of head origin +hdr.headOrigin_coronal = fread(fid,1,'float'); % voxel location of head origin +hdr.headOrigin_axial = fread(fid,1,'float'); % voxel location of head origin +% euler angles to align MR to head coordinate system(angles in degrees !) +hdr.rotate_coronal = fread(fid,1,'float'); % 1. rotate in coronal plane by this angle +hdr.rotate_sagittal = fread(fid,1,'float'); % 2. rotate in sagittal plane by this angle +hdr.rotate_axial = fread(fid,1,'float'); % 3. rotate in axial plane by this angle +hdr.orthogonalFlag = fread(fid,1,'int16'); % if set then image is orthogonal +hdr.interpolatedFlag = fread(fid,1,'int16'); % if set than image was interpolated +hdr.originalSliceThickness = fread(fid,1,'float'); % original spacing between slices before interpolation +transformMatrix = fread(fid,[4 4],'float')', % transformation matrix head->MRI[column][row] +fread(fid,204,'char'); % unused, padding to 1028 bytes +warning on + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% READ THE IMAGE DATA +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +if hdr.dataSize==1 + mri = uint8(fread(fid, 256*256*256, 'uint8')); +elseif hdr.dataSize==2 + mri = uint16(fread(fid, 256*256*256, 'uint16')); +else + error('unknown datasize in CTF mri file'); +end +mri = reshape(mri, [256 256 256]); +fclose(fid); + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% DO POST-PROCESSING +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +% reorient the image data to obtain corresponding image data and transformation matrix +mri = permute(mri, [3 1 2]); % this was determined by trial and error + +% reorient the image data and the transformation matrix along the left-right direction +% remember that the fiducials in voxel coordinates also have to be flipped (see down) +mri = flipdim(mri, 1); +flip = [-1 0 0 256 + 0 1 0 0 + 0 0 1 0 + 0 0 0 1 ]; +transformMatrix = flip*transformMatrix; + +% re-compute the homogeneous transformation matrices (apply voxel scaling) +scale = eye(4); +scale(1,1) = hdr.mmPerPixel_sagittal; +scale(2,2) = hdr.mmPerPixel_coronal; +scale(3,3) = hdr.mmPerPixel_axial; +hdr.transformHead2MRI = transformMatrix*inv(scale); +hdr.transformMRI2Head = scale*inv(transformMatrix); + +% determine location of fiducials in MRI voxel coordinates +% flip the fiducials in voxel coordinates to correspond to the previous flip along left-right +hdr.fiducial.mri.nas = [256 - hdr.HeadModel.Nasion_Sag hdr.HeadModel.Nasion_Cor hdr.HeadModel.Nasion_Axi]; +hdr.fiducial.mri.lpa = [256 - hdr.HeadModel.LeftEar_Sag hdr.HeadModel.LeftEar_Cor hdr.HeadModel.LeftEar_Axi]; +hdr.fiducial.mri.rpa = [256 - hdr.HeadModel.RightEar_Sag hdr.HeadModel.RightEar_Cor hdr.HeadModel.RightEar_Axi]; + +% compute location of fiducials in MRI and HEAD coordinates + +% hdr.fiducial.head.nas = warp3d(hdr.transformMRI2Head, hdr.fiducial.mri.nas, 'homogenous'); +% hdr.fiducial.head.lpa = warp3d(hdr.transformMRI2Head, hdr.fiducial.mri.lpa, 'homogenous'); +% hdr.fiducial.head.rpa = warp3d(hdr.transformMRI2Head, hdr.fiducial.mri.rpa, 'homogenous'); diff --git a/read_ctf_res4.m b/read_ctf_res4.m new file mode 100644 index 0000000..22fdbef --- /dev/null +++ b/read_ctf_res4.m @@ -0,0 +1,237 @@ +function hdr = read_ctf_res4(fname) + +% READ_CTF_RES4 reads the header in RES4 format from a CTF dataset +% +% hdr = read_ctf_res4(filename) +% +% Due to a non-dislosure agreement between CTF and the F.C. Donders Centre, +% the allwoed use of this function is limited. Do not distribute this function. + +% This program is provided to users of CTF MEG systems as a courtesy only. Please +% do not redistribute it without permission from CTF Systems Inc. +% This program has no warranty whatsoever. + +% Author(s): Jim McKay November 1999 +% Last revision: Jim McKay +% Copyright (c) 1999-2000 CTF Systems Inc. All Rights Reserved. +% +% modifications Copyright (C) 2002, Ole Jensen +% modifications Copyright (C) 2003, Robert Oostenveld +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% read header information +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +fid = fopen(fname,'r','b'); + +% Check if header file exist +if fid == -1 + errMsg = strcat('Could not open header file:',fname); + error(errMsg); +end + +% first 8 bytes contain filetype + +% Check is fileformat is correct +r_head=setstr(fread(fid,8,'char'))'; +if (strcmp(r_head(1,1:7),'MEG41RS')==0), + fclose(fid) + errMsg = strcat('Resource file is not in CTF MEG4 format in file:',fname) + error(errMsg); +end %if + +% Read the initial parameters +appName = setstr(fread(fid,256,'char'))' ; +dataOrigin = setstr(fread(fid,256,'char'))' ; +dataDescrip = setstr(fread(fid,256,'char'))' ; +no_trial_avgd = fread(fid,1,'int16') ; +data_time = setstr(fread(fid,255,'char'))'; +data_date = setstr(fread(fid,255,'char'))'; + +fseek(fid,1288,'bof'); +% Read the general recording parameters +no_samples = fread(fid,1,'int32'); +no_channels = fread(fid,1,'int16'); +fseek(fid,2,'cof'); % hole of 2 bytes due to improper alignment +sample_rate = fread(fid,1,'double'); +epoch = fread(fid,1,'double'); +no_trials = fread(fid,1,'int16'); +fseek(fid,2,'cof'); % hole of 2 bytes due to improper alignment +preTrigpts=fread(fid,1,'int32'); + +fseek(fid,1360,'bof'); +% read in the meg4Filesetup structure +run_name = setstr(fread(fid,32,'char')'); +run_title = setstr(fread(fid,256,'char')'); +instruments = setstr(fread(fid,32,'char')'); +coll_desc = setstr(fread(fid,32,'char')'); +subj_id = setstr(fread(fid,32,'char')'); +operator = setstr(fread(fid,32,'char')') ; +sensFilename = setstr(fread(fid,60,'char')') ; + +fseek(fid,1839,'bof'); +% Read in the run description length +rd_len=fread(fid,1,'uint8'); +% Go to the run description and read it in +fseek(fid,1844,'bof'); +run_desc=setstr(fread(fid,rd_len,'char')'); + +% read in the filter information +temp=fread(fid,2,'uint8'); +num_filt=temp(2); +for fi=0:(num_filt-1), + filt_info=fread(fid,18,'uint8'); + num_fparm=filt_info(18); + if num_fparm ~= 0, + filt_parm=fread(fid,8*num_fparm,'uint8'); + end % if +end % for fi + +% Read in the channel names +for i=1:no_channels, + temp=fread(fid,32,'char')'; + temp(find(temp<32 )) = ' '; % remove non-printable characters + temp(find(temp>126)) = ' '; % remove non-printable characters + endstr = findstr(temp, '-'); temp(endstr:end) = ' '; % cut off at '-' + endstr = findstr(temp, ' '); temp(endstr:end) = ' '; % cut off at ' ' + chan_name(i,:) = char(temp); % as char array + chan_label{i} = deblank(char(temp)); % as cell array +end %for + +% pre-allocate some memory space +sensGain = zeros([no_channels,1]); +qGain = zeros([no_channels,1]); +ioGain = zeros([no_channels,1]); +sensType = zeros([no_channels,1]); + +% Read in the sensor information +fp = ftell(fid); +for chan=1:no_channels, + fread(fid,1,'uint8'); % Read and ignore 1 byte from enum + sensType(chan)=fread(fid,1,'uint8'); % Read sensor type + fread(fid,2,'uint8'); % Read and ignore originalRunNum + fread(fid,4,'uint8'); % Read and ignore coilShape + sensGain(chan)=fread(fid,1,'double'); % Read sensor gain in Phi0/Tesla + qGain(chan)=fread(fid,1,'double'); % Read qxx gain (usually 2^20 for Q20) + ioGain(chan)=fread(fid,1,'double'); % Read i/o gain of special sensors (usually 1.0) + ioOffset(chan)=fread(fid,1,'double'); + numCoils(chan)=fread(fid,1,'int16'); + grad_order_no(chan)=fread(fid,1,'int16'); + fread(fid,4,'char'); + + % read the coil positions and orientations + for i=1:8 + Chan(chan).coil(i).pos = fread(fid,3,'double')'; + fread(fid,1,'double'); + Chan(chan).coil(i).ori = fread(fid,3,'double')'; + fread(fid,3,'double'); + end + + % read the coil positions and orientations in head coordinates(?) + for i=1:8 + Chan(chan).coilHC(i).pos = fread(fid,3,'double')'; + fread(fid,1,'double'); + Chan(chan).coilHC(i).ori = fread(fid,3,'double')'; + fread(fid,3,'double'); + end + + % jump to the next sensor info record + fseek(fid, fp+chan*1328, 'bof'); +end % for chan + +% close the header file +fclose(fid); + +% determine the different channel types +rowMEG = []; +rowEEG = []; +rowTRIG = []; +rowREF = []; +rowALL = 1:no_channels; +for k=1:no_channels + if strcmp(char(chan_name(k,1)),'M') + rowMEG = [rowMEG k]; + end + if strcmp(char(chan_name(k,1:3)),'EEG') + rowEEG = [rowEEG k]; + end + if strcmp(char(chan_name(k,1:4)),'STIM') + rowTRIG = [rowTRIG k]; + end + if chan_name(k,1)=='B' | chan_name(k,1)=='G' | chan_name(k,1)=='P' | chan_name(k,1)=='Q' | chan_name(k,1)=='R' + rowREF = [rowREF k]; + end +end + +% assign all the variables that should be outputted as header information +hdr.Fs = sample_rate; +hdr.nChans = no_channels; +hdr.nSamples = no_samples; +hdr.nSamplesPre = preTrigpts; +hdr.timeVec = (1:no_samples)/sample_rate - preTrigpts/sample_rate; +hdr.nTrials = no_trials; +hdr.gainV = ioGain./(qGain.*sensGain); +hdr.label = chan_label(:); +hdr.nameALL = chan_name; +hdr.rowMEG = rowMEG; +hdr.rowEEG = rowEEG; +hdr.rowTRIG = rowTRIG; +hdr.rowREF = rowREF; +hdr.Chan = Chan; +% hdr.nameEEG = []; +% hdr.nameMEG = []; +% hdr.nameEOG = []; +% hdr.trigV = []; +% hdr.SwapData = []; + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% construct the gradiometer system in DEWAR coordinates +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +% combine the bottom and top coil of the MEG channels into hardware gradiometers +numMEG = length(hdr.rowMEG); +for i=1:numMEG + coil1_pos(i,:) = hdr.Chan(hdr.rowMEG(i)).coil(1).pos; + coil1_ori(i,:) = hdr.Chan(hdr.rowMEG(i)).coil(1).ori; + coil2_pos(i,:) = hdr.Chan(hdr.rowMEG(i)).coil(2).pos; + coil2_ori(i,:) = hdr.Chan(hdr.rowMEG(i)).coil(2).ori; +end + +% apparently, some coils are oriented to the wrong side +tmp = coil2_pos - coil1_pos; +sel = find(dot(coil1_ori, tmp, 2)<1); +coil1_ori(sel,:) = -coil1_ori(sel,:); +coil2_ori(sel,:) = -coil2_ori(sel,:); + +gradDEWAR.pnt = [coil1_pos; coil2_pos]; +gradDEWAR.ori = [coil1_ori; coil2_ori]; +gradDEWAR.tra = [eye(numMEG) -eye(numMEG)]; +gradDEWAR.label = hdr.label(rowMEG); + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% construct the gradiometer system in HEAD coordinates +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +% combine the bottom and top coil of the MEG channels into hardware gradiometers +numMEG = length(hdr.rowMEG); +for i=1:numMEG + coil1_pos(i,:) = hdr.Chan(hdr.rowMEG(i)).coilHC(1).pos; + coil1_ori(i,:) = hdr.Chan(hdr.rowMEG(i)).coilHC(1).ori; + coil2_pos(i,:) = hdr.Chan(hdr.rowMEG(i)).coilHC(2).pos; + coil2_ori(i,:) = hdr.Chan(hdr.rowMEG(i)).coilHC(2).ori; +end + +% apparently, some coils are oriented to the wrong side +tmp = coil2_pos - coil1_pos; +sel = find(dot(coil1_ori, tmp, 2)<1); +coil1_ori(sel,:) = -coil1_ori(sel,:); +coil2_ori(sel,:) = -coil2_ori(sel,:); + +gradHC.pnt = [coil1_pos; coil2_pos]; +gradHC.ori = [coil1_ori; coil2_ori]; +gradHC.tra = [eye(numMEG) eye(numMEG)]; +gradHC.label = hdr.label(rowMEG); + +hdr.grad = gradHC; % default is in head-coordinates +hdr.grad.unit = 'cm'; % this is default in all CTF software + diff --git a/read_ctf_sens.m b/read_ctf_sens.m new file mode 100644 index 0000000..52a86e0 --- /dev/null +++ b/read_ctf_sens.m @@ -0,0 +1,118 @@ +function [magn] = read_ctf_sens(filename); + +% READ_CTF_SENS reads MEG sensor information from CTF configuration file +% +% magn = read_ctf_sens(filename) +% +% where the returned structure meg has the fields +% magn.pnt position first coil +% magn.ori orientation first coil +% magn.pnt2 position second coil +% magn.ori2 orientation second coil + +% Copyright (C) 2002, Robert Oostenveld +% +fid = fopen(filename, 'r'); +if fid==-1 + error(sprintf('could not open file %s', filename)); +end + +% skip the first line +line = fgetl(fid); + +% read the channel parameters +chan = 0; +while (1) + line = fgetl(fid); + if ~isempty(line) & line==-1 + % reached end of file + break + end + + element = tokenize(line); + if ~isempty(element) + chan = chan+1; + + % channel label or name + name{chan} = strtok(element{1}, '-'); + + % type of channel (EEG/MEG etc.), convert to uppercase + type{chan} = upper(element{7}); + + % number of coils (magnetometer=1/gradiometer=2) + ncoils(chan) = str2num(element{2}); + + % polarity of channel + polarity(chan) = str2num(element{26}); + + % position of first coil + coil1.pnt(chan,:) = [str2num(element{17}) str2num(element{18}) str2num(element{19})]; + % direction of first coil + coil1.dir(chan,:) = [str2num(element{20}) str2num(element{21})]; + + % length of basline + baseline.length(chan) = str2num(element{16}); + % direction of baseline + baseline.dir(chan,:) = [str2num(element{22}) str2num(element{23})]; + + % direction of second coil + coil2.dir(chan,:) = [str2num(element{24}) str2num(element{25})]; + end +end + +% find the sensor gradiometer channels +indx = find(strcmp(type, 'GRAD1-SENS')); +nchan = length(indx); +label = name(indx); +pnt1 = coil1.pnt(indx,:) * 10; % convert from cm to mm + +% shift offset to origin to make triangulation +offset = [mean(pnt1(:,1)) mean(pnt1(:,2)) min(pnt1(:,3))]; +prj = elproj(pnt1 - repmat(offset, nchan, 1)); +tri = delaunay(prj(:,1), prj(:,2)); + +% compute the directional vectors of each gradiometer: bottom coil +a = coil1.dir(indx,1); +b = coil1.dir(indx,2); +[r1, r2, r3] = sph2cart(a*2*pi/360, pi/2 - b*2*pi/360, ones(nchan,1)); +r1 = -r1 .* polarity(indx)'; +r2 = -r2 .* polarity(indx)'; +r3 = -r3 .* polarity(indx)'; +ori1 = [r1 r2 r3]; + +% compute the directional vectors of each gradiometer: top coil +a = coil2.dir(indx,1); +b = coil2.dir(indx,2); +[r1, r2, r3] = sph2cart(a*2*pi/360, pi/2 - b*2*pi/360, ones(nchan,1)); +r1 = -r1 .* polarity(indx)'; +r2 = -r2 .* polarity(indx)'; +r3 = -r3 .* polarity(indx)'; +ori2 = [r1 r2 r3]; + +% compute the directional vectors of the baseline and the position of the 2nd coil +a = baseline.dir(indx,1); +b = baseline.dir(indx,2); +[r1, r2, r3] = sph2cart(a*2*pi/360, pi/2 - b*2*pi/360, ones(nchan,1)); +oriB = [r1 r2 r3]; +pnt2 = pnt1 + oriB .* repmat(baseline.length(indx)', 1, 3); + +magn.pnt = pnt1; +magn.ori = ori1; +magn.pnt2 = pnt2; +magn.ori2 = ori2; +magn.tri = tri; +magn.label = label; + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function [element] = tokenize(line); +count = 0; +while ~isempty(line) + [tok, line] = strtok(line); + if ~isempty(tok) + count = count+1; + element{count} = tok; + else + break; + end +end + diff --git a/read_ctf_shape.m b/read_ctf_shape.m new file mode 100644 index 0000000..23f6091 --- /dev/null +++ b/read_ctf_shape.m @@ -0,0 +1,23 @@ +function [shape] = read_ctf_shape(filename); + +% READ_CTF_SHAPE reads headshape points and header information +% from a CTF *.shape teh accompanying *.shape_info file. +% +% Use as +% [shape] = read_ctf_shape(filename) +% where filename should have the .shape extension + +% Copyright (C) 2003, Robert Oostenveld +% +shape = read_ctf_ascii([filename '_info']); + +if ~strcmp(shape.MRI_Info.COORDINATES, 'HEAD') + warning('points on head shape are NOT in headcoordinates') +end + +fid = fopen(filename, 'rb'); +num = fscanf(fid, '%d', 1); +shape.pnt = fscanf(fid, '%f', inf); +shape.pnt = reshape(shape.pnt, [3 num])'; +fclose(fid); + diff --git a/read_ctf_trigger.m b/read_ctf_trigger.m new file mode 100644 index 0000000..9f8d424 --- /dev/null +++ b/read_ctf_trigger.m @@ -0,0 +1,43 @@ +function [backpanel, frontpanel] = read_ctf_trigger(dataset) + +% READ_CTF_TRIGGER reads the STIM channel from a dataset and detects +% the trigger moments and values +% +% [backpanel, frontpanel] = read_ctf_trigger(dataset) +% +% This returns all samples of the STIM channel, converted to backpanel +% and frontpanel trigger values. Triggers are placed at the rising flank +% of the STIM channel. +% +% Triggers should be at least 9 samples long and are should not overlap +% each other. +% +% See also READ_CTF_MEG4, READ_CTF_RES4 + +% Copyright (C) 2003, Robert Oostenveld +% +[path, file, ext] = fileparts(dataset); +datafile = fullfile(dataset, [file '.meg4']); +headerfile = fullfile(dataset, [file '.res4']); + +% read the header from the raw CTF data +hdr = read_ctf_res4(headerfile); + +% number of samples to shift the assesment of the trigger value +% this is needed because it takes some time for the rising flank to get to the correct value +trigshift = fix(hdr.Fs * 9/1200); + +% read the stimulus channel from raw CTF data +stimindx = find(strcmp(hdr.label, 'STIM')); +stim = read_ctf_meg4(datafile, hdr, 1, hdr.nTrials*hdr.nSamples, stimindx); + +% determine the precise timing of the triggers +upflank = [0 (diff(stim)>0 & stim(1:(end-1))==0)]; +trigger = upflank(1:(end-trigshift)).*stim((1+trigshift):end); + +% determine the triggers on the backpanel, only take highest 16 bits +backpanel = fix(trigger / 2^16); + +% determine the triggers on the frontpanel, only take lowest 16 bits +frontpanel = double(bitand(uint32(trigger), 2^16-1)); + diff --git a/readdata-ssd.m b/readdata-ssd.m new file mode 100644 index 0000000..2a46ea5 --- /dev/null +++ b/readdata-ssd.m @@ -0,0 +1,87 @@ +% +% +% +% <>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> % +% < > % +% < DISCLAIMER: > % +% < > % +% < THIS PROGRAM IS INTENDED FOR RESEARCH PURPOSES ONLY. > % +% < THIS PROGRAM IS IN NO WAY INTENDED FOR CLINICAL OR > % +% < OFFICIAL USE. > % +% < > % +% <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<> % +% +% +% + +function [read,setup,sensorNames,sensorLocations,sensorOrientations] = readdata(folder,CHAN,TIME,TRIALS); + +[setup,sensorIndex,sensorInfo] = readresfile(folder); + +if nargin == 1 + CHAN = 'allchans'; + TIME = 'alltimes'; + TRIALS = 'alltrials'; +end + +[read,sensorNames,sensorLocations,sensorOrientations] = readmegfile(folder,setup,sensorIndex,sensorInfo,CHAN,TIME,TRIALS); + + + +% Use function [read,setup,sensorNames,sensorLocations] = readdata(folder); to read in parts +% or all of data in a dataset. readdata.m will access readresfile.m to read +% in header, gain/offset, and channel information. It will access +% readmegfile.m to read in the data. +% EXAMPLE: +% [read,sensorNames] = readdata('/data/directory/datasetname.ds'); +% +% Enter channel/time/trial parameters in on line 5 of readdata.m. +% FOR THE FUNCTION [read] = readmegfile(folder,setup,sensor,gain,'megsens','alltimes','alltrials'); +% +% INPUTS--------------------------------------------------------------------- +% folder: In readdata.m, this should remain as 'folder' everywhere in the +% program. It is in the command line of matlab where you indicate +% the file and directory of the dataset you wish to view. It will +% automatically be used in both readresfile.m and readmegfile.m. +% +% setup: Enter as 'setup'; setup header information acquired by readresfile.m. +% This input is needed for the program to work. +% +% sensorIndex: Enter as 'sensorIndex'; sensor information acquired by readresfile.m, +% such as megsens, othersens, refsens, and eegsens. +% +% sensorInfo: Emter as 'gain'; gain/offset information acquired by readresfile.m, +% including proper_gain, io_gain, and channel locations. +% +% CHAN: ex: [30:35] - an interval of the desired channels to be read. +% If CHAN = 'eegsens', only eeg channels/sensors will be read. +% If CHAN = 'megsens', only meg channels/sensors will be read. +% If CHAN = 'refsens', only reference channels/sensors will be read. +% If CHAN = 'othersens' only the other channels/sensors will be +% read. +% +% TIME: ex. [0 5] - seconds 0 to 5: the desired time interval to be read. +% If TIME = 'alltimes', the entire duration of the trial(s) will +% be read (i.e. TIME = [1:setup.duration]). +% +% TRIALS: If TRIALS = n, the nth trial will be read. +% If TRIALS = [3,5,8] (for example), trials 3,5, and 8 will be +% read and read{1} = data for trial three, read{2} = data for +% trial 5, and read{3} = data for trial 8. +% If TRIALS = [3:7] (for example), trials 3 through 7 will be +% read. +% If TRIALS = 'alltrials', the data for all of the trials will be +% read (i.e. TRIALS = [1:setup.duration]). +% +% OUTPUTS-------------------------------------------------------------------- +% read: read contains all of the data. ex. type read{1} for it to display the first +% set of data on the screen. +% +%---------------------------------------------------------------------------- +% +% EXAMPLE: +% [read] = readmegfile(folder,setup,sensorIndex,sensorInfo,'megsens',[0 4],'alltrials'); + + + + diff --git a/readdata.m b/readdata.m new file mode 100644 index 0000000..3e2ef2c --- /dev/null +++ b/readdata.m @@ -0,0 +1,83 @@ +% +% +% +% <>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> % +% < > % +% < DISCLAIMER: > % +% < > % +% < THIS PROGRAM IS INTENDED FOR RESEARCH PURPOSES ONLY. > % +% < THIS PROGRAM IS IN NO WAY INTENDED FOR CLINICAL OR > % +% < OFFICIAL USE. > % +% < > % +% <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<> % +% +% +% + +function [read,setup,sensorNames,sensorLocations,sensorOrientations] = readdata(folder,CHAN,TIME,TRIALS); + +[setup,sensorIndex,sensorInfo] = readresfile(folder); + +if nargin == 1 + CHAN = 'allchans'; + TIME = 'alltimes'; + TRIALS = 'alltrials'; +end + +[read,sensorNames,sensorLocations,sensorOrientations] = readmegfile(folder,setup,sensorIndex,sensorInfo,CHAN,TIME,TRIALS); + + + +% Use function [read,setup,sensorNames,sensorLocations] = readdata(folder); to read in parts +% or all of data in a dataset. readdata.m will access readresfile.m to read +% in header, gain/offset, and channel information. It will access +% readmegfile.m to read in the data. +% EXAMPLE: +% [read,sensorNames] = readdata('/data/directory/datasetname.ds'); +% +% Enter channel/time/trial parameters in on line 5 of readdata.m. +% FOR THE FUNCTION [read] = readmegfile(folder,setup,sensor,gain,'megsens','alltimes','alltrials'); +% +% INPUTS--------------------------------------------------------------------- +% folder: In readdata.m, this should remain as 'folder' everywhere in the +% program. It is in the command line of matlab where you indicate +% the file and directory of the dataset you wish to view. It will +% automatically be used in both readresfile.m and readmegfile.m. +% +% setup: Enter as 'setup'; setup header information acquired by readresfile.m. +% This input is needed for the program to work. +% +% sensorIndex: Enter as 'sensorIndex'; sensor information acquired by readresfile.m, +% such as megsens, othersens, refsens, and eegsens. +% +% sensorInfo: Emter as 'gain'; gain/offset information acquired by readresfile.m, +% including proper_gain, io_gain, and channel locations. +% +% CHAN: ex: [30:35] - an interval of the desired channels to be read. +% If CHAN = 'eegsens', only eeg channels/sensors will be read. +% If CHAN = 'megsens', only meg channels/sensors will be read. +% If CHAN = 'refsens', only reference channels/sensors will be read. +% If CHAN = 'othersens' only the other channels/sensors will be +% read. +% +% TIME: ex. [0 5] - seconds 0 to 5: the desired time interval to be read. +% If TIME = 'alltimes', the entire duration of the trial(s) will +% be read (i.e. TIME = [1:setup.duration]). +% +% TRIALS: If TRIALS = n, the nth trial will be read. +% If TRIALS = [3,5,8] (for example), trials 3,5, and 8 will be +% read and read{1} = data for trial three, read{2} = data for +% trial 5, and read{3} = data for trial 8. +% If TRIALS = [3:7] (for example), trials 3 through 7 will be +% read. +% If TRIALS = 'alltrials', the data for all of the trials will be +% read (i.e. TRIALS = [1:setup.duration]). +% +% OUTPUTS-------------------------------------------------------------------- +% read: read contains all of the data. ex. type read{1} for it to display the first +% set of data on the screen. +% +%---------------------------------------------------------------------------- +% +% EXAMPLE: +% [read] = readmegfile(folder,setup,sensorIndex,sensorInfo,'megsens',[0 4],'alltrials'); diff --git a/readepochs.m b/readepochs.m new file mode 100644 index 0000000..2d1f1e0 --- /dev/null +++ b/readepochs.m @@ -0,0 +1,116 @@ +function [data,ctf] = readepochs(folder,varargin); +% +% +% +% <>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +% < > +% < DISCLAIMER: > +% < > +% < THIS PROGRAM IS INTENDED FOR RESEARCH PURPOSES ONLY. > +% < THIS PROGRAM IS IN NO WAY INTENDED FOR CLINICAL OR > +% < OFFICIAL USE. > +% < > +% <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<> +% +% function to read set time windows (epochs) around event markers. +% +[marker_info] = readmarkerfile(folder); +ctf = ctf_read_res4(folder,1); +CHAN = ctf.sensor.index.megsens; +trials = [1:ctf.setup.number_trials]; +win = 'alltimes'; +for i = 1:size(varargin,2) + + if ~iscell(varargin{i}) + + switch num2str(varargin{i}) + + case 'megsens', + CHAN = ctf.sensor.index.megsens(varargin{i+1}); + + case 'refsens', + CHAN = ctf.sensor.index.refsens(varargin{i+1}); + + case 'eegsens', + CHAN = ctf.sensor.index.eegsens(varargin{i+1}); + + case 'othersens', + CHAN = ctf.sensor.index.othersens(varargin{i+1}); + + case 'vc', + CHAN = ctf.sensor.index.vc(varargin{i+1}); + + case 'allchans', + CHAN = [1:ctf.setup.number_channels]; + + case 'trials', + trials = varargin{i+1}; + + case 'markers', + marks = varargin{i+1}; + + case 'window', + win = varargin{i+1}; + + end + end +end + +if ~exist('marks','var'), + + ctf = ctf_read_meg4(folder,ctf,CHAN,win,trials); + + epochs = cell(1,1); + + epochs{1} = zeros(size(ctf.data{1},1),size(ctf.data{1},2),size(ctf.data,1)); + + for i = 1:size(ctf.data,1), + + epochs{1}(:,:,i) = ctf.data{i}; + + end + +else + + nm = size(marks,2); + + epochs = cell(1,nm); + + for mkr = 1:nm, + + mk=ismember(marker_info.marker_names,marks(mkr)); + + marker_info.marker_names(mk); + + nsamp=marker_info.number_samples(mk) + + nss=0; + + for ns=1:nsamp + + tr = marker_info.trial_times{mk}(ns,1); + + if ismember(tr,trials) + + nss=nss+1; + + tim=marker_info.trial_times{mk}(ns,2); + + times=win+tim; + + ctf = ctf_read_ds(folder,ctf,CHAN,times,tr); + + temp=ctf.data{1}; + + if nss==1, + epochs{mkr}=zeros(size(temp,1),size(temp,2),1); + end + + epochs{mkr}(:,:,nss)=temp; + + end + end + end +end +data = struct('epochs',{epochs},'setup',{ctf.setup},'sensor',{ctf.sensor}); +return diff --git a/readmarkerfile.m b/readmarkerfile.m new file mode 100644 index 0000000..57fdccb --- /dev/null +++ b/readmarkerfile.m @@ -0,0 +1,66 @@ +function [data] = readmarkerfile(folder); +% function reads a CTF data file (.ds), Read 'markerfile.mrk' +% marker is the read-only 'markerfile.mrk' +% creates structure 'data' which contains number_markers, number_samples, +% marker_names, trial_times, marker. + +% +% +% +% <>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> % +% < > % +% < DISCLAIMER: > % +% < > % +% < THIS PROGRAM IS INTENDED FOR RESEARCH PURPOSES ONLY. > % +% < THIS PROGRAM IS IN NO WAY INTENDED FOR CLINICAL OR > % +% < OFFICIAL USE. > % +% < > % +% <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<> % +% +% +% + + +a = exist(fullfile(folder,'MarkerFile.mrk')); +if a == 0 + disp(' '); + disp('Error: Your data could not be found. MarkerFile.mrk does not exist in this directory.'); + disp(' '); + data = []; + return +end % error message if incorrect directory is displayed + +markr = textread(fullfile(folder,'MarkerFile.mrk'),'%s','delimiter','\n'); +% creates markerfile.mrk in FOLDER directory. Type 'marker' to view. + +% define markers +number_markers_id = strmatch('NUMBER OF MARKERS:',markr,'exact'); +markers = str2num(markr{number_markers_id+1}); + +% define samples +number_samples_id = strmatch('NUMBER OF SAMPLES:',markr,'exact'); +samples = str2num(char(markr(number_samples_id+1))); + +for i = 1:length(samples) + if samples(i) == 0 + disp('Error: one of the markers is bad.'); + data = []; + return + end +end + +name_id = strmatch('NAME:',markr,'exact'); +names = markr(name_id+1); +% defines names + +trial = strmatch('LIST OF SAMPLES',markr)+2; + +for i = 1:markers + trials{i} = str2num(char(markr(trial(i):trial(i)+samples(i)))); + trials{i}(:,1) = trials{i}(:,1) + 1; +end + +data = struct('number_markers',{markers},'number_samples',{samples},'marker_names',{names},'trial_times',{trials}); +% defines data + +return diff --git a/readmegfile-ssd.m b/readmegfile-ssd.m new file mode 100644 index 0000000..7fe15d6 --- /dev/null +++ b/readmegfile-ssd.m @@ -0,0 +1,172 @@ +% +% +% +% <>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> % +% < > % +% < DISCLAIMER: > % +% < > % +% < THIS PROGRAM IS INTENDED FOR RESEARCH PURPOSES ONLY. > % +% < THIS PROGRAM IS IN NO WAY INTENDED FOR CLINICAL OR > % +% < OFFICIAL USE. > % +% < > % +% <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<> % +% +% + + +function [read,sensorNames,sensorLocations,sensorOrientations,header] = readmegfile(folder,setup,sensorIndex,sensorInfo,CHAN,TIME,TRIALS); +%INPUTS-------------------------------------------------------------------- +% +% folder: the directory and filename of the .ds data set that is +% to be read. +% +% CHAN: ex: [30:35] - an interval of the desired channels to be read. +% If CHAN = 'eegsens', only eeg channels/sensorIndices will be read. +% If CHAN = 'megsens', only meg channels/sensorIndices will be read. +% If CHAN = 'refsens', only reference channels/sensorIndices will be read. +% If CHAN = 'othersens' only the other channels/sensorIndices will be +% read. +% +% TIME: ex. [0 5] - the desired time interval to be read. +% If TRIALS = 'alltrials', the data for all of the trials will be +% read. +% +% TRIALS: If TRIALS = n, the nth trial will be read. +% If TRIALS = [3,5,8] (for example), trials 3,5, and 8 will be +% read and read{1} = data for trial 3, read{2} = data for +% trial 5, and read{3} = data for trial 8. +% If TRIALS = [3:7] (for example), trials 3 through 7 will be +% read. +% If TIME = 'alltimes', the entire duration of the trial(s) will +% be read (i.e. TIME = [1:setup.duration]). +% +%OUTPUTS------------------------------------------------------------------- +% read: read contains all of the data. ex. type read{1} for it to +% display the first set of data on the screen. +% +% sensorNames: cell array of sensor names. +% +% sensorLocations: array of sensor locations for plotting. +% +% header: used for writing new meg4 file. + + +%[setup,sensorIndex,sensorInfo] = readresfile(folder,1); %------use this line if you only +%want to run readmegfile.m. This line will read .res4 information (i.e. +%setup, sensorIndex, and sensorInfo information) from readresfile.m. +cd(folder); +[path,rootname] = fileparts(folder); + + + +dat4file = [rootname,'.meg4']; +[dat,message] = fopen(dat4file,'rb','s'); +Time = linspace(-setup.pretrig/setup.sample_rate,setup.duration - (setup.pretrig/setup.sample_rate),setup.number_samples); + +for n = 5:nargin + chankey = eval('CHAN'); + timekey = eval('TIME'); + trialkey = eval('TRIALS'); + + if strcmp(chankey,'megsens') + CHAN = sensorIndex.megsens; + end + if strcmp(chankey,'refsens') + CHAN = sensorIndex.refsens; + end + if strcmp(chankey,'eegsens') + CHAN = sensorIndex.eegsens; + end + if strcmp(chankey,'othersens') + CHAN = sensorIndex.othersens; + end + if strcmp(chankey,'allchans') + CHAN = [1:setup.number_channels]; + end + if strcmp(timekey,'alltimes') + TIME = Time; + end + if strcmp(trialkey,'alltrials') + TRIALS = [1:setup.number_trials]; + end +end + +header = char(fread(dat,8,'char')'); +% Apply gains and offsets +%setup.chan_names = char(setup.chan_names{:}) + channel_gain = zeros(setup.number_channels,1); + channel_gain(sensorIndex.megsens) = ([sensorInfo(sensorIndex.megsens).proper_gain]'.*[sensorInfo(sensorIndex.megsens).q_gain]'); + channel_gain(sensorIndex.refsens) = ([sensorInfo(sensorIndex.refsens).proper_gain]'.*[sensorInfo(sensorIndex.refsens).q_gain]'); + channel_gain(sensorIndex.eegsens) = ([sensorInfo(sensorIndex.eegsens).q_gain]'); + channel_gain(sensorIndex.othersens) = ([sensorInfo(sensorIndex.othersens).q_gain]'); +if nargin == 7 + n_trials = TRIALS; + + read = cell(length(TRIALS),1); + + + %fseek(dat,8,-1); + + %smpl = sample*(TIME(end)-TIME(1)); + + s_rt = 1/(Time(2) - Time(1)); + trial_size = 4*setup.number_channels*setup.number_samples; + bet_trials = diff(n_trials)-1; + small_trial = 4*(min(CHAN)-1)*setup.number_samples; + large_trial = 4*(setup.number_channels-max(CHAN))*setup.number_samples; + + if (max(TIME)-min(TIME))>setup.duration + durat = setup.duration; + disp('TIME input too large for trial...setting TIME= duration of trial...'); + pause(1.2); + disp('...done'); + pause(1); + fprintf('TIME= %g seconds',durat); + drawnow + else + durat = (TIME(end)-TIME(1)); + end + + samples = round((durat)*s_rt)+1; + intime = round((TIME(1)-Time(1))*s_rt)+1; + channels = length([min(CHAN):max(CHAN)]); + + + trl = 0; + for trial = n_trials + trl = trl+1; + read{trl} = zeros(channels,samples); + if trial == n_trials(1); %1st trial + fseek(dat,(trial-1)*trial_size + small_trial + 4*(intime-1),0); + else + fseek(dat,(trial-n_trials(trl-1)-1)*trial_size + small_trial + large_trial,0); + end + %Read data + %fseek(dat,ftell(dat) + 4,-1); + read{trl} = fread(dat,[samples channels],[num2str(samples),'*int32=>int32'],4*(setup.number_samples-samples))'; + + + read{trl} = read{trl}(CHAN - min(CHAN)+1,:); + + read{trl} = diag(1./channel_gain(CHAN))*double(read{trl}); + + end + +elseif nargin ~= 7 + disp('Error: incorrect number of inputs'); +end + +for i=CHAN + j=i-min(CHAN)+1; + if length(sensorInfo(i).channel_names) <= 5 + sensorNames{j,1} = sensorInfo(i).channel_names; + else + sensorNames{j,1} = sensorInfo(i).channel_names(1:5); + end + if ~isempty(sensorInfo(i).location) + sensorLocations(j,:) = sensorInfo(i).location(:,1)'; + sensorOrientations(j,:) = sensorInfo(i).orientation(:,1)'; + end +end + + diff --git a/readmegfile.m b/readmegfile.m new file mode 100644 index 0000000..3ea8f37 --- /dev/null +++ b/readmegfile.m @@ -0,0 +1,170 @@ +% +% +% +% <>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> % +% < > % +% < DISCLAIMER: > % +% < > % +% < THIS PROGRAM IS INTENDED FOR RESEARCH PURPOSES ONLY. > % +% < THIS PROGRAM IS IN NO WAY INTENDED FOR CLINICAL OR > % +% < OFFICIAL USE. > % +% < > % +% <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<> % +% +% + + +function [read,sensorNames,sensorLocations,sensorOrientations,header] = readmegfile(folder,setup,sensorIndex,sensorInfo,CHAN,TIME,TRIALS); +%INPUTS-------------------------------------------------------------------- +% +% folder: the directory and filename of the .ds data set that is +% to be read. +% +% CHAN: ex: [30:35] - an interval of the desired channels to be read. +% If CHAN = 'eegsens', only eeg channels/sensorIndices will be read. +% If CHAN = 'megsens', only meg channels/sensorIndices will be read. +% If CHAN = 'refsens', only reference channels/sensorIndices will be read. +% If CHAN = 'othersens' only the other channels/sensorIndices will be +% read. +% +% TIME: ex. [0 5] - the desired time interval to be read. +% If TRIALS = 'alltrials', the data for all of the trials will be +% read. +% +% TRIALS: If TRIALS = n, the nth trial will be read. +% If TRIALS = [3,5,8] (for example), trials 3,5, and 8 will be +% read and read{1} = data for trial 3, read{2} = data for +% trial 5, and read{3} = data for trial 8. +% If TRIALS = [3:7] (for example), trials 3 through 7 will be +% read. +% If TIME = 'alltimes', the entire duration of the trial(s) will +% be read (i.e. TIME = [1:setup.duration]). +% +%OUTPUTS------------------------------------------------------------------- +% read: read contains all of the data. ex. type read{1} for it to +% display the first set of data on the screen. +% +% sensorNames: cell array of sensor names. +% +% sensorLocations: array of sensor locations for plotting. +% +% header: used for writing new meg4 file. + + +%[setup,sensorIndex,sensorInfo] = readresfile(folder,1); %------use this line if you only +%want to run readmegfile.m. This line will read .res4 information (i.e. +%setup, sensorIndex, and sensorInfo information) from readresfile.m. +cd(folder); +[path,rootname] = fileparts(folder); + + + +dat4file = [rootname,'.meg4']; +[dat,message] = fopen(dat4file,'rb','s'); +Time = linspace(-setup.pretrig/setup.sample_rate,setup.duration - (setup.pretrig/setup.sample_rate),setup.number_samples); + +for n = 5:nargin + chankey = eval('CHAN'); + timekey = eval('TIME'); + trialkey = eval('TRIALS'); + + if strcmp(chankey,'megsens') + CHAN = sensorIndex.megsens; + end + if strcmp(chankey,'refsens') + CHAN = sensorIndex.refsens; + end + if strcmp(chankey,'eegsens') + CHAN = sensorIndex.eegsens; + end + if strcmp(chankey,'othersens') + CHAN = sensorIndex.othersens; + end + if strcmp(chankey,'allchans') + CHAN = [1:setup.number_channels]; + end + if strcmp(timekey,'alltimes') + TIME = Time; + end + if strcmp(trialkey,'alltrials') + TRIALS = [1:setup.number_trials]; + end +end + +header = char(fread(dat,8,'char')'); +% Apply gains and offsets +%setup.chan_names = char(setup.chan_names{:}) + channel_gain = zeros(setup.number_channels,1); + channel_gain(sensorIndex.megsens) = ([sensorInfo(sensorIndex.megsens).proper_gain]'.*[sensorInfo(sensorIndex.megsens).q_gain]'); + channel_gain(sensorIndex.refsens) = ([sensorInfo(sensorIndex.refsens).proper_gain]'.*[sensorInfo(sensorIndex.refsens).q_gain]'); + channel_gain(sensorIndex.eegsens) = ([sensorInfo(sensorIndex.eegsens).q_gain]'); + channel_gain(sensorIndex.othersens) = ([sensorInfo(sensorIndex.othersens).q_gain]'); +if nargin == 7 + n_trials = TRIALS; + + read = cell(length(TRIALS),1); + + + %fseek(dat,8,-1); + + %smpl = sample*(TIME(end)-TIME(1)); + + s_rt = 1/(Time(2) - Time(1)); + trial_size = 4*setup.number_channels*setup.number_samples; + bet_trials = diff(n_trials)-1; + small_trial = 4*(min(CHAN)-1)*setup.number_samples; + large_trial = 4*(setup.number_channels-max(CHAN))*setup.number_samples; + + if (max(TIME)-min(TIME))>setup.duration + durat = setup.duration; + disp('TIME input too large for trial...setting TIME= duration of trial...'); + pause(1.2); + disp('...done'); + pause(1); + fprintf('TIME= %g seconds',durat); + drawnow + else + durat = (TIME(end)-TIME(1)); + end + + samples = round((durat)*s_rt)+1; + intime = round((TIME(1)-Time(1))*s_rt)+1; + channels = length([min(CHAN):max(CHAN)]); + + + trl = 0; + for trial = n_trials + trl = trl+1; + read{trl} = zeros(channels,samples); + if trial == n_trials(1); %1st trial + fseek(dat,(trial-1)*trial_size + small_trial + 4*(intime-1),0); + else + fseek(dat,(trial-n_trials(trl-1)-1)*trial_size + small_trial + large_trial,0); + end + %Read data + %fseek(dat,ftell(dat) + 4,-1); + read{trl} = fread(dat,[samples channels],[num2str(samples),'*int32=>int32'],4*(setup.number_samples-samples))'; + + + read{trl} = read{trl}(CHAN - min(CHAN)+1,:); + + read{trl} = diag(1./channel_gain(CHAN))*double(read{trl}); + + end + +elseif nargin ~= 7 + disp('Error: incorrect number of inputs'); +end + +for i=CHAN + j=i-min(CHAN)+1; + if length(sensorInfo(i).channel_names) <= 5 + sensorNames{j,1} = sensorInfo(i).channel_names; + else + sensorNames{j,1} = sensorInfo(i).channel_names(1:5); + end + if ~isempty(sensorInfo(i).location) + sensorLocations(j,:) = sensorInfo(i).location(:,1)'; + sensorOrientations(j,:) = sensorInfo(i).orientation(:,1)'; + end +end diff --git a/readresfile.m b/readresfile.m new file mode 100644 index 0000000..25169c9 --- /dev/null +++ b/readresfile.m @@ -0,0 +1,314 @@ +% +% +% +% +% <>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> % +% < > % +% < DISCLAIMER: > % +% < > % +% < THIS PROGRAM IS INTENDED FOR RESEARCH PURPOSES ONLY. > % +% < THIS PROGRAM IS IN NO WAY INTENDED FOR CLINICAL OR > % +% < OFFICIAL USE. > % +% < > % +% <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<> % +% +% +% + +function [setup,sensorIndex,sensorInfo] = readresfile(folder,SETUP); + +%INPUTS-------------------------------------------------------------------- +% +% folder: the directory and filename of the .ds data set that is +% to be read. If only the folder is inputted, SETUP = 1. +% +% SETUP: If SETUP = 0, when the program is run, 'setup' structure information will +% not be displayed automatically. +% If SETUP = 1, when the program is run, 'setup' structure information will +% automatically be displayed. +% +%OUTPUTS------------------------------------------------------------------- +% setup: a structure of head information consisting of date, time, run +% name, run title, subject, run description, operator, number of +% channels, number of samples, sample rate, number of trials, +% duration, pretrigger points, sensor filename, head zeroing, +% and number of filters. +% +% sensorIndex: a structure with sensor information consisting of EEG sensors, +% MEG sensors, reference sensors, and other sensors. +% +% sensorInfo: a structure with gain and offset information consisting of +% proper gain, Q gain, io gain, io offset, and index. + +if nargin == 1 + SETUP=1; +end +cd(folder); +[path,rootname] = fileparts(folder); +fid4file = [rootname,'.res4']; +[fid,message] = fopen(fid4file,'rb','s'); + + +%DATE/TIME----------------------------------------------------------------- +fseek(fid,778,-1); +tim = char(fread(fid,255,'char')); +fseek(fid,1033,-1); +dat = char(fread(fid,255,'char')); +time = [tim]'; +date = [dat]'; + +if SETUP + fprintf('\n Date Collected: %s',dat); + fprintf('\n Time Collected: %s',tim); + drawnow +end + +%RUN NAME----------------------------------------------------------------- +fseek(fid,1360,-1); +r_name = char(fread(fid,32,'char')); +run_name = [r_name]'; +if SETUP + fprintf('\n Run Name: %s',r_name); + drawnow +end + +%RUN TITLE---------------------------------------------------------------- +fseek(fid,1392,-1); +r_title = char(fread(fid,256,'char')); +run_title = [r_title]'; +if SETUP + fprintf('\n Run Title: %s',r_title); + drawnow +end + +%SUBJECT------------------------------------------------------------------ +fseek(fid,1712,-1); +subj = char(fread(fid,32,'char')); +subject = [subj]'; +if SETUP + fprintf('\n Subject: %s',subj); + drawnow +end + + +%RUN DESCRIPTION----------------------------------------------------------- +fseek(fid,1836,-1); +setup = fread(fid,1,'int32'); +fseek(fid,1844,-1); +run_description = char(fread(fid,setup,'char')); +if SETUP + fprintf('\n Run Description: %s',run_description); + drawnow +end + +%OPERATOR----------------------------------------------------------------- +fseek(fid,1744,-1); +oper = char(fread(fid,32,'char')); +operator = [oper]'; +if SETUP + fprintf('\n Operator: %s',oper); + drawnow +end + +%NUMBER OF CHANNELS-------------------------------------------------------- +fseek(fid,1292,-1); +number_channels = (fread(fid,1,'int16')'); +if SETUP + fprintf('\n Number of Channels: %d',number_channels); + drawnow +end + +%NUMBER OF SAMPLES--------------------------------------------------------- +fseek(fid,1288,-1); +number_samples = (fread(fid,1,'int32')'); +if SETUP + fprintf('\n Number of Samples: %d',number_samples); + drawnow +end + +%SAMPLE RATE--------------------------------------------------------------- +fseek(fid,1296,-1); +sample_rate = fread(fid,1,'double')'; +if SETUP + fprintf('\n Sample Rate: %g Samples per Second',sample_rate); + drawnow +end + +%NUMER OF TRIALS----------------------------------------------------------- +fseek(fid,1312,-1); +number_trials = fread(fid,1,'int16')'; +if SETUP + fprintf('\n Number of Trials: %g Trials',number_trials); + drawnow +end + +%DURATION------------------------------------------------------------------ +fseek(fid,1304,-1); +dur = fread(fid,1,'double')'; +duration = dur/number_trials; +if SETUP + fprintf('\n Duration: %g Seconds per Trial',duration); + drawnow +end + +%PRE_TRIG POINTS----------------------------------------------------------- +fseek(fid,1316,-1); +pretrig = fread(fid,1,'int32')'; +if SETUP + fprintf('\n Pre-Trigger Points: %g Samples',pretrig); + drawnow +end + +%SENSOR FILE NAME---------------------------------------------------------- +fseek(fid,1776,-1); +s_file_name = char(fread(fid,60,'char')); +sensor_file_name = [s_file_name]'; +if SETUP + fprintf('\n Sensor File Name: %s',s_file_name); + drawnow +end + +%HEAD ZEROING-------------------------------------------------------------- +fseek(fid,1348,-1); +h_zero = fread(fid,1,'int32')'; +no_yes = {'no','yes'}; +head_zero = no_yes{h_zero+1}; +if SETUP + fprintf('\n Head Zeroing: %s',no_yes{h_zero+1}); + drawnow +end + +%FILTERS------------------------------------------------------------------- +fseek(fid,1836,-1); +nfsetup = fread(fid,1,'int32')'; + +fseek(fid,1844,-1); +char(fread(fid,nfsetup,'char')); +number_filters = fread(fid,1,'int16'); +if SETUP + fprintf('\n Number of Filters: %d\n',number_filters); + drawnow +end +for jk = 1:number_filters + freq=fread(fid,1,'double'); + class=fread(fid,1,'int32'); + type=fread(fid,1,'int32'); + numparam=fread(fid,1,'int16'); + params=fread(fid,numparam,'double'); + if SETUP + fprintf(' -Filter # \t%g\n',jk) + fprintf(' -Frequency: \t%g Hz\n',freq) + fprintf(' -Class: \t%g\n',class) + fprintf(' -Type: \t%g\n',type) + if ~isempty(params) + fprintf(' -Parameter(s): \t%g\n',params) + end + drawnow + end +end + +setup = struct('date',{date},'time',{time},'run_name',{run_name},'run_title',{run_title},'operator',{operator}... + ,'number_channels',{number_channels},'number_samples',{number_samples},'sample_rate',{sample_rate},... + 'number_trials',{number_trials},'duration',{duration},'run_description',{run_description},'number_filters'... + ,{number_filters},'subject',{subject},'pretrig',{pretrig},'sensor_file_name',{sensor_file_name},'head_zero',{head_zero}); +sensorInfo = struct('proper_gain',[],'q_gain',[],'io_gain',[],'io_offset',[],'index',[],'extra',[],'channel_names',[]); + +for chan = 1:number_channels + temp = fread(fid,32,'char'); + temp(temp>127) = 0; + temp(temp<0) = 0; + temp = strtok(temp,char(0)); + sensorInfo(chan).channel_names = char(temp'); +end + + +Time = linspace(-pretrig/sample_rate,duration - (pretrig/sample_rate),number_samples); + + +for chan = 1:number_channels + ftell(fid); + sensorInfo(chan).index = fread(fid,1,'int16'); + sensorInfo(chan).extra = fread(fid,1,'int16'); + id = fread(fid,1,'int32')+1; + sensorInfo(chan).proper_gain = fread(fid,1,'double'); + sensorInfo(chan).q_gain = fread(fid,1,'double'); + sensorInfo(chan).io_gain = fread(fid,1,'double'); + sensorInfo(chan).io_offset = fread(fid,1,'double'); + fread(fid,1,'int16'); + fread(fid,1,'int16'); + fread(fid,1,'int32'); + %fseek(fid,ftell(fid)+6,0); + + for pos = 1:8 + sensorInfo(chan).coil(pos).position.x = fread(fid,1,'double'); + sensorInfo(chan).coil(pos).position.y = fread(fid,1,'double'); + sensorInfo(chan).coil(pos).position.z = fread(fid,1,'double'); + fread(fid,1,'double'); + sensorInfo(chan).coil(pos).orient.x = fread(fid,1,'double'); + sensorInfo(chan).coil(pos).orient.y = fread(fid,1,'double'); + sensorInfo(chan).coil(pos).orient.z = fread(fid,1,'double'); + fread(fid,1,'double'); + fread(fid,1,'int16'); + fread(fid,1,'int32'); + fread(fid,1,'int16'); + fread(fid,1,'double'); + + %fseek(fid,ftell(fid)+56,0); + %fseek(fid,ftell(fid)-80,0); + end + + for pos = 1:8 + sensorInfo(chan).hcoil(pos).position.x = fread(fid,1,'double'); + sensorInfo(chan).hcoil(pos).position.y = fread(fid,1,'double'); + sensorInfo(chan).hcoil(pos).position.z = fread(fid,1,'double'); + fread(fid,1,'double'); + sensorInfo(chan).hcoil(pos).orient.x = fread(fid,1,'double'); + sensorInfo(chan).hcoil(pos).orient.y = fread(fid,1,'double'); + sensorInfo(chan).hcoil(pos).orient.z = fread(fid,1,'double'); + fread(fid,1,'double'); + fread(fid,1,'int16'); + fread(fid,1,'int32'); + fread(fid,1,'int16'); + fread(fid,1,'double'); + + %fseek(fid,ftell(fid)+56,0); + %fseek(fid,ftell(fid)+80,0); + end + %fseek(fid,ftell(fid)+1288,-1); +end + +megsens = find([sensorInfo.index] == 5); +eegsens = find([sensorInfo.index] == 9); +refsens = find([sensorInfo.index] == 0); +refsens = [refsens,find([sensorInfo.index] == 1)]; +a = [megsens,eegsens,refsens]; +othersens = setdiff([1:setup.number_channels],a); +sensorIndex = struct('refsens',{refsens},'othersens',{othersens},'eegsens',{eegsens},'megsens',{megsens}); + +%Location Coordinates of Channels in centimeters +for chan = 1:number_channels + switch sensorInfo(chan).index + %0=Reference Channels, 1=More Reference Channels, 5=MEG Channels + case {0,1,5} + coord = [sensorInfo(chan).hcoil(:).position]; + coordx = [coord(1:2).x]; + coordy = [coord(1:2).y]; + coordz = [coord(1:2).z]; + sensorInfo(chan).location = [coordx;coordy;coordz]; + orient = [sensorInfo(chan).hcoil(:).orient]; + orientx = [orient(1).x]; + orienty = [orient(1).y]; + orientz = [orient(1).z]; + sensorInfo(chan).orientation = [orientx;orienty;orientz]; + location = sensorInfo(chan).location'; + ps1=sum((location(1,:).*sensorInfo(chan).orientation(:,1)')')'; + sensorInfo(chan).orientation(:,1) = (sign(ps1)*ones(1,3).*sensorInfo(chan).orientation(:,1)')'; + %EEG Channels + case 9 + coord = [sensorInfo(chan).hcoil(:).position]; + coordx = [coord(1:2).x]; + coordy = [coord(1:2).y]; + coordz = [coord(1:2).z]; + sensorInfo(chan).location = [coordx;coordy;coordz]; + end +end