function tsgqc( varargin )
%TSGQC Thermosalinograph (TSG) Quality Control software
% TSGQC is a software for interactive analysis and validation of
% underway SST / SSS (Sea Surface Temperature and Sea Surface Salinity)
% measurements from a SeaBird Thermosalinograph (TSG).
% It has been developed under Matlab.
%
% Usage:
%   tsgqc help
%
% See:
%   Documentation: http://www.ird.fr/us191/spip.php?article63
%   Source code: https://git.outils-is.ird.fr/grelet/TSG-QC
%

% Tips:
%  To get and check tsg structure anywhere during debug:
%  tsg = getappdata( findobj('Tag', 'TAG_TSG-QC_GUI'), 'tsg_data')


%% COPYRIGHT & LICENSE
%  Copyright 2007-2018 - IRD US191, all rights reserved.
%
%  This file is part of tsgqc.
%
%    TSG-QC is free software; you can redistribute it and/or modify
%    it under the terms of the GNU General Public License as publDisplayished by
%    the Free Software Foundation; either version 2 of the License, or
%    (at your option) any later version.
%
%    tsgqc 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 Datagui; if not, write to the Free Software
%    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA


%% Define global variables for VERSIONING
% ---------------------------------------
global VERSION
global CHAR_VERSION
global DATE_VERSION
global GOSUD_FORMAT_VERSION
global DEBUGGING
global DEFAULT_PATH_FILE

% version number, may be used to initialize some files when it change
% 0.90x -> 1.0RCx
% if you modify the tsgqc.preference structure, you need to increment
% or modify the version number to load a new default structure
% -------------------------------------------------------------------
VERSION      = 1.50;  % -> 1.44
CHAR_VERSION = '1.50';
DATE_VERSION = '09/24/2020';

% netcdf file version, see DATA FORMAT TSG document:
% CORTSG_format_gosud.doc
% --------------------------------------------------
GOSUD_FORMAT_VERSION     = '3.02';

%%  Initialization tasks
%   ********************

% Clear Command Window display, giving up a "clean screen."
% ---------------------------------------------------------
clc;

% Find program directory.
% functions (icons) should be store at a lower level
% add directories to Matlab search path, works on UNIX
% and Windows host
% ---------------------------------------------------
tsgqcname = mfilename;
fulltsgqcname = mfilename('fullpath');

% regular expression expr if it occurs at the end of the input string
% -------------------------------------------------------------------
expr = strcat(tsgqcname, '$');

% get pathname
% ------------
DEFAULT_PATH_FILE =  regexprep(fulltsgqcname, expr, '');

% update Matlab pathdef only for session
% addpath isn't mandatory and failed with compiled applications
% -------------------------------------------------------------
if (~isdeployed)
  p = [pathsep,...
    DEFAULT_PATH_FILE,[ 'tsg_util' pathsep],...
    DEFAULT_PATH_FILE,[ 'tsg_util/ScreenCapture' pathsep],...
    DEFAULT_PATH_FILE,[ 'tsg_util/gsw' pathsep],...
    DEFAULT_PATH_FILE,[ 'tsg_data' pathsep],...
    DEFAULT_PATH_FILE,[ 'tsg_io'   pathsep],...
    DEFAULT_PATH_FILE,[ 'tsg_icon' pathsep],...
    DEFAULT_PATH_FILE,[ 'tsg_climato' pathsep],...
    DEFAULT_PATH_FILE,[ 'tsg_map' pathsep]
    ];
  addpath( p, '-end' );
  rehash;
end

% define 'HandleVisibility' property for all objects
% --------------------------------------------------
handleVisibility = 'on';

% % get screen dimensions (pixels)
% % ------------------------------
% set(0,'Units','pixels');
% screenSize = get(0,'ScreenSize');
%
% % set default font size
% % ---------------------
% if screenSize(3) <= 1024
%   tsg.fontSize = 9;
% else
%   tsg.fontSize = 11;
% end

% Screen limits for the GUI
% -------------------------
if verLessThan('matlab','8.4')
  set(0,'Units','normalized');
  guiLimits = get(0,'ScreenSize');
else
  r = groot;
  r.Units = 'normalized';
  guiLimits = r.ScreenSize;
end

guiLimits(1) = guiLimits(1) + 0.01;
guiLimits(2) = guiLimits(2) + 0.05;
guiLimits(3) = guiLimits(3) - 0.02;
guiLimits(4) = guiLimits(4) - 0.15;

%% Optional arguments
% --------------------
inputFile  = '';
outputFile = '';
display    = false;
DEBUGGING  = false;
help       = false;

% parse and set optional arguments with couple 'property', 'value'
% -----------------------------------------------------------------
if length(varargin) == 1
  inputFile = varargin{1};
end
property_argin = varargin(1:end);
while length(property_argin) >= 2
  property = property_argin{1};
  value    = property_argin{2};
  property_argin = property_argin(3:end);
  switch lower(property)
    case {'inputfile', 'input', 'file'}
      inputFile = value;
    case {'outputfile', 'output'}
      outputFile = value;
    case 'display'
      display = value;
    case 'debug'
      DEBUGGING = value;
    case 'help'
      help = value;
    otherwise
      error('Unknow property: %s', property);
  end
end

% if property display is set to display, display them and quit
% -----------------------------------------------------------
if display
  fprintf('inputFile: %s\noutpuFile: %s\n', inputFile, outputFile);
  return;
end

% if property help is set to on, display help and quit
% -----------------------------------------------------------
if strcmp(help, 'on') || ~isempty(strfind(inputFile,'help'))
  fprintf('tsgqc usage:\n');
  fprintf('tsgqc(''<file>'')\n');
  fprintf('tsgqc(''inputfile'', <file>, ''outputfile'', <file>)\n');
  fprintf('tsgqc(''inputfile'', <file>, ''outputfile'', <file>),''display'',''true''\n');
  fprintf('tsgqc(''help'',''true'')\n');
  fprintf('tsgqc --help\n');
  fprintf('tsgqc(''<file>'', ''debug'', 1)\n');
  return;
end

%% Main TSGQC GUI
% ---------------

% Check if main TSGQC figure exist
% --------------------------------
hMainFig = findobj('Tag', 'TAG_TSG-QC_GUI');

% if TSGQC figure exist and still running, don't create a new instance
% --------------------------------------------------------------------
if ~isempty(hMainFig)
  
  % display error dialog box and quit
  % ---------------------------------
  errordlg({'An instance of TSGQC is still running !!!', ...
    'Open it from you task bar'}, 'Warning TSGQC');
  return;
  
end

% check if m_map toolbox is installed
% -----------------------------------
if ~exist('m_lldist.m','file') 
  
  % show dialog box when m_map toolbox is missing
  % -----------------------------------------------
  message = sprintf(['Sorry, but you do not seem to have the m_map Toolbox.\n',...
    'Do you want install it ?']);
  reply  = questdlg(message, 'Toolbox missing', 'Yes', 'No', 'Yes');
  if strcmpi(reply, 'No')
    % User said No, so exit.
    return
  else 
    % User said Yes, go to m_map download page
    web('https://www.eoas.ubc.ca/~rich/map.html');
    return
  end
end

% Create and then hide the GUI as it is being constructed.
% --------------------------------------------------------
hMainFig = figure(...
  'Name', ['TSG-QC Validation software - IRD - v', CHAR_VERSION, ' - ', DATE_VERSION],...
  'NumberTitle', 'off', ...
  'Resize', 'on', ...
  'Menubar', 'none', ...
  'Toolbar', 'none', ...
  'UserData', 'ButtonMotionOff', ...
  'WindowButtonMotionFcn', @MouseMotion, ...
  'CloseRequestFcn', @QuitMenuCallback,...
  'HandleVisibility', handleVisibility,...
  'Visible','on',...
  'Tag','TAG_TSG-QC_GUI',...
  'Units', 'normalized',...
  'Position',guiLimits, ...
  'Color', get( 0, 'DefaultUIControlBackgroundColor' ));

%% Check Matlab version for use of KeyPressFcn and KeyReleaseFcn properties
% -------------------------------------------------------------------------
switch ( version('-release') )
  case { '11', '12', '13', '14', '2006a', '2006b' }
    % dont process KeyPressFcn and KeyReleaseFcn events
  otherwise
    
    % show crossline when shitf key is pressed, vertical bar when ctrl key
    % --------------------------------------------------------------------
    set( hMainFig, 'KeyPressFcn',   @keyPressFcnCallback,...
      'KeyReleaseFcn', @keyReleaseFcnCallback);
end

%% Initialize tsg structure with tsg_preference function
% -----------------------------------------------------
if ~tsg_preferences(hMainFig, tsgqcname, DEFAULT_PATH_FILE)
  quitProgram(DEFAULT_PATH_FILE, hMainFig, hMapFig);
end

% Retrieve named application data
% -------------------------------
tsg = getappdata( hMainFig, 'tsg_data');


%%  Menu File
%   -----------------------------------------------------------------------
hFileMenu = uimenu(...
  'Parent', hMainFig,...
  'HandleVisibility', handleVisibility,...
  'Label', 'File');
hOpenMenu = uimenu(...
  'Parent', hFileMenu,...
  'Label','Open',...
  'Accelerator','O',...
  'HandleVisibility', handleVisibility,...
  'UserData', 'off',...
  'Callback', @OpenMenuCallback);
hSaveMenu = uimenu(...
  'Parent', hFileMenu,...
  'Label','Save',...
  'Accelerator','S',...
  'Enable', 'off',...
  'UserData', 'off',...
  'HandleVisibility', handleVisibility,...
  'Callback',@SaveMenuCallback);
hExportMenu = uimenu(...
  'Parent', hFileMenu,...
  'Label','Export',...
  'Accelerator','E',...
  'Enable', 'off',...
  'UserData', 'off',...
  'HandleVisibility', handleVisibility);
hExportTSG = uimenu(...
  'Parent', hExportMenu,...
  'Label','Tsg ascii file',...
  'Enable', 'on',...
  'HandleVisibility', handleVisibility,...
  'Callback',@ExportTsgCallback);
hExportSAMPLE = uimenu(...
  'Parent', hExportMenu,...
  'Label','Sample ascii file',...
  'Enable', 'on',...
  'HandleVisibility', handleVisibility,...
  'Callback',@ExportSampleCallback);

hQuitMenu = uimenu(...
  'Parent',hFileMenu,...
  'Label','Quit',...
  'Separator','on',...
  'Accelerator','Q',...
  'HandleVisibility', handleVisibility,...
  'Callback',@QuitMenuCallback);

%%  Menu Edit with Undo/Redo submenu
% ---------------------------------
hEditMenu = uimenu(hMainFig,'Label','Edit');
uimenu(hEditMenu,'Label','Undo',...
  'Accelerator','z',...
  'Tag','UIMENU_UNDO',...
  'Enable', 'off',...
  'Callback',@UndoMenuCallback);
uimenu(hEditMenu,'Label','Redo',...
  'Accelerator','r',...
  'Tag','UIMENU_REDO',...
  'Enable', 'off',...
  'Callback',@RedoMenuCallback);

%%  Menu Climatology with Annual/Seasonal/Monthly submenu
% --------------------------------------------------------

% define structure s stored in userdata
% -------------------------------------
s = struct('type', 'annual', 'time', 1);

hClimatoMenu = uimenu(hMainFig,'Label','Climatology', ...
  'Tag', 'TAG_UIMENU_CLIMATO_MAIN', ...
  'UserData', s);

% by defautl at startup, select climatology to annual
% ---------------------------------------------------
uimenu(hClimatoMenu,'Label','Annual',...
  'Checked','on',...
  'Tag','TAG_UIMENU_CLIMATO_ANNUAL',...
  'Enable', 'on',...
  'Callback', {@ClimatoSelectMenuCallback, 'annual', 1});

% declare top-level seasonal menu
% -------------------------------
hClimatoSeasonalMenu = uimenu(hClimatoMenu,'Label','Seasonal');

% declare label for seasonal submenu
% ----------------------------------
label = {'jan-feb-mar','apr-may-jun','jul-aug-sept','oct-nov-dec'};

% loop over the four submenu
% --------------------------
for i = 1:4
  uimenu(hClimatoSeasonalMenu,'Label',label{i},...
    'Checked','off',...
    'Tag',['TAG_UIMENU_CLIMATO_SEASONAL_' i],...
    'Enable', 'on',...
    'Callback',{@ClimatoSelectMenuCallback, 'seasonal', i});
end

% declare top-level monthly menu
% -------------------------------
hClimatoMonthlyMenu = uimenu(hClimatoMenu,'Label','Monthly');

% declare label for monthly submenu
% ----------------------------------
label = {'january','february','march','april','may','june','july','august',...
  'september','october','november','december'};

% loop over the four submenu
% --------------------------
for i = 1:12
  uimenu(hClimatoMonthlyMenu,'Label',label{i},...
    'Checked','off',...
    'Tag',['TAG_UIMENU_CLIMATO_MONTHLY_' i],...
    'Enable', 'on',...
    'Callback',{@ClimatoSelectMenuCallback, 'monthly', i});
end

%%  Menu Option with Preferences submenu
% --------------------------------------------------------
hOptionMenu = uimenu(hMainFig,'Label','Option');
uimenu(hOptionMenu,'Label','Preferences',...
  'Tag','TAG_UIMENU_OPTION_PREFERENCES',...
  'Enable', 'on',...
  'Callback', {@PreferencesMenuCallback});

%%  Menu QC automatic
%   Dependent functions : preferenceForm.m; tsg_preference.m,
%   @QCMenuCallback
%   ----------------------------------------------------------
hQCMenu = uimenu(...
  'Parent', hMainFig, 'Enable', 'off', 'HandleVisibility', handleVisibility,...
  'Label', 'QCauto');
hFlowMenu = uimenu(...
  'Parent', hQCMenu, 'Label','Flow', 'HandleVisibility', handleVisibility,...
  'UserData', 'off', 'Callback', {@QCMenuCallback,'Flow'});
hPressMenu = uimenu(...
  'Parent', hQCMenu, 'Label','Press', 'HandleVisibility', handleVisibility,...
  'UserData', 'off', 'Callback', {@QCMenuCallback,'Press'});
hSpeedMenu = uimenu(...
  'Parent', hQCMenu, 'Label','Ship Speed', 'HandleVisibility', handleVisibility,...
  'UserData', 'off', 'Callback', {@QCMenuCallback,'Speed'});
hSSPSminMenu = uimenu(...
  'Parent', hQCMenu, 'Label','SSPS min', 'HandleVisibility', handleVisibility,...
  'UserData', 'off', 'Callback', {@QCMenuCallback,'SSPSmin'});
hSSPSmaxMenu = uimenu(...
  'Parent', hQCMenu, 'Label','SSPS max', 'HandleVisibility', handleVisibility,...
  'UserData', 'off', 'Callback', {@QCMenuCallback,'SSPSmax'});
hSSJTminMenu = uimenu(...
  'Parent', hQCMenu, 'Label','SSJT min', 'HandleVisibility', handleVisibility,...
  'UserData', 'off', 'Callback', {@QCMenuCallback,'SSJTmin'});
hSSJTmaxMenu = uimenu(...
  'Parent', hQCMenu, 'Label','SSJT max', 'HandleVisibility', handleVisibility,...
  'UserData', 'off', 'Callback', {@QCMenuCallback,'SSJTmax'});
hSSTPminMenu = uimenu(...
  'Parent', hQCMenu, 'Label','SSTP min', 'HandleVisibility', handleVisibility,...
  'UserData', 'off', 'Callback', {@QCMenuCallback,'SSTPmin'});
hSSTPmaxMenu = uimenu(...
  'Parent', hQCMenu, 'Label','SSTP max', 'HandleVisibility', handleVisibility,...
  'UserData', 'off', 'Callback', {@QCMenuCallback,'SSTPmax'});

%%  Menu Help with F1 Help and About submenu
% --------------------------------------------------------
hOptionMenu = uimenu(hMainFig,'Label','Help');
uimenu(hOptionMenu,'Label','Help',...
  'Tag','TAG_UIMENU_HELP_HELP',...
  'Enable', 'on',...
  'Callback', {@HelpMenuCallback});
uimenu(hOptionMenu,'Label','About TSGQC',...
  'Tag','TAG_UIMENU_HELP_ABOUT',...
  'Enable', 'on',...
  'Callback', {@AboutMenuCallback});

%%  Toolbar pushbuttons
%   -----------------------------------------------------------------------
hToolbar       =   uitoolbar(...   % Toolbar for Open and Print buttons
  'Parent',hMainFig, ...
  'HandleVisibility','on');
hOpenPushtool  =   uipushtool(...   % Opendoc toolbar button
  'Parent',hToolbar,...
  'TooltipString','Open file',...
  'CData', iconReadMat('opendoc.mat'),...
  'HandleVisibility','on', ...
  'Tag','PUSHTOOL_OPEN',...
  'UserData', 'off',...
  'Enable', 'on',...
  'ClickedCallback', @OpenMenuCallback);
hSavePushtool  =   uipushtool(...   % Open Save toolbar button
  'Parent',hToolbar,...
  'TooltipString','Save NetCDF file',...
  'CData', iconReadMat('savedoc.mat'),...
  'HandleVisibility','on', ...
  'Tag','PUSHTOOL_SAVE',...
  'Enable', 'off',...
  'ClickedCallback', @SaveMenuCallback);
hPrintFigPushtool  =   uipushtool(...   % Open Save toolbar button
  'Parent',hToolbar,...
  'TooltipString','Print figures',...
  'CData', iconReadMat('printdoc.mat'),...
  'HandleVisibility','on', ...
  'Tag','PUSHTOOL_PRINTFIG',...
  'visible', 'on', 'Enable', 'on',...
  'ClickedCallback', @PrintFigMenuCallback);
hZoomInToggletool = uitoggletool(...   % Open Zoom In (increase) toolbar button
  'Parent',hToolbar,...
  'Separator', 'on', ...
  'TooltipString','Zoom In (increase)',...
  'CData', iconReadMat('zoomplus.mat'),...
  'HandleVisibility','on', ...
  'Tag','PUSHTOOL_ZOOM_IN',...
  'OnCallback',  @ZoomIn_OnMenuCallback,...
  'OffCallback',  @ZoomIn_OffMenuCallback);
hZoomOutToggletool = uitoggletool(...   % Open Zoom Out (decrease) toolbar button
  'Parent',hToolbar,...
  'Separator', 'on', ...
  'TooltipString','Zoom Out (decrease)',...
  'CData', iconReadMat('zoomminus.mat'),...
  'HandleVisibility','on', ...
  'Tag','PUSHTOOL_ZOOM_OUT',...
  'OnCallback',  @ZoomOut_OnMenuCallback,...
  'OffCallback',  @ZoomOut_OffMenuCallback);
hPanToggletool  =   uitoggletool(...   % Open Pan toolbar button
  'Parent',hToolbar,...
  'TooltipString','Pan',...
  'CData', iconReadMat('pan.mat'),...
  'HandleVisibility','on', ...
  'Tag','PUSHTOOL_PAN',...
  'Enable', 'off',...
  'OffCallback', @Pan_OffMenuCallback,...
  'OnCallback',  @Pan_OnMenuCallback);
hQCToggletool  =   uitoggletool(...   % Open QC toolbar button
  'Parent',hToolbar,...
  'TooltipString','Validation codes',...
  'Separator', 'on', ...
  'CData', iconReadMat('qcicon.mat'),...
  'HandleVisibility','on', ...
  'Tag','PUSHTOOL_QC',...
  'UserData', 'off',...
  'Enable', 'off',...
  'OffCallback', @QC_OffMenuCallback,...
  'OnCallback',  @QC_OnMenuCallback);
hTimelimitToggletool  = uitoggletool(...
  'Parent',hToolbar,...
  'TooltipString','Select time limit',...
  'CData', iconReadMat('selecttime.mat'),...
  'HandleVisibility','on', ...
  'Tag', 'CORRECT_STARTTIME', ...
  'UserData', 'off',...
  'Enable', 'off',...
  'OffCallback', @SelectTime_OffMenuCallback,...
  'OnCallback',  @SelectTime_OnMenuCallback);
hMapToggletool  =   uitoggletool(...   % Open Map toolbar button
  'Parent',hToolbar,...
  'TooltipString','Display ship track with m_map',...
  'Separator', 'on', ...
  'CData', iconReadMat('mapicon.mat'),...
  'HandleVisibility','on', ...
  'Tag','PUSHTOOL_MAP',...
  'UserData', 'off', ...
  'Enable', 'off',...
  'OffCallback', @Map_OffMenuCallback,...
  'OnCallback',  @Map_OnMenuCallback);
hGoogleEarthPushtool  = uipushtool(...   % Open Google Earth and plot track
  'Parent',hToolbar,...
  'TooltipString','Display ship track with Google Earth',...
  'CData', iconReadMat('google_earth.mat'),...
  'HandleVisibility','on', ...
  'Tag','PUSHTOOL_GOOGLEARTH',...
  'Enable', 'off',...
  'ClickedCallback', @GoogleEarthMenuCallback);
hClimToggletool  =   uitoggletool(...   % Open Climatology toolbar button
  'Parent',hToolbar,...
  'TooltipString','Climatology',...
  'CData', iconReadMat('climicon.mat'),...
  'HandleVisibility','on', ...
  'Tag','PUSHTOOL_CLIM',...
  'UserData', 'off',...
  'Enable', 'off',...
  'OffCallback', @Clim_OffMenuCallback,...
  'OnCallback',  @Clim_OnMenuCallback);
hCalToggletool  =   uitoggletool(...   %
  'Parent',hToolbar,...
  'TooltipString','Calibration sensors',...
  'Separator', 'on', ...
  'CData', iconReadMat('outils.mat'),...
  'HandleVisibility','on', ...
  'Tag','PUSHTOOL_CAL',...
  'UserData', 'off',...
  'Enable', 'off',...
  'OffCallback', @Cal_OffMenuCallback,...
  'OnCallback',  @Cal_OnMenuCallback);
hInterpToggletool  =   uitoggletool(...   %
  'Parent',hToolbar,...
  'TooltipString','Interpolate missing position',...
  'CData', iconReadMat('interp.mat'),...
  'HandleVisibility','on', ...
  'Tag','PUSHTOOL_INTERP',...
  'UserData', 'off',...
  'Enable', 'off',...
  'OffCallback', @Inter_OffMenuCallback,...
  'OnCallback',  @Inter_OnMenuCallback);
hBottleToggletool  = uitoggletool(...   % Correction module toolbar button
  'Parent',hToolbar,...
  'TooltipString','Correct the SSS TSG data',...
  'CData', iconReadMat('bottleicon.mat'),...
  'HandleVisibility','on', ...
  'Tag','PUSHTOOL_BOTTLE',...
  'UserData', 'off',...
  'Enable', 'off',...
  'OffCallback', @Bottle_OffMenuCallback,...
  'OnCallback',  @Bottle_OnMenuCallback);

hHeaderPushtool  = uipushtool(...   % Open headerForm button
  'Parent',hToolbar,...
  'TooltipString','Fill the header form',...
  'Separator', 'on', ...
  'CData', iconReadMat('hdricon.mat'),...
  'HandleVisibility','on', ...
  'Tag','PUSHTOOL_HEADER',...
  'Enable', 'off',...
  'ClickedCallback', @HeaderMenuCallback);

