Unverified Commit 5e0b668f authored by Sreekanth kura's avatar Sreekanth kura Committed by GitHub
Browse files

Development sk (#135)

* Update 3D to 2D projection

* Fix LengthUnit error

* update MetaDataClass Set method

* remove ProbeClass.m.bak file

* fix bugs in MetaDataTagsClass and SnirfClass

* Make circular 2D probe pos range -1 to 1

* Fix merge issues with fig file

* Fix probe3dto2d issue when snirf file has incorrect landmarklabels

* Generate source2D and detector2D positions same time instead of seperately when labelmark3D are not available

* Minor changes to make code clean
parent 771c5dd7
Loading
Loading
Loading
Loading
+467 −0

File added.

Preview size limit exceeded, changes collapsed.

+6 −5
Original line number Diff line number Diff line
@@ -10,7 +10,6 @@ classdef MetaDataTagsClass < FileLoadSaveClass
        function obj = MetaDataTagsClass(varargin)
            % Set class properties not part of the SNIRF format
            obj.SetFileFormat('hdf5');

            obj.tags.SubjectID = 'default';
            obj.tags.MeasurementDate = datestr(now,29);
            obj.tags.MeasurementTime = datestr(now,'hh:mm:ss');
@@ -175,10 +174,12 @@ classdef MetaDataTagsClass < FileLoadSaveClass
        
        
        % ----------------------------------------------------------------------------------
        function Set(obj, name, val) %#ok<INUSL>
            eval(sprintf('obj.tags.%s = %s;', name, val));
        function Set(obj, name, value)
            if ~exist('name', 'var') || ~exist('value', 'var')
                retrun
            end                                     
            eval( sprintf('obj.tags.%s = ''%s'';', name, value) )   
        end        
        
        
        % ----------------------------------------------------------------------------------
        function SetLengthUnit(obj, unit)
+123 −20
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ classdef ProbeClass < FileLoadSaveClass
    end
    
    
    
    methods
        
        % -------------------------------------------------------
@@ -122,31 +123,118 @@ classdef ProbeClass < FileLoadSaveClass
            end
        end
        
        % -------------------------------------------------------------------------------
        function xy = convert_optodepos_to_circlular_2D_pos(obj, pos, T, norm_factor)
            pos = [pos ones(size(pos,1),1)];
            pos_unit_sphere = pos*T;
            pos_unit_sphere_norm = sqrt(sum(pos_unit_sphere.^2,2));
            pos_unit_sphere = pos_unit_sphere./pos_unit_sphere_norm ;

            [azimuth,elevation,r] = cart2sph(pos_unit_sphere(:,1),pos_unit_sphere(:,2),pos_unit_sphere(:,3));
            elevation = pi/2-elevation;
            [x,y] = pol2cart(azimuth,elevation);      % get plane coordinates
            xy = [x y];
            xy = xy/norm_factor;               % set maximum to unit length
        end
        
        
        % ----------------------------------------------
        function isValid = isValidLandmarkLabels(obj)
            isValid = 1;
            refpts_labels = {'T7','T8','Oz','Fpz','Cz','C3','C4','Pz','Fz'};
            for u = 1:length(refpts_labels)
                label = refpts_labels{u};
                idx = ismember(obj.landmarkLabels, label);
                if sum(idx) == 0
                    isValid = 0;
                    return
                end
            end 
        end

        % -------------------------------------------------------
        function Project_3D_to_2D(obj) 
            if isempty(obj.landmarkPos2D) || isempty(obj.landmarkPos3D)
            
                % When 3D landmarks aren't available use crude default 3D-to-2D projection algorithm 
                if isempty(obj.sourcePos2D)
                    obj.sourcePos2D = project_3D_to_2D(obj.sourcePos3D);
            if isempty(obj.sourcePos2D) && isempty(obj.detectorPos2D)
                if isempty(obj.landmarkPos3D) || ~obj.isValidLandmarkLabels()
                    optodePos3D = [];
                    nSource = 0;
                    optodePos3D = [obj.sourcePos3D; obj.detectorPos3D];
                    nSource = size(optodePos3D,1);
                    
                    optodePos2D = project_3D_to_2D(optodePos3D);
                    if ~isempty(optodePos2D)
                        if nSource ~= 0
                            obj.sourcePos2D = optodePos2D(1:nSource,:);
                        end
                        if size(optodePos3D,1) > nSource
                            obj.detectorPos2D = optodePos2D(nSource+1:end,:);
                        end
                if isempty(obj.detectorPos2D)
                    obj.detectorPos2D = project_3D_to_2D(obj.detectorPos3D);
                    end
                
                else
                     if ~isempty(obj.sourcePos3D) && ~isempty(obj.detectorPos3D)
                        [sphere.label, sphere.theta, sphere.phi, sphere.r, sphere.xc, sphere.yc, sphere.zc] = textread('10-5-System_Mastoids_EGI129.csd','%s %f %f %f %f %f %f','commentstyle','c++');
                        % ref pt labels used for affine transformation
                        refpts_labels = {'T7','T8','Oz','Fpz','Cz','C3','C4','Pz','Fz'};

                % 3D landmarks are available, use ...
                        % get positions for refpts_labels from both sphere and probe ref pts
                        for u = 1:length(refpts_labels)
                            label = refpts_labels{u};

                            idx = ismember(obj.landmarkLabels, label);
                            if isempty(idx)
                                return
                            end
                            probe_refps_pos(u,:) = obj.landmarkPos3D(idx,:);
                            idx = ismember(sphere.label, label);
                            sphere_refpts_pos(u,:) = [sphere.xc(idx) sphere.yc(idx) sphere.zc(idx)];
                        end

                        % get affine transformation
                        % probe_refps*T = sphere_refpts
                        probe_refps_pos = [probe_refps_pos(:,1:3) ones(size(probe_refps_pos,1),1)];
                        T = probe_refps_pos\sphere_refpts_pos;

                        % tranform optode positions onto unit sphere.
                        % opt_pos = probe.optpos_reg;
                        % opt_pos = [opt_pos ones(size(opt_pos,1),1)];
                        % sphere_opt_pos = opt_pos*T;
                        % sphere_opt_pos_norm = sqrt(sum(sphere_opt_pos.^2,2));
                        % sphere_opt_pos = sphere_opt_pos./sphere_opt_pos_norm ;
                        %%
                        % get 2D circular refpts for current selecetd reference point system
                        probe_refpts_idx =  ismember(sphere.label, obj.landmarkLabels);

                        % refpts_2D.pos = [sphere_xc(probe_refpts_idx) sphere_yc(probe_refpts_idx) sphere_zc(probe_refpts_idx)];
                        refpts_2D.label = sphere.label(probe_refpts_idx);
                        %%
                        refpts_theta =  sphere.theta(probe_refpts_idx);
                        refpts_phi = 90 - sphere.phi(probe_refpts_idx); % elevation angle from top axis

                        refpts_theta = (2 * pi * refpts_theta) / 360; % convert to radians
                        refpts_phi = (2 * pi * refpts_phi) / 360;
                        [x,y] = pol2cart(refpts_theta, refpts_phi);      % get plane coordinates
                        xy = [x y];

                        %%
                        norm_factor = max(max(xy));
                        xy = xy/norm_factor;               % set maximum to unit length
                        refpts_2D.pos = xy;
                        obj.landmarkPos2D = refpts_2D.pos;

                        %%

                        obj.sourcePos2D = convert_optodepos_to_circlular_2D_pos(obj, obj.sourcePos3D, T, norm_factor);
                        obj.detectorPos2D = convert_optodepos_to_circlular_2D_pos(obj, obj.detectorPos3D, T, norm_factor);
                    end
                end
            end
        end

        
        
        % -------------------------------------------------------
        function err = LoadHdf5(obj, fileobj, location)
        function err = LoadHdf5(obj, fileobj, location, LengthUnit)
            err = 0;
            
            % Arg 1
@@ -161,6 +249,19 @@ classdef ProbeClass < FileLoadSaveClass
                location = ['/',location];
            end
            
            % Arg3
            scaling = 1;
            if exist('LengthUnit','var')
                if strcmpi(LengthUnit,'m')
                    scaling = 1000;
                elseif strcmpi(LengthUnit,'cm')
                    scaling = 10;
                end
            end
            
            

              
            % Error checking            
            if ~isempty(fileobj) && ischar(fileobj)
                obj.SetFilename(fileobj);
@@ -179,12 +280,12 @@ classdef ProbeClass < FileLoadSaveClass
                % Load datasets
                obj.wavelengths               = HDF5_DatasetLoad(gid, 'wavelengths');
                obj.wavelengthsEmission       = HDF5_DatasetLoad(gid, 'wavelengthsEmission');
                obj.sourcePos2D               = HDF5_DatasetLoad(gid, 'sourcePos2D', [], '2D');
                obj.detectorPos2D             = HDF5_DatasetLoad(gid, 'detectorPos2D', [], '2D');
                obj.landmarkPos2D             = HDF5_DatasetLoad(gid, 'landmarkPos2D', [], '2D');
                obj.sourcePos3D               = HDF5_DatasetLoad(gid, 'sourcePos3D', [], '3D');
                obj.detectorPos3D             = HDF5_DatasetLoad(gid, 'detectorPos3D', [], '3D');
                obj.landmarkPos3D             = HDF5_DatasetLoad(gid, 'landmarkPos3D', [], '2D');
                obj.sourcePos2D               = HDF5_DatasetLoad(gid, 'sourcePos2D', [], '2D')*scaling;
                obj.detectorPos2D             = HDF5_DatasetLoad(gid, 'detectorPos2D', [], '2D')*scaling;
                obj.landmarkPos2D             = HDF5_DatasetLoad(gid, 'landmarkPos2D', [], '2D')*scaling;
                obj.sourcePos3D               = HDF5_DatasetLoad(gid, 'sourcePos3D', [], '3D')*scaling;
                obj.detectorPos3D             = HDF5_DatasetLoad(gid, 'detectorPos3D', [], '3D')*scaling;
                obj.landmarkPos3D             = HDF5_DatasetLoad(gid, 'landmarkPos3D', [], '2D')*scaling;
                obj.frequencies               = HDF5_DatasetLoad(gid, 'frequencies');
                obj.timeDelays                 = HDF5_DatasetLoad(gid, 'timeDelays');
                obj.timeDelayWidths            = HDF5_DatasetLoad(gid, 'timeDelayWidths');
@@ -248,6 +349,7 @@ classdef ProbeClass < FileLoadSaveClass
                fid = H5F.create(fileobj, 'H5F_ACC_TRUNC', 'H5P_DEFAULT', 'H5P_DEFAULT');
                H5F.close(fid);
            end 
            
            hdf5write_safe(fileobj, [location, '/wavelengths'], obj.wavelengths, 'array');
            hdf5write_safe(fileobj, [location, '/wavelengthsEmission'], obj.wavelengthsEmission, 'array');
            hdf5write_safe(fileobj, [location, '/sourcePos2D'], obj.sourcePos2D, 'array');
@@ -269,6 +371,7 @@ classdef ProbeClass < FileLoadSaveClass
        
        
        
        
        % ---------------------------------------------------------
        function wls = GetWls(obj)
            wls = obj.wavelengths;
+4 −1
Original line number Diff line number Diff line
@@ -479,8 +479,11 @@ classdef SnirfClass < AcqDataClass & FileLoadSaveClass
        
        % -------------------------------------------------------
        function err = LoadProbe(obj, fileobj, ~)
            % get lenth unit through class method
            LengthUnit = obj.metaDataTags.Get('LengthUnit');
            obj.probe = ProbeClass();
            err = obj.probe.LoadHdf5(fileobj, [obj.location, '/probe']);
            err = obj.probe.LoadHdf5(fileobj, [obj.location, '/probe'], LengthUnit);
            obj.metaDataTags.Set('LengthUnit','mm');
            
            % This is a required field. If it's empty means the whole snirf object is bad
            if isempty(obj.probe)
+25 −0
Original line number Diff line number Diff line
@@ -822,6 +822,31 @@ function menuItemPlotProbeGUI_Callback(hObject, ~, handles)
global maingui
LaunchChildGuiFromMenu('PlotProbeGUI', hObject, GetDatatype(handles), maingui.condition);

% --------------------------------------------------------------------
% function menuItemPlotProbe2_Callback(hObject, ~, handles)
% global maingui

%%%% It will be in the next release
% procElem = maingui.dataTree.currElem;
% % Derived data that we want to save in a Snirf file.
% % To save in a snirf file we need to create a SnirfClass
% % object. A SnirfClass object is DataTree's implementation 
% % of the Snirf format.  
% data(1) = procElem.procStream.output.dcAvg; 
% data(2) = procElem.procStream.output.dod;
% 
% % To complete SnirfClass object arguments we need to supply these
% % which we get from acquired data of the first run associated with 
% % our procElem.
% probe = procElem.acquired.probe;
% stim = procElem.acquired.stim;
% metaDataTags = procElem.acquired.metaDataTags;
% 
% obj = SnirfClass(data, stim, probe, metaDataTags);
% 
% % call PlotProbe2 GUI
% PlotProbe2(obj);



% -------------------------------------------------------------------