Unverified Commit 27a642ee authored by jayd1860's avatar jayd1860 Committed by GitHub
Browse files

Fix SpatialUnit scaling in SD NirsClass (#165)

* v1.75.0

-- In syncSubmodules.m add option to ignore last revision dates of the parent repo and submodules and instead force the direction of copying changes from parent repo to submodules ('parent2submodules') or submodules to parent repo ('submodules2parent').

* DataTree, v1.9.0, v1.8.3
-- Fix wrong probe scaling converting units in SnirfClass.ProbeClass and NirsClass
-- Add m (meter) to SpatialUnits NirsClass add appropriate scaling. When changing units in SDgui ask iof fixing incorrect units or simply changing units and associated coordinates.

* Utils, v1.4.0, v1.3.5
-- Remove non-class method convert_optodepos_to_circlular_2D_pos.m from ProbeClass to Utils.
-- Add missing function pretty_print_struct.m  used in DataTree to Utils library
-- Fix bug in last commit having to do with the MenuBox radiobutton dialog selction of spatial unit change: either a) correcting them and changing units ONLY  or  b) changing units and coordinates.
-- Add radiobutton selection style option to MenuBox.m
-- Fix some issues with MenuBox.m including issue with MenuBox disappearing outside of screen when run standalone with no parent GUI.

* v1.75.1

-- DataTree, v1.10.0, Fix error in probe registration loading SD file where anchor points are not copied correctly.
parent 4544f60f
Loading
Loading
Loading
Loading
+43 −24
Original line number Diff line number Diff line
@@ -1056,7 +1056,7 @@ classdef NirsClass < AcqDataClass & FileLoadSaveClass
                'MeasList',[], ...
                'MeasListAct',[], ...
                'SpringList',[], ...
                'AnchorList',[], ...
                'AnchorList',{{}}, ...
                'SrcMap',[], ...
                'SpatialUnit','', ...
                'xmin',0, ...
@@ -1070,19 +1070,35 @@ classdef NirsClass < AcqDataClass & FileLoadSaveClass
        
        
        % ----------------------------------------------------------------------------------
        function SetProbeSpatialUnit(obj, spatialUnitNew)
        function SetProbeSpatialUnit(obj, spatialUnitNew, scaling)
            % Set scaling based on current units and desired units if they do not match AND
            % scaling was not explcitly specified (i.e., passed in as an argument). 
            if ~exist('scaling','var') || isempty(scaling)
                scaling = 1;
                if strcmpi(spatialUnitNew,'mm')
                    if strcmpi(obj.SD.SpatialUnit,'cm')
                        scaling = 10;
                    elseif strcmpi(obj.SD.SpatialUnit,'m')
                        scaling = 1000;
                    end
                elseif strcmpi(spatialUnitNew,'cm')
                    if strcmpi(obj.SD.SpatialUnit,'mm')
                        scaling = 1/10;
                    elseif strcmpi(obj.SD.SpatialUnit,'m')
                        scaling = 100;
                    end
                elseif strcmpi(spatialUnitNew,'m')
                    if strcmpi(obj.SD.SpatialUnit,'mm')
                        scaling = 1/1000;
                    elseif strcmpi(obj.SD.SpatialUnit,'cm')
                        scaling = 1/100;
                    end
                else
                    spatialUnitNew = '';
                end
            end 
            
            
            obj.SD.SpatialUnit = spatialUnitNew;
            obj.SD.SrcPos = obj.SD.SrcPos * scaling;
            obj.SD.DetPos = obj.SD.DetPos * scaling;
@@ -1102,22 +1118,25 @@ classdef NirsClass < AcqDataClass & FileLoadSaveClass
        function FixProbeSpatialUnit(obj)        
            if isempty(obj.SD.SpatialUnit)
                q = MenuBox('Spatial units not provided in probe data. Please specify spatial units of the optode coordinates?', ...
                    {'mm','cm',sprintf('do not know')});
                    {'mm','cm','m'});
                if q==1
                    obj.SD.SpatialUnit = 'mm';
                elseif q==2
                    obj.SD.SpatialUnit = 'cm';
                elseif q==3
                    obj.SD.SpatialUnit = '';
                end
            end
            if ~strcmpi(obj.SD.SpatialUnit,'mm')
                q = MenuBox(sprintf('This probe uses ''%s'' units for probe coordinates. We recommend converting to ''mm'' units, to be consistent with Homer. Do you want to convert probe coordinates from %s to mm?', ...
                    obj.SD.SpatialUnit), {'YES','NO'}, 'upperleft');
                if q==1
                    obj.SetProbeSpatialUnit('mm')       
                    obj.SD.SpatialUnit = 'm';
                end
            end
            % We don't need to force anything on the user since homer and AV do internal conversions to 'mm'
            %
            %             if ~strcmpi(obj.SD.SpatialUnit,'mm')
            %                 q = MenuBox(sprintf('This probe uses ''%s'' units for probe coordinates. We recommend converting to ''mm'' units, to be consistent with Homer. Do you want to convert probe coordinates from %s to mm?', ...
            %                     obj.SD.SpatialUnit), {'YES','NO'}, 'upperleft');
            %                 if q==1
            %                     obj.SetProbeSpatialUnit('mm')
            %                 end
            %             end
            %
        end
        
        