hReportPushtool  = uipushtool(...   % Open Report saving button
  'Parent',hToolbar,...
  'TooltipString','Save a report',...
  'CData', iconReadMat('reporticon.mat'),...
  'HandleVisibility','on', ...
  'Tag','PUSHTOOL_REPORT',...
  'Enable', 'off',...
  'ClickedCallback', @ReportMenuCallback);


%% Dynamic text area
%   -----------------------------------------------------------------------
%  Dynamic text area that displays the loaded filename, date, position and
%  salinity, temperature
%  ------------------------------------------------------------------------

% Create an uipanel
% -----------------
hInfoPanel = uipanel( ...
  'Parent', hMainFig, ...
  'Units', 'normalized', ...
  'BorderType', 'none',...
  'Visible', 'on', ...
  'Position',[.01, .96, .98, .04]);

% Dynamic text area that displays the date
% ----------------------------------------
uicontrol(...
  'Parent', hInfoPanel, ...
  'Units', 'normalized', ...
  'Style', 'Text', ...
  'Fontsize', tsg.fontSize, ...
  'Fontweight', 'bold', ...
  'HorizontalAlignment', 'left', ...
  'Position',[.01, .25, .04, .6], ...
  'String', 'File:');
hInfoFileText = uicontrol(...
  'Parent', hInfoPanel, ...
  'Style', 'text', ...
  'Fontsize', tsg.fontSize, ...
  'Visible','on',...
  'Units', 'normalized',...
  'HorizontalAlignment', 'left', ...
  'String', 'No file loaded', ...
  'Position', [.05, .25, .1, .6]);

% Text area that displays the date
% --------------------------------
uicontrol(...
  'Parent', hInfoPanel, ...
  'Units', 'normalized', ...
  'Style', 'Text', ...
  'Fontsize', tsg.fontSize, ...
  'Fontweight', 'bold', ...
  'HorizontalAlignment', 'left', ...
  'Position',[.15, .25, .04, .6], ...
  'String', 'Date:');
hInfoDateText = uicontrol(...
  'Parent', hInfoPanel, ...
  'Style', 'text', ...
  'Fontsize', tsg.fontSize, ...
  'Visible','on',...
  'Units', 'normalized',...
  'HorizontalAlignment', 'left', ...
  'String', 'N/A', ...
  'Position', [.20, .25, .13, .6]);

% Text area that displays the latitude
% ------------------------------------
uicontrol(...
  'Parent', hInfoPanel, ...
  'Units', 'normalized', ...
  'Style', 'Text', ...
  'Fontsize', tsg.fontSize, ...
  'Fontweight', 'bold', ...
  'HorizontalAlignment', 'left', ...
  'Position',[.33, .25, .06, .6], ...
  'String', 'Latitude:');
hInfoLatText = uicontrol(...
  'Parent', hInfoPanel, ...
  'Style', 'text', ...
  'Fontsize', tsg.fontSize, ...
  'Visible','on',...
  'Units', 'normalized',...
  'HorizontalAlignment', 'left', ...
  'String', 'N/A', ...
  'Position', [.4, .25, .9, .6]);

% Text area that displays the longitude
% -------------------------------------
uicontrol(...
  'Parent', hInfoPanel, ...
  'Units', 'normalized', ...
  'Style', 'Text', ...
  'Fontsize', tsg.fontSize, ...
  'Fontweight', 'bold', ...
  'HorizontalAlignment', 'left', ...
  'Position',[.495, .25, .08, .6], ...
  'String', 'Longitude:');
hInfoLongText = uicontrol(...
  'Parent', hInfoPanel, ...
  'Style', 'text', ...
  'Fontsize', tsg.fontSize, ...
  'Visible','on',...
  'Units', 'normalized',...
  'HorizontalAlignment', 'left', ...
  'String', 'N/A', ...
  'Position', [.585, .25, .09, .6]);

% Text area that display salinity and temperature
% -----------------------------------------------
uicontrol(...
  'Parent', hInfoPanel, ...
  'Units', 'normalized', ...
  'Style', 'Text', ...
  'Fontsize', tsg.fontSize, ...
  'Fontweight', 'bold', ...
  'HorizontalAlignment', 'left', ...
  'Position', [.68, .25, .05, .6], ...
  'String', 'SSPS:');
hInfoSSPSText = uicontrol(...
  'Parent', hInfoPanel, ...
  'Style', 'text', ...
  'Fontsize', tsg.fontSize, ...
  'Visible','on',...
  'Units', 'normalized',...
  'HorizontalAlignment', 'left', ...
  'String', 'N/A', ...
  'Position', [.73, .25, .05, .6]);
uicontrol(...
  'Parent', hInfoPanel, ...
  'Units', 'normalized', ...
  'Style', 'Text', ...
  'Fontsize', tsg.fontSize, ...
  'Fontweight', 'bold', ...
  'HorizontalAlignment', 'left', ...
  'Position',[.785, .25, .05, .6], ...
  'String', 'SSJT:');
hInfoSSJTText = uicontrol(...
  'Parent', hInfoPanel, ...
  'Style', 'text', ...
  'Fontsize', tsg.fontSize, ...
  'Visible','on',...
  'Units', 'normalized',...
  'HorizontalAlignment', 'left', ...
  'String', 'N/A', ...
  'Position', [.835, .25, .05, .6]);
uicontrol(...
  'Parent', hInfoPanel, ...
  'Units', 'normalized', ...
  'Style', 'Text', ...
  'Fontsize', tsg.fontSize, ...
  'Fontweight', 'bold', ...
  'HorizontalAlignment', 'left', ...
  'Position',[.89, .25, .05, .6], ...
  'String', 'SSTP:');
hInfoSSTPText = uicontrol(...
  'Parent', hInfoPanel, ...
  'Style', 'text', ...
  'Fontsize', tsg.fontSize, ...
  'Visible','on',...
  'Units', 'normalized',...
  'HorizontalAlignment', 'left', ...
  'String', 'N/A', ...
  'Position', [.94, .25, .05, .6]);

%% Plot axes
%   -----------------------------------------------------------------------
% The axes 1,2 and 3 will be plot in a uipanel
% axe 1 as propertie 'HandleVisibility' set to 'on' to prevent hidden
% visibility when first plot is empty
%--------------------------------------------------------------------
hPlotsPanel = uipanel( ...
  'Parent', hMainFig, ...
  'Units', 'normalized', ...
  'BorderType', 'etchedin',...
  'Visible', 'on',...
  'Position',[0.15, 0.0, .85, .952]);
hPlotAxes(1) = axes( 'Parent', hPlotsPanel, 'Visible', 'off', ...
  'box', 'on', 'Units', 'normalized','Tag', 'TAG_AXES_1', ...
  'HandleVisibility','on', 'Position',[.05, .64, .93, .35]);
hPlotAxes(2) = axes( 'Parent', hPlotsPanel, 'Visible', 'off',...
  'box', 'on', 'Units', 'normalized', 'Tag', 'TAG_AXES_2', ...
  'HandleVisibility','on', 'Position',[.05, .33, .93, .27]);
hPlotAxes(3) = axes('Parent', hPlotsPanel, 'Visible', 'off',...
  'box', 'on', 'Units', 'normalized', 'Tag', 'TAG_AXES_3', ...
  'HandleVisibility','on', 'Position',[.05, .02, .93, .27]);

% The map will be plot a new figure
% ---------------------------------
hMapFig = figure(...
  'BackingStore','off',...
  'Name', 'TSG SHIP TRACK', ...
  'NumberTitle', 'off', ...
  'Resize', 'on', ...
  'Menubar','none', ...
  'Toolbar', 'none', ...
  'Tag', 'MAP_FIGURE', ...
  'Visible','off',...
  'WindowStyle', 'normal', ...
  'CloseRequestFcn', @QuitMapCallback,...
  'Units', 'normalized',...
  'Color', get(0, 'DefaultUIControlBackgroundColor'));
%  'Position',[0.17, 0.05, .8, .44],...

% display map menus
% -----------------
hMapResolutionMenu = uimenu(...
  'Parent', hMapFig,...
  'HandleVisibility', handleVisibility,...
  'Label', 'Map');

uimenu(hMapResolutionMenu,'Label','Low',...
  'Checked','off',...
  'Tag','TAG_UIMENU_MAP_RESOLUTION_1',...
  'Enable', 'on',...
  'Callback', {@mapResolutionCallback, 1});

uimenu(hMapResolutionMenu,'Label','Medium',...
  'Checked','off',...
  'Tag','TAG_UIMENU_MAP_RESOLUTION_2',...
  'Enable', 'on',...
  'Callback', {@mapResolutionCallback, 2});

uimenu(hMapResolutionMenu,'Label','Intermediate',...
  'Checked','off',...
  'Tag','TAG_UIMENU_MAP_RESOLUTION_3',...
  'Enable', 'on',...
  'Callback', {@mapResolutionCallback, 3});

uimenu(hMapResolutionMenu,'Label','High',...
  'Checked','off',...
  'Tag','TAG_UIMENU_MAP_RESOLUTION_4',...
  'Enable', 'on',...
  'Callback', {@mapResolutionCallback, 4});

% set 'checked' property to 'on' for current map resolution
% ------------------------------------------------------------
hdls = flipud(findobj( '-regexp', 'tag', 'TAG_UIMENU_MAP_RESOLUTION_'));
set(hdls(tsg.preference.map.resolution), 'checked', 'on');

% display map Type menu
% ---------------------
hMapPatchMenu = uimenu(hMapFig,'Label','Type', ...
  'Tag', 'TAG_UIMENU_MAP_PATCH');

% preset map patch menu from preference
if tsg.preference.map.patch_value == 2
  chk_with_patch = 'on';
  chk_without_patch = 'off';
else
  chk_with_patch = 'off';
  chk_without_patch = 'on';
end

uimenu(hMapPatchMenu,'Label','Map without patch (faster)',...
  'Checked',chk_without_patch,...
  'Tag','TAG_UIMENU_MAP_WITHOUT_PATCH',...
  'Enable', 'on',...
  'Callback', {@mapPatchMenuCallback, 0});

uimenu(hMapPatchMenu,'Label','Map with patch (slower)',...
  'Checked',chk_with_patch,...
  'Tag','TAG_UIMENU_MAP_WITH_PATCH',...
  'Enable', 'on',...
  'Callback', {@mapPatchMenuCallback, 1});

% display map Border menu
% ------------------------
hMapBorderMenu = uimenu(...
  'Parent', hMapFig,...
  'HandleVisibility', handleVisibility,...
  'Label', 'Border');

uimenu(hMapBorderMenu,'Label','0',...
  'Checked','off',...
  'Tag','TAG_UIMENU_MAP_BORDER_1',...
  'Enable', 'on',...
  'Callback', {@mapDynaBorderCallback, 0});

uimenu(hMapBorderMenu,'Label','1',...
  'Checked','off',...
  'Tag','TAG_UIMENU_MAP_BORDER_2',...
  'Enable', 'on',...
  'Callback', {@mapDynaBorderCallback, 1});

uimenu(hMapBorderMenu,'Label','2',...
  'Checked','off',...
  'Tag','TAG_UIMENU_MAP_BORDER_3',...
  'Enable', 'on',...
  'Callback', {@mapDynaBorderCallback, 2});

uimenu(hMapBorderMenu,'Label','5',...
  'Checked','off',...
  'Tag','TAG_UIMENU_MAP_BORDER_4',...
  'Enable', 'on',...
  'Callback', {@mapDynaBorderCallback, 5});

uimenu(hMapBorderMenu,'Label','10',...
  'Checked','off',...
  'Tag','TAG_UIMENU_MAP_BORDER_5',...
  'Enable', 'on',...
  'Callback', {@mapDynaBorderCallback, 10});

uimenu(hMapBorderMenu,'Label','15',...
  'Checked','off',...
  'Tag','TAG_UIMENU_MAP_BORDER_6',...
  'Enable', 'on',...
  'Callback', {@mapDynaBorderCallback, 15});

% set 'checked' property to 'on' for current map border menu
% ----------------------------------------------------------
hdls = flipud(findobj( '-regexp', 'tag', 'TAG_UIMENU_MAP_BORDER_'));
set(hdls(tsg.preference.map.border_value), 'checked', 'on');

% map Climatology menu
% --------------------
hMapClimatologyMenu = uimenu(hMapFig,'Label','Climatology', ...
  'Tag', 'TAG_UIMENU_MAP_CLIMATOLOGY');

uimenu(hMapClimatologyMenu,'Label','off',...
  'Checked', 'on',...
  'Tag','TAG_UIMENU_MAP_CLIMATOLOGY_WITH_NONE',...
  'Enable', 'on',...
  'Callback', {@mapClimatologyCallback, 'none'});

uimenu(hMapClimatologyMenu,'Label','pcolor',...
  'Checked', 'off',...
  'Tag','TAG_UIMENU_MAP_CLIMATOLOGY_WITH_PCOLOR',...
  'Enable', 'off',...
  'Callback', {@mapClimatologyCallback, 'pcolor'});

uimenu(hMapClimatologyMenu,'Label','contour',...
  'Checked', 'off',...
  'Tag','TAG_UIMENU_MAP_CLIMATOLOGY_WITH_CONTOURF',...
  'Enable', 'off',...
  'Callback', {@mapClimatologyCallback, 'contourf'});

% map Track menu, select color and size for track and ship
% --------------------------------------------------------
hMapCustomizeMenu = uimenu(hMapFig, ...
  'Label', 'Customize', ...
  'Tag', 'TAG_UIMENU_MAP_CUSTOMIZE');

hMapShipMenu = uimenu(hMapCustomizeMenu,'Label','Ship', ...
  'Tag', 'TAG_UIMENU_MAP_SHIP');

hMapShipSizeMenu = uimenu(hMapShipMenu,'Label','Size', ...
  'Tag', 'TAG_UIMENU_MAP_SHIP_SIZE');

hMapShipColorMenu = uimenu(hMapShipMenu,'Label','Color', ...
  'Tag', 'TAG_UIMENU_MAP_SHIP_COLOR');

uimenu(hMapShipMenu,'Label','Color picker', ...
  'Checked','off',...
  'Tag', 'TAG_UIMENU_MAP_SHIP_COLOR_PICKER',...
  'Enable', 'on',...
  'Callback', {@mapColorPickerCallback, 'SHIP_COLOR'});

hMapTrackMenu = uimenu(hMapCustomizeMenu,'Label','Track', ...
  'Tag', 'TAG_UIMENU_MAP_TRACK');

hMapTrackSizeMenu = uimenu(hMapTrackMenu,'Label','Size', ...
  'Tag', 'TAG_UIMENU_MAP_TRACK_SIZE');

% hMapTrackColorMenu = uimenu(hMapTrackMenu,'Label','Color', ...
%   'Tag', 'TAG_UIMENU_MAP_TRACK_COLOR');

uimenu(hMapShipSizeMenu,'Label','4',...
  'Checked','off',...
  'Tag','TAG_UIMENU_MAP_SHIP_SIZE_4',...
  'Enable', 'on',...
  'Callback', {@mapCustomizeCallback, 4, 'SHIP_SIZE'});

uimenu(hMapShipSizeMenu,'Label','5',...
  'Checked','off',...
  'Tag','TAG_UIMENU_MAP_SHIP_SIZE_5',...
  'Enable', 'on',...
  'Callback', {@mapCustomizeCallback, 5, 'SHIP_SIZE'});

uimenu(hMapShipSizeMenu,'Label','6',...
  'Checked','off',...
  'Tag','TAG_UIMENU_MAP_SHIP_SIZE_6',...
  'Enable', 'on',...
  'Callback', {@mapCustomizeCallback, 6, 'SHIP_SIZE'});

uimenu(hMapShipSizeMenu,'Label','7',...
  'Checked','off',...
  'Tag','TAG_UIMENU_MAP_SHIP_SIZE_7',...
  'Enable', 'on',...
  'Callback', {@mapCustomizeCallback, 7, 'SHIP_SIZE'});

% set 'checked' property to 'on' for current map ship/size menu
% ----------------------------------------------------------
hdls = flipud(findobj( '-regexp', 'tag', 'TAG_UIMENU_MAP_SHIP_SIZE_'));
set(hdls(tsg.preference.map.ship.size_index), 'checked', 'on');

uimenu(hMapShipColorMenu,'Label','red',...
  'Checked','off',...
  'Tag','TAG_UIMENU_MAP_SHIP_COLOR_R',...
  'Enable', 'on',...
  'Callback', {@mapCustomizeCallback, 'r', 'SHIP_COLOR'});

uimenu(hMapShipColorMenu,'Label','black',...
  'Checked','off',...
  'Tag','TAG_UIMENU_MAP_SHIP_COLOR_K',...
  'Enable', 'on',...
  'Callback', {@mapCustomizeCallback, 'k', 'SHIP_COLOR'});

uimenu(hMapShipColorMenu,'Label','blue',...
  'Checked','off',...
  'Tag','TAG_UIMENU_MAP_SHIP_COLOR_B',...
  'Enable', 'on',...
  'Callback', {@mapCustomizeCallback, 'b', 'SHIP_COLOR'});

uimenu(hMapShipColorMenu,'Label','green',...
  'Checked','off',...
  'Tag','TAG_UIMENU_MAP_SHIP_COLOR_G',...
  'Enable', 'on',...
  'Callback', {@mapCustomizeCallback, 'g', 'SHIP_COLOR'});

% set 'checked' property to 'on' for current map ship/color menu
% ----------------------------------------------------------
hdls = flipud(findobj( '-regexp', 'tag', 'TAG_UIMENU_MAP_SHIP_COLOR_'));
set(hdls(tsg.preference.map.ship.color_index), 'checked', 'on');

uimenu(hMapTrackSizeMenu,'Label','1',...
  'Checked','off',...
  'Tag','TAG_UIMENU_MAP_TRACK_SIZE_1',...
  'Enable', 'on',...
  'Callback', {@mapCustomizeCallback, 1, 'TRACK_SIZE'});

uimenu(hMapTrackSizeMenu,'Label','2',...
  'Checked','off',...
  'Tag','TAG_UIMENU_MAP_TRACK_SIZE_2',...
  'Enable', 'on',...
  'Callback', {@mapCustomizeCallback, 2, 'TRACK_SIZE'});

uimenu(hMapTrackSizeMenu,'Label','3',...
  'Checked','off',...
  'Tag','TAG_UIMENU_MAP_TRACK_SIZE_3',...
  'Enable', 'on',...
  'Callback', {@mapCustomizeCallback, 3, 'TRACK_SIZE'});

uimenu(hMapTrackSizeMenu,'Label','4',...
  'Checked','off',...
  'Tag','TAG_UIMENU_MAP_TRACK_SIZE_4',...
  'Enable', 'on',...
  'Callback', {@mapCustomizeCallback, 4, 'TRACK_SIZE'});

% set 'checked' property to 'on' for current map track/size menu
% ----------------------------------------------------------
hdls = flipud(findobj( '-regexp', 'tag', 'TAG_UIMENU_MAP_TRACK_SIZE_'));
set(hdls(tsg.preference.map.track.size_index), 'checked', 'on');

% map Print menu
% --------------------
hMapPrintMenu = uimenu(hMapFig,'Label','Print', ...
  'Tag', 'TAG_UIMENU_MAP_PRINT');

hMapPrintPreviewMenu = uimenu(hMapPrintMenu,'Label','Print Preview',...
  'Tag','TAG_UIMENU_MAP_PRINT_PREVIEW',...
  'Callback', {@mapPrintPreviewCallback});

hMapPrintPrintMenu = uimenu(hMapPrintMenu,'Label','Print',...
  'Tag','TAG_UIMENU_MAP_PRINT_PREVIEW',...
  'Accelerator','P',...
  'Callback', {@mapPrintCallback});

uimenu(hMapPrintMenu,'Label','Save as',...
  'Tag','TAG_UIMENU_MAP_PRINT_SAVEAS',...
  'Callback', {@mapSaveAsCallback});

% disable print and printpreview bug on Matlab version < R2014b
% see issue #12 
% --------------------------------------------------------------
if verLessThan('matlab','8.4')
  set(hMapPrintPrintMenu, 'enable', 'off');
  set(hMapPrintPreviewMenu, 'enable', 'off');
end

% map Toolbar display menu
% --------------------
hMapToolbarMenu = uimenu(hMapFig,'Label','ToolBar', ...
  'Tag', 'TAG_UIMENU_MAP_TOOLBAR',...
  'Checked','off',...
  'Enable', 'on',...
  'Callback', {@mapToolBarCallback});

% set uipanel for map axes and climato
% ------------------------------------
hMapAxesPanel = uipanel( ...
  'Parent', hMapFig, ...
  'Units', 'normalized', ...
  'Visible', 'on',...
  'tag', 'TAG_MAP_CLIMATO_AXES',...
  'Position',[0, 0, 1, 1]);
%   'BorderType', 'etchedin',...

hMapClimatoPanel = uipanel( ...
  'Parent', hMapFig, ...
  'Units', 'normalized', ...
  'Visible', 'off',...
  'tag', 'TAG_MAP_CLIMATO_UIPANEL',...
  'Position',[.8, 0, .2, 1]);

% set map axes
% ------------
hPlotAxes(4) = axes(...     % the axes for plotting ship track map
  'Parent', hMapAxesPanel, ...
  'Units', 'normalized', ...
  'Visible', 'off', ...
  'Tag', 'TAG_AXES_4', ...
  'Color', 'none', ...
  'UserData', 'off', ...
  'HandleVisibility','on');

% display climatology control title
% ---------------------------------
uicontrol(...
  'Parent', hMapClimatoPanel, ...
  'Units', 'normalized', ...
  'Style', 'Text', 'Fontsize', tsg.fontSize, 'FontWeight', 'bold',...
  'HorizontalAlignment', 'Center', ...
  'Position',[.1, .9, .8, .05],'String', 'Range');

% display climatology min value text
% ----------------------------------
uicontrol(...
  'Parent', hMapClimatoPanel, ...
  'Units', 'normalized', ...
  'Style', 'Text', ...
  'Fontsize', tsg.fontSize-2, ...
  'HorizontalAlignment', 'center', ...
  'Position',[.2, .85, .6, .05], ...
  'String', 'Min value');

% display climatology min value uicontrol
% ---------------------------------------
uicontrol(...
  'Parent', hMapClimatoPanel, ...
  'Units', 'normalized',...
  'Style', 'Edit',...
  'BackgroundColor', 'w', ...
  'Fontsize', tsg.fontSize-2, 'HorizontalAlignment', 'right', ...
  'Position', [.2, .8, .6, .04], ...
  'String', '', ...
  'TooltipString', 'climatology min value', ...
  'Tag', 'CLIMATO_MIN_VALUE',...
  'Callback', {@mapContourfCallback, 'min'});

% display climatology max value text
% ----------------------------------
uicontrol(...
  'Parent', hMapClimatoPanel, ...
  'Units', 'normalized', ...
  'Style', 'Text', ...
  'Fontsize', tsg.fontSize-2, ...
  'HorizontalAlignment', 'center', ...
  'Position',[.2, .75, .6, .05], ...
  'String', 'Max value');

