Skip to content
Snippets Groups Projects
gtDrawGrainUnitCells.m 22.78 KiB
function [f_handles, p_handle] = gtDrawGrainUnitCells(grains, varargin)
% GTDRAWGRAINUNITCELLS  Generalized case for more than one dataset
%     [f_handle, p_handle] = gtDrawGrainUnitCells(grains, varargin)
%     -------------------------------------------------------------
%     Draws grains by their unit cell representing grain size, location and
%     orientation by cubes or hexagonal prismes based on their Rodrigues vectors.
%
%     INPUT (- cell array -):
%       grains      = <cell>         grain cell-structure from indexing;
%                                    one for each phase or one for each dataset
%
%     OPTIONAL INPUT (p/v pairs - cell arrays -): as in gtAppDrawGrainPars
%       ids         = <int>          list of grain IDs of interest; by default all
%                                    the grains are drawn
%       cmap        = <double>       can be a component of the strain tensor
%                                    {grain.strain.strainT(3,3)} or a color map
%       hlight      = <int>          grain id-s to be highlighted {[]}
%       linecolor   = <double>       color for edges (1x3) {[0 0 0],[1 0 0],...}
%       strain      = <double>       scale factor for the strain values, if wanted. {0}
%                                    (zero to use the unstrained unit cell)
%       alpha       = <double>       transparency value for patches {1}
%       phaseid     = <int>          phase number {1}
%       patch       = <logical>      true if drawing the patch of the unit cell <true>
%       pxsize      = <double>       pixel size (mm/px) {0.001}
%       ratio       = <double>       c/a ratio; if empty, taken from parameters.cryst {[]}
%       type        = <string>       unit cell type; if empty, taken from parameters.cryst {''}
%       label       = <string>       name for entry in the legend {''}
%
%     OPTIONAL INPUT (p/v pairs): as in gtAppDrawGrainPars
%       orig        = <double>       sample reference (arrows) origin (mm)
%       caxis       = <logical>      flag to draw the c-axis {false}
%       pixels      = <logical>      flag to switch to pixels {false}
%       draw        = <logical>      Draw grain patches {true}
%       scale       = <logical>      Scale grain size {true}
%       size        = <double>       Factor to scale all the grains equally
%                                    {[]}
%       translate   = <logical>      Translate grain centers {true}
%
%       section     = <logical>      Draw a section for each grain {false}
%       secpos      = <double>       Section position {[]}
%       plane       = <string>       Section plane {'xy'}
%       paired      = <logical>      paired grains drawing useful for twins
%                                    One figure for each pair {false}
%
%       figure      = <logical>      Display or not the figure {true}
%       figpos      = <double>       figure position in pixels (1x4) {[100 100 700 500]}
%       figcolor    = <double>       figure background color {[0 0 0]}
%       legend      = <logical>      display or not the legend {false}
%       legendpos   = <double>       location of the legend box {'NorthEast'}
%       showaxes    = <string>       Shows axes or not {'on'}
%       sampleaxes  = <logical>      Draw sample axes {true}
%       sampleenv   = <logical>      Draw sample envelope {true}
%       zoom        = <double>       zoom in of this quantity {[]}
%       view        = <double>       3D angular view (1x2) {[-45 20]}
%       debug       = <logical>      print comments {false}
%
%       hf          = <handle>       existing figure handle {[]}
%       ha          = <handle>       existing axes handle {[]}
%
%     OUTPUT:
%       f_handles   = <struct>       figure handles
%       p_handle    = <handle>       patches handle
%
%     Usage:
%       For IPF-Z coloring for phase 1:
%         load parameters
%         load 4_grains/phase_01/index.mat grain
%         gtDrawGrainUnitCells({grain},'cmap',{gtIPFCmap(1,[0 0 1])},'pxsize',{parameters.acq.pixelsize})
%
%       With random coloring and displaying only some grains:
%         gtDrawGrainUnitCells({grain},'ids',{1:10},'cmap',{gtRandCmap(10)},'pxsize',{parameters.acq.pixelsize})   
%
%     Version 009 30-07-2014 by LNervo
%       Created gtAppDrawGrainPars

%     Version 008 20-01-2014 by LNervo
%     Version 007 17-10-2013 by LNervo
%       Added some options
%     Version 006 06-06-2013 by LNervo
%       Added function to compute unit cell vertices, modified
%       gtPlotGrainUnitCell
%     Version 005 11-03-2013 by LNervo
%       Use cell arrays to plot multiple datasets
%     Version 004 15-11-2012 by LNervo
%       Use gtDrawSampleGeometry(labgeo) to create the graphics with axis and reference
%       system
%     Version 003 23-10-2012 by LNervo
%       Add varargin


