function [] = AccTool() clear all screen = get(0,'MonitorPositions'); low_x = (screen(1,3)-110)/2; low_y = (screen(1,4)-110)/2; R.f = figure(... 'units','pixels',... 'position',[low_x low_y 250 100],... 'menubar','none',... 'name','Number of classes?',... 'numbertitle','off',... 'resize','off'); R.hp = uipanel(... 'parent',R.f,... 'BackgroundColor',[0.9 0.9 0.9],... 'Units','pixels',... 'Position',[0 0 250 100]); R.t = uicontrol(... 'parent',R.f,... 'String','Specify the number of map classes',... 'Style', 'text',... 'BackgroundColor',[0.9 0.9 0.9],... 'Horizontalalignment','Left',... 'Position', [10 50 230 40]); R.pp = uicontrol(... 'style','pop',... 'units','pixels',... 'BackgroundColor',[0.9 0.9 0.9],... 'position',[100 15 50 40],... 'string',{'2','3','4','5','6','7','8','9','10','11','12','13','14','15'}); set(R.pp,'callback',{@pp_call,R}); % Set the callback. function [] = pp_call(varargin) R = varargin{3}; % Get the structure. S.q = get(R.pp,'Value') + 1; close(gcbf) empty_m = zeros(S.q+1,S.q+3); f_width = 448 + (S.q-2)*75.8; f_height = 350 + 10 + (S.q-2)*2*18; t_height = 76 + (S.q-2)*18; hp_height = 274 + (S.q-2)*18; cl_height = 30 + (S.q-2)*16; cl_width = 54; switch S.q case 2 cnames = {'Class 1','Class 2','Total','Am','Wh'}; S.rnames = {'Class 1','Class 2','Total'}; columneditable = [true true false true false]; case 3 cnames = {'Class 1','Class 2','Class 3','Total','Am','Wh'}; S.rnames = {'Class 1','Class 2','Class 3','Total'}; columneditable = [true true true false true false]; case 4 cnames = {'Class 1','Class 2','Class 3','Class 4','Total','Am','Wh'}; S.rnames = {'Class 1','Class 2','Class 3','Class 4','Total'}; columneditable = [true true true true false true false]; case 5 cnames = {'Class 1','Class 2','Class 3','Class 4','Class 5',... 'Total','Am','Wh'}; S.rnames = {'Class 1','Class 2','Class 3','Class 4','Class 5',... 'Total'}; columneditable = [true true true true true false true false]; case 6 cnames = {'Class 1','Class 2','Class 3','Class 4','Class 5',... 'Class 6','Total','Am','Wh'}; S.rnames = {'Class 1','Class 2','Class 3','Class 4','Class 5',... 'Class 6','Total'}; columneditable = [true true true true true true false true false]; case 7 cnames = {'Class 1','Class 2','Class 3','Class 4','Class 5',... 'Class 6','Class 7','Total','Am','Wh'}; S.rnames = {'Class 1','Class 2','Class 3','Class 4','Class 5',... 'Class 6','Class 7','Total'}; columneditable = [true true true true true true true false true... false]; case 8 cnames = {'Class 1','Class 2','Class 3','Class 4','Class 5',... 'Class 6','Class 7','Class 8','Total','Am','Wh'}; S.rnames = {'Class 1','Class 2','Class 3','Class 4','Class 5',... 'Class 6','Class 7','Class 8','Total'}; columneditable = [true true true true true true true true false... true false]; case 9 cnames = {'Class 1','Class 2','Class 3','Class 4','Class 5',... 'Class 6','Class 7','Class 8','Class 9','Total','Am','Wh'}; S.rnames = {'Class 1','Class 2','Class 3','Class 4','Class 5',... 'Class 6','Class 7','Class 8','Class 9','Total'}; columneditable = [true true true true true true true true true... false true false]; case 10 cnames = {'Class 1','Class 2','Class 3','Class 4','Class 5',... 'Class 6','Class 7','Class 8','Class 9','Class10',... 'Total','Am','Wh'}; S.rnames = {'Class 1','Class 2','Class 3','Class 4','Class 5',... 'Class 6','Class 7','Class 8','Class 9','Class10',... 'Total'}; columneditable = [true true true true true true true true true... true false true false]; case 11 cnames = {'Class 1','Class 2','Class 3','Class 4','Class 5',... 'Class 6','Class 7','Class 8','Class 9','Class10',... 'Class11','Total','Am','Wh'}; S.rnames = {'Class 1','Class 2','Class 3','Class 4','Class 5',... 'Class 6','Class 7','Class 8','Class 9','Class10',... 'Class11','Total'}; columneditable = [true true true true true true true true true... true true false true false]; case 12 cnames = {'Class 1','Class 2','Class 3','Class 4','Class 5',... 'Class 6','Class 7','Class 8','Class 9','Class10',... 'Class11','Class12','Total','Am','Wh'}; S.rnames = {'Class 1','Class 2','Class 3','Class 4','Class 5',... 'Class 6','Class 7','Class 8','Class 9','Class10',... 'Class11','Class12','Total'}; columneditable = [true true true true true true true true true... true true true false true false]; case 13 cnames = {'Class 1','Class 2','Class 3','Class 4','Class 5',... 'Class 6','Class 7','Class 8','Class 9','Class10',... 'Class11','Class12','Class13','Total','Am','Wh'}; S.rnames = {'Class 1','Class 2','Class 3','Class 4','Class 5',... 'Class 6','Class 7','Class 8','Class 9','Class10',... 'Class11','Class12','Class13','Total'}; columneditable = [true true true true true true true true true... true true true true false true false]; case 14 cnames = {'Class 1','Class 2','Class 3','Class 4','Class 5',... 'Class 6','Class 7','Class 8','Class 9','Class 10',... 'Class11','Class12','Class13','Class13','Total','Am','Wh'}; S.rnames = {'Class 1','Class 2','Class 3','Class 4','Class 5',... 'Class 6','Class 7','Class 8','Class 9','Class10',... 'Class11','Class12','Class13','Class14','Total'}; columneditable = [true true true true true true true true true... true true true true true false true false]; case 15 cnames = {'Class 1','Class 2','Class 3','Class 4','Class 5',... 'Class 6','Class 7','Class 8','Class 9','Class10',... 'Class11','Class12','Class13','Class14','Class15',... 'Total','Am','Wh'}; S.rnames = {'Class 1','Class 2','Class 3','Class 4','Class 5',... 'Class 6','Class 7','Class 8','Class 9','Class10',... 'Class11','Class12','Class13','Class14','Class15',... 'Total'}; columneditable = [true true true true true true true true true... true true true true true true false true false]; end screen = get(0,'MonitorPositions'); low_x = (screen(1,3)-f_width)/2; low_y = (screen(1,4)-f_height)/2; close(findobj('type','figure','Tag','MainAccTool')) S.f = figure(... 'Name','Accuracy, Area and Uncertainty Estimation Tool',... 'Tag','MainAccTool',... 'NumberTitle','off',... 'Color',[0.9 0.9 0.9],... 'Menubar','none',... 'Resize','off',... 'Position',[low_x low_y f_width f_height]); S.t = uitable(... 'parent',S.f,... 'Tag','matrix',... 'Data',empty_m,... 'ColumnName',cnames,... 'RowName',S.rnames,... 'Units','pixels',... 'Position',[0 hp_height f_width t_height],... 'ColumnEditable', columneditable,... 'CellEditCallback',{@matrixCall,S}); S.reftext = uicontrol(... 'parent',S.f,... 'String','Reference classes in columns (map classes in rows). Enter areas for each class in ''Am''.',... 'BackgroundColor',[0.9 0.9 0.9],... 'Style', 'text',... 'Horizontalalignment','Center',... 'FontSize',8,... 'Position', [0 f_height-10 f_width 10]); S.hp = uipanel(... 'parent',S.f,... 'FontSize',12,... 'BackgroundColor',[0.9 0.9 0.9],... 'Units','pixels',... 'Position',[0 0 f_width hp_height]); % testha = axes('Parent',S.f,'Visible','off','Position',[0 0 f_width f_height]) % % testht = text(... % 'Parent',testha, ... % 'String','Map', ... % 'Rotation',270,... % 'FontSize',8,... % 'Horizontalalignment','left',... % 'Units','pixels',... % 'Position',[6,f_height-t_height/2]); %%% BUTTONS S.b1 = uicontrol(... 'parent',S.hp,... 'Style', 'pushbutton',... 'String', 'OK',... 'BackgroundColor',[0.9 0.9 0.9],... 'HandleVisibility', 'Callback',... 'Units','pixels',... 'Position', [10 10 50 26]); S.b2 = uicontrol(... 'parent',S.hp,... 'Style', 'pushbutton',... 'BackgroundColor',[0.9 0.9 0.9],... 'String', 'Close',... 'Position', [70 10 50 26],... 'Callback',{@closeCall,S}); S.b3 = uicontrol(... 'parent',S.hp,... 'Style', 'pushbutton',... 'BackgroundColor',[0.9 0.9 0.9],... 'String', 'Help',... 'Position', [f_width-60 10 50 26],... 'Callback',{@helpCall,S}); S.b3 = uicontrol(... 'parent',S.hp,... 'Style', 'pushbutton',... 'BackgroundColor',[0.9 0.9 0.9],... 'String', 'Export',... 'Position', [130 10 50 26]); %%% TEXT CONTROLS %%% %%% Area %%% if S.q < 7 pos.t1 = [10 hp_height-2*18 300 20]; pos.t11 = [10 hp_height-cl_height-2*18 cl_width cl_height]; pos.t12 = [70 hp_height-cl_height-2*18 100 cl_height]; pos.t2 = [10 hp_height-cl_height-5*18 200 35]; pos.t21 = [10 hp_height-2*cl_height-5*18 cl_width cl_height]; pos.t22 = [70 hp_height-2*cl_height-5*18 400 cl_height]; pos.t3 = [273 hp_height-2*18 150 20]; pos.t31 = [273 hp_height-3*18 100 20]; pos.t32 = [273+60 hp_height-3*18 100 20]; pos.t4 = [273 hp_height-5*18 150 20]; pos.t41 = [273 hp_height-cl_height-5*18 cl_width cl_height]; pos.t42 = [273+60 hp_height-cl_height-5*18 100 cl_height]; pos.t5 = [273 hp_height-cl_height-7*18 150 20]; pos.t51 = [273 hp_height-2*cl_height-7*18 cl_width cl_height]; pos.t52 = [273+60 hp_height-2*cl_height-7*18 100 cl_height]; else % Area props pos.t1 = [10 hp_height-3*18 160 40]; pos.t11 = [10 hp_height-cl_height-3*18 cl_width cl_height]; pos.t12 = [70 hp_height-cl_height-3*18 100 cl_height]; % Area estimates pos.t2 = [10+130 hp_height-3*18 170 40]; pos.t21 = [10+130 hp_height-cl_height-3*18 cl_width cl_height]; pos.t22 = [70+130 hp_height-cl_height-3*18 400 cl_height]; % User's pos.t4 = [10+2*190 hp_height-2*18 160 20]; pos.t41 = [10+2*190 hp_height-cl_height-2*18 cl_width cl_height]; pos.t42 = [70+2*190 hp_height-cl_height-2*18 100 cl_height]; % Overall pos.t3 = [10+2*190 hp_height-cl_height-4*18 160 20]; pos.t31 = [10+2*190 hp_height-cl_height-5*18 100 20]; pos.t32 = [70+2*190 hp_height-cl_height-5*18 100 20]; % Producer's pos.t5 = [10+510 hp_height-2*18 160 20]; pos.t51 = [10+510 hp_height-cl_height-2*18 cl_width cl_height]; pos.t52 = [70+510 hp_height-cl_height-2*18 100 cl_height]; end S.t1 = uicontrol(... 'parent',S.hp,... 'String','Estimated area proportions',... 'FontWeight','bold',... 'BackgroundColor',[0.9 0.9 0.9],... 'Style', 'text',... 'Horizontalalignment','Left',... 'Position', pos.t1); S.t11 = uicontrol(... 'parent',S.hp,... 'String',S.rnames(1:S.q),... 'BackgroundColor',[0.9 0.9 0.9],... 'Style', 'text',... 'Horizontalalignment','Left',... 'Position', pos.t11); S.t12 = uicontrol(... 'parent',S.hp,... 'String',' ',... 'BackgroundColor',[0.9 0.9 0.9],... 'Style', 'text',... 'Horizontalalignment','Left',... 'Position', pos.t12); S.t2 = uicontrol(... 'parent',S.hp,... 'String','Estimated areas +- 95% confidence interval',... 'FontWeight','bold',... 'BackgroundColor',[0.9 0.9 0.9],... 'Style', 'text',... 'Horizontalalignment','Left',... 'Position', pos.t2); S.t21 = uicontrol(... 'parent',S.hp,... 'String',S.rnames(1:S.q),... 'BackgroundColor',[0.9 0.9 0.9],... 'Style', 'text',... 'Horizontalalignment','Left',... 'Position', pos.t21); S.t22 = uicontrol(... 'parent',S.hp,... 'String',' ',... 'BackgroundColor',[0.9 0.9 0.9],... 'Style', 'text',... 'Horizontalalignment','Left',... 'Position', pos.t22); %%% Accuracy %%% S.t3 = uicontrol(... 'parent',S.hp,... 'String','Overall accuracy',... 'FontWeight','bold',... 'BackgroundColor',[0.9 0.9 0.9],... 'Style', 'text',... 'Horizontalalignment','Left',... 'Position', pos.t3); S.t31 = uicontrol(... 'parent',S.hp,... 'String','All',... 'BackgroundColor',[0.9 0.9 0.9],... 'Style', 'text',... 'Horizontalalignment','Left',... 'Position', pos.t31); S.t32 = uicontrol(... 'parent',S.hp,... 'String',' ',... 'BackgroundColor',[0.9 0.9 0.9],... 'Style', 'text',... 'Horizontalalignment','Left',... 'Position', pos.t32); S.t4 = uicontrol(... 'parent',S.hp,... 'String','User''s accuracy',... 'FontWeight','bold',... 'BackgroundColor',[0.9 0.9 0.9],... 'Style', 'text',... 'Horizontalalignment','Left',... 'Position', pos.t4); S.t41 = uicontrol(... 'parent',S.hp,... 'String',S.rnames(1:S.q),... 'BackgroundColor',[0.9 0.9 0.9],... 'Style', 'text',... 'Horizontalalignment','Left',... 'Position', pos.t41); S.t42 = uicontrol(... 'parent',S.hp,... 'String',' ',... 'BackgroundColor',[0.9 0.9 0.9],... 'Style', 'text',... 'Horizontalalignment','Left',... 'Position', pos.t42); S.t5 = uicontrol(... 'parent',S.hp,... 'String','Producer''s accuracy ',... 'FontWeight','bold',... 'BackgroundColor',[0.9 0.9 0.9],... 'Style', 'text',... 'Horizontalalignment','Left',... 'Position', pos.t5); S.t51 = uicontrol(... 'parent',S.hp,... 'String',S.rnames(1:S.q),... 'BackgroundColor',[0.9 0.9 0.9],... 'Style', 'text',... 'Horizontalalignment','Left',... 'Position', pos.t51); S.t52 = uicontrol(... 'parent',S.hp,... 'String',' ',... 'BackgroundColor',[0.9 0.9 0.9],... 'Style', 'text',... 'Horizontalalignment','Left',... 'Position', pos.t52); %%% Checkbox error plot S.c = uicontrol(... 'parent',S.hp,... 'Style','checkbox',... 'BackgroundColor',[0.9 0.9 0.9],... 'String','Error plot?',... 'Value',1,... 'Position', [10 40 100 20]); %%% Define callbacks %%% set([S.b1,S.b3],{'callback'},{{@okCall,S};{@expCall,S}}); %%% Get error matrix %%% function [] = matrixCall(varargin) [h,S] = varargin{[1,3]}; S.M = get(h,'Data'); for i = 1:S.q W(i) = S.M(i,S.q+2)/sum(S.M(1:S.q,S.q+2)); end Ws = [W sum(W)]; n_xp = sum(S.M(1:S.q,1:S.q),2); M_1 = [n_xp; 0]; S.M = [S.M(:,1:S.q) M_1 S.M(:,S.q+2) Ws']; n_px = sum(S.M(1:S.q,1:S.q),1); M_2 = [n_px sum((S.M(1:S.q,S.q+1))) sum(S.M(1:S.q,S.q+2)) sum(W(1:S.q))]; S.M = [S.M(1:S.q,:);M_2]; set(h,'Data',S.M); guidata(S.f,S.M) %%% Calculate accuracy, area, and CI when OK pushed %%% function [] = okCall(varargin) S = varargin{3}; S.M = guidata(S.f); if isempty(S.M) errordlg('You need to populate the error matrix!') S.M = zeros(S.q+1,S.q+3); end Wh = S.M(1:S.q,S.q+3); cells = S.M(1:S.q,1:S.q); sm = sum(cells,2); for i = 1:S.q S.p(:,i) = Wh.*cells(:,i)./sm; V(i) = sum(Wh.^2.*(((1-cells(:,i)./sm).*cells(:,i)./sm)./(sm-1))); end % Reference and map area proportions p_r = sum(S.p,1); p_r = p_r'; p_m = sum(S.p,2); % Estimated areas adjusted for classification errors A_tot = S.M(S.q+1,S.q+2); S.A = round(A_tot.*p_r); % Area +- margin of error SE_p = sqrt(V); S.MoE = round(A_tot*1.96*SE_p); S.MoE = S.MoE'; A_ = strcat(num2str(S.A),' +- ',num2str(S.MoE)); % Accuracy measures S.over = sum(diag(S.p)); S.user = diag(S.p)./p_m; S.prod = diag(S.p)./p_r; set(S.t12,'String',num2str(round(p_r*10000)/10000)); set(S.t22,'String',A_); set(S.t32,'String',num2str(round(S.over*1000)/1000)); set(S.t42,'String',num2str(round(S.user*1000)/1000)); set(S.t52,'String',num2str(round(S.prod*1000)/1000)); if get(S.c,'Value') == 1 points = S.A./S.M(1:S.q,S.q+2);assignin('base','points',points) err = S.MoE./S.M(1:S.q,S.q+2);assignin('base','MoE',S.MoE) if isequal(err,zeros(S.q,1)) | max(isnan(points))==1 errordlg('No errorbars to display'); else S.f2 = figure; set(S.f2,'Name','Error Plot','NumberTitle','off','Menubar','none'); errorbar(points, err,'o'); hold on; plot(points,'o','MarkerEdgeColor','k','MarkerFaceColor','g','MarkerSize',8); plot(0:S.q+1,ones(S.q+2,1),'k') ylim([floor(min(points)-max(err)) ceil(max(points)+max(err))]) set(gca,'XTick',1:S.q) set(gca,'XTickLabel',S.rnames(1:S.q)) ylabel 'Area \pm margin of error (normalized by mapped area)' end end set([S.b1,S.b3],{'callback'},{{@okCall,S};{@expCall,S}}); %%% Export variables to workspace %%% function [] = expCall(varargin) S = varargin{3}; S.M = guidata(S.f); def = {'ErrorMatrix','AreaPropMatrix','Areas','OverUserProd'}; assignin('base',def{1},S.M) assignin('base',def{2},S.p) assignin('base',def{3},[(1:S.q)' S.A S.MoE]) assignin('base',def{4},[(1:S.q)' repmat(S.over,S.q,1) S.user S.prod]) msgtext = cellstr('The following variables were exported to the workspace: '); msgspace = cellstr(' '); msgbox([msgtext msgspace def]) %%% Print info and instructions when Help pushed %%% function [] = helpCall(varargin) disp(' ') disp(' ') disp(' ') disp(' ') disp(' **************************************************************') disp(' * *') disp(' * Accuracy, Area and Uncertainty Estimation Tool *') disp(' * *') disp(' * Pontus Olofsson, Dept. of Earth and Environment, Boston *') disp(' * University (olofsson@bu.edu people.bu.edu/olofsson) *') disp(' * *') disp(' **************************************************************') disp(' ') disp(' This tool estimates map class area (+- 95% CI) and accuracy'); disp(' using stratified estimation. All calculations are based on '); disp(' the information in an error matrix. Simply enter the sample'); disp(' counts together with the mapped areas of the classes, and '); disp(' click ''OK''. Note that the reference data are represented '); disp(' by the columns and mapped data by the rows. Specify the '); disp(' mapped areas for the different classes in column ''Am''. The'); disp(' mapped area proportions are automatically updated in column'); disp(' ''Wh''. ') disp(' ') disp(' Click ''OK'' to get estimates of accuracy and class area '); disp(' including 95% confidence intervals. If ''Error plot?'' is '); disp(' checked, a plot is generated showing the estimated area and'); disp(' the confidence interval relative the mapped area for each '); disp(' class (a value of one means that the estimated area and the'); disp(' mapped area are equal). '); disp(' '); disp(' The ''Export'' button exports the error matrix, the area '); disp(' proportions, the accuracy measures and the estimated areas '); disp(' including the confidence intervals to the current workspace.'); disp(' '); disp(' The eS.quations are described in Olofsson P, et al. (2012) ') disp(' ''Making better use of accuracy data in land change studies') disp(' estimating accuracy and area and S.quantifying uncertainty'',') disp(' Remote Sensing of Environment, in review.') disp(' ') disp(' ') %%% Close tool when Close is pushed function [] = closeCall(varargin) close(gcbf)