+32 −2
Original line number Diff line number Diff line
@@ -1040,8 +1040,29 @@ classdef DataClass < FileLoadSaveClass
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    methods
        
        
        
        % ----------------------------------------------------------------------------------
        function Copy(obj, obj2)
            if isempty(obj)
                obj = DataClass();
            end
            if isempty(obj2)
                obj = DataClass();
                return;
            end
            if ~isa(obj2, 'DataClass')
                return;
            end
            obj.CopyMeasurementList(obj2);
            obj.dataTimeSeries = obj2.dataTimeSeries;
            obj.time = obj2.time;
        end
        
        
        
        % ----------------------------------------------------------------------------------
        function CopyMeasurementList(obj, obj2)
            if isempty(obj)
                obj = DataClass();
            end
@@ -1055,11 +1076,10 @@ classdef DataClass < FileLoadSaveClass
            for ii=1:length(obj2.measurementList)
                obj.measurementList(ii) = obj2.measurementList(ii).copy();      % shallow copy ok because MeasListClass has no handle properties
            end
            obj.dataTimeSeries = obj2.dataTimeSeries;
            obj.time = obj2.time;
        end
        
        
        
        % -------------------------------------------------------
        function B = eq(obj, obj2)
            B = false;
@@ -1081,6 +1101,16 @@ classdef DataClass < FileLoadSaveClass
            if length(obj.measurementList)~=length(obj2.measurementList)
                return;
            end
            if ~obj.EqualMeasurementLists(obj2)
                return;
            end
            B = true;
        end
        
        
        % -------------------------------------------------------
        function B = EqualMeasurementLists(obj, obj2)
            B = false;
            for ii=1:length(obj.measurementList)
                if obj.measurementList(ii)~=obj2.measurementList(ii)
                    return;
+10 −0
Original line number Diff line number Diff line
@@ -191,6 +191,16 @@ classdef MetaDataTagsClass < FileLoadSaveClass
        end
        
        
        % ----------------------------------------------------------------------------------
        function val = GetLengthUnit(obj)
            val = '';
            if isempty(obj)
                return
            end
            val = obj.tags.LengthUnit;
        end
        
        
        % ----------------------------------------------------------------------------------
        function nbytes = MemoryRequired(obj)
            nbytes = 0;
+10 −22
Original line number Diff line number Diff line
@@ -41,22 +41,22 @@ classdef ProbeClass < FileLoadSaveClass
                    SD = n.SD;
                    obj.wavelengths = SD.Lambda;
                    obj.wavelengthsEmission  = [];
                    if isfield(SD,'SrcPos2D') &  ~isempty(SD.SrcPos2D)
                    if isfield(SD,'SrcPos2D') &&  ~isempty(SD.SrcPos2D)
                        obj.sourcePos2D  = SD.SrcPos2D;
                    else
                        obj.sourcePos2D  = SD.SrcPos;
                    end
                    if isfield(SD,'DetPos2D') & ~isempty(SD.DetPos2D)
                    if isfield(SD,'DetPos2D') && ~isempty(SD.DetPos2D)
                        obj.detectorPos2D  = SD.DetPos2D;
                    else
                        obj.detectorPos2D  = SD.DetPos;
                    end
                    if isfield(SD,'SrcPos3D') & ~isempty(SD.SrcPos3D)
                    if isfield(SD,'SrcPos3D') && ~isempty(SD.SrcPos3D)
                        obj.sourcePos3D  = SD.SrcPos3D;
                    else
                        obj.sourcePos3D  = SD.SrcPos;
                    end
                    if isfield(SD,'DetPos3D') & ~isempty(SD.DetPos3D)
                    if isfield(SD,'DetPos3D') && ~isempty(SD.DetPos3D)
                        obj.detectorPos3D  = SD.DetPos3D;
                    else
                        obj.detectorPos3D  = SD.DetPos;
@@ -132,19 +132,6 @@ 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
        
        
        % ----------------------------------------------