% display climatology min value uicontrol
% ---------------------------------------
uicontrol(...
  'Parent', hMapClimatoPanel, ...
  'Units', 'normalized',...
  'Style', 'Edit',...
  'BackgroundColor', 'w', ...
  'Fontsize', tsg.fontSize-2, 'HorizontalAlignment', 'right', ...
  'Position', [.2, .70, .6, .04], ...
  'String', '', ...
  'TooltipString', 'climatology max value', ...
  'Tag', 'CLIMATO_MAX_VALUE',...
  'Callback', {@mapContourfCallback, 'max'});


% display climatology contour step text
% ----------------------------------
uicontrol(...
  'Parent', hMapClimatoPanel, ...
  'Units', 'normalized', ...
  'Style', 'Text', ...
  'Fontsize', tsg.fontSize-2, ...
  'HorizontalAlignment', 'center', ...
  'Position',[.2, .65, .6, .05], ...
  'String', 'Contour step');

% display climatology contour step uicontrol
% ---------------------------------------
uicontrol(...
  'Parent', hMapClimatoPanel, ...
  'Units', 'normalized',...
  'Style', 'Edit',...
  'BackgroundColor', 'w', ...
  'Fontsize', tsg.fontSize-2, 'HorizontalAlignment', 'right', ...
  'Position', [.2, .60, .6, .04], ...
  'String', '', ...
  'TooltipString', 'climatology contouring step', ...
  'Tag', 'CLIMATO_STEP_VALUE',...
  'Callback', {@mapContourfCallback, 'step'});



%% uipanel for Quality Control Buttons - uibutton group
%   -----------------------------------------------------------------------
hbgQc = uibuttongroup(...
  'Parent', hMainFig, ...
  'Title', 'Validation Codes', ...
  'FontSize', tsg.fontSize-2, 'Fontweight', 'bold', ...
  'tag', 'TAG_QC_DISPLAY_PANEL',...
  'HandleVisibility','on',...
  'Visible', 'off',...
  'BorderType', 'etchedin',...
  'Units', 'normalized', 'Position', [.0, .71, .15, .25]);

% Initialize CallBack for button group properties
% -----------------------------------------------
set(hbgQc,'SelectionChangeFcn',@radioButtonQc);

%% Context Menus

% RadioButtons for Quality control
% -----------------------------------------------------------------------
hQcCmenu = uicontextmenu(...
  'Parent', hMainFig, ...
  'HandleVisibility','on' );

% get list of keys from hashtable tsg.qc.hash, defined inside
% tsg_initialisation.m
% -----------------------------------------------------------
qc_list = keys(tsg.qc.hash);

% internal loop count with state to on
% ------------------------------------
count = 0;

% iterate (loop) on each key store inside hastable
% ------------------------------------------------
for key = qc_list
  
  % get key and some values in hashtable tsg.qc.hash
  % ------------------------------------------------
  label = tsg.qc.hash.(key).label;
  color = tsg.qc.hash.(key).color;
  state = tsg.qc.hash.(key).state;
  
  % construct context menu with only code set to 'on' (valid)
  % ---------------------------------------------------------
  if strcmp( state, 'on')
    
    % add menu to hQcCmenu uicontextmenu
    % ----------------------------------
    uimenu(...
      'Parent', hQcCmenu,...
      'HandleVisibility','on', ...
      'Label', label,...
      'ForegroundColor', color,...
      'Callback', {@QC_ContextMenuCallback, key});
    
    % add button QC to hbgQc uibuttongroup
    % ------------------------------------
    uicontrol(...
      'Parent', hbgQc,...
      'Style', 'radiobutton',...
      'Fontsize', tsg.fontSize-1, 'ForegroundColor', color,...
      'HorizontalAlignment', 'left', ...
      'HandleVisibility','on', ...
      'String', label,...
      'Tag', ['TAG_QC_RADIO_' char(key)], ...
      'Units', 'normalized', 'Position', [.01, .85-count*.12, .6, 0.09]);
    
    % add text QC display statistic on hQcPanel
    % -----------------------------------------
    uicontrol(...
      'Parent', hbgQc,...
      'Style', 'text',...
      'Fontsize', tsg.fontSize-1, 'ForegroundColor', color,...
      'HorizontalAlignment', 'right', ...
      'HandleVisibility','on', ...
      'String', 'N/A ',...
      'Tag', ['TAG_QC_TEXT_' char(key)],...
      'Units', 'normalized', 'Position', [.61, .85-count*.12, .37, 0.09]);
    
    % increment count
    % ---------------
    count = count + 1;
  end
  
end % end of for loop

% zoom context menu
% -----------------
zoom_context_menu = uicontextmenu(...
  'Parent', hMainFig, 'HandleVisibility','on' );

uimenu('parent',zoom_context_menu, 'Label', 'Zoom Out (shift + click)', ...
  'Callback', @zoom_out_callback);
uimenu('parent',zoom_context_menu, 'Label', 'Reset to Original view', ...
  'Callback', @zoom_reset_callback);


%% uipanel for checkboxes
%   --------------------------------------
hCorPanel = uipanel(...
  'Parent', hMainFig, ...
  'Title', 'Correction applied to ...', ...
  'FontSize', tsg.fontSize-1, 'Fontweight', 'bold', ...
  'tag', 'TAG_CORRECTION_DISPLAY_PANEL',...
  'HandleVisibility','on',...
  'Visible', 'off',...
  'BorderType', 'etchedin',...
  'Units', 'normalized', 'Position', [.0, .001, .15, .24]);

% internal loop count with state to on
% ------------------------------------
count = 0;

% iterate (loop) on each key store inside hastable
% ------------------------------------------------
for key = qc_list
  
  % get key and some values in hashtable tsg.qc.hash
  % ------------------------------------------------
  label = tsg.qc.hash.(key).label;
  color = tsg.qc.hash.(key).color;
  state = tsg.qc.hash.(key).state;
  
  value = 0;
  if strcmp(char(key), 'HARBOUR') || strcmp(char(key), 'GOOD') ||...
      strcmp(char(key), 'PROBABLY_GOOD')
    value = 1;
  end
  
  % construct context menu with only code set to 'on' (valid)
  % ---------------------------------------------------------
  if strcmp( state, 'on')
    
    % add button QC to hbgQc uibuttongroup
    % ------------------------------------
    cbCorr(i) = uicontrol(...
      'Parent', hCorPanel, ...
      'Style', 'checkbox', ...
      'String', label, ...
      'Fontsize', tsg.fontSize-1, 'ForegroundColor', color,...
      'Value', value, ...
      'Tag',  ['TAG_CHECK_CORRECTION_' char(key)], ...
      'HandleVisibility', 'on',...
      'Units', 'normalized', 'Position', [.01, .85-count*.12, .6, 0.09]);
    
    % increment count
    % ---------------
    count = count + 1;
  end
  
end %end for loop

%% uibutton group panel - Choose the parameter (SSPS - SSTP - SSJT)
%   POP_UP filled in with the function "initParameterChoice"
%   -----------------------------------------------------------------------
hbgParameter = uibuttongroup(...
  'Parent', hMainFig, ...
  'Title', 'TSG Parameter', ...
  'FontSize', tsg.fontSize-1, 'Fontweight', 'bold', ...
  'tag', 'TAG_PARA_DISPLAY_PANEL',...
  'HandleVisibility','on',...
  'Visible', 'off',...
  'BorderType', 'etchedin',...
  'Units', 'normalized', 'Position', [.0, .78, .15, .18]);

text= {'Validation - Top'; 'Middle plot'; 'Bottom plot'};
ybottom = [.7 .38 .05];
for ipmh= 1 : 3
  pmhPara(ipmh) = uicontrol(...
    'Parent', hbgParameter, 'Style', 'popupmenu', ...
    'String', { 'NONE' }, 'Value', 1, ...
    'HandleVisibility', handleVisibility, ...
    'Tag', sprintf('SELECT_PARAMETER_%d', ipmh), ...
    'Callback', {@SelectParameter, ipmh}, ...
    'Units', 'normalized', 'Position', [.01, ybottom(ipmh), .3, 0.25]);
  htParameter(ipmh) = uicontrol( ...
    'Parent', hbgParameter, 'Style', 'Text', ...
    'String', text{ipmh}, ...
    'HorizontalAlignment', 'left', 'FontSize', tsg.fontSize-1, ...
    'Units', 'normalized',  'Position',[.35, ybottom(ipmh), .6, 0.25]);
end

%% uipanel for QC duplication
%   --------------------------------------
hDuplicateQcPanel = uipanel(...
  'Parent', hMainFig, ...
  'Title', 'Duplicate QC', ...
  'FontSize', tsg.fontSize-1, 'Fontweight', 'bold', ...
  'tag', 'TAG_CORRECTION_DISPLAY_PANEL',...
  'HandleVisibility','on',...
  'Visible', 'off',...
  'BorderType', 'etchedin',...
  'Units', 'normalized', 'Position', [.0, .40, .15, .10]);

hButtonDuplicateQC = uicontrol( ...
  'Style','pushbutton', ...
  'Parent',hDuplicateQcPanel, ...
  'Units', 'normalized', ...
  'String','Duplicate QC',...
  'FontSize',tsg.fontSize-1,...
  'Tag', 'DUPLICATE_QC_PUSH', ...
  'pos',[.2 .3 .6 .4], ...
  'HandleVisibility', handleVisibility, ...
  'Callback', @duplicateQc);

%% uiButtonGroup set to choose the Correction method
% -------------------------------------------------------------------------

% Create the button group
hbgCorMethod = uibuttongroup( ...
  'Parent',hMainFig, ...
  'Title','Correction Method', ...
  'Units', 'normalized', ...
  'FontSize',tsg.fontSize-1, 'Fontweight', 'bold',...
  'Visible', 'off', ...
  'Position',[.0, .24, .15, .29]);

% Create 4 radio buttons in the button group
hrbCorCancel = uicontrol( ...
  'Style','pushbutton', ...
  'Parent',hbgCorMethod, ...
  'Units', 'normalized', ...
  'String','Cancel all',...
  'FontSize',tsg.fontSize-1,...
  'Tag', 'CORRECT_CANCEL_PUSH', ...
  'pos',[.05 .04 .9 .13],...
  'HandleVisibility', handleVisibility, ...
  'Callback', {@cancelCorrectionCallback,'total'});
hrbPartCorCancel = uicontrol( ...
  'Style','pushbutton', ...
  'Parent',hbgCorMethod, ...
  'Units', 'normalized', ...
  'String',{'Cancel within Date Limits'},...
  'FontSize',tsg.fontSize-1,...
  'Tag', 'CORRECT_PART_CANCEL_PUSH', ...
  'pos',[.05 .19 .9 .13],...
  'HandleVisibility', handleVisibility, ...
  'Callback', {@cancelCorrectionCallback,'part'});
hrbCorBiais = uicontrol( ...
  'Style','pushbutton', ...
  'Parent',hbgCorMethod, ...
  'Units', 'normalized', ...
  'String','Bias adjustment',...
  'FontSize',tsg.fontSize-1,...
  'Tag', 'CORRECT_BIAIS_PUSH', ...
  'pos',[.05 .41 .9 .13],...
  'HandleVisibility', handleVisibility, ...
  'Callback', @biasCorrectionCallback);
hrbCorGradient = uicontrol( ...
  'Style','pushbutton', ...
  'Parent',hbgCorMethod, ...
  'Units', 'normalized', ...
  'String','Gradient adjustment',...
  'FontSize',tsg.fontSize-1,...
  'Tag', 'CORRECT_GRADIENT_PUSH', ...
  'pos',[.05 .56 .9 .13],...
  'HandleVisibility', handleVisibility, ...
  'Callback', @gradientCorrectionCallback);
hrbCorLinear = uicontrol( ...
  'Style','pushbutton', ...
  'Parent',hbgCorMethod, ...
  'Units', 'normalized', ...
  'String','Linear adjustment',...
  'FontSize',tsg.fontSize-1,...
  'Tag', 'CORRECT_LINEAR_PUSH', ...
  'pos',[.05 .71 .9 .13], ...
  'HandleVisibility', handleVisibility, ...
  'Callback', @linearCorrectionCallback);
hrbCorMedian = uicontrol( ...
  'Style','pushbutton', ...
  'Parent',hbgCorMethod, ...
  'Units', 'normalized', ...
  'String','Median filter adjustment',...
  'FontSize',tsg.fontSize-1,...
  'Tag', 'CORRECT_MEDIAN_PUSH', ...
  'pos',[.05 .86 .9 .13], ...
  'HandleVisibility', handleVisibility, ...
  'Callback', @medianCorrectionCallback);

%% uiPanel for the Date limits used in the Correction module

% Choose the date limits for the correction
% --------------------------------------------------
% Create the uipanel
hpDateLimit = uipanel( ...
  'Parent', hMainFig, ...
  'Title', 'Date Limits', ...
  'Units', 'normalized', ...
  'FontSize', tsg.fontSize-1, 'Fontweight', 'bold', ...
  'Visible', 'off', ...
  'Position', [.0, .53, .15, .18]);

htDateMin = uicontrol( ...
  'Parent', hpDateLimit, ...
  'Style', 'Text', ...
  'String', 'Min : yyyy-mm-dd hh:mm:ss', ...
  'HorizontalAlignment', 'left', ...
  'Units', 'normalized', ...
  'FontSize', tsg.fontSize-1, ...
  'Position',[.01 .8 .95 .15]);
hetDateMin = uicontrol( ...
  'Parent', hpDateLimit, ...
  'Style', 'edit', ...
  'Units', 'normalized', ...
  'BackgroundColor', 'white',...
  'FontSize', tsg.fontSize, ...
  'Tag', 'CORRECT_DATEMIN_EDIT',...
  'Position',[.01 .6 .95 .17]);

htDateMax = uicontrol( ...
  'Parent', hpDateLimit, ...
  'Style', 'Text', ...
  'String', 'Max : yyyy-mm-dd hh:mm:ss', ...
  'HorizontalAlignment', 'left', ...
  'Units', 'normalized', ...
  'FontSize', tsg.fontSize-1, ...
  'Position',[.01 .35 .95 .15]);
hetDateMax = uicontrol( ...
  'Parent', hpDateLimit, ...
  'Style', 'edit', ...
  'Units', 'normalized', ...
  'BackgroundColor', 'white',...
  'FontSize', tsg.fontSize, ...
  'Tag', 'CORRECT_DATEMAX_EDIT',...
  'Position',[.01 .15 .95 .17]);

%% uiPanel for the Calibration coefficient used the Correction module

% Create the uipanel
hpCalCoef = uipanel( ...
  'Parent', hMainFig, ...
  'Title', 'Calibration', ...
  'FontSize', tsg.fontSize-1, 'Fontweight', 'bold', ...
  'Visible', 'off', ...
  'Units', 'normalized','Position', [.0, .46, .15, .50]);

htCalCNDC1 = uicontrol( ...
  'Parent', hpCalCoef, ...
  'Style', 'Text', 'String', 'Conductivity : C = A*C + B', ...
  'HorizontalAlignment', 'left', 'FontSize', tsg.fontSize-1, ...
  'Units', 'normalized', 'Position',[.01 .925 .95 .05]);
htCalCNDC2 = uicontrol( ...
  'Parent', hpCalCoef, ...
  'Style', 'Text', 'String', 'A', ...
  'HorizontalAlignment', 'left', 'FontSize', tsg.fontSize-1, ...
  'Units', 'normalized', 'Position',[.01 .85 .08 .05]);
hetCalCNDCSlope = uicontrol( ...
  'Parent', hpCalCoef, ...
  'Style', 'edit', ...
  'FontSize', tsg.fontSize, 'BackgroundColor', 'white',...
  'Tag', 'CORRECT_CAL_CNDC_A',...
  'HandleVisibility','on', ...
  'Units', 'normalized', 'Position',[.1 .85 .85 .05]);
htCalCNDC3 = uicontrol( ...
  'Parent', hpCalCoef, ...
  'Style', 'Text', 'String', 'B', ...
  'HorizontalAlignment', 'left',  'FontSize', tsg.fontSize-1, ...
  'Units', 'normalized', 'Position',[.01 .775 .08 .05]);
hetCalCNDCOffset = uicontrol( ...
  'Parent', hpCalCoef, ...
  'Style', 'edit', ...
  'FontSize', tsg.fontSize, 'BackgroundColor', 'white',...
  'HandleVisibility','on', ...
  'Tag', 'CORRECT_CAL_CNDC_B',...
  'Units', 'normalized', 'Position',[.1 .775 .85 .05]);

htCalSSJT1 = uicontrol( ...
  'Parent', hpCalCoef, ...
  'Style', 'Text', 'String', 'SSJT : T = A*T + B', ...
  'HorizontalAlignment', 'left', 'FontSize', tsg.fontSize-1, ...
  'Units', 'normalized', 'Position',[.01 .675 .95 .05]);
htCalSSJT2 = uicontrol( ...
  'Parent', hpCalCoef, ...
  'Style', 'Text', 'String', 'A', ...
  'HorizontalAlignment', 'left', 'FontSize', tsg.fontSize-1, ...
  'Units', 'normalized', 'Position',[.01 .6 .08 .05]);
hetCalSSJTSlope = uicontrol( ...
  'Parent', hpCalCoef, ...
  'Style', 'edit', ...
  'BackgroundColor', 'white',...
  'FontSize', tsg.fontSize, ...
  'HandleVisibility','on', ...
  'Tag', 'CORRECT_CAL_SSJT_A',...
  'Units', 'normalized', 'Position',[.1 .6 .85 .05]);
htCalSSJT3 = uicontrol( ...
  'Parent', hpCalCoef, ...
  'Style', 'Text', 'String', 'B', ...
  'HorizontalAlignment', 'left', 'FontSize', tsg.fontSize-1, ...
  'Units', 'normalized', 'Position',[.01 .525 .08 .05]);
hetCalSSJTOffset = uicontrol( ...
  'Parent', hpCalCoef, ...
  'Style', 'edit', ...
  'FontSize', tsg.fontSize, 'BackgroundColor', 'white',...
  'HandleVisibility','on', ...
  'Tag', 'CORRECT_CAL_SSJT_B',...
  'Units', 'normalized', 'Position',[.1 .525 .85 .05]);

htCalSSTP1 = uicontrol( ...
  'Parent', hpCalCoef, ...
  'Style', 'Text', 'String', 'SSPT : T = A*T + B', ...
  'HorizontalAlignment', 'left', 'FontSize', tsg.fontSize-1, ...
  'Units', 'normalized', 'Position',[.01 .425 .95 .05]);
htCalSSTP2 = uicontrol( ...
  'Parent', hpCalCoef, ...
  'Style', 'Text', 'String', 'A', ...
  'HorizontalAlignment', 'left', 'FontSize', tsg.fontSize-1, ...
  'Units', 'normalized', 'Position',[.01 .35 .08 .05]);
hetCalSSTPSlope = uicontrol( ...
  'Parent', hpCalCoef, ...
  'Style', 'edit', ...
  'BackgroundColor', 'white',...
  'FontSize', tsg.fontSize, ...
  'HandleVisibility','on', ...
  'Tag', 'CORRECT_CAL_SSJT_A',...
  'Units', 'normalized', 'Position',[.1 .35 .85 .05]);
htCalSSTP3 = uicontrol( ...
  'Parent', hpCalCoef, ...
  'Style', 'Text', 'String', 'B', ...
  'HorizontalAlignment', 'left', 'FontSize', tsg.fontSize-1, ...
  'Units', 'normalized', 'Position',[.01 .275 .08 .05]);
hetCalSSTPOffset = uicontrol( ...
  'Parent', hpCalCoef, ...
  'Style', 'edit', ...
  'FontSize', tsg.fontSize, 'BackgroundColor', 'white',...
  'HandleVisibility','on', ...
  'Tag', 'CORRECT_CAL_SSJT_B',...
  'Units', 'normalized', 'Position',[.1 .275 .85 .05]);

hrbCal = uicontrol( ...
  'Style','pushbutton', 'Parent',hpCalCoef, ...
  'String','Calibrate',...
  'FontSize',tsg.fontSize-1,...
  'Tag', 'CORRECT_CAL_PUSH', ...
  'Units', 'normalized','pos',[.05 .15 .9 .075], ...
  'HandleVisibility', handleVisibility, ...
  'Callback', @CalibrateCallback);
hrbCancelCal = uicontrol( ...
  'Style','pushbutton', 'Parent',hpCalCoef, ...
  'String','Cancel calibration',...
  'FontSize',tsg.fontSize-1,...
  'Tag', 'CORRECT_CAL_PUSH', ...
  'Units', 'normalized','pos',[.05 .05 .9 .075], ...
  'HandleVisibility', handleVisibility, ...
  'Callback', @CancelCalibrationCallback);


%% uiPanel for Interpolation of position

% Create the uipanel
hpInterpPos = uipanel( ...
  'Parent', hMainFig, ...
  'Title', 'Lat-Lon interpolation', ...
  'FontSize', tsg.fontSize-1, 'Fontweight', 'bold', ...
  'Visible', 'off', ...
  'Units', 'normalized','Position', [.0, .75, .15, .21]);
hrbInterpLinear = uicontrol( ...
  'Style','pushbutton', 'Parent',hpInterpPos, ...
  'String','Linear interpolation',...
  'FontSize',tsg.fontSize-1,...
  'Tag', 'TAG_PUSH_INTERP_LINEAR', ...
  'Units', 'normalized','pos',[.05 .65 .9 .25], ...
  'HandleVisibility', handleVisibility, ...
  'Callback', @InterpPosLinearCallback);
hrbInterpOther = uicontrol( ...
  'Style','pushbutton', 'Parent',hpInterpPos, ...
  'String','Other method',...
  'FontSize',tsg.fontSize-1,...
  'Tag', 'TAG_PUSH_INTERP_OTHER', ...
  'Units', 'normalized','pos',[.05 .35 .9 .25], ...
  'HandleVisibility', handleVisibility, ...
  'Callback', @InterpPosOtherCallback);
hrbInterpCancel = uicontrol( ...
  'Style','pushbutton', 'Parent',hpInterpPos, ...
  'String','Cancel interpolation',...
  'FontSize',tsg.fontSize-1,...
  'Tag', 'TAG_PUSH_INTERP_CANCEL', ...
  'Units', 'normalized','pos',[.05 .05 .9 .25], ...
  'HandleVisibility', handleVisibility, ...
  'Callback', @InterpPosCancelCallback);

%
% end of main function (GUI definition)
%
if ~isempty(inputFile)
  OpenMenuCallback
end


%% *************************** CALLBACKS **********************************
%  All following callback are in nested functions

