classdef videoView < matlab.apps.AppBase

    % Properties that correspond to app components
    properties (Access = public)
        UIFigure                matlab.ui.Figure
        Slider                  matlab.ui.control.Slider
        Label                   matlab.ui.control.Label
        StopButton              matlab.ui.control.Button
        PlayPauseButton         matlab.ui.control.Button
        TextArea                matlab.ui.control.TextArea
        Panel                   matlab.ui.container.Panel
        UDPCheckBox             matlab.ui.control.CheckBox
        ChanDropDown            matlab.ui.control.DropDown
        ChanDropDownLabel       matlab.ui.control.Label
        SaveButton              matlab.ui.control.Button
        fpsCheckBox             matlab.ui.control.CheckBox
        freezeCheckBox          matlab.ui.control.CheckBox
        FixedCheckBox           matlab.ui.control.CheckBox
        SLBCheckBox             matlab.ui.control.CheckBox
        CFARCheckBox            matlab.ui.control.CheckBox
        RangeSpinner            matlab.ui.control.Spinner
        RangeSpinnerLabel       matlab.ui.control.Label
        DopplerSpinner          matlab.ui.control.Spinner
        DopplerSpinnerLabel     matlab.ui.control.Label
        DetectionsListBox       matlab.ui.control.ListBox
        DetectionsListBoxLabel  matlab.ui.control.Label
        TabGroup                matlab.ui.container.TabGroup
        RangeTab                matlab.ui.container.Tab
        RangeCells              matlab.ui.control.UIAxes
        DopplerTab              matlab.ui.container.Tab
        DopplerCells            matlab.ui.control.UIAxes
        CIPNumberSpinner        matlab.ui.control.Spinner
        CIPNumberSpinnerLabel   matlab.ui.control.Label
        FileEditField           matlab.ui.control.EditField
        FileEditFieldLabel      matlab.ui.control.Label
        SelectFileButton        matlab.ui.control.Button
        RangeDoppler            matlab.ui.control.UIAxes
    end

    
    properties (Access = public)
        myRadar; % mpdrRadar type
        myCip; % cip data cube
        myRadarIO;
        myRDMap;
        rawData;
        cipMetaData;
        scaling;
        dispChan
        startRange;
        endRange;
        fn;
        dir;
        plots;
        thresholds;
        realTimeVideo;
        useUDP;
        playing=false;
    end
    
    methods (Access = private)
                           
        function updateRangeDopplerDisplay(app)
            cipNum = app.CIPNumberSpinner.Value;
            if app.cipMetaData.cipNum ~= cipNum
                % jump to requested CIP process data and update displays.
                if(app.realTimeVideo)
                    frameTime=1/30*(cipNum);
                    app.myCip.loadCip([],frameTime);
                    app.myCip.setCipNum(cipNum);
                else
                    app.realTimeVideo=false;
                    app.cipMetaData=app.myCip.loadCip(cipNum);
                end
                app.rawData=app.myCip.getCipCube();
                app.myCip.correctDcBias();
                
                app.myCip.calibrate()
                app.myCip.compress();
                app.myCip.dopplerFilter();
                app.myCip.normalize();
                app.plots=app.myCip.threshold(app.dispChan);
                keepers = app.plots.range <= diff(app.myRDMap.mRange);
                if(isfield(app.plots,'amp_db'))
                    app.plots.amp_db = app.plots.amp_db(keepers);
                    app.plots.dAz_deg = app.plots.dAz_deg(keepers);
                    app.plots.fineRange = app.plots.fineRange(keepers);
                end 
                app.plots.doppler = app.plots.doppler(keepers);
                app.plots.range = app.plots.range(keepers);
            
                numPlots=length(app.plots.range);
                app.thresholds=app.myCip.getThresholds(app.dispChan); 
                
                [cipData,app.cipMetaData] = app.myCip.getMagSqCube();
                
                [~]=app.myRDMap.plot(app.RangeDoppler,cipData,app.cipMetaData,app.plots,app.realTimeVideo);
                
                app.DetectionsListBox.Items={' ',' ',' ',' '};
                %             app.DetectionsListBox.Value={1,2,3,4,5,6,7,8,9,10};
                if numPlots > 0
                    plotList{numPlots} = '';
                    app.DetectionsListBox.Items={' ',' ',' ',' '};
                    for ii=1:numPlots
                        plotList{ii}=sprintf('%3d: R:%7.1f m \tD:%7.1f m/s \tA:%5.1f dB \tri:%4d \tdi:%4d ',ii,...
                            (app.plots.range(ii)+app.plots.fineRange(ii))*app.cipMetaData.rangeCellSize_m(app.dispChan) ,...
                            app.cipMetaData.dopplerBins_mps(app.plots.doppler(ii)),...
                            app.plots.amp_db(ii),...
                            app.plots.range(ii),app.plots.doppler(ii));
                        
                    end
                    app.DetectionsListBox.Items=plotList;
                    app.DetectionsListBox.ItemsData=1:numPlots;
                    app.DetectionsListBox.Value=1;
                    app.plotRangeData(1);
                    app.plotDopplerData(1);
                else
                    app.plotRangeData(0);
                    app.plotDopplerData(0);
                end
                
            else
                [cipData,app.cipMetaData] = app.myCip.getMagSqCube();
                [~]=app.myRDMap.plot(app.RangeDoppler,cipData,app.cipMetaData,app.plots,app.realTimeVideo);
                value = app.DetectionsListBox.Value;
                app.plotRangeData(value);
                app.plotDopplerData(value);
            end
            drawnow
            
        end
        
        function plotRangeData(app,plotNum,varargin)
            if plotNum > length(app.plots.range)
                warning("plot number too large");
            end
            xUnits=(0:app.cipMetaData.cells.detEnd(app.dispChan)-...
                app.cipMetaData.cells.rangeZero(app.dispChan)).*...
                app.cipMetaData.rangeCellSize_m(app.dispChan);
            
            [cipData,app.cipMetaData] = app.myCip.getMagSqCube();
            dopplerBin=-1;
            if app.freezeCheckBox.Value
                dopplerBin=app.DopplerSpinner.Value;
                
            elseif plotNum > 0
                dopplerBin=app.plots.doppler(plotNum);
                app.DopplerSpinner.Value=app.plots.doppler(plotNum);
                
            elseif plotNum == -1 && nargin > 0
                dopplerBin=varargin{1};
                
            end
            if dopplerBin ~= -1
                plot(app.RangeCells,xUnits,10*log10(cipData(app.dispChan,...
                    app.cipMetaData.cells.rangeZero(app.dispChan):app.cipMetaData.cells.detEnd(app.dispChan),...
                    dopplerBin)),"Color","b");
                hold(app.RangeCells,"on");
                if app.CFARCheckBox.Value
                    plot(app.RangeCells,app.thresholds.ranges(:),10*log10(app.thresholds.cfar(:,dopplerBin)),"color","r","LineStyle",":");
                end
                if app.FixedCheckBox.Value
                    peakTh=10*log10(ones(size(app.thresholds.ranges))*app.thresholds.peakThreshold);
                    plot(app.RangeCells,app.thresholds.ranges(:),peakTh,"color","r","LineStyle","--");
                end
                if app.SLBCheckBox.Value
                    plot(app.RangeCells,app.thresholds.ranges(:),10*log10(app.thresholds.slb(:,dopplerBin)),"color",[0.3 0.4 0.6],"LineStyle","-.");
                end
                if ~isempty(app.plots.range)
                    targetsToPlot=find(app.plots.doppler==dopplerBin);
                    if ~isempty(targetsToPlot)
                        plot(app.RangeCells,(app.plots.range(targetsToPlot)*...
                            app.cipMetaData.rangeCellSize_m(app.dispChan)),...
                            app.plots.amp_db(targetsToPlot),'color','red',"Marker","s",...
                            "LineWidth",2,"MarkerSize",10,"LineStyle","none");
                    end
                end
                hold(app.RangeCells,"off");
            else
                cla(app.RangeCells);
            end
            if dopplerBin>0
                titleStr=sprintf('Range at %6.2f meters/sec (idx): %d',...
                    app.cipMetaData.dopplerBins_mps(dopplerBin),dopplerBin);
                title(app.RangeCells,titleStr)
            else
                title(app.RangeCells, 'Range')
            end
            ylim(app.RangeCells,[-20,50])
            xlim(app.RangeCells,[0,2000])
            xlabel(app.RangeCells,'Range (m)')
            ylabel(app.RangeCells,'dB')
        end

        %% plot the doppler data slice at the requested range or target
        function plotDopplerData(app,plotNum,varargin)
            rangeBin = [];
            if plotNum > length(app.plots.range)
                warning("plot number too large");
            end
            
            % generate the plots....
            [cipData,app.cipMetaData] = app.myCip.getMagSqCube();
            if app.freezeCheckBox.Value
                % operator froze the range bin...
                rangeBin=app.RangeSpinner.Value;
                plot(app.DopplerCells,app.cipMetaData.dopplerBins_mps,...
                    squeeze(10*log10(cipData(app.dispChan,...
                    rangeBin+...
                    app.cipMetaData.cells.rangeZero(app.dispChan),:))));
            elseif plotNum > 0
                % display of a plot...
                rangeBin=round(app.plots.range(plotNum));
                plot(app.DopplerCells,app.cipMetaData.dopplerBins_mps,...
                    squeeze(10*log10(cipData(app.dispChan,...
                    rangeBin + app.cipMetaData.cells.rangeZero(app.dispChan),:))));
                app.RangeSpinner.Value=app.plots.range(plotNum);
                
            elseif plotNum == -1 && nargin > 0
                % operator requested a particular range cell
                rangeBin=varargin{1};
                plot(app.DopplerCells,app.cipMetaData.dopplerBins_mps,...
                    squeeze(10*log10(cipData(app.dispChan,...
                    rangeBin+app.cipMetaData.cells.rangeZero(app.dispChan),:))));
            else
                % no plots are available for this video frame...
                cla(app.DopplerCells);
            end
            % add detections to display
            if ~isempty(app.plots.range)
                targetsToPlot=find(app.plots.range==rangeBin);
                if ~isempty(targetsToPlot)
                    hold(app.DopplerCells,"on");
                    plot(app.DopplerCells,...
                        app.cipMetaData.dopplerBins_mps(app.plots.doppler(targetsToPlot)),...
                        app.plots.amp_db(targetsToPlot),'color','red',"Marker","s",...
                        "LineWidth",2,"MarkerSize",10,"LineStyle","none");
                    hold(app.DopplerCells,"off");
                end
            end
            % add units and title to plot...
            ylim(app.DopplerCells,[-20,50])
            xlim(app.DopplerCells,[floor(app.cipMetaData.dopplerBins_mps(1)) ceil(app.cipMetaData.dopplerBins_mps(end))]);
            if ~isempty(rangeBin)
                titleStr=sprintf('Doppler at %6.2f meters (idx): %d',...
                    rangeBin* app.cipMetaData.rangeCellSize_m(app.dispChan),rangeBin);
                title(app.DopplerCells,titleStr)
            else
                title(app.DopplerCells, 'Doppler')
            end
            
            xlabel(app.DopplerCells,'RadialVelocity (m/s)')
        end

        function setDispChan(app, aUserSelection)
            if exist('aUserSelection','var') && ~isempty(aUserSelection)
                selection = aUserSelection;
            else
                selection = 1;
            end
            if selection == 2
                app.dispChan = uint32(radChan.sumLr);
                app.endRange=ceil(app.myRadar.configVals.LrMaxRange/app.cipMetaData.rangeCellSize_m(app.dispChan)+ ...
                        app.cipMetaData.cells.rangeZero(app.dispChan));
                app.scaling=app.myRadar.configVals.LrScaling;
            else
                app.dispChan = uint32(radChan.sumSr);
                app.endRange=ceil(app.myRadar.configVals.SrMaxRange/app.cipMetaData.rangeCellSize_m(app.dispChan)+ ...
                        app.cipMetaData.cells.rangeZero(app.dispChan));
                app.scaling=app.myRadar.configVals.SrScaling;
            end
        end
    end
    

    % Callbacks that handle component events
    methods (Access = private)

        % Code that executes after component creation
        function startupFcn(app, varargin)
            app.myRadar = mpdrRadar('Config/mpdr2PlusRadarConfig.yaml');
            app.useUDP=app.UDPCheckBox.Value;
            if nargin > 1
                aFile=varargin{1};
                if nargin > 2
                    aPath=varargin{2};
                else
                    aPath = pwd;
                end
                app.FileEditField.Value=aFile;

                app.fn=aFile;
                app.dir=aPath;
                app.myCip=cipCube.factory(app.myRadar, app.useUDP, aFile, aPath);

                app.cipMetaData = app.myCip.cipMetaData;

                app.setDispChan();
                app.startRange=app.cipMetaData.cells.rangeZero(app.dispChan);

                if (app.cipMetaData.wxMode)
                    app.ChanDropDown.set(2); % Set to long range
                end
                
                if app.ChanDropDown == 2
                    % process full range extent
                    %                     app.endRange=app.cipMetaData.cells.detEnd(app.dispChan);
                    app.endRange=ceil(app.myRadar.configVals.LrMaxRange/app.cipMetaData.rangeCellSize_m(app.dispChan)+ ...
                        app.cipMetaData.cells.rangeZero(app.dispChan));
                    app.scaling=pp.myRadar.configVals.LrScaling;
                else
                    % process only up to 2 km
                    app.endRange=ceil(app.myRadar.configVals.SrMaxRange/app.cipMetaData.rangeCellSize_m(app.dispChan)+ ...
                        app.cipMetaData.cells.rangeZero(app.dispChan));
                    app.scaling=app.myRadar.configVals.SrScaling;
                end

                app.myCip=cipCube.factory(app.myRadar);
                app.myRDMap=rangeDopplerMap(app.UIFigure,app.dispChan,app.cipMetaData,app.scaling,[app.startRange app.endRange]);
                value = app.fpsCheckBox.Value;
                app.realTimeVideo=value;
                app.updateRangeDopplerDisplay();
            end
            
        end

        % Button pushed function: SelectFileButton
        function SelectFileButtonPushed(app, event)
            app.useUDP=false;
            app.TextArea.Value='';
            [aFile, aPath]=uigetfile('*.dat*', ...
                'Select file to process');
            app.FileEditField.Value=aFile;
            %            set(app.RangeDoppler,'position',[0 0 500 800]);
            app.fn=aFile;
            app.dir=aPath;
            app.myCip=cipCube.factory(app.myRadar, app.useUDP, aFile, aPath);
            app.cipMetaData = app.myCip.cipMetaData;
            if (app.cipMetaData.wxMode)
                app.ChanDropDown.Value = 2; % Set to long range
            end
            app.setDispChan();
            app.startRange=app.cipMetaData.cells.rangeZero(app.dispChan);
            dispString = strcat(app.TextArea.Value{:},sprintf("Processing data record file: \n(\'%s\',\'%s\')\n", aFile,aPath));
            app.cipMetaData.priPerVideoFrame = floor(app.cipMetaData.videoFrameTime/app.cipMetaData.priTime_s);
            videoCips=floor(app.cipMetaData.fileSizePris/251); % todo calculate the magic number...            
            dispString = strcat(dispString,sprintf("file contains %d %1d-pulse cips (%d video cips), %1.1f sec\n", ...
                app.cipMetaData.fileSizeCips,app.cipMetaData.numPris,videoCips, ...
                app.cipMetaData.priTime_s * app.cipMetaData.fileSizePris));
            app.TextArea.Value = dispString;
            app.Slider.Limits=[0 app.cipMetaData.fileSizeCips-1];
            app.CIPNumberSpinner.Limits=[0 app.cipMetaData.fileSizeCips-1];
            app.myRDMap=rangeDopplerMap(app.UIFigure,app.dispChan,app.cipMetaData,app.scaling,[app.startRange app.endRange]);
            app.updateRangeDopplerDisplay();
            app.PlayPauseButton.Enable="on";
        end

        % Value changed function: CIPNumberSpinner
        function CIPNumberSpinnerValueChanged(app, event)
            app.Slider.Value=app.CIPNumberSpinner.Value;
            app.updateRangeDopplerDisplay();
        end

        % Value changed function: DetectionsListBox
        function DetectionsListBoxValueChanged(app, event)
            value = app.DetectionsListBox.Value;
            app.freezeCheckBox.Value=false;
            app.RangeSpinner.Value=app.plots.range(value);
            app.DopplerSpinner.Value=app.plots.doppler(value);
            app.updateRangeDopplerDisplay();
        end

        % Value changed function: RangeSpinner
        function RangeSpinnerValueChanged(app, event)
            value = app.RangeSpinner.Value;
            app.TabGroup.SelectedTab=app.TabGroup.Children(2,1);
            app.plotDopplerData(-1,value);
        end

        % Value changed function: DopplerSpinner
        function DopplerSpinnerValueChanged(app, event)
            value = app.DopplerSpinner.Value;
            app.TabGroup.SelectedTab=app.TabGroup.Children(1,1);
            app.plotRangeData(-1,value);
        end

        % Value changed function: CFARCheckBox
        function CFARCheckBoxValueChanged(app, event)
            value = app.DopplerSpinner.Value;
            app.plotRangeData(-1,value);
        end

        % Value changed function: SLBCheckBox
        function SLBCheckBoxValueChanged(app, event)
            value = app.DopplerSpinner.Value;
            app.plotRangeData(-1,value);
        end

        % Value changed function: FixedCheckBox
        function FixedCheckBoxValueChanged(app, event)
            value = app.DopplerSpinner.Value;
            app.plotRangeData(-1,value);
        end

        % Value changed function: fpsCheckBox
        function fpsCheckBoxValueChanged(app, event)
            value = app.fpsCheckBox.Value;
            app.realTimeVideo=value;
            if ~isempty(app.myCip) % Reset cipNum and cipTime_s to zero if this box is toggled with a file loaded
                app.CIPNumberSpinner.Value=0;
                app.updateRangeDopplerDisplay();
            end
        end

        % Button pushed function: SaveButton
        function SaveButtonPushed(app, event)
            lmyRadar = app.myRadar;
            lmyCip = app.myCip;
            lrawData = app.rawData;