% default app parameters
app = gtAppDrawGrainPars(grains);

app = parse_pv_pairs(app,varargin);

app.linecolor = app.linecolor(1:numel(grains));

parameters = [];
load('parameters.mat');
labgeo  = parameters.labgeo;
if isempty(app.pxsize{1})
    app.pxsize{1}  = (labgeo.pixelsizeu + labgeo.pixelsizev)/2;
end

if isempty(app.hf)
    if (app.pixels)
        h_tmp = gtDrawSampleGeometry(labgeo,'orig',app.orig,'pxsize',app.pxsize{1},'max',100,'axes',app.sampleaxes,'sample',app.sampleenv);
    else
        h_tmp = gtDrawSampleGeometry(labgeo,'orig',app.orig,'centered',true,'axes',false,'sample',app.sampleenv);
    end
    h.fig = h_tmp.fig;
    app.hf = h_tmp.fig;
else
    h.fig = app.hf;
end
app.rot3d = h_tmp.rot3d;

if isempty(app.ha)
    if ~isempty(gca)
        app.ha = get(h.fig,'CurrentAxes');
    else
        app.ha = axes('Parent',h.fig);
    end
end

% create GUI
h = sfCreateGUI(h);
set(app.ha,'Parent',h.axis_panel);

% draw unit cells
hold(app.ha,'on');

hp = [];
% loop over datasets
for ii = 1 : numel(grains)

    if ii > 1
        if numel(app.type)==1,    app.type{ii}    = app.type{1}; end
        if numel(app.ratio)==1,   app.ratio{ii}   = app.ratio{1}; end
        if numel(app.pxsize)==1,  app.pxsize{ii}  = app.pxsize{1}; end
        if numel(app.cmap)==1,    app.cmap{ii}    = app.cmap{1}; end
        if numel(app.hlight)==1,  app.hlight{ii}  = app.hlight{1}; end
        if numel(app.label)==1,   app.label{ii}   = app.label{1}; end
        if numel(app.phaseid)==1, app.phaseid{ii} = app.phaseid{1}; end
        if numel(app.strain)==1,  app.strain{ii}  = app.strain{1}; end
    end
    cryst = parameters.cryst(app.phaseid{ii});
    if isempty(app.type{ii}),  app.type{ii}  = cryst.crystal_system; end
    if isempty(app.ratio{ii}), app.ratio{ii} = cryst.latticepar(3)/cryst.latticepar(1); end
    if isempty(app.ids{ii}),   app.ids{ii}   = 1:length(grains{ii}); end
    if isempty(app.cmap{ii}),  app.cmap{ii}  = repmat([1 0 0],length(grains{ii}),3); end %red color
    
    ids   = app.ids{ii};
    grain = grains{ii};
    cmap  = app.cmap{ii};
    
    % if single value (RGB), copy it for all the grains
    if size(cmap,1)==1 && size(cmap,2)>1
        cmap = repmat(cmap,length(grain),1);
    end
    % remove bkg color
    if all(cmap(1,:) == [0 0 0])
        cmap = cmap(2:end,:);
    end
    % get selected grains for current datasets
    grain = grain(ids);
    cmap  = cmap(ids,:);
    
    % vertices and faces calculation : TO DO LIST : unify in one function
    if strcmpi(app.type{ii},'cubic')
        data{ii} = gtCubicUnitCell('ratio',app.ratio{ii},'draw',false,'centered',true,'caxis',app.caxis);
    elseif strcmpi(app.type{ii},'hexagonal')
        data{ii} = gtHexagonalUnitCell('ratio',app.ratio{ii},'draw',false,'centered',true,'caxis',app.caxis);
    end

    p = [];
    for jj = 1:length(grain)

        % grain size
        if isfield(grain{jj},'stat') 
            if isfield(grain{jj}.stat,'size_int')
                grain{jj}.radius = 0.5*app.pxsize{ii}*grain{jj}.stat.size_int; % mm
            elseif isfield(grain{jj}.stat,'bbxsmean') && isfield(grain{jj}.stat,'bbysmean')
                grain{jj}.radius = 0.5*app.pxsize{ii}*(grain{jj}.stat.bbxsmean + grain{jj}.stat.bbysmean)/2; % mm
            end
        else
            grain{jj}.radius = 0.5*app.pxsize{ii}*10;
        end
        if (app.scale == false && ~isempty(app.size) && isnumeric(app.size) && app.size > 0) % it should be a multiplying factor
            grain{jj}.radius = 0.5*app.pxsize{ii}*app.size;
        end
        if (app.pixels)
            grain{jj}.radius = grain{jj}.radius/app.pxsize{ii};
            grain{jj}.center = grain{jj}.center/app.pxsize{ii};
        end
        % translate
        if (~app.translate)
            grain{jj}.center = zeros(1,3);
        end
        % grain strain
        if ~isfield(grain{jj},'strain')
            grain{jj}.strain.strainT = NaN(3);
        end
        % highlight grain?
        if ismember(jj,app.hlight{ii}), hl = true; else hl = false; end

        % computes vertices and caxis coordinates
        vertices{jj} = gtComputeGrainUnitCell(grain{jj}.R_vector,data{ii}.vertices,...
            grain{jj}.radius,grain{jj}.center,grain{jj}.strain.strainT,app.strain{ii});
        if (app.caxis)
            caxis{jj} = gtComputeGrainUnitCell(grain{jj}.R_vector,data{ii}.c_axis,...
                grain{jj}.radius,grain{jj}.center,grain{jj}.strain.strainT,app.strain{ii});
        else
            caxis{jj} = [];
        end

        % save the settings
        grain{jj}.cmap         = cmap(jj,:);
        grain{jj}.caxis        = caxis{jj};
        grain{jj}.vertices     = vertices{jj};
        grain{jj}.strain.scale = app.strain{ii};
        grain{jj}.linecolor    = app.linecolor{ii};
        grain{jj}.faces        = data{ii}.faces;
        grain{jj}.alpha        = app.alpha{ii};
        grain{jj}.patch        = app.patch{ii};
        grain{jj}.dataset      = ii;
        if ii > 1 && app.patch{ii-1} == false && app.patch{ii} == true
            app.linecolor{ii} = [0 0 0];
        end
        % draw the patch
        if (app.draw)
            % draws patches for prismatic planes
            p{end+1} = gtPlotGrainUnitCell(vertices{jj},caxis{jj},data{ii}.faces,...
                cmap(jj,:),hl,app.linecolor{ii},app.alpha{ii},app.patch{ii});

            set(p{end},'UserData',[ii ids(jj)]);
            set(p{end},'Tag',sprintf('data_%02d_grain_%04d',ii,grain{jj}.id));
            set(p{end},'ButtonDownFcn',@(src,evt)displayTag(src,evt,h.phaseselected_edit,h.grainselected_edit))
            patchMenu(p{end}, grain{jj})
        end

    end % end for jj % loop over grains

    % update cmap and data
    app.cmap{ii} = cmap;
    app.data{ii} = data{ii};
    % save the settings
    plotdata{ii} = grain;
    hp{ii} = p;

    % set the labels if empty
    if isempty(app.label{ii})
        app.label{ii} = app.type{ii};
    end