%----------------------------------------------------------------------
%% OpenMenuCallback function run when the Open menu item is selected
%----------------------------------------------------------------------
  function OpenMenuCallback(src, evnt)
    
    % Activate or desactivate uipanels
    % --------------------------------
    set( hpCalCoef,            'Visible', 'off' );
    set( hpDateLimit,          'Visible', 'off' );
    set( hpInterpPos,          'Visible', 'off' );
    %     set( hMapFig,            'Visible', 'off' );
    %    set( hbgParameter,         'Visible', 'off');
    
    % Toggle button
    % -------------
    set( hBottleToggletool,    'state', 'off' );
    set( hCalToggletool,       'state', 'off' );
    set( hClimToggletool,      'state', 'off' );
    set( hInterpToggletool,    'state', 'off' );
    set( hPanToggletool,       'state', 'off' );
    set( hQCToggletool,        'state', 'off' );
    %     set( hMapToggletool,       'state', 'off' );
    set( hTimelimitToggletool, 'state', 'off' );
    %    set( hZoomToggletool,      'state', 'off' );
    
    % Get the tsg structure
    % ---------------------
    tsg = getappdata( hMainFig, 'tsg_data');
    
    % Open standard dialog box for retrieving files
    % ---------------------------------------------
    if isempty(inputFile)
      [fileName, pathname, filterIndex] = uigetfile( tsg.preference.fileExtension, 'Pick a file');
    else
      % batch mode
      [pathname,fileName,ext] = fileparts(inputFile);
      fileName = strcat(fileName, ext);
      inputFile = [];
      filterIndex = 1;
    end
    
    % flushes the evnt queue and updates the closed uigetfile window
    % ---------------------------------------------------------------
    drawnow;
    
    % if the user clicks the Cancel button or closes the dialog window,
    % FileName and PathName are set to 0.
    % -----------------------------------------------------------------
    if ~isequal(fileName, 0)
      
      % uigetfile add an extra index (*.*) and a bug if user select file from
      % *.* and fileExtension(filterIndex) create an Index exceeds matrix
      % now, we use strcat('*',ext) instead
      [~,~,ext] = fileparts(fileName);
      
      % Pointer set to watch during reading and plotting
      % ------------------------------------------------
      set( hMainFig, 'Pointer', 'watch' );
      
      % construct valid and full file path
      % -----------------------------------
      fullFileName = fullfile(pathname, fileName);
      
      % the last extension selected move on top in cell array preference.fileExtensions
      % ----------------------------------------------------------------------
      tsg.preference.fileExtension = ...
        circshift(tsg.preference.fileExtension, 1 - filterIndex);
      setappdata( hMainFig, 'tsg_data', tsg);
      
      % Read the data
      % -------------
      [errTsg, errSpl] = read_data( hMainFig, strcat('*',ext), fullFileName);
      
      % Keep the pathname of the tsgqc m_file
      % -------------------------------------
      %       tsgqcname = mfilename;
      %       fulltsgqcname = mfilename('fullpath');
      %       tsg.DEFAULT_PATH_FILE = strrep(fulltsgqcname, tsgqcname, '') ;
      %       setappdata( hMainFig, 'tsg_data', tsg);
      
      % A TSG file has been read
      % ------------------------
      if errTsg > 0
        
        % set WindowButtonMotionFcn on
        % ----------------------------
        set( hMainFig, 'WindowButtonMotionFcn', @MouseMotion);
        
        % A TSG file has been open and read
        % ---------------------------------
        set( hOpenMenu, 'UserData', 'on' );
        
        % enable toolbar menu pushtool
        % ----------------------------
        hdls_pushtool = findobj('-regexp','Tag', 'PUSHTOOL_');
        set(hdls_pushtool, 'Enable', 'on');
        
        set( hbgParameter, 'Visible', 'on');
        
        % Enable Save and Export menu
        % ---------------------------
        set(hSaveMenu,   'Enable', 'on');
        set(hExportMenu, 'Enable', 'on');
        set(hQCMenu, 'Enable', 'on');
        
        % update some fields in tsg structure and restore tsg
        % ---------------------------------------------------
        %         updateTsgStruct(hMainFig );
        %         tsg = getappdata( hMainFig, 'tsg_data');
        
        % update the filename display
        % ---------------------------
        set( hInfoFileText, 'String', fileName);
        
        % The callback to detect the mouse motion can be set to on
        % --------------------------------------------------------
        set( hMainFig, 'UserData', 'ButtonMotionOn');
        
        % Update QC statistics
        % --------------------
        display_QC( hMainFig );
        
        % Initialise the popupmenu displaying the parameters that can be
        % plot
        % --------------------------------------------------------------
        initParameterChoice( hMainFig, pmhPara );
        tsg = getappdata( hMainFig, 'tsg_data');
        
        % Test if there is records with the same date and time.
        % very simple test made because of a bug in the acquisition
        % software used on IRD VOS
        % ---------------------------------------------------------
        testDoubleDate(hMainFig);
        
        % Test if there are fillable missing positions
        % ---------------------------------------------------------
        testMissPos(hMainFig);
        
      elseif errTsg > -2
        
        % Problem to read the file or
        % Choice of parameters for Labview file canceled by the user
        % TSG structure has been reinitialize
        % Disable toolbar menu pushtool except the open file button
        % ----------------------------------------------------------
        hdls_pushtool = findobj('-regexp','Tag', 'PUSHTOOL_');
        set(hdls_pushtool, 'Enable', 'off');
        
        set( hOpenPushtool, 'Enable', 'on' );
        
      end    %if errTsg > 0
      
      if errTsg == 1 || errSpl == 1
        
        % Draw the 3 plots of the validation figure
        % The plots need to be re-initialize because of a bug with
        % the zoom function. When you open a new TSG file and you
        % have used the zoom funtion with the preceding file.
        % The zoom function keep the X and Y limits of the preceding file
        % ---------------------------------------------------------------
        delete( hPlotAxes(1) );
        delete( hPlotAxes(2) );
        delete( hPlotAxes(3) );
        
        hPlotAxes(1) = axes( 'Parent', hPlotsPanel, 'Visible', 'off', ...
          'box', 'on', 'Units', 'normalized','Tag', 'TAG_AXES_1', ...
          'HandleVisibility','on', 'Position',[.05, .64, .93, .35]);
        hPlotAxes(2) = axes( 'Parent', hPlotsPanel, 'Visible', 'off',...
          'box', 'on', 'Units', 'normalized', 'Tag', 'TAG_AXES_2', ...
          'HandleVisibility','on', 'Position',[.05, .33, .93, .27]);
        hPlotAxes(3) = axes('Parent', hPlotsPanel, 'Visible', 'off',...
          'box', 'on', 'Units', 'normalized', 'Tag', 'TAG_AXES_3', ...
          'HandleVisibility','on', 'Position',[.05, .02, .93, .27]);
        
        resetAxes( hMainFig, hPlotAxes )
        
        plot_Validation( hMainFig, hPlotAxes, 1, tsg.plot.parameter{1} );
        plot_Validation( hMainFig, hPlotAxes, 2, tsg.plot.parameter{2} );
        plot_Validation( hMainFig, hPlotAxes, 3, tsg.plot.parameter{3} );
        
        set( hMapFig, 'Name', tsg.file.name);
        
        % Update the map if already displayed
        % -----------------------------------
        if strcmp( get(hMapFig,'visible'), 'on') == 1
          erase_Line( hPlotAxes, 4 );
          plot_map( hMainFig, hPlotAxes);
        end
        
      end
      
    end    % if ~isequal(fileName, 0)
    
    % Pointer reset to arrow
    % ----------------------
    set( hMainFig, 'Pointer', 'arrow' );
    
  end

%% Inter_OnMenuCallback ................................... Interpolation
%----------------------------------------------------------------------
% Callback function run when
%
  function Inter_OnMenuCallback( src, evnt)
    
    % Activate or desactivate uipanels
    % --------------------------------
    set( hpDateLimit,          'Visible', 'on' );
    set( hpInterpPos,          'Visible', 'on' );
    set( hpCalCoef,            'Visible', 'off');
    set( hbgQc,                'Visible', 'off');
    set( hbgParameter,         'Visible', 'off');
    
    % Toggle button
    % -------------
    set( hBottleToggletool,    'state', 'off', 'enable', 'off');
    set( hCalToggletool,       'state', 'off', 'enable', 'off');
    set( hClimToggletool,      'state', 'off', 'enable', 'off');
    set( hPanToggletool,       'state', 'off', 'enable', 'on' );
    set( hQCToggletool,        'enable', 'off');
    set( hTimelimitToggletool, 'state', 'off', 'enable', 'on' );
    set( hZoomInToggletool,    'state', 'off', 'enable', 'on' );
    set( hZoomOutToggletool,   'state', 'off', 'enable', 'on' );
    
    set( hHeaderPushtool,      'enable', 'off' );
    
    % Get application data TSG
    % ------------------------
    tsg = getappdata( hMainFig, 'tsg_data');
    
    % Get the information on time limits of the time series
    % Write them in the uipanel
    % -----------------------------------------------------
    noNaN = tsg.DAYD(~isnan( tsg.DAYD ));
    set( hetDateMin, 'String', datestr(noNaN(1), 31));
    set( hetDateMax, 'String', datestr(noNaN(end), 31));
    
    % Draw the 3 plots of the interpolation figure
    % --------------------------------------------
    plot_Interpolation( hMainFig, hPlotAxes, 1 );
    plot_Interpolation( hMainFig, hPlotAxes, 2 );
    plot_Interpolation( hMainFig, hPlotAxes, 3 );
    
  end

%% Inter_OffMenuCallback .................................. Interpolation
%----------------------------------------------------------------------
% Callback function run when
%
  function Inter_OffMenuCallback( src, evnt)
    
    % Activate or desactivate uipanels
    % --------------------------------
    set( hpCalCoef,            'Visible', 'off' );
    set( hpDateLimit,          'Visible', 'off' );
    set( hpInterpPos,          'Visible', 'off' );
    set( hbgParameter,         'Visible', 'on'  );
    
    % Enable Pushbuttons
    % ------------------
    set( hBottleToggletool,    'state', 'off', 'enable', 'on' );
    set( hCalToggletool,       'state', 'off', 'enable', 'on'  );
    set( hClimToggletool,      'state', 'off', 'enable', 'on'  );
    set( hPanToggletool,       'state', 'off', 'enable', 'on'  );
    set( hQCToggletool,        'state', 'off', 'enable', 'on'  );
    set( hTimelimitToggletool, 'state', 'off', 'enable', 'off' );
    set( hZoomInToggletool,    'state', 'off', 'enable', 'on' );
    set( hZoomOutToggletool,   'state', 'off', 'enable', 'on' );
    
    set( hHeaderPushtool,      'enable', 'on' );
    
    % Get tsg structure
    % -----------------
    tsg = getappdata( hMainFig, 'tsg_data' );
    
    % Draw the 3 plots of the validation figure
    % -----------------------------------------
    plot_Validation( hMainFig, hPlotAxes, 1, tsg.plot.parameter{1} );
    plot_Validation( hMainFig, hPlotAxes, 2, tsg.plot.parameter{2} );
    plot_Validation( hMainFig, hPlotAxes, 3, tsg.plot.parameter{3} );
    
    % Set the pointer
    % ---------------
    set( hMainFig, 'Pointer', 'arrow');
    
  end

%% InterpLinearCallback ...............................Interpolation Linear
%------------------------------------------------------------------------
% Callback function run when
%----------------------------------------------------------------------
  function InterpPosLinearCallback( src, evnt)
    
    % Get the time limits for the correction A TESTER
    % --------------------------------------
    dateMin = datenum(get( hetDateMin, 'String'), 'yyyy-mm-dd HH:MM:SS');
    dateMax = datenum(get( hetDateMax, 'String'), 'yyyy-mm-dd HH:MM:SS');
    
    error = interpPosLinear( hMainFig, dateMin, dateMax );
    
    switch error
      
      case 1
        
        % Plot in the 3 axes
        % ------------------
        plot_Interpolation( hMainFig, hPlotAxes, 2 );
        plot_Interpolation( hMainFig, hPlotAxes, 3 );
        
      case -1
        msgbox( 'Date limits are not correct',...
          'Correction module', 'warn', 'modal');
    end
    
    
  end

%% InterpOtherCallback ...............................Interpolation OTher
%----------------------------------------------------------------------
% Callback function run when
%----------------------------------------------------------------------
  function InterpPosOtherCallback( src, evnt)
    
    msgbox( 'Method not yet implemented', ...
      'Function InterpOtherCallback', ...
      'warn',...
      'modal' );
  end

%% InterpPosCancelCallback ..........................Cancel Interpolation
%----------------------------------------------------------------------
  function InterpPosCancelCallback(src, evnt)
    % Callback function run when
    
    % Get tsg application data
    % ------------------------
    tsg = getappdata( hMainFig, 'tsg_data' );
    
    % Get NO_CONTROL and INTERPOLATED_VALUE codes
    % -------------------------------------------
    NO_CONTROL         = tsg.qc.hash.NO_CONTROL.code;
    INTERPOLATED_VALUE = tsg.qc.hash.INTERPOLATED_VALUE.code;
    
    if ~isempty( tsg.POSITION_QC )
      iINTERP = find(  tsg.POSITION_QC == INTERPOLATED_VALUE);
      tsg.LATX( iINTERP ) = NaN * ones( size( iINTERP), 1 );
      tsg.LONX( iINTERP ) = NaN * ones( size( iINTERP), 1 );
      tsg.POSITION_QC = [];
    end
    
    % Save tsg application data
    % --------------------------
    setappdata( hMainFig, 'tsg_data', tsg );
    
    % Refresh plots
    % -------------
    plot_Interpolation( hMainFig, hPlotAxes, 1 );
    plot_Interpolation( hMainFig, hPlotAxes, 2 );
    plot_Interpolation( hMainFig, hPlotAxes, 3 );
    
  end


%% Cal_OnMenuCallback ..................................... Calibration
%----------------------------------------------------------------------
% Callback function run when
%----------------------------------------------------------------------
  function Cal_OnMenuCallback( src, evnt)
    
    % Activate or desactivate uipanels
    % --------------------------------
    set( hpCalCoef,         'Visible', 'on' );
    set( hbgParameter,      'Visible', 'off');
    set( hbgQc,             'Visible', 'off');
    
    % Pushbutton
    % ----------
    set( hQCToggletool,     'enable', 'off' );
    set( hClimToggletool,   'enable', 'off', 'state', 'off' );
    set( hBottleToggletool, 'enable', 'off' );
    set( hInterpToggletool, 'enable', 'off' );
    set( hHeaderPushtool,   'enable', 'off' );
    
    set( hPanToggletool,       'state', 'off', 'enable', 'on' );
    set( hTimelimitToggletool, 'state', 'off', 'enable', 'off' );
    set( hZoomInToggletool,    'state', 'off', 'enable', 'on' );
    set( hZoomOutToggletool,   'state', 'off', 'enable', 'on' );
    
    % Get tsg application data
    % ------------------------
    tsg = getappdata( hMainFig, 'tsg_data' );
    
    % Draw the 3 plots of the validation figure
    % -----------------------------------------
    plot_Calibration( hMainFig, hPlotAxes, 1, 'SSPS' );
    plot_Calibration( hMainFig, hPlotAxes, 2, 'SSJT' );
    plot_Calibration( hMainFig, hPlotAxes, 3, 'SSTP' );
    
    % find SLOPE (A) and OFFSET (B) indices in _LINCOEF_CONV array
    % ------------------------------------------------------------
    A_CNDC = strmatch('SLOPE', tsg.CNDC_LINCOEF_CONV);
    B_CNDC = strmatch('OFFSET',tsg.CNDC_LINCOEF_CONV);
    A_SSJT = strmatch('SLOPE', tsg.SSJT_LINCOEF_CONV);
    B_SSJT = strmatch('OFFSET',tsg.SSJT_LINCOEF_CONV);
    A_SSTP = strmatch('SLOPE', tsg.SSTP_LINCOEF_CONV);
    B_SSTP = strmatch('OFFSET',tsg.SSTP_LINCOEF_CONV);
    
    % Write the Cal Coef in the Editable uicontrol
    % --------------------------------------------
    set( hetCalCNDCSlope,  'String', num2str(tsg.CNDC_LINCOEF(A_CNDC)));
    set( hetCalCNDCOffset, 'String', num2str(tsg.CNDC_LINCOEF(B_CNDC)));
    set( hetCalSSJTSlope,  'String', num2str(tsg.SSJT_LINCOEF(A_SSJT)));
    set( hetCalSSJTOffset, 'String', num2str(tsg.SSJT_LINCOEF(B_SSJT)));
    set( hetCalSSTPSlope,  'String', num2str(tsg.SSTP_LINCOEF(A_SSTP)));
    set( hetCalSSTPOffset, 'String', num2str(tsg.SSTP_LINCOEF(B_SSTP)));
    
    % Intermediate variables
    % ----------------------
    tsg.CNDC_LINCOEF_NEW(A_CNDC) = str2num(get( hetCalCNDCSlope,  'String'));
    tsg.CNDC_LINCOEF_NEW(B_CNDC) = str2num(get( hetCalCNDCOffset, 'String'));
    tsg.SSJT_LINCOEF_NEW(A_SSJT) = str2num(get( hetCalSSJTSlope,  'String'));
    tsg.SSJT_LINCOEF_NEW(B_SSJT) = str2num(get( hetCalSSJTOffset, 'String'));
    tsg.SSTP_LINCOEF_NEW(A_SSTP) = str2num(get( hetCalSSTPSlope,  'String'));
    tsg.SSTP_LINCOEF_NEW(B_SSTP) = str2num(get( hetCalSSTPOffset, 'String'));
    
    % Save tsg application data
    % --------------------------
    setappdata( hMainFig, 'tsg_data', tsg );
    
  end


%% Cal_OffMenuCallback ..................................... Calibration
%----------------------------------------------------------------------
% Callback function run when
%----------------------------------------------------------------------
  function Cal_OffMenuCallback( src, evnt)
    
    % Activate or desactivate uipanels
    % --------------------------------
    set( hpCalCoef,         'Visible', 'off' );
    set( hbgParameter,      'Visible', 'on');
    
    % Enable Pushbuttons
    % ------------------
    set( hClimToggletool,   'enable', 'on' );
    set( hBottleToggletool, 'enable', 'on' );
    set( hInterpToggletool, 'enable', 'on' );
    set( hHeaderPushtool,   'enable', 'on' );
    set( hQCToggletool,        'state', 'off', 'enable', 'on'  );
    set( hPanToggletool,       'state', 'off', 'enable', 'on' );
    set( hTimelimitToggletool, 'state', 'off', 'enable', 'on' );
    set( hZoomInToggletool,    'state', 'off', 'enable', 'on' );
    set( hZoomOutToggletool,   'state', 'off', 'enable', 'on' );
    
    % Get tsg application data
    % ------------------------
    tsg = getappdata( hMainFig, 'tsg_data' );
    
    % find SLOPE (A) and OFFSET (B) indices in _LINCOEF_CONV array
    % ------------------------------------------------------------
    A_CNDC = strmatch('SLOPE', tsg.CNDC_LINCOEF_CONV);
    B_CNDC = strmatch('OFFSET',tsg.CNDC_LINCOEF_CONV);
    A_SSJT = strmatch('SLOPE', tsg.SSJT_LINCOEF_CONV);
    B_SSJT = strmatch('OFFSET',tsg.SSJT_LINCOEF_CONV);
    A_SSTP = strmatch('SLOPE', tsg.SSTP_LINCOEF_CONV);
    B_SSTP = strmatch('OFFSET',tsg.SSTP_LINCOEF_CONV);
    
    % Save the calibration coefficient
    % --------------------------------
    tsg.CNDC_LINCOEF(A_CNDC) = tsg.CNDC_LINCOEF_NEW(A_CNDC);
    tsg.CNDC_LINCOEF(B_CNDC) = tsg.CNDC_LINCOEF_NEW(B_CNDC);
    tsg.SSJT_LINCOEF(A_SSJT) = tsg.SSJT_LINCOEF_NEW(A_SSJT);
    tsg.SSJT_LINCOEF(B_SSJT) = tsg.SSJT_LINCOEF_NEW(B_SSJT);
    tsg.SSTP_LINCOEF(A_SSTP) = tsg.SSTP_LINCOEF_NEW(A_SSTP);
    tsg.SSTP_LINCOEF(B_SSTP) = tsg.SSTP_LINCOEF_NEW(B_SSTP);
    
    tsg.CNDC_LINCOEF_NEW = [];
    tsg.SSJT_LINCOEF_NEW = [];
    tsg.SSTP_LINCOEF_NEW = [];
    
    % Save tsg application data
    % --------------------------
    setappdata( hMainFig, 'tsg_data', tsg );
    
    % Draw the 3 plots of the validation figure
    % -----------------------------------------
    plot_Validation( hMainFig, hPlotAxes, 1, tsg.plot.parameter{1} );
    plot_Validation( hMainFig, hPlotAxes, 2, tsg.plot.parameter{2} );
    plot_Validation( hMainFig, hPlotAxes, 3, tsg.plot.parameter{3} );
    
    
  end

%% CalibrateCallback .......................................... Calibration
  function CalibrateCallback(src, evnt)
    % Callback function run when
    
    % Get tsg application data
    % ------------------------
    tsg = getappdata( hMainFig, 'tsg_data' );
    
    % find SLOPE (A) and OFFSET (B) indices in _LINCOEF_CONV array
    % ------------------------------------------------------------
    A_CNDC = strmatch('SLOPE', tsg.CNDC_LINCOEF_CONV);
    B_CNDC = strmatch('OFFSET',tsg.CNDC_LINCOEF_CONV);
    A_SSJT = strmatch('SLOPE', tsg.SSJT_LINCOEF_CONV);
    B_SSJT = strmatch('OFFSET',tsg.SSJT_LINCOEF_CONV);
    A_SSTP = strmatch('SLOPE', tsg.SSTP_LINCOEF_CONV);
    B_SSTP = strmatch('OFFSET',tsg.SSTP_LINCOEF_CONV);
    
    % Get the calibration coefficients.
    % They will be used in the function calibration
    % ---------------------------------------------
    tsg.CNDC_LINCOEF_NEW(A_CNDC) = str2num(get( hetCalCNDCSlope,  'String'));
    tsg.CNDC_LINCOEF_NEW(B_CNDC) = str2num(get( hetCalCNDCOffset, 'String'));
    tsg.SSJT_LINCOEF_NEW(A_SSJT) = str2num(get( hetCalSSJTSlope,  'String'));
    tsg.SSJT_LINCOEF_NEW(B_SSJT) = str2num(get( hetCalSSJTOffset, 'String'));
    tsg.SSTP_LINCOEF_NEW(A_SSTP) = str2num(get( hetCalSSTPSlope,  'String'));
    tsg.SSTP_LINCOEF_NEW(B_SSTP) = str2num(get( hetCalSSTPOffset, 'String'));
    
    % Save tsg application data
    % --------------------------
    setappdata( hMainFig, 'tsg_data', tsg );
    
    % Calibrate the sensors
    % ---------------------
    calibration( hMainFig );
    
    % Update the Adjusted variables (SSPS - SSJT) with calibrated records
    % -------------------------------------------------------------------
    % updateAdjustedVariable( hMainFig );
    
    % Refresh plot #1
    % ---------------
    plot_Calibration( hMainFig, hPlotAxes, 1, 'SSPS' );
    plot_Calibration( hMainFig, hPlotAxes, 2, 'SSJT' );
    plot_Calibration( hMainFig, hPlotAxes, 3, 'SSTP' );
    
    % As soon as a modification took place the data should be saved
    % -------------------------------------------------------------
    set( hSaveMenu, 'UserData', 'on' );
    
  end