@@ -161,9 +148,10 @@ classdef ProbeClass < FileLoadSaveClass
            end 
        end

        
        
        % -------------------------------------------------------
        function Project_3D_to_2D(obj)             
            
            if isempty(obj.sourcePos2D) && isempty(obj.detectorPos2D)
                if isempty(obj.landmarkPos3D) || ~obj.isValidLandmarkLabels()
                    nSource = size(obj.sourcePos3D,1);
@@ -230,8 +218,8 @@ classdef ProbeClass < FileLoadSaveClass
                        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);
                        obj.sourcePos2D = convert_optodepos_to_circlular_2D_pos(obj.sourcePos3D, T, norm_factor);
                        obj.detectorPos2D = convert_optodepos_to_circlular_2D_pos(obj.detectorPos3D, T, norm_factor);
                    end
                end
            end
@@ -259,7 +247,7 @@ classdef ProbeClass < FileLoadSaveClass
            if exist('LengthUnit','var')
                % Figure out the scaling factor to multiple by to get the coorinates to be in mm units
                if strcmpi(LengthUnit,'m')  % meter units
                    obj.scaling = 100;
                    obj.scaling = 1000;
                elseif strcmpi(LengthUnit,'cm')  % centimeter units
                    obj.scaling = 10;
                end
+73 −0
Original line number Diff line number Diff line
@@ -1794,6 +1794,79 @@ classdef SnirfClass < AcqDataClass & FileLoadSaveClass
            
        end
        
        
        
        % -----------------------------------------------------------------------
        function [md2d, md3d] = GetChannelsMeanDistance(obj)
            ml = obj.data(1).GetMeasListSrcDetPairs();
            d1 = zeros(size(ml,1),1);
            for ii = 1:length(d1)
                d1(ii) = dist3(obj.probe.sourcePos2D(ml(ii,1),:), obj.probe.detectorPos2D(ml(ii,2),:)); 
                d2(ii) = dist3(obj.probe.sourcePos3D(ml(ii,1),:), obj.probe.detectorPos3D(ml(ii,2),:)); 
            end
            md2d = mean(d1);
            md3d = mean(d2);
        end
        
        
        
        % -----------------------------------------------------------------------
        function err = ErrorCheckSpatialUnits(obj)
            err = 0;
            msg = [];
            [md2d, md3d] = obj.GetChannelsMeanDistance();
            LengthUnitDeclared = obj.metaDataTags.GetLengthUnit();            
            magnitudeMm = log10(30);
            magnitudeCm = log10(3);
            magnitudeM  = log10(.03);
            
            % 2D coordinates
            diffMm = abs(magnitudeMm - log10(md2d));
            diffCm = abs(magnitudeCm - log10(md2d));
            diffM = abs(magnitudeM - log10(md2d));
            [~, idx] =  min([diffMm, diffCm, diffM]);
            if idx == 1
                LengthUnitActual2D = 'mm';
            elseif idx == 2
                LengthUnitActual2D = 'cm';
            elseif idx == 3
                LengthUnitActual2D = 'm';
            end
            if ~strcmpi(LengthUnitDeclared, LengthUnitActual2D)
                msg{1} = sprintf('WARNING: Declared LengthUnit (%s) might not match the likely actual units (%s) of the 2D coordinates\n', ...
                    LengthUnitDeclared, LengthUnitActual2D);
            end
            
            % 2D coordinates
            diffMm = abs(magnitudeMm - log10(md3d));
            diffCm = abs(magnitudeCm - log10(md3d));
            diffM = abs(magnitudeM - log10(md3d));
            [~, idx] =  min([diffMm, diffCm, diffM]);
            if idx == 1
                LengthUnitActual3D = 'mm';
            elseif idx == 2
                LengthUnitActual3D = 'cm';
            elseif idx == 3
                LengthUnitActual3D = 'm';
            end
            if ~strcmpi(LengthUnitDeclared, LengthUnitActual3D)
                msg{2} = sprintf('WARNING: Declared LengthUnit (%s) might not match the likely actual units (%s) of the 3D coordinates\n\n', ...
                    LengthUnitDeclared, LengthUnitActual3D);
            end
            
            % Compare 2D units with 3D units
            if ~strcmpi(LengthUnitActual2D, LengthUnitActual3D)
                msg{3} = sprintf('WARNING: The likely actual units of the 2D coordinates (%s) might not match the like actual units of the 3D coordinates (%s)\n\n', ...
                    LengthUnitActual3D, LengthUnitActual3D);
            end
            
            if ~isempty(msg)
                MenuBox(msg);
            end
        end
        
        
        
    end
    
    
Loading