end % end for ii % loop over datasets
% update plotted data
app.plotdata = plotdata;

% draw a section if true
if (app.section)
    pos=min(mean(data{1}.vertices(data{1}.faces_end(1,:),1)),mean(data{1}.vertices(data{1}.faces_end(2,:),1)));
    if ~isempty(app.secpos)
        pos = app.secpos;
    end
    section_plane_vertices=[pos 1 1; pos 1 -1; pos -1 1; pos -1 -1];
    if strcmpi(app.plane,'xz')
        section_plane_vertices = section_plane_vertices(:,[2 1 3]);
    end
    if strcmpi(app.plane,'xy')
        section_plane_vertices = section_plane_vertices(:,[2 3 1]);
    end
    app.h.p_section = gtPlotGrainUnitCell(section_plane_vertices,[],[1 2 4 3],...
             [0 0 0],[],[0 0 0],0.4,true);
end

% paired grains
if (app.paired) && length(plotdata{1}) == length(plotdata{2})
    N = ceil(length(plotdata{1})/3 ) +1;
    for jj=1:length(plotdata{1})
        hf = gtSubFigure(N,4,jj);
        [~, hh] = gtPlotHexagon([plotdata{1}(jj); plotdata{2}(jj)],...
            'ids',[1 2],'cmap',[plotdata{1}{jj}.cmap; plotdata{2}{jj}.cmap;],...
            'reference',false,'overlap',true,'caxis',true,'alpha',0.4);
        set(hh.hf,'Position',get(hf,'Position'));
        delete(hf)
    end
end

