%TRAININGPROGRESSMONITOR  Monitor and plot training progress for deep learning
% custom training loops
%
%   MONITOR = TRAININGPROGRESSMONITOR() creates a TrainingProgressMonitor 
%   object MONITOR. When using a custom training loop, use a 
%   TrainingProgressMonitor object to track the progress of the training, 
%   update information fields, record metric values, and produce training 
%   plots.
%
%   MONITOR = TRAININGPROGRESSMONITOR(__,PROP=VAL) specifies optional values 
%   for the properties of the object.
%
%   TrainingProgressMonitor properties:
%
%       Metrics                 - Metric names, specified as a string, 
%                                 character vector, string array, or cell 
%                                 array of character vectors. Valid names 
%                                 begin with a letter, and can contain 
%                                 letters, digits, and underscores. Each 
%                                 metric appears in its own training subplot.
%                                 The default value is an empty string array.
%       Info                    - Info names, specified as a string, character 
%                                 vector, string array, or cell array of 
%                                 character vectors. Valid names begin with 
%                                 a letter, and can contain letters, digits,  
%                                 and underscores. These names appear in the 
%                                 training progress window. The default value 
%                                 is an empty string array.
%       Stop                    - Flag to stop training, returned as a 
%                                 numeric or logical 1 (true) or 0 (false). 
%                                 The value of this property changes to true
%                                 when you click Stop in the training progress 
%                                 window. This property is read-only.
%       Visible                 - State of visibility of the training progress
%                                 window, specified as 'on' or 'off', or as
%                                 numeric or logical 1 (true) or 0 (false).
%                                 A value of 'on' is equivalent to true, and
%                                 'off' is equivalent to false. Thus, you can
%                                 use the value of this property as a logical
%                                 value.
%       Progress                - Training progress percentage, specified as
%                                 a numeric scalar between 0 and 100.
%       XLabel                  - Horizontal axis label in the training plot,
%                                 specified as a string or character vector.
%                                 The default value is an empty scalar string.
%       Status                  - Training status, specified as a string or
%                                 character vector. The default value is an
%                                 empty scalar string.
%       MetricData              - Metric values, returned as a structure array.
%                                 The field names are the same as those 
%                                 specified by Metrics. Each field contains
%                                 a matrix with two columns. The first column
%                                 contains the custom training loop step values
%                                 and the second column contains the metric
%                                 values. This property is read-only.
%       InfoData                - Info values, returned as a structure array. 
%                                 The field names are the same as those 
%                                 specified by Info. Each field is a column
%                                 vector containing the information values.
%                                 This property is read-only.
%
%   TrainingProgressMonitor methods:
% 
%       groupSubPlot            - Group metrics in a single training subplot
%                                 so that they appear on the same axes.
%       recordMetrics           - Record metric values in the training 
%                                 plots and the MetricData property of the 
%                                 TrainingProgressMonitor.
%       updateInfo              - Update information values in the training 
%                                 progress window and save the values in the
%                                 InfoData property of the TrainingProgressMonitor.
%
%   Example 1: Create a TrainingProgressMonitor object to track and visualize 
%   metrics and information during training.
%
%       % Create a TrainingProgressMonitor.
%       monitor = trainingProgressMonitor(Metrics="Loss",Info="Epoch");
%
%       % Set the x-axis label.
%       monitor.XLabel = "Epoch";
%
%       % Loop over epochs and stop if the Stop property is true.
%       epoch = 0;
%       maxEpochs = 100;
%       loss = dlarray(single(rand(1,maxEpochs)));
%
%       while epoch < maxEpochs && ~monitor.Stop
%           epoch = epoch + 1;
%
%           % Record the loss metric values at each epoch. This will also 
%           % update the training plot.
%           recordMetrics(monitor,epoch,Loss=loss(epoch));
%
%           % Update the epoch info value at each epoch. This will update 
%           % the info value in the training progress window.
%           updateInfo(monitor,Epoch=epoch);
%           
%           % Update the Progress property. This will update the progress bar
%           % in the training progress window.
%           monitor.Progress = 100 * (epoch/maxEpochs);
%       end
%
%   Example 2: Create a TrainingProgressMonitor object with grouped metrics.
%
%       % Create a TrainingProgressMonitor.
%       monitor = trainingProgressMonitor(Metrics=["TrainingLoss",...
%       "ValidationLoss"]);
%
%       % Group TrainingLoss and ValidationLoss in the same subplot with the 
%       % title Loss.
%       groupSubPlot(monitor,"Loss",["TrainingLoss","ValidationLoss"]);
%
% See also experiments.Monitor, dlarray

%   Copyright 2022 The MathWorks, Inc.

function monitor = trainingProgressMonitor(args)
arguments
    args.Metrics = string.empty();
    args.Info = string.empty();
    args.XLabel = "";
    args.Status = "";
    args.Visible = true;
    args.Progress
end

factory = deepmonitor.internal.DLTMonitorFactory();
model = experiment.shared.model.MonitorModel();
monitor = deep.TrainingProgressMonitor(model, factory);

monitor.Metrics = args.Metrics;
monitor.Info = args.Info;
monitor.XLabel = args.XLabel;
monitor.Status = args.Status;

if isfield(args, "Progress")
    monitor.Progress = args.Progress;
end

monitor.Visible = args.Visible;
end