%% CancelCalibrationCallback .................................. Calibration
  function CancelCalibrationCallback(src, evnt)
    % Callback function run when
    
    % Get tsg application data
    % ------------------------
    tsg = getappdata( hMainFig, 'tsg_data' );
    
    % Emptied the CAL variables
    % -------------------------
    tsg.CNDC_CAL = [];
    tsg.SSPS_CAL = [];
    tsg.SSJT_CAL = [];
    tsg.SSTP_CAL = [];
    
    % Save tsg application data
    % --------------------------
    setappdata( hMainFig, 'tsg_data', tsg );
    
    % Update the Adjusted variables
    % -----------------------------
    % updateAdjustedVariable( hMainFig );
    
    % find SLOPE (A) and OFFSET (B) indices in _LINCOEF_CONV array
    % ------------------------------------------------------------
    A_CNDC = strmatch('SLOPE', tsg.CNDC_LINCOEF_CONV);
    B_CNDC = strmatch('OFFSET',tsg.CNDC_LINCOEF_CONV);
    A_SSJT = strmatch('SLOPE', tsg.SSJT_LINCOEF_CONV);
    B_SSJT = strmatch('OFFSET',tsg.SSJT_LINCOEF_CONV);
    A_SSTP = strmatch('SLOPE', tsg.SSTP_LINCOEF_CONV);
    B_SSTP = strmatch('OFFSET',tsg.SSTP_LINCOEF_CONV);
    
    % Write the Cal Coef in the Editable uicontrol
    % --------------------------------------------
    set( hetCalCNDCSlope,  'String', num2str(tsg.CNDC_LINCOEF(A_CNDC)));
    set( hetCalCNDCOffset, 'String', num2str(tsg.CNDC_LINCOEF(B_CNDC)));
    set( hetCalSSJTSlope,  'String', num2str(tsg.SSJT_LINCOEF(A_SSJT)));
    set( hetCalSSJTOffset, 'String', num2str(tsg.SSJT_LINCOEF(B_SSJT)));
    set( hetCalSSTPSlope,  'String', num2str(tsg.SSTP_LINCOEF(A_SSTP)));
    set( hetCalSSTPOffset, 'String', num2str(tsg.SSTP_LINCOEF(B_SSTP)));
    
    % Refresh plot #1
    % ---------------
    plot_Calibration( hMainFig, hPlotAxes, 1, 'SSPS' );
    plot_Calibration( hMainFig, hPlotAxes, 2, 'SSJT' );
    plot_Calibration( hMainFig, hPlotAxes, 3, 'SSTP' );
    
    % As soon as a modification took place the data should be saved
    % -------------------------------------------------------------
    set( hSaveMenu, 'UserData', 'on' );
    
  end

%% ZoomIn_OnMenuCallback
%----------------------------------------------------------------------
% Callback function run when the toolbar zoom in (increase) push button
% is pressed
%----------------------------------------------------------------------
  function ZoomIn_OnMenuCallback(src, evnt)
    
    % Desactivate some toggle buttons, hZoomOutToggletool changed state
    % must be call before zoom function because the callback set zoom to
    % off
    % -------------------------------------------------------------------
    set( hZoomOutToggletool,   'state', 'off' );
    set( hQCToggletool,        'state', 'off' );
    set( hPanToggletool,       'state', 'off' );
    set( hTimelimitToggletool, 'state', 'off' );
    
    % returns a zoom mode object for the figure hMainFig handle
    % ---------------------------------------------------------
    hZoom = zoom(hMainFig);
    
    % Set the UI Context Menu to the custom menu
    % -----------------------------------------
    set(hZoom, 'UIContextMenu', zoom_context_menu)
    
    % Turns off the automatic adaptation of date ticks
    % ------------------------------------------------
    zoomAdaptiveDateTicks('off');
    
    % turns interactive zooming to in (increase)
    % ------------------------------------------
    set(hZoom, 'direction', 'in');
    
    % test zoom operation on the MAP axes objects
    % --------------------------------------------------
    %     hMapZoom = zoom(hMapFig);
    %     setAllowAxesZoom(hMapZoom, hPlotAxes(4), true);
    %      set(hMapZoom, 'enable', 'on');
    
    % turns on interactive zooming (same effect than zoom on) but prevent
    % side effect on another figure
    % -------------------------------------------------------------------
    set(hZoom, 'enable', 'on');
    
    % Set this callback to listen to when a zoom operation finishes
    % must be call after enable zoom (bug ?)
    % -------------------------------------------------------------
    set(hZoom, 'ActionPostCallback', @ZoomPan_PostCallback);
    
    
    % Set map with border and save tsg
    % --------------------------------
    %tsg.preference.map.border = 0;
    setappdata( hMainFig, 'tsg_data', tsg );
    
  end

%% ZoomIn_OffMenuCallback
%----------------------------------------------------------------------
% Callback function run when the toolbar zoom in (increase) push button
% is pressed
%----------------------------------------------------------------------
  function ZoomIn_OffMenuCallback(src, evnt)
    
    % disable zoom mode
    % -----------------
    zoom('off');
    
  end

%% ZoomOut_OnMenuCallback
%------------------------------------------------------------------------
% Callback function run when the toolbar zoom out (descrease) push button
% is pressed
%------------------------------------------------------------------------
  function ZoomOut_OnMenuCallback(src, evnt)
    
    % Desactivate Zoom In Toggle toggle button
    % -----------------------------------------
    set( hZoomInToggletool,    'state', 'off' );
    set( hQCToggletool,        'state', 'off' );
    set( hPanToggletool,       'state', 'off' );
    set( hTimelimitToggletool, 'state', 'off' );
    
    % returns a zoom mode object for the figure hMainFig handle
    % ---------------------------------------------------------
    hZoom = zoom(hMainFig);
    
    % Set the UI Context Menu to the custom menu
    % -----------------------------------------
    set(hZoom, 'UIContextMenu', zoom_context_menu)
    
    % turns interactive zooming out (decrease)
    % ----------------------------------------
    set(hZoom, 'direction', 'out');
    
    % Disallows a zoom operation on the MAP axes objects
    % --------------------------------------------------
    %     setAllowAxesZoom(hZoom, hPlotAxes(4), false);
    
    % turns on interactive zooming (same effect than zoom on) but prevent
    % side effect on another figure
    % -------------------------------------------------------------------
    set(hZoom, 'enable', 'on');
    
    % Set this callback to listen to when a zoom operation finishes
    % -------------------------------------------------------------
    set(hZoom, 'ActionPostCallback', @ZoomPan_PostCallback);
    
  end

%% ZoomOut_OffMenuCallback
%------------------------------------------------------------------------
% Callback function run when the toolbar zoom out (descrease) push button
% is pressed
%------------------------------------------------------------------------
  function ZoomOut_OffMenuCallback(src, evnt)
    
    % turns interactive zooming off
    % -----------------------------
    zoom off;
    
    % cursor back to normal, test if it's really necessery
    % -----------------------------------------------------
    % set(hMainFig, 'Pointer', 'arrow');
    
    % Desactivate Zoom Out Toggle toggle button
    % -----------------------------------------
    set( hZoomOutToggletool,    'state', 'off' );
    
  end

% callback function run from context menu from right clic in zoom mode
% --------------------------------------------------------------------
  function zoom_reset_callback(src, evnt)
    
    % restore map border to its preference setting for next map plotting
    % call by ZoomPan_PostCallback
    % ------------------------------------------------------------------
    tsg.preference.map.border = ...
      str2double(tsg.preference.map.border_string(tsg.preference.map.border_value));
    setappdata( hMainFig, 'tsg_data', tsg );
    
    % returns the plot to its initial zoom setting and desactivate zoom
    % -----------------------------------------------------------------
    hZoom = zoom(hMainFig);
    zoom out;
    % zoom off doesn't work
    set(hZoom, 'enable', 'off');
    
    % Desactivate Zoom In/Out Toggle toggle button
    % -----------------------------------------
    set( hZoomInToggletool,    'state', 'off' );
    set( hZoomOutToggletool,    'state', 'off' );
    
  end

% callback function run from context menu from right clic in zoom mode
% --------------------------------------------------------------------
  function zoom_out_callback(src, evnt)
    
    % zoom out by the specified zoom factor 0.5
    % ------------------------------------------
    zoom(0.5);
    
  end

%% Pan_OnMenuCallback
%----------------------------------------------------------------------
% Callback function run when the pan toggle toolbar is selected
%----------------------------------------------------------------------
  function Pan_OnMenuCallback(src, evnt)
    
    % Desactivate some toggle buttons
    % -------------------------------
    set( hQCToggletool,        'state', 'off' );
    set( hTimelimitToggletool, 'state', 'off' );
    set( hZoomInToggletool,    'state', 'off' );
    set( hZoomOutToggletool,   'state', 'off' );
    
    % Hide the map. Otherwise it slows down the panning
    % -------------------------------------------------
    %     set( hMapToggletool,       'state', 'off' );
    
    % Returns a pan mode object for the figure handle
    % -----------------------------------------------
    hPan = pan(hMainFig);
    
    % Disallows a pan operation on the MAP axes objects
    % --------------------------------------------------
    %     setAllowAxesPan(hPan, hPlotAxes(4), false);
    
    % turns on interactive pan (same effect than pan on) but prevent
    % side effect on another figure
    % --------------------------------------------------------------
    set(hPan, 'enable', 'on');
    
    % Set this callback to listen to when a zoom operation finishes
    % must be call after enable zoom (bug ?)
    % -------------------------------------------------------------
    set(hPan, 'ActionPostCallback', @ZoomPan_PostCallback);
    
  end

%% Pan_OffMenuCallback
%----------------------------------------------------------------------
% Callback function run when the pan toggle toolbar is released
%----------------------------------------------------------------------
  function Pan_OffMenuCallback(src, evnt)
    
    % turns interactive pan off
    % -------------------------
    pan off;
    
    % cursor back to normal, test if it's really necessery
    % -----------------------------------------------------
    %set(hMainFig, 'Pointer', 'arrow');
    
  end

%% ZoomPan_PostCallback
%------------------------------------------------------------------------
% Callback function run when zoom or pan action finishes: redraw axes
%------------------------------------------------------------------------
  function ZoomPan_PostCallback(src, evnt)
    
    % Set the right limit and interval to the 3 axes
    % ----------------------------------------------
    for iaxe = 1:3
      set(hPlotAxes(iaxe), 'XTickMode', 'auto')
      datetick(hPlotAxes(iaxe), 'x', 'keeplimits')
    end
    
    % Re-draw the map once the zoom/pan is off
    % ----------------------------------------
    if strcmp( get(hMapFig,'visible'), 'on') == 1
      erase_Line( hPlotAxes, 4 );
      plot_map( hMainFig, hPlotAxes);
    end
    
  end

%% QCMenuCallback
%----------------------------------------------------------------------
% Callback function run when the Automatic QC menu item is selected
%
% Si vous modiifer ce CallBack verifier les modifications a apporter a
% 1 - preferenceForm.m
% 2 - tsg_preference.m
%----------------------------------------------------------------------
  function QCMenuCallback(src, evnt, test)
    
    switch test
      case 'Speed'
        minSpeedQC(hMainFig)
      case 'Flow'
        minFlowQC(hMainFig)
      case 'Press'
        minPressQC(hMainFig)
      case 'SSPSmin'
        minSSPSQC(hMainFig)
      case 'SSPSmax'
        maxSSPSQC(hMainFig)
      case 'SSJTmin'
        minSSJTQC(hMainFig)
      case 'SSJTmax'
        maxSSJTQC(hMainFig)
      case 'SSTPmin'
        minSSTPQC(hMainFig)
      case 'SSTPmax'
        maxSSTPQC(hMainFig)
      otherwise
        msgbox('QCMenuCallback : erreur', 'QCMenuCallback','error', 'modal');
    end
    
    % --------------------------
    % refresh QC statistic panel
    % --------------------------
    display_QC( hMainFig );
    
    % ------------------
    % Refresh the plots
    %-------------------
    
    % Get the parameter displayed on plot number 1 : figure at the top
    % -----------------------------------------------------------------
    PARA = getParaCorModule( hMainFig );
    
    % Draw plot 1
    % -----------
    plot_Validation( hMainFig, hPlotAxes, 1, PARA{1} );
    
    % Update the map if already displayed
    % -----------------------------------
    if strcmp( get(hMapFig,'visible'), 'on') == 1
      erase_Line( hPlotAxes, 4 );
      plot_map( hMainFig, hPlotAxes);
    end
    
    % enable Undo menu if QC flags applied
    % ------------------------------------
    if (tsg.qc_history_pointer > 0)
      set(findobj('tag','UIMENU_UNDO'),'enable','on');
    end
    
  end


%% QC_OnMenuCallback ............................... Quality Control Module
%----------------------------------------------------------------------
% Callback function run when the QC toggle tool is pressed
%----------------------------------------------------------------------
  function QC_OnMenuCallback(src, evnt)
    
    % Make the QC code uipanel visible
    % --------------------------------
    set( hbgQc,                'Visible' ,'on');
    set( hDuplicateQcPanel,  'Visible', 'on');
    set( hbgParameter,         'Visible', 'off');
    
    
    % Desactivate toggletools.
    % ------------------------
    set( hZoomInToggletool,    'state', 'off', 'enable', 'on' );
    set( hZoomOutToggletool,   'state', 'off', 'enable', 'on' );
    set( hPanToggletool,        'state', 'off' );
    set( hTimelimitToggletool,  'state', 'off' );
    set( hCalToggletool,        'state', 'off', 'enable', 'off'  );
    set( hInterpToggletool,     'state', 'off', 'enable', 'off' );
    
    % Retrieve named application data
    % -------------------------------
    tsg = getappdata( hMainFig, 'tsg_data');
    
    PARA = getParaCorModule( hMainFig );
    SAMPLE = tsg.plot.sample;
    
    % refresh QC statistic panel
    % --------------------------
    display_QC( hMainFig );
    
    % Activate right clic context menu on first axes
    % ---------------------------------------------------------
    set(hPlotAxes(1),'UIContextMenu', hQcCmenu);
    
    % Activate clic mouse menu on first axes for next rbbox
    % ----------------------------------------------------------------
    set(hPlotAxes(1),'ButtonDownFcn', @QC_SelectCallback);
    
    % change cursor to crosshair aspect
    % ---------------------------------
    set( hMainFig, 'Pointer', 'crosshair');
    
    % -------------------------------------------------------------
    % nested function on mouse clic when QC toggle tool is selected
    % -------------------------------------------------------------
    function QC_SelectCallback(src, evnt)
      
      % disable zoom by default in QC mode
      try
        zoom(hMainFig, 'off');
      catch
      end
      
      % disable ButtonMotion on main fig during select
      % prevent drawing to map
      % ----------------------------------------------
      set( hMainFig, 'WindowButtonMotionFcn', []);
      
      % Selection of the data within the figure
      % ---------------------------------------
      point1    = get(src,'CurrentPoint');    % button down detected
      rbbox;                      % Create rubberband box for area selection
      point2    = get(src,'CurrentPoint');    % button up detected
      
      point1 = point1(1,1:2);                 % extract x and y
      point2 = point2(1,1:2);
      
      p1 = min(point1,point2);
      p2 = max(point1,point2);                % calculate locations
      
      % The following code is only executed if the left mouse button is clicked.
      % If the right mouse button is clicked, this code must not be
      % executed as the variable 'ind' will be emptied. And this variable
      % is used when the context menu (callback 'QC_ContextMenuCallback') is called
      % -----------------------------------------------------------------
      if ~strcmp( get(gcf, 'SelectionType'), 'alt')
        % if evnt.Button == 1 % this works only with Matlab version > R2014
        
        % The QC is applied either on TSG data either on Sample data.
        % it depends if the Botte Toggle button has been cliked on
        % -----------------------------------------------------------
        if strcmp( get(hBottleToggletool, 'state'), 'on')
          
          % get index on selected zone
          % --------------------------
          if ~isempty(tsg.DAYD_EXT)
            
            ind = find(tsg.DAYD_EXT > p1(1) &  tsg.DAYD_EXT < p2(1) & ...
              tsg.EXT_DIF  > p1(2) &  tsg.EXT_DIF  < p2(2));
            
            % Keep the information on the indices of the selected zone
            % --------------------------------------------------------
            tsg.rbboxind = ind .* ones(size(ind));
            
            % Modifiy the QC
            % --------------
            [tsg.qc.active.Code, tsg.qc.active.Color] = get_active_QC(hMainFig);
            tsg.([SAMPLE '_EXT_QC'])(ind) = tsg.qc.active.Code;
            
            
            % Save the modifications
            % ----------------------
            setappdata( hMainFig, 'tsg_data', tsg);
            
            % plot selected data with selected code
            % --------------------------------------
            plot_Correction( hMainFig, hPlotAxes, PARA);
            
          end
          
        else
          
          % store last QC in history for undo
          % ---------------------------------
          
          if (tsg.qc_history_pointer == 0)
            tsg.qc_history_state = int8(zeros(size(tsg.([PARA{1} '_QC']),1),tsg.qc_history_size));
          end
          
          if (tsg.qc_history_pointer == tsg.qc_history_size)
            tsg.qc_history_state = circshift(tsg.qc_history_state,[0 -1]);
          else
            tsg.qc_history_pointer = tsg.qc_history_pointer + 1;
          end
          
          tsg.qc_history_state(:,tsg.qc_history_pointer) = tsg.([PARA{1} '_QC']);
          tsg.qc_redo_possible = 0;
          
          
          % get index on selected zone
          % ---------------------------
          ind = find(tsg.DAYD   > p1(1,1) & tsg.DAYD   < p2(1,1) & ...
            tsg.(PARA{1}) > p1(1,2) & tsg.(PARA{1}) < p2(1,2));
          
          % Keep the information on the indices of the selected zone
          % --------------------------------------------------------
          tsg.rbboxind = ind .* ones(size(ind));
          
          % Modify the QC
          % --------------
          [tsg.qc.active.Code, tsg.qc.active.Color] = get_active_QC(hMainFig);
          tsg.([PARA{1} '_QC'])(ind) = tsg.qc.active.Code;
          
          % Save the modifications
          % ----------------------
          setappdata( hMainFig, 'tsg_data', tsg);
          
          % Draw plot 1 of the validation figure
          % ------------------------------------
          plot_Validation( hMainFig, hPlotAxes, 1, PARA{1} );
          
          % refresh QC statistic panel
          % --------------------------
          display_QC( hMainFig );
          
          % Update the map if already displayed
          % -----------------------------------
          if strcmp( get(hMapFig,'visible'), 'on') == 1
            erase_Line( hPlotAxes, 4 );
            plot_map( hMainFig, hPlotAxes);
          end
          
          % enable Undo menu if QC flags applied
          % ------------------------------------
          if (tsg.qc_history_pointer > 0)
            set(findobj('tag','UIMENU_UNDO'),'enable','on');
          end
          
          % enable Redo menu if QC flags applied
          % ------------------------------------
          if (tsg.qc_redo_possible > 0)
            set(findobj('tag','UIMENU_REDO'),'enable','on');
          end
          
        end
        
        % As soon as a modification took place the data should be saved
        % -------------------------------------------------------------
        set( hSaveMenu, 'UserData', 'on' );
        
      end
      
      % enable ButtonMotion on main fig after select QC area
      % ----------------------------------------------------
      set( hMainFig, 'WindowButtonMotionFcn', @MouseMotion);
      
    end
    
  end

%% QC_OffMenuCallback .............................. Quality Control Module
%----------------------------------------------------------------------
% Callback function run when the QC toggle tool is released
%----------------------------------------------------------------------
  function QC_OffMenuCallback(src, evnt)
    
    % Desactive right clic menu on first axes (salinity)
    % ---------------------------------------------------
    set(hPlotAxes(1),'UIContextMenu', []);
    
    % Desactive clic mouse menu (zoom) on first axes (salinity)
    % ----------------------------------------------------------
    set(hPlotAxes(1),'ButtonDownFcn', []);
    
    % Uipanel visible or not
    % -----------------------
    set( hbgQc,        'Visible', 'off' );
    set( hDuplicateQcPanel,  'Visible', 'off');
    
    if strcmp( get(hBottleToggletool, 'state'), 'off' )
      set( hCalToggletool,        'state', 'off', 'enable', 'on' );
      set( hInterpToggletool,     'state', 'off', 'enable', 'on' );
    end
    
    % uibuttongroup uipanel used to choose a parameter is set to
    % on only if the Correction screen (bottle toggletool) is off
    % -----------------------------------------------------------
    if  strcmp( get( hBottleToggletool, 'state'), 'off')
      set( hbgParameter, 'Visible', 'on');
    end
    
    % set POSITION_QC from LATX_QC or LONX_QC after validation
    % give same value for  LATX_QC and LONX_QC
    % ---------------------------------------------------------
    tsg.POSITION_QC = max(tsg.LATX_QC,tsg.LONX_QC );
    tsg.LATX_QC = tsg.POSITION_QC;
    tsg.LONX_QC = tsg.POSITION_QC;
    
    % Save the modifications
    % ----------------------
    setappdata( hMainFig, 'tsg_data', tsg);
    
    % cursor back to normal
    % ---------------------
    set(hMainFig,'Pointer','arrow');
    
  end

%% QC_ContextMenuCallback context menu selected ........................ Quality Control Module
%-----------------------------------------------------------
% Context menu used to attribute a QC to a previously selected
% TSG time series
%-----------------------------------------------------------
  function QC_ContextMenuCallback(src, evnt, key)
    
    % Retrieve Default Quality Code and Color
    % ---------------------------------------
    tsg = getappdata( hMainFig, 'tsg_data');
    
    % Get the parameter (SSPS, SSJT or SSTP)
    % --------------------------------------
    PARA = getParaCorModule( hMainFig );
    SAMPLE = tsg.plot.sample;
    
    % get key and some values in hashtable
    % ------------------------------------
    code  = tsg.qc.hash.(key).code;
    color = tsg.qc.hash.(key).color;
    
    % set active code and color from selected context menu
    % ----------------------------------------------------
    tsg.qc.active.Code  = code;
    tsg.qc.active.Color = color;
    
    % Modify and plot the last selected tsg data
    % ------------------------------------------
    if isfield(tsg, 'rbboxind') && ~isempty( tsg.rbboxind )
      
      if strcmp( get(hBottleToggletool, 'state'), 'on')
        
        tsg.([SAMPLE '_EXT_QC'])(tsg.rbboxind) = tsg.qc.active.Code;
        
        % Save tsg.SSPS_QC and tsg.qc.active.Code
        % in the application data
        % ----------------------------------------
        setappdata( hMainFig, 'tsg_data', tsg );
        
        % Draw the 3 plots of the Correction figure
        % -----------------------------------------
        plot_Correction( hMainFig, hPlotAxes, PARA );
        
      else
        
        % store last QC in history for undo
        % ---------------------------------
        
        if (tsg.qc_history_pointer == 0)
          tsg.qc_history_state = int8(zeros(size(tsg.([PARA{1} '_QC']),1),tsg.qc_history_size));
        end
        
        if (tsg.qc_history_pointer == tsg.qc_history_size)
          tsg.qc_history_state = circshift(tsg.qc_history_state,[0 -1]);
        else
          tsg.qc_history_pointer = tsg.qc_history_pointer + 1;
        end
        
        tsg.qc_history_state(:,tsg.qc_history_pointer) = tsg.([PARA{1} '_QC']);
        tsg.qc_redo_possible = 0;
        set(findobj('tag','UIMENU_REDO'),'enable','off');    
        
        % Modify the QC
        % --------------
        tsg.([PARA{1} '_QC'])(tsg.rbboxind) = tsg.qc.active.Code;
        
        % Save tsg.SSPS_QC in the application data before use
        % inside plot_Validation
        % ---------------------------------------------------
        setappdata( hMainFig, 'tsg_data', tsg );
        
        % Draw plot 1 of the validation figure
        % ------------------------------------
        plot_Validation( hMainFig, hPlotAxes, 1, PARA{1} );
        
      end
      
      % Re-draw the map
      % -------------------------------------------------------------
      if strcmp( get(hMapFig, 'visible'), 'on') == 1
        erase_Line( hPlotAxes, 4 );
        plot_map( hMainFig, hPlotAxes);
      end
      
    end
    
    % Update the radio button corresponding to the selected
    % QC context menu (rbg : RadioButtonGroup)
    % -----------------------------------------------------
    radioTag     = ['TAG_QC_RADIO_' char(key)];        % Build the TAG of the CODE
    hbgChildren  = get(hbgQc,'Children');        % Get the handles of the rbg
    hbgTagCell   = get(hbgChildren, 'tag');      % get the TAG of the rbg
    ind          = strcmp(radioTag, hbgTagCell); % Compare the TAG
    hRadioButton = hbgChildren( ind == 1 );      % Get the handle of the button
    set(hbgQc, 'SelectedObject', hRadioButton);  % Make this button active
    
    % refresh QC statistic panel
    % ---------------------------
    display_QC( hMainFig);
    
    %setappdata( hMainFig, 'tsg_data', tsg );
    
  end