% draw the legend
if (app.legend)
    h.obj = [];
    for ii=1:numel(grains)
        tmp = hp{ii};
        h.obj(ii) = tmp{end}(1);
    end
    [h.axes_leg,~] = legend(h.obj,app.label,...
       'Location',app.legendpos,'Box','off','EdgeColor',[1 1 1],'Parent',h.fig);
    h.patch_leg = findobj(get(h.axes_leg,'Children'),'Type','patch');
    % only for the legend patches
    set(h.patch_leg,'FaceColor',[1 1 1]);
end

% general settings axes and figure
if (~app.scale || ~app.translate)
    axis('auto')
end
if (app.pixels)
    axis('equal')
    axis('tight')
end
if ~isempty(app.zoom)
    zoom('out');
    zoom(app.zoom)
    zoom('off')
end
view(app.view);
axis('equal')
set(app.ha,'Visible',app.showaxes);
set(h.fig,'Position',app.figpos)
set(h.fig,'Renderer','zbuffer')
set(h.fig,'ToolBar','none')
set(h.fig,'Color',app.figcolor);

if (~app.figure)
    set(h.fig,'Visible','off');
end

% update handles
app.hf = h.fig;
app.hp = hp;

h.patch = hp;
h.axes  = app.ha;

% save application data
setappdata(h.fig,'AppData',app);
setappdata(h.fig,'hp',hp)

set(h.sample_show,    'Callback', @(src,evt)toggleSample(src,evt,h_tmp.senv));
set(h.axis_show,      'Callback', @(src,evt)toggleAxes(src,evt,app.ha));
set(h.grain_select_ok,'Callback', @(src,evt)selectGrains(src,evt,h.fig,h.grain_select_edit));
set(h.patch_show,     'Callback', @(src,evt)togglePatches(src,evt,hp));
set(h.rotate_active,  'Callback', @(src,evt)toggleRotate3d(src,evt,app.rot3d));
set(h.zoom_in,        'Callback', @(src,evt)setZoom(src,evt,app.ha,1.1));
set(h.zoom_out,       'Callback', @(src,evt)setZoom(src,evt,app.ha,0.9));
set(h.patch_display,  'Callback', @(src,evt)toggleFaces(src,evt,hp));

toggleRotate3d(h.rotate_active,[],app.rot3d);
setZoom([],[],app.ha,0.7);

if (app.debug)
    print_structure(app,'AppData')
end

% output arguments
if nargout > 0
    f_handles = h;
    if nargout > 1
        p_handle = hp;
    end
end

end % end of function

%%
% sub-functions
function h = sfCreateGUI(h)

    % GUI
    h.main_boxes = uiextras.HBox('Parent',h.fig,...
        'Tag','h_main_boxes');
      h.left_panel = uipanel('Parent',h.main_boxes,...
          'Tag','h_left_panel');
        h.leftbutton_boxes = uiextras.VButtonBox('Parent',h.left_panel,...
            'Tag','h_leftbutton_boxes');
          h.phaseselected_label = uicontrol('Parent',h.leftbutton_boxes,...
              'String','Selected dataset','Style','text');
          h.phaseselected_edit = uicontrol('Parent',h.leftbutton_boxes,...
              'String','','Style','text','FontWeight','bold');
          h.grainselected_label = uicontrol('Parent',h.leftbutton_boxes,...
              'String','Selected grain','Style','text');
          h.grainselected_edit = uicontrol('Parent',h.leftbutton_boxes,...
              'String','','Style','text','FontWeight','bold');

          uicontrol('Parent',h.leftbutton_boxes,'Visible','off','Enable','off');

          h.rotate_active = uicontrol('Parent',h.leftbutton_boxes,...
              'Style','pushbutton',...
              'String','Rotate3d OFF');
          h.zoom_in = uicontrol('Parent',h.leftbutton_boxes,...
              'Style','pushbutton',...
              'String','Zoom IN');
          h.zoom_out = uicontrol('Parent',h.leftbutton_boxes,...
              'Style','pushbutton',...
              'String','Zoom OUT');
          h.patch_display = uicontrol('Parent',h.leftbutton_boxes,...
              'Style', 'pushbutton',...
              'String','Hide faces');
          h.patch_show = uicontrol('Parent',h.leftbutton_boxes,...
              'Style','pushbutton',...
              'String','Hide grains');
          h.sample_show = uicontrol('Parent',h.leftbutton_boxes,...
              'Style','pushbutton',...
              'String','Hide sample',...
              'Callback',@(src,evt)toggleSample(src,evt,h_tmp.senv));
          h.axis_show = uicontrol('Parent',h.leftbutton_boxes,...
              'Style','pushbutton',...
              'String','Hide axes',...
              'Callback',@(src,evt)toggleAxes(src,evt,app.ha));

          uicontrol('Parent',h.leftbutton_boxes,'Enable','off','Visible','off');

          h.grain_panel = uicontrol('Parent',h.leftbutton_boxes,'Style','text','String','Toggle grains');
          h.grain_select_edit = uicontrol('Parent',h.leftbutton_boxes,'Style','edit','String','');
          h.grain_select_ok = uicontrol('Parent',h.leftbutton_boxes,'Style','pushbutton','String','OK');

      h.center_panel = uipanel('Parent',h.main_boxes,'BorderType','none',...
          'Tag','h_center_panel');
        h.center_boxes = uiextras.VBox('Parent',h.center_panel,...
            'Tag','h_center_boxes');
          h.axis_panel   = uipanel('Parent',h.center_boxes,...
              'Position',[0.25 0.1 0.85 0.9],...
              'BackgroundColor',[1 1 1],...
              'BorderType','line','BorderWidth',15,...
              'Tag','h_axis_panel');

    set(h.main_boxes,'Sizes',[140 -1]);

    buttonSize = get(h.leftbutton_boxes,'ButtonSize');
    buttonSize(1) = 130;
    set(h.leftbutton_boxes,'ButtonSize',buttonSize);
    buttonSize(1) = 50;