%             lmyRDMap = app.myRDMap;
            lcipMetaData = app.cipMetaData;
            lscaling = app.scaling;
            ldispChan = app.dispChan;
            lstartRange = app.startRange;
            lendRange = app.endRange;
            
            save('videoView.mat','lmyRadar','lmyCip',...
                'lcipMetaData','lrawData',...
                'lscaling','ldispChan','lstartRange',...
                'lendRange','-mat');
        end

        % Value changed function: ChanDropDown
        function ChanDropDownValueChanged(app, event)
            app.setDispChan(app.ChanDropDown.Value)
            app.myRDMap=rangeDopplerMap(app.UIFigure,app.dispChan,app.cipMetaData,app.scaling,[app.startRange app.endRange]);
            app.updateRangeDopplerDisplay();
        end

        % Value changed function: UDPCheckBox
        function UDPCheckBoxValueChanged(app, event)
            value = app.UDPCheckBox.Value;
            
        end

        % Value changed function: Slider
        function SliderValueChanged(app, event)
            value = round(app.Slider.Value);
            app.Slider.Value=value;
            app.CIPNumberSpinner.Value = value;
            app.updateRangeDopplerDisplay();
        end

        % Value changing function: Slider
        function SliderValueChanging(app, event)
            changingValue = event.Value;
            
        end

        % Button pushed function: PlayPauseButton
        function PlayPauseButtonPushed(app, event)
            if app.playing
                app.playing = false;
            else
                app.playing = true;
                app.StopButton.Enable="on";
                while app.cipMetaData.cipNum < app.CIPNumberSpinner.Limits(2) && app.playing
                    app.CIPNumberSpinner.Value=app.CIPNumberSpinner.Value + 1;
                    app.Slider.Value=app.CIPNumberSpinner.Value;
                    app.updateRangeDopplerDisplay();
                end
            end
        end

        % Button pushed function: StopButton
        function StopButtonPushed(app, event)
            if app.playing
                app.playing = false;
                app.CIPNumberSpinner.Value=0;
                app.updateRangeDopplerDisplay();
                app.StopButton.Enable="off";
            end
        end
    end

    % Component initialization
    methods (Access = private)

        % Create UIFigure and components
        function createComponents(app)

            % Get the file path for locating images
            pathToMLAPP = fileparts(mfilename('fullpath'));

            % Create UIFigure and hide until all components are created
            app.UIFigure = uifigure('Visible', 'off');
            app.UIFigure.Position = [100 100 1661 994];
            app.UIFigure.Name = 'MATLAB App';

            % Create RangeDoppler
            app.RangeDoppler = uiaxes(app.UIFigure);
            title(app.RangeDoppler, 'Range / Doppler Map')
            xlabel(app.RangeDoppler, 'mps')
            ylabel(app.RangeDoppler, 'meters')
            app.RangeDoppler.XTickLabelRotation = 0;
            app.RangeDoppler.YTickLabelRotation = 0;
            app.RangeDoppler.ZTickLabelRotation = 0;
            app.RangeDoppler.Interruptible = 'off';
            app.RangeDoppler.Position = [26 114 596 863];

            % Create SelectFileButton
            app.SelectFileButton = uibutton(app.UIFigure, 'push');
            app.SelectFileButton.ButtonPushedFcn = createCallbackFcn(app, @SelectFileButtonPushed, true);
            app.SelectFileButton.Position = [640 955 100 22];
            app.SelectFileButton.Text = 'Select File';

            % Create FileEditFieldLabel
            app.FileEditFieldLabel = uilabel(app.UIFigure);
            app.FileEditFieldLabel.HorizontalAlignment = 'right';
            app.FileEditFieldLabel.Position = [774 955 28 22];
            app.FileEditFieldLabel.Text = 'File:';

            % Create FileEditField
            app.FileEditField = uieditfield(app.UIFigure, 'text');
            app.FileEditField.Position = [812 955 359 22];

            % Create CIPNumberSpinnerLabel
            app.CIPNumberSpinnerLabel = uilabel(app.UIFigure);
            app.CIPNumberSpinnerLabel.HorizontalAlignment = 'right';
            app.CIPNumberSpinnerLabel.Position = [640 917 72 22];
            app.CIPNumberSpinnerLabel.Text = 'CIP Number';

            % Create CIPNumberSpinner
            app.CIPNumberSpinner = uispinner(app.UIFigure);
            app.CIPNumberSpinner.Limits = [0 9999];
            app.CIPNumberSpinner.RoundFractionalValues = 'on';
            app.CIPNumberSpinner.ValueChangedFcn = createCallbackFcn(app, @CIPNumberSpinnerValueChanged, true);
            app.CIPNumberSpinner.Position = [727 917 100 22];

            % Create TabGroup
            app.TabGroup = uitabgroup(app.UIFigure);
            app.TabGroup.Position = [642 155 951 473];

            % Create RangeTab
            app.RangeTab = uitab(app.TabGroup);
            app.RangeTab.Title = 'Range';

            % Create RangeCells
            app.RangeCells = uiaxes(app.RangeTab);
            title(app.RangeCells, 'Range Cells')
            xlabel(app.RangeCells, 'X')
            ylabel(app.RangeCells, 'Y')
            app.RangeCells.PlotBoxAspectRatio = [2.41823056300268 1 1];
            app.RangeCells.XTickLabelRotation = 0;
            app.RangeCells.YTickLabelRotation = 0;
            app.RangeCells.ZTickLabelRotation = 0;
            app.RangeCells.XGrid = 'on';
            app.RangeCells.YGrid = 'on';
            app.RangeCells.Position = [1 10 949 428];

            % Create DopplerTab
            app.DopplerTab = uitab(app.TabGroup);
            app.DopplerTab.Title = 'Doppler';

            % Create DopplerCells
            app.DopplerCells = uiaxes(app.DopplerTab);
            title(app.DopplerCells, 'Doppler Cells')
            xlabel(app.DopplerCells, 'X')
            ylabel(app.DopplerCells, 'Y')
            app.DopplerCells.PlotBoxAspectRatio = [2.41978609625668 1 1];
            app.DopplerCells.XTickLabelRotation = 0;
            app.DopplerCells.YTickLabelRotation = 0;
            app.DopplerCells.ZTickLabelRotation = 0;
            app.DopplerCells.XGrid = 'on';
            app.DopplerCells.YGrid = 'on';
            app.DopplerCells.Position = [-2 9 952 429];

            % Create DetectionsListBoxLabel
            app.DetectionsListBoxLabel = uilabel(app.UIFigure);
            app.DetectionsListBoxLabel.HorizontalAlignment = 'right';
            app.DetectionsListBoxLabel.Position = [640 774 62 22];
            app.DetectionsListBoxLabel.Text = 'Detections';

            % Create DetectionsListBox
            app.DetectionsListBox = uilistbox(app.UIFigure);
            app.DetectionsListBox.ValueChangedFcn = createCallbackFcn(app, @DetectionsListBoxValueChanged, true);
            app.DetectionsListBox.Position = [717 638 392 160];

            % Create DopplerSpinnerLabel
            app.DopplerSpinnerLabel = uilabel(app.UIFigure);
            app.DopplerSpinnerLabel.HorizontalAlignment = 'right';
            app.DopplerSpinnerLabel.Position = [1126 638 48 22];
            app.DopplerSpinnerLabel.Text = 'Doppler';

            % Create DopplerSpinner
            app.DopplerSpinner = uispinner(app.UIFigure);
            app.DopplerSpinner.Limits = [0 160];
            app.DopplerSpinner.ValueDisplayFormat = '%4d';
            app.DopplerSpinner.ValueChangedFcn = createCallbackFcn(app, @DopplerSpinnerValueChanged, true);
            app.DopplerSpinner.Position = [1189 638 100 22];

            % Create RangeSpinnerLabel
            app.RangeSpinnerLabel = uilabel(app.UIFigure);
            app.RangeSpinnerLabel.HorizontalAlignment = 'right';
            app.RangeSpinnerLabel.Position = [1133 678 41 22];
            app.RangeSpinnerLabel.Text = 'Range';

            % Create RangeSpinner
            app.RangeSpinner = uispinner(app.UIFigure);
            app.RangeSpinner.Limits = [0 2000];
            app.RangeSpinner.ValueDisplayFormat = '%4d';
            app.RangeSpinner.ValueChangedFcn = createCallbackFcn(app, @RangeSpinnerValueChanged, true);
            app.RangeSpinner.Position = [1189 678 100 22];

            % Create CFARCheckBox
            app.CFARCheckBox = uicheckbox(app.UIFigure);
            app.CFARCheckBox.ValueChangedFcn = createCallbackFcn(app, @CFARCheckBoxValueChanged, true);
            app.CFARCheckBox.Text = 'CFAR';
            app.CFARCheckBox.Position = [1483 680 54 22];

            % Create SLBCheckBox
            app.SLBCheckBox = uicheckbox(app.UIFigure);
            app.SLBCheckBox.ValueChangedFcn = createCallbackFcn(app, @SLBCheckBoxValueChanged, true);
            app.SLBCheckBox.Text = 'SLB';
            app.SLBCheckBox.Position = [1484 657 45 22];

            % Create FixedCheckBox
            app.FixedCheckBox = uicheckbox(app.UIFigure);
            app.FixedCheckBox.ValueChangedFcn = createCallbackFcn(app, @FixedCheckBoxValueChanged, true);
            app.FixedCheckBox.Text = 'Fixed';
            app.FixedCheckBox.Position = [1484 636 51 22];

            % Create freezeCheckBox
            app.freezeCheckBox = uicheckbox(app.UIFigure);
            app.freezeCheckBox.Text = 'freeze';
            app.freezeCheckBox.Position = [1190 657 55 22];

            % Create fpsCheckBox
            app.fpsCheckBox = uicheckbox(app.UIFigure);
            app.fpsCheckBox.ValueChangedFcn = createCallbackFcn(app, @fpsCheckBoxValueChanged, true);
            app.fpsCheckBox.Text = '30 fps';
            app.fpsCheckBox.Position = [1203 955 55 22];

            % Create SaveButton
            app.SaveButton = uibutton(app.UIFigure, 'push');
            app.SaveButton.ButtonPushedFcn = createCallbackFcn(app, @SaveButtonPushed, true);
            app.SaveButton.Position = [643 114 100 22];
            app.SaveButton.Text = 'Save';

            % Create ChanDropDownLabel
            app.ChanDropDownLabel = uilabel(app.UIFigure);
            app.ChanDropDownLabel.HorizontalAlignment = 'right';
            app.ChanDropDownLabel.Position = [897 917 34 22];
            app.ChanDropDownLabel.Text = 'Chan';

            % Create ChanDropDown
            app.ChanDropDown = uidropdown(app.UIFigure);
            app.ChanDropDown.Items = {'SR', 'LR'};
            app.ChanDropDown.ItemsData = [1 2];
            app.ChanDropDown.ValueChangedFcn = createCallbackFcn(app, @ChanDropDownValueChanged, true);
            app.ChanDropDown.Tooltip = {'Channel type to display'};
            app.ChanDropDown.Position = [946 917 100 22];
            app.ChanDropDown.Value = 1;

            % Create UDPCheckBox
            app.UDPCheckBox = uicheckbox(app.UIFigure);
            app.UDPCheckBox.ValueChangedFcn = createCallbackFcn(app, @UDPCheckBoxValueChanged, true);
            app.UDPCheckBox.Enable = 'off';
            app.UDPCheckBox.Visible = 'off';
            app.UDPCheckBox.Text = 'UDP';
            app.UDPCheckBox.Position = [1324 955 47 22];

            % Create Panel
            app.Panel = uipanel(app.UIFigure);
            app.Panel.Title = 'Panel';
            app.Panel.Position = [-347 1112 2 2];

            % Create TextArea
            app.TextArea = uitextarea(app.UIFigure);
            app.TextArea.Position = [714 811 879 87];

            % Create PlayPauseButton
            app.PlayPauseButton = uibutton(app.UIFigure, 'push');
            app.PlayPauseButton.ButtonPushedFcn = createCallbackFcn(app, @PlayPauseButtonPushed, true);
            app.PlayPauseButton.Enable = 'off';
            app.PlayPauseButton.Position = [352 21 117 56];
            app.PlayPauseButton.Text = 'Play/Pause';
            app.PlayPauseButton.Icon = fullfile(pathToMLAPP, '10419335.png');

            % Create StopButton
            app.StopButton = uibutton(app.UIFigure, 'push');
            app.StopButton.ButtonPushedFcn = createCallbackFcn(app, @StopButtonPushed, true);
            app.StopButton.Enable = 'off';
            app.StopButton.Position = [227 21 90 55];
            app.StopButton.Text = 'Stop';
            app.StopButton.Icon = fullfile(pathToMLAPP, '10054710.png');

            % Create Label
            app.Label = uilabel(app.UIFigure);
            app.Label.HorizontalAlignment = 'right';
            app.Label.FontColor = [0.149 0.149 0.149];
            app.Label.Position = [70 92 25 22];
            app.Label.Text = '';

            % Create Slider
            app.Slider = uislider(app.UIFigure);
            app.Slider.MajorTicks = [];
            app.Slider.MajorTickLabels = {''};
            app.Slider.ValueChangedFcn = createCallbackFcn(app, @SliderValueChanged, true);
            app.Slider.ValueChangingFcn = createCallbackFcn(app, @SliderValueChanging, true);
            app.Slider.MinorTicks = [];
            app.Slider.FontColor = [0.149 0.149 0.149];
            app.Slider.Position = [59 101 553 7];

            % Show the figure after all components are created
            app.UIFigure.Visible = 'on';
        end
    end

    % App creation and deletion
    methods (Access = public)

        % Construct app
        function app = videoView(varargin)

            % Create UIFigure and components
            createComponents(app)

            % Register the app with App Designer
            registerApp(app, app.UIFigure)

            % Execute the startup function
            runStartupFcn(app, @(app)startupFcn(app, varargin{:}))

            if nargout == 0
                clear app
            end
        end

        % Code that executes before app deletion
        function delete(app)

            % Delete UIFigure when app is deleted
            delete(app.UIFigure)
        end
    end
end