%% Radiobutton Quality Control ..................... Quality Control Module
% ---------------------------------------------------------------
% Callback to select CODE and COLOR QC from the RadioButton Group
% ---------------------------------------------------------------
  function radioButtonQc(source, evnt)
    
    % Retrieve Default Quality Code and Color
    % ---------------------------------------
    tsg = getappdata( hMainFig, 'tsg_data');
    
    % Retrieve the key from the active RadioButton
    % --------------------------------------------
    rbTag = get(evnt.NewValue,'Tag');
    key = strrep(rbTag, 'TAG_QC_RADIO_', '');
    
    % store his handle to uibuttongroup userdata
    % ------------------------------------------
    set(hbgQc,'Userdata', evnt.NewValue);
    
    % set active code and color from selected context menu
    % ----------------------------------------------------
    tsg.qc.active.Code  = tsg.qc.hash.(key).code;
    tsg.qc.active.Color = tsg.qc.hash.(key).color;
    
    % save tsg struct
    % ----------------
    setappdata( hMainFig, 'tsg_data', tsg );
    
  end

%% preQcPanCallback .................................Quality Control Module
% ---------------------------------------------------------------
% Callback function ... to be completed
% ---------------------------------------------------------------
  function preQcPanCallback(obj, evd)
    
    set(hQCToggletool, 'state', 'off' );
    
  end

%% postQcPanCallback ............................... Quality Control Module
% ---------------------------------------------------------------
% Callback function ... to be completed
% ---------------------------------------------------------------
  function postQcPanCallback(obj, evd)
    
    % Set the right limit and interval to the 3 axes
    % ----------------------------------------------
    for iaxe = 1:3
      set(hPlotAxes(iaxe),'XTickMode','auto')
      datetick(hPlotAxes(iaxe),'x','keeplimits')
    end
    
    % Re-draw the map once the pan is off -  only valide in QC mode
    % -------------------------------------------------------------
    if strcmp( get(hMapFig, 'visible'), 'on') == 1
      erase_Line( hPlotAxes, 4 );
      plot_map( hMainFig, hPlotAxes);
    end
    
    % restacks the figure to the top of the screen
    % --------------------------------------------
    figure( hMainFig);
    
    set(hQCToggletool, 'state', 'on' );
    
  end

%% MouseMotion
%---------------------------------------------------------------------
% Callback function run when mouse pointer is moving on temperature plot
% draw corresponding measurement position on map
%---------------------------------------------------------------------
  function MouseMotion(src, evnt)
    
    % Test if the callback can be activated
    % -------------------------------------
    if strcmp( get( hMainFig, 'UserData'), 'ButtonMotionOn')
      
      % Retrieve named application data
      % -------------------------------
      tsg = getappdata( hMainFig, 'tsg_data');
      
      % Get current position of cusor and return its coordinates in
      % axes with handle h_axes
      % -----------------------------------------------------------
      a = get(hPlotAxes(1), 'CurrentPoint');
      x = a(2,1);
      y = a(2,2);
      
      % Get the Limits of axes 1
      % ------------------------
      limx = get(hPlotAxes(1), 'XLim');
      limy = get(hPlotAxes(1), 'YLim');
      
      % Code to Activate the PAN function when QC mode is active
      % A PAN zone is defined in the bottom (10%) of PlotAxes(1)
      % 2 callback are needed :
      %    1 - one to desactivate QC when Pan is set to on.
      %    2 - one to reactivate QC once the pan has been used.
      % ---------------------------------------------------------
      
      % if we are in QC mode
      % ---------------------
      if strcmp( get(hQCToggletool, 'state' ), 'on' );
        
        % Suppose that Y axes is increasing from the bottom to the top
        % ------------------------------------------------------------
        limy2 = limy(1) + (limy(2)-limy(1)) * 0.10;
        
        if  x > limx(1) && x < limx(2) &&  y <= limy2 && y >= limy(1)
          hPan = pan(hMainFig);
          set(hPan,'ActionPreCallback',  @preQcPanCallback);
          set(hPan,'ActionPostCallback', @postQcPanCallback);
          set(hPan,'Enable','on');
        else
          try
            pan(hMainFig, 'off');
          catch
          end
          
        end % end of cursor test location
        
      end % end of QC mode test
      
      % Dynamically display data in uicontrol for valid data
      % ----------------------------------------------------
      if x > tsg.DAYD(1) && x < tsg.DAYD(end)
        
        % get index of cursor location
        % ----------------------------
        indCursor = find( tsg.DAYD > x, 1, 'first');
        
        % display informations of cursor location in text uicontrol
        % ---------------------------------------------------------
        set( hInfoDateText, 'String',...
          datestr(tsg.DAYD(indCursor),'dd/mm/yyyy   HH:MM'));
        if tsg.preference.positions_format_value == 1
          set( hInfoLatText,  'String', dd2dm(tsg.LATX(indCursor), 0) );
          set( hInfoLongText, 'String', ...
            dd2dm(mod(tsg.LONX(indCursor) + 180, 360) - 180, 1) );
        else
          set( hInfoLatText,  'String', tsg.LATX(indCursor) );
          set( hInfoLongText, 'String', ...
            mod(tsg.LONX(indCursor) + 180, 360) - 180 );
        end
        if ~isempty(tsg.SSPS)
          set( hInfoSSPSText, 'String', tsg.SSPS(indCursor) );
        end
        if ~isempty(tsg.SSJT)
          set( hInfoSSJTText, 'String', tsg.SSJT(indCursor) );
        end
        if ~isempty(tsg.SSTP)
          set( hInfoSSTPText, 'String', tsg.SSTP(indCursor) );
        end
        
        % Plot the position on the map if this one is active
        % --------------------------------------------------
        if strcmp( get(hMapFig, 'Visible'), 'on')
          
          % Select the map axes, we cannot use mline as line with an axes
          % in first parameter like:  m_line(hPlotAxes(4), ....)
          % ------------------------------------------------------------
          axes( hPlotAxes(4));
          
          % Look for a MARKER (Red point) on the ship track
          % -----------------------------------------------
          h = findobj( hPlotAxes(4), '-regexp','Tag', 'TAG_PLOT4_LINE_MARKER');
          
          if isempty( h )   % if no Marker
            
            if ~isnan( tsg.LONX(indCursor) )
              
              % Plot a Marker (Red point) on the ship track
              % -------------------------------------------
              hMarker = m_line(mod(tsg.LONX(indCursor(1)) + ...
                tsg.lonplus, tsg.lonmod) - tsg.lonplus,...
                tsg.LATX(indCursor(1)),...
                'Marker', 'o', 'MarkerSize', tsg.preference.map.ship.size, ...
                'Color', tsg.preference.map.ship.color, 'MarkerFaceColor', ...
                tsg.preference.map.ship.color);
              
              % Put a tag on the Marker - This tag allows to get the handle
              % of the Marker
              % -----------------------------------------------------------
              set( hMarker, 'TAG', 'TAG_PLOT4_LINE_MARKER' );
            end
            
          else         % a marker exists
            
            if ~isnan( tsg.LONX(indCursor) )
              
              % Delete the Marker and redraw it
              % -------------------------------
              delete( h);
              hMarker = m_line(...
                tsg.LONX(indCursor), tsg.LATX(indCursor),...
                'Marker', 'o', 'MarkerSize', tsg.preference.map.ship.size, ...
                'Color', tsg.preference.map.ship.color,...
                'MarkerFaceColor', tsg.preference.map.ship.color);
              
              % Put a tag on the Marker - This tag allows to get the handle
              % of the Marker
              % -----------------------------------------------------------
              set( hMarker, 'TAG', 'TAG_PLOT4_LINE_MARKER' );
            end
          end
          
        end % end of map visible
        
      else
        
        % if cursor is out of valid data, display blank
        % ---------------------------------------------
        set( hInfoDateText, 'String', '' );
        set( hInfoLatText,  'String', '' );
        set( hInfoLongText, 'String', '' );
        set( hInfoSSPSText, 'String', '' );
        set( hInfoSSTPText, 'String', '' );
        set( hInfoSSJTText, 'String', '' );
      end
      
    end % end of BuntonMotionOn
    
  end % end of mouseMotion function

%% Map_OnMenuCallback
%---------------------------------------------------------------------
% Callback function run when the Map tool bar item is selected
%---------------------------------------------------------------------
  function Map_OnMenuCallback(src, evnt)
    
    % Desactivate Zoom and Pan toggle buttons
    % ---------------------------------------
    set(hZoomInToggletool,  'state', 'off' );
    set(hZoomOutToggletool,  'state', 'off' );
    set(hPanToggletool,   'state', 'off' );
    
    % Make the earth map visible
    % --------------------------
    set(hMapFig, 'Visible', 'on' );
    
    erase_Line( hPlotAxes, 4 );
    
    plot_map( hMainFig, hPlotAxes)
    
    % De-activate keyPressFcn callback on main fig
    % --------------------------------------------
    %set(hMainFig, 'KeyPressFcn', []);
    
  end

%% Map_OffMenuCallback
%---------------------------------------------------------------------
% Callback function run when the Map tool bar item is unselected
%---------------------------------------------------------------------
  function Map_OffMenuCallback(src, evnt)
    
    % Make the earth map invisible
    % ----------------------------
    set(hMapFig, 'Visible', 'off' );
    
    % Re-activate keyPressFcn callback on main fig
    % see Enabling user callbacks during zoom/pan on Undocumented Matlab
    % https://undocumentedmatlab.com/blog/enabling-user-callbacks-during-zoom-pan
    % This should work in both HG1 and HG2:
    % ------------------------------------------------------------------------
    %     hManager = uigetmodemanager(hMainFig);
    %     try
    %       set(hManager.WindowListenerHandles, 'Enable', 'off'); % HG1 (prior R2014b)
    %     catch
    %       [hManager.WindowListenerHandles.Enabled] = deal(false);  % HG2 (R2014b)
    %     end
    %    set(hMainFig, 'WindowKeyPressFcn', []);
    
    % comment this line to prevent warning
    %    set(hMainFig, 'KeyPressFcn', @keyPressFcnCallback);
    
  end

%% Bottle_OnMenuCallback ................................ Correction Module
%---------------------------------------------------------------------
% Callback function run when the bootle push tool is selected
%---------------------------------------------------------------------
  function Bottle_OnMenuCallback(src, evnt)
    % Callback function run when the Bottle tool bar item is selected
    
    % Get the tsg structure
    % ---------------------
    tsg = getappdata(hMainFig, 'tsg_data');
    
    % Get the parameter we are working on (SSPS, SSJT, SSTP)
    % ------------------------------------------------------
    SAMPLE = tsg.plot.sample;
    PARA = getParaCorModule( hMainFig );
    
    % Switch somme buttons
    % --------------------
    set( hQCToggletool,         'state',  'off' );
    set( hZoomInToggletool,     'state', 'off', 'enable', 'on' );
    set( hZoomOutToggletool,    'state', 'off', 'enable', 'on' );
    set( hPanToggletool,        'state',  'off' );
    %     set( hMapToggletool,        'state',  'off' );
    set( hClimToggletool,       'state',  'off', 'enable', 'off');
    set( hCalToggletool,        'enable', 'off' );
    set( hInterpToggletool,     'enable', 'off' );
    set( hTimelimitToggletool,  'enable', 'on' );
    
    % Activate or desactivate uipanels
    % ---------------------------------
    set( hpDateLimit,           'Visible', 'on' );
    set( hbgCorMethod,          'Visible', 'on' );
    set( hCorPanel,             'Visible', 'on' );
    set( hbgParameter,          'Visible', 'off');
    set( hbgQc,                 'Visible', 'off');
    
    if ~isempty( tsg.([SAMPLE '_EXT']) )
      
      % Compute the sample-TSG differences
      % ----------------------------------
      diffTsgSample( hMainFig, PARA );
      tsg = getappdata( hMainFig, 'tsg_data');
      
    else
      
      msgbox('No sample data file has been read', 'modal');
      
    end
    
    % Plot in the 3 axes
    % ------------------
    plot_Correction( hMainFig, hPlotAxes, PARA );
    
    % Necessary to unzoom as the new plot keep in memory the preceding zoom
    % ---------------------------------------------------------------------
    zoom out;
    
    % reset map border
    % ----------------
    tsg.preference.map.border = ...
      str2double(tsg.preference.map.border_string(tsg.preference.map.border_value));
    setappdata( hMainFig, 'tsg_data', tsg );
    
    % Get the information on time limits of the time series
    % Write them in the uipanel
    % -----------------------------------------------------
    noNaN = tsg.DAYD(~isnan( tsg.DAYD ));
    set( hetDateMin, 'String', datestr(noNaN(1), 31));
    set( hetDateMax, 'String', datestr(noNaN(end), 31));
    
  end

%% Bottle_OffMenuCallback ............................... Correction module
%---------------------------------------------------------------------
% Callback function run when the bootle push tool is selected
%---------------------------------------------------------------------
  function Bottle_OffMenuCallback(src, evnt)
    
    % If necessary toggle off some buttons
    % ------------------------------------
    set( hQCToggletool,        'state',  'off' );
    set( hZoomInToggletool,    'state',  'off' );
    set( hZoomOutToggletool,   'state',  'off' );
    set( hPanToggletool,       'state',  'off' );
    %     set( hMapToggletool,       'state',  'off' );
    set( hClimToggletool,      'enable', 'on');
    set( hCalToggletool,       'enable', 'on'  );
    set( hInterpToggletool,    'enable', 'on' );
    set( hTimelimitToggletool, 'enable', 'off' );
    
    % Activate or Desactivate uipanel
    % --------------------------------
    set( hpDateLimit,          'Visible', 'off' );
    set( hCorPanel,            'Visible', 'off' );
    set( hbgCorMethod,         'Visible', 'off' );
    set( hbgParameter,         'Visible', 'on');
    
    % Desactivate Click Mouse on figure
    % ---------------------------------
    set( hMainFig, 'WindowButtonDownFcn', []);
    
    % Get tsg structure
    % -----------------
    tsg  = getappdata( hMainFig, 'tsg_data' );
    
    % Draw the 3 plots of the validation figure and unzoom as the new
    % plot keep in memory the preceding zoom
    % -----------------------------------------
    plot_Validation( hMainFig, hPlotAxes, 1, tsg.plot.parameter{1} );
    zoom out;
    plot_Validation( hMainFig, hPlotAxes, 2, tsg.plot.parameter{2} );
    zoom out;
    plot_Validation( hMainFig, hPlotAxes, 3, tsg.plot.parameter{3} );
    zoom out;
    
    % reset map border
    % ----------------
    tsg.preference.map.border = ...
      str2double(tsg.preference.map.border_string(tsg.preference.map.border_value));
    setappdata( hMainFig, 'tsg_data', tsg );
    
    % Set the pointer
    % ---------------
    set( hMainFig, 'Pointer', 'arrow');
    
  end

%% cancelCorrectionCallback .................................... Correction Module
  function cancelCorrectionCallback(src, evnt, Limits)
    % Callback function run when the user want to cancel the
    % corrections made from comparison with bottles or ARGO data.
    % The deletion can be made for th whole time series or
    % between 2 dates.
    
    % Desactivate somme Toggle button
    % -------------------------------
    set( hZoomInToggletool,       'state', 'off' );
    set( hZoomOutToggletool,       'state', 'off' );
    set( hPanToggletool,        'state', 'off' );
    set( hQCToggletool,         'state', 'off' );
    set( hTimelimitToggletool,  'state', 'off' );
    
    % Get tsg application data
    % ------------------------
    tsg = getappdata(hMainFig, 'tsg_data');
    
    % Get parameter we are working on (SSPS, SSJT, SSTP)
    % or SSPS_CAL, SSJT_CAL, SSTP_CAL
    % -------------------------------------------------
    PARA = getParaCorModule( hMainFig );
    
    % The correction will be cancelled either for the entire
    % time series or within date limits
    % ------------------------------------------------------
    ind = 0;
    switch Limits
      
      % Get the indices of the whole time series
      % ----------------------------------------
      case 'total'
        
        ind = find( tsg.DAYD >= tsg.DAYD(1) &  tsg.DAYD <= tsg.DAYD(end) );
        
        %         ind = size(tsg.([PARA{1} '_ADJUSTED']));
        
        % Get the indices between 2 dates
        % --------------------------------
      case 'part'
        
        % Get the date limits used for the correction
        % -------------------------------------------
        dateMin = datenum(get( hetDateMin, 'String'), 'yyyy-mm-dd HH:MM:SS');
        dateMax = datenum(get( hetDateMax, 'String'), 'yyyy-mm-dd HH:MM:SS');
        
        % Find indices within date limits
        % --------------------------------
        if dateMax > dateMin
          ind = find( tsg.DAYD >= dateMin &  tsg.DAYD <= dateMax );
        end
        
      otherwise
        msgbox( 'cancelCorrectionCallback : error', 'cancelCorrectionCallback', 'error', 'modal');
    end
    
    if ~isempty(ind) && ~isempty( tsg.([PARA{1} '_ADJUSTED']) )
      
      % Cancel the correction : set the ADJUSTED variable to NaN
      % and ADJUSTED_QC to 0 (Bytes)
      % --------------------------------------------------------
      tsg.([PARA{1} '_ADJUSTED'])(ind) = ...
        NaN*ones(size(tsg.([PARA{1} '_ADJUSTED'])(ind))) ;
      tsg.([PARA{1} '_ADJUSTED_QC'])(ind) = ...
        zeros*ones(size(tsg.([PARA{1} '_ADJUSTED_QC'])(ind))) ;
      tsg.([PARA{1} '_ADJUSTED_ERROR'])(ind) = ...
        NaN*ones(size(tsg.([PARA{1} '_ADJUSTED_ERROR'])(ind))) ;
      
    end
    
    % Save tsg data
    % -------------
    setappdata(hMainFig, 'tsg_data', tsg);
    
    % Plot in the 3 axes
    % ------------------
    plot_Correction( hMainFig, hPlotAxes, PARA );
    
  end


%% gradientCorrectionCallback .................................... Correction Module
  function gradientCorrectionCallback(src, evnt)
    % Callback function run when
    
    % Desactivate somme Toggle button
    % -------------------------------
    set( hZoomInToggletool,     'state', 'off' );
    set( hZoomOutToggletool,    'state', 'off' );
    set( hPanToggletool,        'state', 'off' );
    set( hQCToggletool,         'state', 'off' );
    set( hTimelimitToggletool,  'state', 'off' );
    
    % Get the time limits for the correction
    % --------------------------------------
    dateMin = datenum(get( hetDateMin, 'String'), 'yyyy-mm-dd HH:MM:SS');
    dateMax = datenum(get( hetDateMax, 'String'), 'yyyy-mm-dd HH:MM:SS');
    
    % Get tsg application data
    % ------------------------
    tsg    = getappdata(hMainFig, 'tsg_data');
    
    % Get parameter we are working on (SSPS, SSJT, SSTP)
    % or SSPS_CAL, SSJT_CAL, SSTP_CAL
    % -------------------------------------------------
    PARA = getParaCorModule( hMainFig );
    SAMPLE = tsg.plot.sample;
    
    if ~isempty( tsg.([SAMPLE '_EXT']) )
      
      % Compute the sample-TSG differences
      % ----------------------------------
      diffTsgSample( hMainFig, PARA );
      
      % Correction
      % ----------
      error = corTsgGradient(hMainFig, PARA, dateMin, dateMax);
      
      switch error
        
        case 1
          
          % Plot in the 3 axes
          % ------------------
          plot_Correction( hMainFig, hPlotAxes, PARA );
          
        case -1
          
          if dateMax <= dateMin
            msgbox( 'Date limits are not correct',...
              'Correction module', 'warn', 'modal');
          end
          
      end
      
    end
    
  end

%% biasCorrectionCallback .................................... Correction Module
  function biasCorrectionCallback(src, evnt)
    % Callback function run when
    
    % Desactivate somme Toggle button
    % -------------------------------
    set( hZoomInToggletool,     'state', 'off' );
    set( hZoomOutToggletool,    'state', 'off' );
    set( hPanToggletool,        'state', 'off' );
    set( hQCToggletool,         'state', 'off' );
    set( hTimelimitToggletool,  'state', 'off' );
    
    % Get the time limits for the correction A TESTER
    % -----------------------------------------------
    dateMin = datenum(get( hetDateMin, 'String'), 'yyyy-mm-dd HH:MM:SS');
    dateMax = datenum(get( hetDateMax, 'String'), 'yyyy-mm-dd HH:MM:SS');
    
    % Get tsg application data
    % ------------------------
    tsg    = getappdata(hMainFig, 'tsg_data');
    
    % Get parameter we are working on (SSPS, SSJT, SSTP)
    % or SSPS_CAL, SSJT_CAL, SSTP_CAL
    % -------------------------------------------------
    PARA = getParaCorModule( hMainFig );
    SAMPLE = tsg.plot.sample;
    
    if ~isempty( tsg.([SAMPLE '_EXT']) )
      
      % Compute the sample-TSG differences
      % ----------------------------------
      diffTsgSample( hMainFig, PARA );
      
    end
    
    % Correction
    % ----------
    error = corTsgBias(hMainFig, PARA, dateMin, dateMax);
    
    switch error
      
      case 0
        
        % canceled by user, do nothing
        
      case 1
        
        % Plot in the 3 axes
        % ------------------
        plot_Correction( hMainFig, hPlotAxes, PARA );
        
      case -1
        
        % date mismatch
        % --------------
        msgbox( 'Date limits are not correct',...
          'Correction module', 'warn', 'modal');
        
      otherwise
        msgbox( {'corTsgBias : unknow error', sprintf('error = %d', error)});
        
    end
  end