end

function patchMenu(hObj,app)

    hcmenu = uicontextmenu();
    uimenu('Parent',hcmenu,...
        'Label','Toggle Trasparency',...
        'Callback',@(src,evt)switchPatchRender(src,evt,hObj));
    uimenu('Parent',hcmenu,...
        'Label','Print Grain Info',...
        'Callback',@(src,evt)displayInfoGrain(src,evt,app));
    uimenu('Parent',hcmenu,...
        'Label','Get Grain Info',...
        'Callback',@(src,evt)getInfoGrain(src,evt,app));
    set(hObj,'UIContextMenu',hcmenu)

end

function displayInfoGrain(~, ~, app, fields)

    if ~exist('fields','var') || isempty(fields)
        fields = {'phaseid','id','dataset','R_vector','center','radius',...
        'cmap','caxis','vertices','linecolor',...
        'faces','alpha','patch'};
    end

    ind = findValueIntoCell(fieldnames(app), fields);
    cellStruct = struct2cell(app);
    cellStruct = cellStruct(ind(:,1));
    grain = cell2struct(cellStruct, fields, 1);
    print_structure(grain,'Grain info')
    

end

function getInfoGrain(~, ~, app)

    gID = app.id;
    pID = app.phaseid;
    disp(['Saved ''' ['grain' num2str(gID)] ''' variable for grain ' num2str(gID) ' phase ' num2str(pID) ' to the base workspace'])
    assignin('base',['grain' num2str(gID)],app)

end

function toggleFaces(hObj, ~, hp, h_edit)

    if ~exist('h_edit','var')
        h_edit = [];
    end

    [tags, ids] = getTagsIndexes(hObj,[],hp,h_edit);
    tags = vertcat(tags{:});

    for ii=1:length(tags)
        tag_patch = tags{ii};
        current_id = getIDfromTagName(tag_patch);
        current_ids = ids(ids(:,1)==current_id(1),:);
        [hasP, ind] = ismember(current_id(2), current_ids(:,2));
        if (hasP)
            switchPatchRender([],[],hp{current_id(1)}{ind});
        end
    end

end

function switchPatchRender(~,~,hObj)

    facecolor = get(hObj, 'FaceColor');
    edgecolor = get(hObj, 'EdgeColor');

    if ~isempty(findStringIntoCell(facecolor,{'none'},1)) || ~isempty(findValueIntoCell(facecolor,{[0 0 0]}))
        for ii=1:length(hObj)
            changePatchProperty(hObj(ii), 'FaceColor', edgecolor{ii})
            changePatchProperty(hObj(ii), 'EdgeColor', [0 0 0])
            changePatchProperty(hObj(ii), 'LineWidth', 1)
        end
    elseif ~isempty(findStringIntoCell(edgecolor,{'none'},1)) || ~isempty(findValueIntoCell(edgecolor,{[0 0 0]}))
        for ii=1:length(hObj)
            changePatchProperty(hObj(ii), 'EdgeColor', facecolor{ii})
            changePatchProperty(hObj(ii), 'FaceColor', 'none')
            changePatchProperty(hObj(ii), 'LineWidth', 2)
        end
    end

end

function changePatchProperty(h, property, value)

    if ~exist('property','var') || isempty(property)
        property = 'FaceColor';
    end

    if ~isprop(h, property)
        disp('Wrong property for the surrent handle')
        return
    end

    try
        set(h,property,value);
    catch Mexc

    end
    
end

function toggleRotate3d(hObj, ~, h)

    toggleStatus(h, 'Enable');
    toggleLabel(hObj,{'OFF','ON'})

end

function setZoom(~, ~, h, value)

    axes(h)
    zoom(value)

end

function selectGrains(hObj, ~, hf, h_edit)

    hp = getappdata(hf,'hp');
    set(hObj,'Callback',@(src,evt)togglePatches(src,evt,hp,h_edit));

end
function closeFigure(~,~,h)

    if ishandle(h)
        delete(h)
    end

end

function [tags, ids] = getTagsIndexes(hObj,~,hp,h_edit)

    tags = cell(1,0);
    ids = [];
    for ii=1:length(hp)
        p = cellfun(@(x) unique(get(x,'Tag')), hp{ii}, 'UniformOutput', false);
        p = vertcat(p{:});
        tags{ii} = p;
        tmp = cellfun(@(x) getIDfromTagName(x), tags{ii}, 'UniformOutput', false);
        ids = [ids; cell2mat(tmp)];
        
    end

    if exist('h_edit','var') && ~isempty(h_edit)
        ids = str2num(get(h_edit,'String'));
    else
%         tmp = cellfun(@(x) getIDfromTagName(x), tags, 'UniformOutput', false);
%         ids = mat2cell(cell2mat(tmp),size(tags,1),[2 2]);
        toggleLabel(hObj,[]);
    end
end

function togglePatches(hObj,~,hp,h_edit)

    if ~exist('h_edit','var')
        h_edit = [];
    end

    [tags, ids] = getTagsIndexes(hObj,[],hp,h_edit);
    tags = vertcat(tags{:});
    all_ids = cell2mat(cellfun(@(x) getIDfromTagName(x), tags, 'UniformOutput', false));
    if size(ids,2) == 2 && size(ids,1) > 0
        ids = ids(:,2);
    end
    for ii=1:length(ids)
        [hasP, ind] = ismember(ids(ii), reshape(all_ids(:,2), 1, []));
        if (hasP)
            current_id = all_ids(ind, :);
            current_ids = all_ids(all_ids(:,1) == current_id(1), :);

            if current_id(1) > 1
                [~, ind] = ismember(ids(ii), reshape(current_ids(:,2), 1, []));
            end
            toggleStatus(hp{current_id(1)}{ind});
        end
    end

end

function toggleSample(hObj,~,h_sample)

    toggleStatus(h_sample);
    toggleLabel(hObj,[]);

end

function toggleLabel(hObj,labels)

    if ~exist('labels','var') || isempty(labels)
        labels = {'Hide','Show'};
    end
    try
        curr_label = get(hObj,'String');
        curr_prop = 'String';
    catch Mexc
        curr_label = get(hObj,'Label');
        curr_prop = 'Label';
    end

    if ~isempty(strfind(curr_label,labels{1}))
        set(hObj,curr_prop,strrep(curr_label,labels{1},labels{2}))
    elseif ~isempty(strfind(curr_label,labels{2}))
        set(hObj,curr_prop,strrep(curr_label,labels{2},labels{1}))
    end

end

function toggleAxes(hObj,~,h_ax)

    toggleStatus(h_ax);
    toggleLabel(hObj,[]);

end

function toggleStatus(h, property)

    if ~exist('property','var') || isempty(property)
        property = 'Visible';
    end

    if ~isprop(h, property)
        disp('Wrong property for the surrent handle')
        return
    end

    curr_status = get(h,property);
    if strcmpi(curr_status, 'on')
        set(h,property,'off');
    elseif strcmpi(curr_status, 'off')
        set(h,property,'on');
    end

end

function ids = getIDfromTagName(tagname)

    ids = [];
    if ~isempty(tagname)
        ids = str2double( regexp(tagname, '\d*', 'match') );
    end
end

function displayTag(hObj, ~, h1, h2)

    current_tag = get(hObj, 'Tag');
    id = getIDfromTagName(current_tag);
    set(h1,'String',num2str(id(1)));
    set(h2,'String',num2str(id(2)));

end