classdef uasCipCube < cipCube
    %uasCipCube -- simplified cipCube focused on UAS Processing Only.
    %
    
    properties
        null;
        cfarFilter;
        cfarOffset;
        peakThreshold;
        slbMult;
        slb;
        bgCfarEst;
        azAngles_deg;
        azMpRatio;
    end
    
    methods
        %% Constructor for the Uas Cip Cube
        function obj = uasCipCube(myRadar)
            %uasCipCube Construct an instance of this class
            obj=obj@cipCube(myRadar);
%             obj.LrChans=[uint32(radChan.sumLr),uint32(radChan.auxLr)];
%             obj.SrChans=[uint32(radChan.sumSr),uint32(radChan.auxSr)];
            
            obj.LrChans=radChan.getLrChans;
            obj.SrChans=radChan.getSrChans;
            
            threshold=10^(obj.myRadar.configVals.cfarThreshold_dB/10);
            obj.cfarFilter = [ones(1,obj.myRadar.configVals.cfarWindowSize) ...
                zeros(1,2*obj.myRadar.configVals.cfarGuardCells+1) ...
                ones(1,obj.myRadar.configVals.cfarWindowSize)]*threshold/...
                (obj.myRadar.configVals.cfarWindowSize*2);
            obj.cfarOffset=myRadar.configVals.cfarWindowSize+myRadar.configVals.cfarGuardCells;
            obj.peakThreshold=10^(obj.myRadar.configVals.peakThreshold_dB/10);  % convert from dB to linear.
            obj.slbMult=10^(obj.myRadar.configVals.slbMultiplier_dB/10);
            lMpTable=yaml.loadFile("Mpdr/mpTable.yaml","ConvertToArray", true);
            obj.azAngles_deg = lMpTable.Lookup.elAngles_d;
            obj.azMpRatio = lMpTable.Lookup.elmpRatio;
            
        end
        %% myTest function -- to demonstrate inheratence and polymorphism... TODO delete.
        function myTest(obj) %#ok<MANU>
            fprintf("uas cube\n");
        end
        %% threshold -- function to find a few targets in the many range cells
        function returnVal = threshold(obj,aChan)
            % sumLr=radChan.sumLr;
            if aChan==radChan.sumSr
                detChan=uint32(radChan.sumSr);
                detAux=uint32(radChan.auxSr);
                detDAz=uint32(radChan.dAzSr);
            else
                detChan=uint32(radChan.sumLr);
                detAux=uint32(radChan.auxLr);
                detDAz=uint32(radChan.dAzLr);
            end
            if ~obj.magSqValid
                obj.magSquared();
            end
            
            magSq = squeeze(obj.magSqCube(detChan,:,obj.dopplerCells));
            obj.slb = squeeze(obj.magSqCube(detAux,:,obj.dopplerCells))*obj.slbMult;
            dazMagSq =  squeeze(obj.magSqCube(detDAz,:,obj.dopplerCells));
            
            obj.bgCfarEst=filter(obj.cfarFilter,1,magSq,[],1);
            
            % find threshold crossings
            exTh=(magSq(obj.cipMetaData.cells.detStart(detChan):obj.cipMetaData.cells.detEnd(detChan),:)>obj.peakThreshold);
            % cfar threshold
            cfarTh=(magSq(obj.cipMetaData.cells.detStart(detChan):obj.cipMetaData.cells.detEnd(detChan),:)>...
                obj.bgCfarEst(obj.cipMetaData.cells.detStart(detChan)+obj.cfarOffset:...
                obj.cipMetaData.cells.detEnd(detChan)+obj.cfarOffset,:));
            
            % slb threshold
            slbTh=(magSq(obj.cipMetaData.cells.detStart(detChan):obj.cipMetaData.cells.detEnd(detChan),:)>...
                 obj.slb(obj.cipMetaData.cells.detStart(detChan):obj.cipMetaData.cells.detEnd(detChan),:));
             
             % delta az threshold
            dazTh=(magSq(obj.cipMetaData.cells.detStart(detChan):obj.cipMetaData.cells.detEnd(detChan),:)>...
                dazMagSq(obj.cipMetaData.cells.detStart(detChan):obj.cipMetaData.cells.detEnd(detChan),:));
            
            % find range peaks...
            %             rPk=(islocalmax(magSq(obj.cipMetaData.cells.detStart(detChan):...
            %                 obj.cipMetaData.cells.detEnd(detChan),:),1,'MinSeparation',32));
            rPk=(islocalmax(magSq(obj.cipMetaData.cells.detStart(detChan):...
                obj.cipMetaData.cells.detEnd(detChan),:),1));
            % find doppler peaks..
            dPk=(islocalmax(magSq(obj.cipMetaData.cells.detStart(detChan):...
                obj.cipMetaData.cells.detEnd(detChan),:),2));
            % find peaks in both range and doppler...
            
            plots=find((exTh & cfarTh & slbTh & dazTh & rPk & dPk));
            [range,doppler]=ind2sub(size(magSq(obj.cipMetaData.cells.detStart(detChan):...
                obj.cipMetaData.cells.detEnd(detChan),:)),plots);
            plot.range=range+obj.cipMetaData.cells.detStart(detChan)-obj.cipMetaData.cells.rangeZero(detChan)-1;
            plot.fineRange=zeros(1,length(plot.range));
            plot.doppler=obj.dopplerCells(doppler);
            plot.amp_db=zeros(1,length(plot.range));
            plot.dAz_deg=zeros(1,length(plot.range));
            plot.mpDazRatio=zeros(1,length(plot.range));
            dataCubeDopplerInds=doppler + obj.myRadar.numClutterCells*double(doppler >= min(obj.myRadar.clutterCells));
            for ii=1:size(plot.range)
                %fprintf("cip:%d range:%d, doppler:%d\n",obj.cipMetaData.cipNum,plot.range(ii),plot.doppler(ii));
                plot.amp_db(ii)=10*log10(magSq(plot.range(ii)+obj.cipMetaData.cells.rangeZero(detChan),doppler(ii)));
                mpDazRatio=imag(obj.dataCube(detDAz,plot.range(ii)+obj.cipMetaData.cells.rangeZero(detChan),dataCubeDopplerInds(ii))/...
                    obj.dataCube(detChan,plot.range(ii)+obj.cipMetaData.cells.rangeZero(detChan),dataCubeDopplerInds(ii)));
                [~,mpIndex]=min(abs(obj.azMpRatio-mpDazRatio));
                plot.dAz_deg(ii) = obj.azMpRatio(mpIndex);
                % do fine range estimate... ala Woody's code
                range=plot.range(ii)+obj.cipMetaData.cells.rangeZero(detChan);
                corrData = magSq((range-1:range+1),doppler(ii));
                maxOffset = (corrData(3) - corrData(1))/(2*(2*corrData(2) - corrData(3) - corrData(1)));
                plot.fineRange(ii)=maxOffset;
            end
            returnVal=plot;
        end
        function [sumPsd,nBurst] = sumMagnitudeRadial(obj,dispChan,sumPsd,nBurst)
            if (nBurst == 0)
                sumPsd = abs(squeeze(obj.dataCube(dispChan,1:size(sumPsd,1),:)));
            else
                sumPsd = sumPsd + abs(squeeze(obj.dataCube(dispChan,1:size(sumPsd,1),:)));
            end
            nBurst = nBurst + 1;
        end
        function [sumPsd,nBurst] = sumPowerRadial(obj,dispChan,sumPsd,nBurst)
            if (nBurst == 0) 
                sumPsd = abs(squeeze(obj.dataCube(dispChan,1:size(sumPsd,1),:))).^2;
            else
                sumPsd = sumPsd + abs(squeeze(obj.dataCube(dispChan,1:size(sumPsd,1),:))).^2;
            end
            nBurst = nBurst + 1;
        end
		%% get the calculated thresholds for the current CIP... must be called after executing threshold function for the CIP.
        function thresholds=getThresholds(obj,detChan)
            
            thresholds.peakThreshold=obj.peakThreshold;
            %need to expand the number of doppler cells to include the zero
            %doppler cells that are not thresholded...
            thresholds.cfar=zeros(obj.cipMetaData.cells.detEnd(detChan)-obj.cipMetaData.cells.detStart(detChan)+1,obj.cipMetaData.numPris);
            thresholds.cfar(:,obj.dopplerCells)=obj.bgCfarEst(obj.cipMetaData.cells.detStart(detChan)+obj.cfarOffset:...
                obj.cipMetaData.cells.detEnd(detChan)+obj.cfarOffset,:);
            thresholds.slb=zeros(obj.cipMetaData.cells.detEnd(detChan)-obj.cipMetaData.cells.detStart(detChan)+1,obj.cipMetaData.numPris);
            thresholds.slb(:,obj.dopplerCells)=obj.slb(obj.cipMetaData.cells.detStart(detChan):...
                obj.cipMetaData.cells.detEnd(detChan),:);
            thresholds.ranges=(obj.cipMetaData.cells.detStart(detChan)-obj.cipMetaData.cells.rangeZero(detChan):...
                obj.cipMetaData.cells.detEnd(detChan)-obj.cipMetaData.cells.rangeZero(detChan))*obj.cipMetaData.rangeCellSize_m(detChan);
        end
    end
end