%% linearCorrectionCallback .................................... Correction Module
  function linearCorrectionCallback(src, evnt)
    % Callback function run when
    
    % Desactivate somme Toggle button
    % -------------------------------
    set( hZoomInToggletool,     'state', 'off' );
    set( hZoomOutToggletool,    'state', 'off' );
    set( hPanToggletool,        'state', 'off' );
    set( hQCToggletool,         'state', 'off' );
    set( hTimelimitToggletool,  'state', 'off' );
    
    % Get the time limits for the correction A TESTER
    % -----------------------------------------------
    dateMin = datenum(get( hetDateMin, 'String'), 'yyyy-mm-dd HH:MM:SS');
    dateMax = datenum(get( hetDateMax, 'String'), 'yyyy-mm-dd HH:MM:SS');
    
    % Get tsg application data
    % ------------------------
    tsg    = getappdata(hMainFig, 'tsg_data');
    
    % Get parameter we are working on (SSPS, SSJT, SSTP)
    % or SSPS_CAL, SSJT_CAL, SSTP_CAL
    % -------------------------------------------------
    PARA = getParaCorModule( hMainFig );
    SAMPLE = tsg.plot.sample;
    
    if ~isempty( tsg.([SAMPLE '_EXT']) )
      
      % Compute the sample-TSG differences
      % ----------------------------------
      diffTsgSample( hMainFig, PARA );
      
      % Correction
      % ----------
      error = corTsgLinear(hMainFig, PARA, dateMin, dateMax);
      
      switch error
        
        case 1
          
          % Plot in the 3 axes
          % ------------------
          plot_Correction( hMainFig, hPlotAxes, PARA );
          
        case -1
          msgbox( 'Date limits are not correct',...
            'Correction module', 'warn', 'modal');
      end
      
    end
    
  end

%% medianCorrectionCallback .................................... Correction Module
  function medianCorrectionCallback(src, evnt)
    % Callback function run when
    
    % Desactivate somme Toggle button
    % -------------------------------
    set( hZoomInToggletool,       'state', 'off' );
    set( hZoomOutToggletool,       'state', 'off' );
    set( hPanToggletool,        'state', 'off' );
    set( hQCToggletool,         'state', 'off' );
    set( hTimelimitToggletool,  'state', 'off' );
    
    % Get the time limits for the correction A TESTER
    % --------------------------------------
    dateMin = datenum(get( hetDateMin, 'String'), 'yyyy-mm-dd HH:MM:SS');
    dateMax = datenum(get( hetDateMax, 'String'), 'yyyy-mm-dd HH:MM:SS');
    
    % Get tsg application data
    % ------------------------
    tsg = getappdata(hMainFig, 'tsg_data');
    
    % Get parameter we are working on (SSPS, SSJT, SSTP)
    % or SSPS_CAL, SSJT_CAL, SSTP_CAL
    % -------------------------------------------------
    PARA = getParaCorModule( hMainFig );
    SAMPLE = tsg.plot.sample;
    
    if ~isempty( tsg.([SAMPLE '_EXT']) )
      
      % Compute the sample-TSG differences
      % ----------------------------------
      diffTsgSample( hMainFig, PARA );
      
      % Correction
      % ----------
      error = corTsgMedian(hMainFig, PARA, dateMin, dateMax);
      
      switch error
        
        case 1
          
          % Plot in the 3 axes
          % ------------------
          plot_Correction( hMainFig, hPlotAxes, PARA );
          
        case -1
          
          % dateMax <= dateMin
          % ------------------
          msgbox( {'Function corTsgMedian'; ' '; ...
            'Date limits are not correct' },...
            'Correction Method', 'warn', 'modal');
          
        case -2
          
          % the date are not strictly increasing interp1 cannot be used
          % -----------------------------------------------------------
          msgbox( {'Function corTsgMedian'; ' '; ...
            'At least 2 samples have the same date';...
            'The soft cannot make the interpolation'},...
            'Correction Method', 'warn');
          
        otherwise
          
          msgbox( {'corTsgMedian : unknow error', sprintf('error = %d', error)});
      end
      
    end
  end

%% PopupMenu Select Parameter
% POP_UP filled in with the function "initParameterChoice"
% ---------------------------
  function SelectParameter(src, evnt, nplot)
    % Callback function run when the ....
    
    % Get application data
    % --------------------
    tsg = getappdata( hMainFig, 'tsg_data');
    
    % Get the active string of the selected box
    % -----------------------------------------
    val             = get( src, 'Value' );
    string_list     = get( src, 'String' );
    selected_string = string_list{val};
    
    % Get the default parameter
    % -------------------------
    tsg.plot.parameter{nplot} =  selected_string;
    if nplot == 1
      tsg.plot.sample = selected_string;
      if strcmp( tsg.plot.sample, 'SSJT' )
        tsg.plot.sample = 'SSTP';
      end
    end
    
    % Save application data
    % --------------------
    setappdata( hMainFig, 'tsg_data', tsg);
    
    % Disable the climatology
    % -----------------------
    plotClim = 0;
    if strcmp( get(hClimToggletool, 'state'), 'on' )
      set( hClimToggletool, 'state', 'off' );
      plotClim = 1;
    end
    
    % Disable the climatology
    % -----------------------
    set( hClimToggletool, 'state', 'off' );
    
    plot_Validation( hMainFig, hPlotAxes, 1, tsg.plot.parameter{1} );
    plot_Validation( hMainFig, hPlotAxes, 2, tsg.plot.parameter{2} );
    plot_Validation( hMainFig, hPlotAxes, 3, tsg.plot.parameter{3} );
    
    % Plot the climatology if it was already plotted
    % ----------------------------------------------
    if plotClim
      set( hClimToggletool, 'state', 'on' );
      plot_Climatology(hMainFig, hPlotAxes);
    end
    
  end

%% SelectTime_OnMenuCallback
%---------------------------
  function SelectTime_OnMenuCallback(src, evnt)
    % Callback function run when the ....
    
    % Desactivate Zoom and Pan functions.
    % ----------------------------------
    set( hZoomInToggletool, 'state', 'off' );
    set( hZoomOutToggletool, 'state', 'off' );
    set( hQCToggletool,   'state', 'off' );
    set( hPanToggletool,  'state', 'off' );
    
    % Create a pointer to select the time limits
    % ------------------------------------------
    selTimePointer = ones(16)+1;
    selTimePointer(1,:)       = 1; selTimePointer(16,:)      = 1;
    selTimePointer(:,1)       = 1; selTimePointer(:,16)      = 1;
    selTimePointer(1:4,8:9)   = 1; selTimePointer(13:16,8:9) = 1;
    selTimePointer(8:9,1:4)   = 1; selTimePointer(8:9,13:16) = 1;
    selTimePointer(5:12,5:12) = NaN; % Create a transparent region in the center
    
    % Activate clic mouse menu on second axes (salinity) for next rbbox
    % ----------------------------------------------------------------
    set(hMainFig,'WindowButtonDownFcn', @Time_SelectCallback);
    
    % change cursor
    % ---------------
    set( hMainFig, 'Pointer', 'custom',...
      'PointerShapeCData', selTimePointer, 'PointerShapeHotSpot',[9 9]);
    
    % ----------------------------------------------------------------------
    % nested function on mouse clic when Select Time toggle tool is selected
    % ----------------------------------------------------------------------
    function Time_SelectCallback(src, evnt)
      
      % disable ButtonMotion on main fig during select
      % prevent drawing to map
      % ----------------------------------------------
      set( hMainFig, 'WindowButtonMotionFcn', []);
      
      % Retrieve named application data
      % -------------------------------
      tsg = getappdata( hMainFig, 'tsg_data');
      
      % Selection of the data within the figure
      % ---------------------------------------
      point1    = get(gca,'CurrentPoint');    % button down detected
      finalRect = rbbox;                      % return figure units
      point2    = get(gca,'CurrentPoint');    % button up detected
      
      point1 = point1(1,1:2);                 % extract x and y
      point2 = point2(1,1:2);
      
      p1 = min(point1,point2);
      p2 = max(point1,point2);                % calculate locations
      
      % get index on selected zone - Only on X axes (time)
      % --------------------------------------------------
      ind = find(tsg.DAYD >= p1(1,1) & tsg.DAYD <= p2(1,1));
      
      % Write the date in the Editable uicontrol
      % ----------------------------------------
      set( hetDateMin, 'String', datestr(tsg.DAYD(ind(1)),   31));
      set( hetDateMax, 'String', datestr(tsg.DAYD(ind(end)), 31));
      
      % enable ButtonMotion on main fig after select QC area
      % ----------------------------------------------------
      set( hMainFig, 'WindowButtonMotionFcn', @MouseMotion);
    end
  end

%% SelectTime_OffMenuCallback
%----------------------------
  function SelectTime_OffMenuCallback(src, evnt)
    % Callback function run when the ....
    
    % Desactivate time limit buttons
    % ------------------------------
    set( hTimelimitToggletool, 'state', 'off');
    
    set( hMainFig, 'WindowButtonDownFcn', []);
    
    set( hMainFig, 'Pointer', 'arrow');
    
  end

%% Clim_OffMenuCallback
%------------------------------------------------------------------------
% Callback function run when the Levitus climatology toolbar is unselected
%------------------------------------------------------------------------
  function Clim_OffMenuCallback(src, evnt)
    
    % Get the tsg struct from the application GUI
    % -------------------------------------------
    tsg = getappdata( hMainFig, 'tsg_data');
    
    % set climato on map to none (disable)
    % ------------------------------------
    tsg.preference.map.climatology = 'none';
    
    % mask climato range uipanel on map
    set(findobj('tag', 'TAG_MAP_CLIMATO_UIPANEL'),'Visible', 'off');
    % resize map panel for axes
    set(findobj('tag', 'TAG_MAP_CLIMATO_AXES'),'Position',[0, 0, 1, 1])
    
    % Save tsg structure
    % ------------------
    setappdata( hMainFig, 'tsg_data', tsg);
    
    % Get lines handles from tag
    % --------------------------
    hLines = findobj('-regexp', 'Tag', 'TAG_LINE_CLIMATO_');
    
    % disable and check/uncheck climato menu on map
    set(findobj('tag', 'TAG_UIMENU_MAP_CLIMATOLOGY_WITH_PCOLOR'),...
      'enable', 'off', 'checked', 'off');
    set(findobj('tag', 'TAG_UIMENU_MAP_CLIMATOLOGY_WITH_CONTOURF'),...
      'enable', 'off', 'checked', 'off');
    set(findobj('tag', 'TAG_UIMENU_MAP_CLIMATOLOGY_WITH_NONE'),...
      'checked', 'on');
    
    % Delete climatology lines on axes
    % ---------------------------------
    delete(hLines);
    
    % Update the map (if visible)
    % ----------------------------
    if strcmp( get(hMapFig,'visible'), 'on') == 1
      erase_Line( hPlotAxes, 4 );
      plot_map( hMainFig, hPlotAxes);
    end
    
  end

%% Clim_OnMenuCallback
%------------------------------------------------------------------------
% Callback function run when the Levitus climatology toolbar is unselected
%------------------------------------------------------------------------
  function Clim_OnMenuCallback(src, evnt)
    
    % Test if the TSG and bucket files have been read
    % -----------------------------------------------
    if strcmp( get(hOpenMenu, 'UserData'), 'on' )
      
      % Read surface climatology (annual, seasonal or monthly)
      % ------------------------------------------------------
      if read_Climatology(hMainFig)
        
        % enable climato menu on map
        set(findobj('tag', 'TAG_UIMENU_MAP_CLIMATOLOGY_WITH_PCOLOR'),'enable', 'on');
        set(findobj('tag', 'TAG_UIMENU_MAP_CLIMATOLOGY_WITH_CONTOURF'),'enable', 'on');
        
        % find all climato on map submenu and set 'checked' property to 'off'
        % ------------------------------------------------------------
        hdl = findobj( '-regexp', 'tag', 'TAG_UIMENU_MAP_CLIMATOLOGY_WITH_');
        set(hdl, 'checked', 'off');
        
        % check menu with the previously selected climatology
        % ---------------------------------------------------
        switch tsg.preference.map.climatology
          case 'pcolor'
            set(findobj('tag', 'TAG_UIMENU_MAP_CLIMATOLOGY_WITH_PCOLOR'),'checked', 'on');
          case 'contourf'
            set(findobj('tag', 'TAG_UIMENU_MAP_CLIMATOLOGY_WITH_CONTOURF'),'checked', 'on');
          otherwise
            set(findobj('tag', 'TAG_UIMENU_MAP_CLIMATOLOGY_WITH_NONE'),'checked', 'on');
        end
        
        % plot climatology
        % ----------------
        plot_Climatology(hMainFig, hPlotAxes);
      end
      
    end
  end

%% ClimatoSelectMenuCallback
% -------------------------------------------------------------------
% Callback function run when climato submenu is selected
% -------------------------------------------------------------------
  function ClimatoSelectMenuCallback(src, evnt, climato, time)
    
    % find all climato submenu and set 'checked' property to 'off'
    % ------------------------------------------------------------
    hdl = findobj( '-regexp', 'tag', 'TAG_UIMENU_CLIMATO');
    set(hdl, 'checked', 'off');
    
    % set current climato submenu checked
    % -----------------------------------
    set(src, 'checked', 'on');
    
    % memorize action on climatology menu for next use
    % ------------------------------------------------
    s.type = climato;
    s.time = time;
    set(hClimatoMenu, 'userdata', s);
    
    % check if climatology toggle button is set
    % -----------------------------------------
    if strcmp(get(hClimToggletool, 'state'), 'on')
      
      % clear last plotted climatology
      % ------------------------------
      Clim_OffMenuCallback;
      
      % Read surface climatology (annual, seasonal or monthly)
      % ------------------------------------------------------
      read_Climatology(hMainFig);
      
      % plot and read (eventually) new climatology
      % ------------------------------------------
      plot_Climatology(hMainFig, hPlotAxes);
    end
    
  end

%% PreferencesMenuCallback
% -------------------------------------------------------------------
% Callback function run when Option/Preference is selected
% -------------------------------------------------------------------
  function PreferencesMenuCallback(src, evnt)
    
    oldmapres=tsg.preference.map.resolution;
    
    % call preferences form function
    % ------------------------------
    if( preferencesForm(hMainFig) )
      
      % if form is validate, update plots only if plot exist
      % ----------------------------------------------------
      if ~isempty(findobj( '-regexp', 'Tag', ('TAG_PLOT\d_LINE_')))
        SelectParameter(pmhPara(1),[],1);
      end
      
      % Update the map (if visible) if ship speed QC has been applied
      % or map resolution has been changed
      % -------------------------------------------------------------
      if (strcmp( get(hMapFig,'visible'), 'on') == 1 & ...
          tsg.preference.map.resolution ~= oldmapres)
        erase_Line( hPlotAxes, 4 );
        plot_map( hMainFig, hPlotAxes);
      end
      
    end
    
  end

%% HelpMenuCallback
% -------------------------------------------------------------------
% Callback function run when Help/Help is selected
% -------------------------------------------------------------------
  function HelpMenuCallback(src, evnt)
    msgbox( 'Function Help not yet implemented', 'warn', 'modal');
  end

%% AboutMenuCallback
% -------------------------------------------------------------------
% Callback function run when Help/About is selected
% -------------------------------------------------------------------
  function AboutMenuCallback(src, evnt)
    %splash('Thermo.jpg', 3000);
    aboutDialog(hMainFig, DEFAULT_PATH_FILE);
  end

%% Map menus
% -----------
  function mapResolutionCallback(src, evnt, resolution)
    
    % get the tsg structure
    % ---------------------
    tsg = getappdata( hMainFig, 'tsg_data');
    
    hdls = findobj( '-regexp', 'tag', 'TAG_UIMENU_MAP_RESOLUTION_');
    set(hdls, 'Checked', 'off');  % set all menu off
    set(src, 'Checked', 'on');   % set the menu on
    
    % set map resolution
    % ------------------
    tsg.preference.map.resolution = resolution;
    
    % Save the modifications for use new setting
    % -----------------------------------------
    setappdata( hMainFig, 'tsg_data', tsg);
    
    % redraw map
    % ------------------------------------------
    erase_Line( hPlotAxes, 4 );
    plot_map(hMainFig, hPlotAxes);
  end

  function mapPatchMenuCallback(src, evnt, patch)
    
    % get the tsg structure
    % ---------------------
    tsg = getappdata( hMainFig, 'tsg_data');
    
    if patch
      % find map with patch submenu and set 'checked' property to 'off'
      % ------------------------------------------------------------
      hdl = findobj( '-regexp', 'tag', 'TAG_UIMENU_MAP_WITHOUT_PATCH');
      set(hdl, 'checked', 'off');
      
      % set current climato submenu checked
      % -----------------------------------
      set(src, 'checked', 'on');
      
      % set tsg.preference for next use
      % ------------------------------------------------
      tsg.preference.map.patch_value = 2;
      
    else
      hdl = findobj( '-regexp', 'tag', 'TAG_UIMENU_MAP_WITH_PATCH');
      set(hdl, 'checked', 'off');
      
      % set current climato submenu checked
      % -----------------------------------
      set(src, 'checked', 'on');
      
      % set tsg.preference for next use
      % ------------------------------------------------
      tsg.preference.map.patch_value = 1;
    end
    
    % Save the modifications for use new setting
    % -----------------------------------------
    setappdata( hMainFig, 'tsg_data', tsg);
    
    % redraw map
    % ------------------------------------------
    erase_Line( hPlotAxes, 4 );
    plot_map(hMainFig, hPlotAxes);
    
  end


% function mapDynaBorderCallback
% --------------------------------
  function mapDynaBorderCallback(src, evnt, border)
    
    % get the tsg structure
    % ---------------------
    tsg = getappdata( hMainFig, 'tsg_data');
    
    hdls = findobj( '-regexp', 'tag', 'TAG_UIMENU_MAP_BORDER_');
    set(hdls, 'Checked', 'off');
    set(src, 'Checked', 'on');
    
    % change the map border from menu on map
    % --------------------------------------
    tsg.preference.map.border = border;
    setappdata( hMainFig, 'tsg_data', tsg);
    
    % redraw map
    % ------------------------------------------
    erase_Line( hPlotAxes, 4 );
    plot_map(hMainFig, hPlotAxes);
  end

% display 2D climatology on map if pushbutton climato is on
% ---------------------------------------------------------
  function mapClimatologyCallback(src, evnt, climato)
    
    % get the tsg structure
    % ---------------------
    tsg = getappdata( hMainFig, 'tsg_data');
    
    % check only the selected menu
    % -----------------------------
    hdls = findobj( '-regexp', 'tag', 'TAG_UIMENU_MAP_CLIMATOLOGY_WITH_');
    set(hdls, 'Checked', 'off');
    set(src, 'Checked', 'on');
    
    % change the map 2D climatology from menu on map
    % ----------------------------------------------
    tsg.preference.map.climatology = climato;
    
    % save tsg.preference.map.climatology
    % -----------------------------------
    setappdata( hMainFig, 'tsg_data', tsg);
    
    % redraw map
    % ------------------------------------------
    erase_Line( hPlotAxes, 4 );
    plot_map(hMainFig, hPlotAxes);
    
  end

% call when user change range value for contourf climato on map
% -------------------------------------------------------------
  function mapContourfCallback(src, evnt, type)
    
    % get the tsg structure
    % ---------------------
    tsg = getappdata( hMainFig, 'tsg_data');
    
    
    % change the map 2D climatology from menu on map
    % ----------------------------------------------
    tsg.preference.map.climato.(tsg.plot.sample).(type) = str2double(get(src,'string'));
    
    % save tsg.preference.map.climatology
    % -----------------------------------
    setappdata( hMainFig, 'tsg_data', tsg);
    
    % redraw map
    % ------------------------------------------
    erase_Line( hPlotAxes, 4 );
    plot_map(hMainFig, hPlotAxes);
    
  end

% Generic function for all customization menus.
% The tag argument (second) is used to extract the handle of the selected
% menu.
% We use a regular expression to access and modify the preference structure
% -------------------------------------------------------------------------
  function mapCustomizeCallback(src, evnt, val, tag)
    
    % get the tsg structure
    % ---------------------
    tsg = getappdata( hMainFig, 'tsg_data');
    
    hdls = findobj( '-regexp', 'tag', ['TAG_UIMENU_MAP_' tag]);
    set(hdls, 'Checked', 'off');
    set(src, 'Checked', 'on');
    
    % change the value from customize menu on map, dynamically transform
    % tag to structure member
    % -------------------------------------------------------------
    member =  regexp(lower(tag),'(\w+)_(\w+)','tokens');
    tsg.preference.map.(member{1}{1}).(member{1}{2}) = val;
    
    % save the selected position menu (index) for next use
    index = [member{1}{2} '_index'];
    tsg.preference.map.(member{1}{1}).(index) = get(src, 'position');
    
    % save tsg struct
    setappdata( hMainFig, 'tsg_data', tsg);
    
    % redraw map
    % ------------------------------------------
    erase_Line( hPlotAxes, 4 );
    plot_map(hMainFig, hPlotAxes);
  end

% color picker callback
% ---------------------
  function mapColorPickerCallback(src, evnt, tag)
    
    % open color picker
    theColor = uisetcolor;
    
    % if user select cancel, abort
    if length(theColor) == 1 && theColor == 0
      return
    end
    
    % call generic function
    mapCustomizeCallback(src, evnt, theColor, tag)
  end

% print map figure from menu
% ----------------------------
  function mapPrintCallback(src, evnt)
    % cache the contourf setting panel before printing
    set(findobj('tag', 'TAG_MAP_CLIMATO_UIPANEL'),'Visible', 'off');
    % resize map panel for full figure
    if strcmp(tsg.preference.map.climatology, 'contourf')
      set(findobj('tag', 'TAG_MAP_CLIMATO_AXES'),'Position',[0, 0, 1, 1])
    end
    % call the print dialog box to the figure handle
    printdlg(get(get(hPlotAxes(4),'parent'),'parent'));
    if strcmp(tsg.preference.map.climatology, 'contourf')
      set(findobj('tag', 'TAG_MAP_CLIMATO_AXES'),'Position',[0, 0, .8, 1])
      % enable the contourf setting panel
      set(findobj('tag', 'TAG_MAP_CLIMATO_UIPANEL'),'Visible', 'on');
    end
  end

% print preview of the map figure, parent of panel and axe
% --------------------------------------------------------
  function mapPrintPreviewCallback(src, evnt)
  
    % cache the contourf setting panel before printing
    set(findobj('tag', 'TAG_MAP_CLIMATO_UIPANEL'),'Visible', 'off');
    % resize map panel for full figure
    if strcmp(tsg.preference.map.climatology, 'contourf')
      set(findobj('tag', 'TAG_MAP_CLIMATO_AXES'),'Position',[0, 0, 1, 1])
    end
    printpreview(get(get(hPlotAxes(4),'parent'),'parent'));
    % resize map panel for axes only when contourf is selected
    if strcmp(tsg.preference.map.climatology, 'contourf')
      set(findobj('tag', 'TAG_MAP_CLIMATO_AXES'),'Position',[0, 0, .8, 1])
      % enable the contourf setting panel
      set(findobj('tag', 'TAG_MAP_CLIMATO_UIPANEL'),'Visible', 'on');
    end
  end

% enable toolbar on map figure from menu
% see Reverting axes controls in figure toolbar under:
% https://undocumentedmatlab.com/blog/reverting-axes-controls-in-figure-toolbar
% and Matlab Central:
% https://fr.mathworks.com/matlabcentral/answers/419036-what-happened-to-the-figure-toolbar-in-r2018b-why-is-it-an-axes-toolbar-how-can-i-put-the-buttons
% --------------------------------------------------------------------
  function mapToolBarCallback(src, evnt)
    
    if( strcmp(get(hMapFig, 'toolbar'), 'none'))
      set(hMapFig, 'toolbar', 'figure');
      if ~verLessThan('matlab','9.5')
        addToolbarExplorationButtons(hMapFig);
      end
    else
      set(hMapFig, 'toolbar', 'none');
    end
  end

% save the map as image file
% --------------------------
  function mapSaveAsCallback(src, evnt)
    [file, path] = uiputfile({'*.jpeg';'*.png';'*.pdf';'*.tiff';'*.bmp';'*.eps'});
    if file == 0
      return
    end
    fprintf(1, 'Save figure map as %s\n', fullfile(path,file));
    % cache the contourf setting panel before printing
    set(findobj('tag', 'TAG_MAP_CLIMATO_UIPANEL'),'Visible', 'off');
    % resize map panel for full figure
    if strcmp(tsg.preference.map.climatology, 'contourf')
      set(findobj('tag', 'TAG_MAP_CLIMATO_AXES'),'Position',[0, 0, 1, 1])
    end
    % save figure to specific file format
    map_hdl = get(get(hPlotAxes(4), 'parent'), 'parent');
    
    % bug with saveas for version < R2014b when figure as panel children
    % -------------------------------------------------------------------
    if verLessThan('matlab','8.4')
      screencapture(map_hdl, fullfile(path,file));
    else
      saveas(map_hdl, fullfile(path,file));
    end
    % resize map panel for axes only when contourf is selected
    if strcmp(tsg.preference.map.climatology, 'contourf')
      set(findobj('tag', 'TAG_MAP_CLIMATO_AXES'),'Position',[0, 0, .8, 1])
      % enable the contourf setting panel
      set(findobj('tag', 'TAG_MAP_CLIMATO_UIPANEL'),'Visible', 'on');
    end
  end


%% HeaderMenuCallback
% -------------------------------------------------------------------
% Callback function run when the headerForm tool bar item is selected
% -------------------------------------------------------------------
  function HeaderMenuCallback(src, evnt)
    
    % call header form function
    % -------------------------
    headerForm(hMainFig);
    
  end

%% PrintFigMenuCallback
% -------------------------------------------------------------------
% Callback function run when the Report tool bar item is selected
% -------------------------------------------------------------------
  function PrintFigMenuCallback(src, evnt)
    
    % disable ButtonMotion on main fig during select
    % ----------------------------------------------
    set( hMainFig, 'WindowButtonMotionFcn', []);
    
    % Get the tsg structure
    % ---------------------
    tsg = getappdata( hMainFig, 'tsg_data');
    
    
    hPrintFig = figure( 'Name', 'Print','NumberTitle', 'off','Resize', 'on');
    hPlot(1) = subplot(3,1,1);
    hPlot(2) = subplot(3,1,2);
    hPlot(3) = subplot(3,1,3);
    title( hPlot(1), tsg.file.name, 'interpreter', 'none');
    
    if strcmp(get(hBottleToggletool,'state'), 'on')
      
      % Default parameter
      % -----------------------------------------------------
      PARA = getParaCorModule( hMainFig );
      
      plot_Correction( hMainFig, hPlot, PARA );
      
    elseif strcmp(get(hCalToggletool,'state'), 'on')
      
      plot_Calibration( hMainFig, hPlot, 1, 'SSPS' );
      plot_Calibration( hMainFig, hPlot, 2, 'SSJT' );
      plot_Calibration( hMainFig, hPlot, 3, 'SSTP' );
      %     elseif strcmp(get(hMapToggletool,'state'), 'on')
      %      plot_map( hMainFig, hPlot)
      
    elseif strcmp(get(hInterpToggletool,'state'), 'on')
      
      plot_Interpolation( hMainFig, hPlot, 1 );
      plot_Interpolation( hMainFig, hPlot, 2 );
      plot_Interpolation( hMainFig, hPlot, 3 );
      
    else
      
      plot_Validation( hMainFig, hPlot, 1, tsg.plot.parameter{1} );
      plot_Validation( hMainFig, hPlot, 2, tsg.plot.parameter{2} );
      plot_Validation( hMainFig, hPlot, 3, tsg.plot.parameter{3} );
      
      %       I = getframe(hPlotAxes(1));
      %       imwrite(I.cdata, 'myplot.png');
    end
    
    linkaxes([hPlot(1),hPlot(2),hPlot(3)], 'x');
    for i = 1 : length( hPlot )
      %      set(hPlot(i), 'box', 'on','XTickMode','auto');
      set(hPlot(i), 'box', 'on','XTickMode','auto');
      datetick(hPlot(i),'x','mm/dd','keepticks' );
    end
    
    % enable ButtonMotion on main fig after select QC area
    % ----------------------------------------------------
    set( hMainFig, 'WindowButtonMotionFcn', @MouseMotion);
    
  end

%% ReportMenuCallback
% -------------------------------------------------------------------
% Callback function run when the Report tool bar item is selected
% -------------------------------------------------------------------
  function ReportMenuCallback(src, evnt)
    
    % call report function
    % --------------------
    saveReport(hMainFig);
    
  end

%% GoogleEarthMenuCallback
% -------------------------------------------------------------------
% Callback function run when the Google Earth tool bar item is selected
% -------------------------------------------------------------------
  function GoogleEarthMenuCallback(src, evnt)
    
    % Get tsg application data
    % ------------------------
    tsg = getappdata( hMainFig, 'tsg_data' );
    
    % call KML Toolbox functions
    % --------------------------
    k = kml(tsg.CYCLE_MESURE);
    
    % get indice from the selected area
    if verLessThan('matlab','8.4')
      XLim = get(hPlotAxes(1), 'XLim');
      ind = find(tsg.DAYD > XLim(1) & tsg.DAYD < XLim(2));
    else
      ind = find(tsg.DAYD > hPlotAxes(1).XLim(1) & ...
        tsg.DAYD < hPlotAxes(1).XLim(2) );
    end
    
    % Color value format must be passed as a character array according
    % to the format string 'AABBGGRR', eg: red = 'FF0000FF'
    k.plot(tsg.LONX(ind),tsg.LATX(ind), 'linewidth', 2, 'linecolor', 'FF0000FF');
    k.run;
    
  end

%% SaveMenuCallback
% -------------------------------------------------------------------
% Callback function run when the Save menu item is selected
% -------------------------------------------------------------------
  function SaveMenuCallback(src, evnt)
    
    % Retrieve named application data
    % -------------------------------
    tsg = getappdata( hMainFig, 'tsg_data');
    
    % fill or append header form
    % -------------------------
    error = headerForm(hMainFig);
    
    % if user press continue button, ask for netcdf file
    % ------------------------------------------------
    if error ~= -1
      [fileName, pathName, filterindex] = uiputfile('*.nc', ...
        'Save file name', strcat(tsg.file.name, '.nc'));
      
      % if user press cancel button, all var are set to zero
      % ----------------------------------------------------
      if filterindex == 0
        return;
      end
      
      % Pointer set to watch during reading and plotting
      % ------------------------------------------------
      set( hMainFig, 'Pointer', 'watch' );
      
      % flushes the evnt queue and updates the closed uiputfile window
      % ---------------------------------------------------------------
      drawnow;
      
      % write netcdf file
      % -----------------
      error = writeTSGDataNetCDF(hMainFig, strcat(pathName, fileName));
      
      % Pointer reset to arrow
      % ----------------------
      set( hMainFig, 'Pointer', 'arrow' );
      
      % Check for NetCDF writing error
      % must to be rewriting
      % ------------------------------
      if error == -1
        warning('tsgqc:SaveMenuCallback', ...
          'NetCDF writing error: %s %s', pathName, fileName);
        return;
      end
      
      % update the display
      % ------------------
      set( hInfoFileText, 'String', fileName);
      
      % enable Quality Control mode
      % ---------------------------
      hdl_pushtool = findobj('Tag', 'QC');
      set(hdl_pushtool, 'Enable', 'on');
    end
    
  end

%% ExportTsgCallback
% -------------------------------------------------------------------
% Callback function run when the Export menu item is selected
% -------------------------------------------------------------------
  function ExportTsgCallback(src, evnt)
    
    % Retrieve named application data
    % -------------------------------
    tsg = getappdata( hMainFig, 'tsg_data');
    
    % Desactivate MouseMotion 'off'
    % ----------------------------
    set( hMainFig, 'WindowButtonMotionFcn', []);
    
    % Open standard dialog box for saving files
    % -----------------------------------------
    [fileName, pathName, filterindex] = uiputfile('*.tsgqc', ...
      'Save file name', strcat(tsg.file.name, '.tsgqc'));
    
    % if user press cancel button, all var are set to zero
    % ----------------------------------------------------
    if filterindex == 0
      return;
    end
    
    % Pointer set to watch during reading and plotting
    % ------------------------------------------------
    set( hMainFig, 'Pointer', 'watch' );
    
    % Write a .TSG (ascii)  file
    % --------------------------
    error = writeAsciiTsg(hMainFig, strcat(pathName, fileName));
    
    % Pointer reset to arrow
    % ----------------------
    set( hMainFig, 'Pointer', 'arrow' );
    
    % enable Quality Control mode
    % ---------------------------
    hdl_pushtool = findobj('Tag', 'QC');
    set(hdl_pushtool, 'Enable', 'on');
    
    % Set MouseMotion 'on'
    % --------------------
    set( hMainFig, 'WindowButtonMotionFcn', @MouseMotion);
    
    % Check for .TSG writing error - must to be rewriting
    % Because of the 'return' - These line must be at the end
    % --------------------------------------------------------
    if error == -1
      warning('tsgqc:SaveMenuCallback', ...
        'TSG no ouput: %s %s', pathName, fileName);
      return;
    end
    
  end
%% ExportSampleCallback
% -------------------------------------------------------------------
% Callback function run when the Export menu item is selected
% -------------------------------------------------------------------
  function ExportSampleCallback(src, evnt)
    
    % Retrieve named application data
    % -------------------------------
    tsg = getappdata( hMainFig, 'tsg_data');
    
    % Desactivate MouseMotion 'off'
    % ----------------------------
    set( hMainFig, 'WindowButtonMotionFcn', []);
    
    % Open standard dialog box for saving files
    % -----------------------------------------
    [fileName, pathName, filterindex] = uiputfile('*.spl', ...
      'Save file name', strcat(tsg.file.name, '.spl'));
    
    % if user press cancel button, all var are set to zero
    % ----------------------------------------------------
    if filterindex == 0
      return;
    end
    
    % Pointer set to watch during reading and plotting
    % ------------------------------------------------
    set( hMainFig, 'Pointer', 'watch' );
    
    % Write a .SPL (ascii)  file
    % --------------------------
    error = writeAsciiSample(hMainFig, strcat(pathName, fileName));
    
    % Pointer reset to arrow
    % ----------------------
    set( hMainFig, 'Pointer', 'arrow' );
    
    % enable Quality Control mode
    % ---------------------------
    hdl_pushtool = findobj('Tag', 'QC');
    set(hdl_pushtool, 'Enable', 'on');
    
    % Set MouseMotion 'on'
    % --------------------
    set( hMainFig, 'WindowButtonMotionFcn', @MouseMotion);
    
    % Check for .TSG writing error - must to be rewriting
    % Because of the 'return' - These line must be at the end
    % --------------------------------------------------------
    if error == -1
      warning('tsgqc:SaveMenuCallback', ...
        'TSG no ouput: %s %s', pathName, fileName);
      return;
    end
    
  end

%% UndoMenuCallback
% -----------------------------------------------------------------------
% Callback function run when the Edit/Undo menu item is selected (Ctrl+Z)
% -----------------------------------------------------------------------
  function UndoMenuCallback(src, evnt)
    
    if (tsg.qc_history_pointer > 0)
      
      % Get the parameter (SSPS, SSJT or SSTP)
      % --------------------------------------
      PARA = getParaCorModule( hMainFig );
      
      if (tsg.qc_history_pointer == tsg.qc_history_size)
        tsg.qc_history_state = circshift(tsg.qc_history_state,[0 -1]);
        tsg.qc_history_pointer = tsg.qc_history_pointer - 1;
      end
      
      % Back to previous QC flags
      % -------------------------
      tsg.qc_history_state(:,tsg.qc_history_pointer+1) = tsg.([PARA{1} '_QC']);
      tsg.([PARA{1} '_QC']) = tsg.qc_history_state(:,tsg.qc_history_pointer);
      tsg.qc_history_pointer = tsg.qc_history_pointer - 1;
      
      % Allow redo
      % ----------
      tsg.qc_redo_possible = tsg.qc_redo_possible + 1;
      set(findobj('tag','UIMENU_REDO'),'enable','on');
      
      % Save the modifications
      % ----------------------
      setappdata( hMainFig, 'tsg_data', tsg);
      
      % Draw plot 1 of the validation figure
      % ------------------------------------
      plot_Validation( hMainFig, hPlotAxes, 1, PARA{1} );
      
      % refresh QC statistic panel
      % --------------------------
      display_QC( hMainFig );
      
      % Update the map if already displayed
      % -----------------------------------
      if strcmp( get(hMapFig,'visible'), 'on') == 1
        erase_Line( hPlotAxes, 4 );
        plot_map( hMainFig, hPlotAxes);
      end
      
      % As soon as a modification took place the data should be saved
      % -------------------------------------------------------------
      set( hSaveMenu, 'UserData', 'on' );
      
    else
      
      msgbox('Undo not possible', 'modal');
      
    end
    
  end


%% RedoMenuCallback
% -----------------------------------------------------------------------
% Callback function run when the Edit/Redo menu item is selected (Ctrl+R)
% -----------------------------------------------------------------------
  function RedoMenuCallback(src, evnt)
    
    if (tsg.qc_redo_possible > 0)
      
      % Get the parameter (SSPS, SSJT or SSTP)
      % --------------------------------------
      PARA = getParaCorModule( hMainFig );
      
      % Forward to undone QC flags
      % --------------------------
      tsg.qc_history_pointer = tsg.qc_history_pointer + 1;
      tsg.([PARA{1} '_QC']) = tsg.qc_history_state(:,tsg.qc_history_pointer+1);
      
      % Reduce number of possible redo
      % ------------------------------
      tsg.qc_redo_possible = tsg.qc_redo_possible-1;
      if tsg.qc_redo_possible == 0
        set(findobj('tag','UIMENU_REDO'),'enable','off');
      end
          
      % Save the modifications
      % ----------------------
      setappdata( hMainFig, 'tsg_data', tsg);
      
      % Draw plot 1 of the validation figure
      % ------------------------------------
      plot_Validation( hMainFig, hPlotAxes, 1, PARA{1} );
      
      % refresh QC statistic panel
      % --------------------------
      display_QC( hMainFig );
      
      % Update the map if already displayed
      % -----------------------------------
      if strcmp( get(hMapFig,'visible'), 'on') == 1
        erase_Line( hPlotAxes, 4 );
        plot_map( hMainFig, hPlotAxes);
      end
      
      % As soon as a modification took place the data should be saved
      % -------------------------------------------------------------
      set( hSaveMenu, 'UserData', 'on' );
      
    else
      
      msgbox('Redo not possible', 'modal');   
    end
    
    
  end

%% This function is called after to duplicate QC from upper plot to middle
% plot
% -----------------------------------------------------------------------
  function duplicateQc(src, evnt)
    
    % Get the data from the application GUI
    % -------------------------------------
    tsg = getappdata( hMainFig, 'tsg_data');
    
    source = tsg.plot.parameter{1};
    dest = tsg.plot.parameter{2};
    valid = {'SSPS', 'SSTP'};
    
    if any(strcmp(valid, source)) && any(strcmp(valid, dest))
      
      % duplicate QC from parameter 1 to 2
      % ----------------------------------
      tsg.([dest '_QC']) = tsg.([source '_QC']);
      
      % Save tsg structure first for plot_Validation
      % ---------------------------------------------
      setappdata( hMainFig, 'tsg_data', tsg);
      
      % plot with QC on middle plot
      % ---------------------------
      plot_Validation( hMainFig, hPlotAxes, 2, tsg.plot.parameter{2} );
      
    else
      msgbox( 'Duplication QC code only on SSPS or SSTP variable',...
        'Choose the correct variable first', 'warn', 'modal');
    end
    
  end

%% KeyPressFcnCallback
% -----------------------------------------------------------------------
% Callback function run when key is pressed
% -----------------------------------------------------------------------
  function keyPressFcnCallback(src, evnt)
    
    % MATLAB generates repeated KeyPressFcn events, desactivate callback
    % ------------------------------------------------------------------
    set(src, 'KeyPressFcn', []);
    
    % check if key is pressed
    % -----------------------
    if ~isempty(evnt.Key)
      
      % test key, shift or control
      % --------------------------
      switch evnt.Key
        
        case 'shift'
          
          % get current pointer shape
          % -------------------------
          pointerShape = get(src, 'pointer');
          
          % save current cursor shape
          % -------------------------
          setappdata( hMainFig, 'tsg_pointer', pointerShape);
          
          % set cursor to fullcross or reset to normal arrow
          % ------------------------------------------------
          set(src, 'pointer', 'crosshair');
          
        case 'alt'
          
          % Get current position of cusor and return its coordinates in
          % axes
          % -----------------------------------------------------------
          a = get(hPlotAxes(1), 'CurrentPoint');
          x = a(2,1);
          
          % Test if cursor is inside data interval
          % -------------------------------------
          if x > tsg.DAYD(1) && x < tsg.DAYD(end)
            
            % loop over 3 subplot and draw vertical lines
            % -------------------------------------------
            for iplot = 1:3
              % axes( hPlotAxes(iplot));
              limy = get(hPlotAxes(iplot), 'YLim');
              line(hPlotAxes(iplot), [x x], limy,...
                'color', 'k', 'tag', 'VERTICAL_TAG_LINE');
              
              % to immediately display changes to object data, call
              % the drawnow function instead of setting EraseMode to 'xor'.
              % since R2014
              drawnow;
            end
            
          end
          
      end % end of switch
      
    end
    
  end


%% KeyReleaseFcnCallback
% -----------------------------------------------------------------------
% Callback function run when key is release
% -----------------------------------------------------------------------
  function keyReleaseFcnCallback(src, evnt)
    
    % check if key is pressed
    % -----------------------
    if ~isempty(evnt.Key)
      
      % test key, shift or control
      % --------------------------
      switch evnt.Key
        
        case 'shift'
          
          % get stored cursor shape
          % -----------------------
          pointerShape = getappdata( hMainFig, 'tsg_pointer');
          
          % if pointer equal to fullcrosshair, oups, error, reset to arrow
          % ---------------------------------------------------------------
          if strcmp(pointerShape, 'fullcrosshair')
            pointerShape = 'arrow';
            set(src, 'pointer', pointerShape);
          end
          
          % set pointer
          % -----------
          set(src, 'pointer', pointerShape);
          
        case 'alt'
          
          % find vertical lines and delete them
          % -----------------------------------
          hdl_lines = findobj( 'Tag', 'VERTICAL_TAG_LINE' );
          delete(hdl_lines);
          
      end  % end of switch
      
    end  % end of if
    
    % Re-activate callback
    % --------------------
    set(src, 'KeyPressFcn', @keyPressFcnCallback);
    
  end

%% QuitMapCallback
% -----------------------------------------------------------------
% Callback function run when the Quit Map Figure item is selected
% -----------------------------------------------------------------
  function QuitMapCallback(src, evnt)
    
    % Make the earth map invisible
    % ----------------------------
    set(hMapFig, 'Visible', 'off' );
    set(hMapToggletool, 'state',  'off' );
    
  end

%% QuitMenuCallback
% -----------------------------------------------------------------
% Callback function run when the Quit menu item is selected
% -----------------------------------------------------------------
  function QuitMenuCallback(src, evnt)
    
    % Get the data from the application GUI
    % -------------------------------------
    tsg = getappdata(hMainFig, 'tsg_data');
    
    % in case of bad initialisation, the user could close the windows
    % ---------------------------------------------------------------
    try
      
      % save config mat file in prefdir
      % -------------------------------
      config_file = [prefdir, filesep, tsgqcname, '.mat'];
      
      % save preference mat file
      % ------------------------
      if exist('tsg', 'var') && isfield( tsg, 'preference')
        preference = tsg.preference;
        save( config_file, 'preference');
      end
      
      % leave program directly in debug mode
      % ------------------------------------
      if DEBUGGING
        quitProgram(DEFAULT_PATH_FILE, hMainFig, hMapFig);
        return
      end
      
      % If the data have been modified and not save, the program
      % ask to save the data
      % --------------------------------------------------------
      if  strcmp( get( hSaveMenu, 'UserData' ), 'on')
        selection = ...
          questdlg('The file has been modified.  Do you want to save it ?',...
          'Save before Quit?',...
          'Yes', 'No', 'Yes');
        
        if strcmp(selection, 'Yes')
          
          % call File/Save Menu Callback before before quit
          % -----------------------------------------------
          SaveMenuCallback;
          
        end
        
        % quit program
        % ------------
        quitProgram(DEFAULT_PATH_FILE, hMainFig, hMapFig);
        
      else
        selection = ...
          questdlg(['Quit ' get(hMainFig, 'Name') '?'],...
          ['Quit ' get(hMainFig, 'Name') '?'],...
          'Yes', 'No', 'Yes');
        if strcmp(selection, 'No')
          return;
        else
          quitProgram(DEFAULT_PATH_FILE, hMainFig, hMapFig);
        end
      end
      
      % catch error during close windows
      % --------------------------------
    catch
      % display message to console and quit program
      % -------------------------------------------
      fprintf('abnormal program termination during close user request\n');
      quitProgram(DEFAULT_PATH_FILE, hMainFig);
    end
    
  end % end of QuitMenuCallback

  function quitProgram(DEFAULT_PATH_FILE, varargin)
    
    % close all windows
    % -----------------
    for ii=1:size(varargin,2)
      delete(varargin{ii});
    end
    
    % reset userdata property of root Matalab object (0) for next use
    % ---------------------------------------------------------------
    set(0, 'userdata', []);
    
    % reset Matlab search path to default
    % addpath isn't mandatory and failed with compiled applications
    % --------------------------------------------------------------
    if (~isdeployed)
      rmpath( [DEFAULT_PATH_FILE filesep 'tsg_util'] );
      rmpath( [DEFAULT_PATH_FILE filesep 'tsg_util/ScreenCapture'] ); 
      rmpath( [DEFAULT_PATH_FILE filesep 'tsg_util/gsw'] );       
      rmpath( [DEFAULT_PATH_FILE filesep 'tsg_data'] );
      rmpath( [DEFAULT_PATH_FILE filesep 'tsg_io'] );
      rmpath( [DEFAULT_PATH_FILE filesep 'tsg_icon'] );
      rmpath( [DEFAULT_PATH_FILE filesep 'tsg_climato'] );
      rmpath( [DEFAULT_PATH_FILE filesep 'tsg_map'] );
    end
    
    % Refresh file system caches
    % --------------------------
    rehash;
    
    % clear base workspace just before quit, this is the only method
    % to clear NetCDF variables assign to base workspace with assignin
    % ----------------------------------------------------------------
    evalin('base','clear all');
    
  end % end of quitProgram

end % end of tsgqc
