 classdef ImagingDataSet < handle
    properties (SetObservable)
        Data ImagingData
    end
    properties (SetAccess = private, SetObservable)
        FilePath string
        FileName string
		Cells
    end
    properties (Dependent)
		MeasurementDate string
		SamplingFrequency double
		SWActiveCellRatio double
		PhaseLock double
    end
    properties (Transient, SetObservable)
    end
    
    methods
        % Set methods
        
        % Get methods
		function value = get.MeasurementDate(this)
			if ~isempty(this.Data)
				value = string(cellfun(@(x) x.MeasurementDate, {this.Data.MesMetadata}, 'UniformOutput', false)');
			end
		end

		function value = get.PhaseLock(this)
			if ~isempty(this.Data)
				timefromstart = nan(length(this.Data), 1);
				plvgMean = nan(length(this.Data), 1);
				plvgSem = nan(length(this.Data), 1);
				plvnMean = nan(length(this.Data), 1);
				plvnSem = nan(length(this.Data), 1);
				plvgnMean = nan(length(this.Data), 1);
				plvgnSem = nan(length(this.Data), 1);
				measurementstart = datetime(this.Data(1).MesMetadata(1).MeasurementDate, 'InputFormat', 'yyyy.MM.dd. HH:mm:ss,SSS');
				for i = 1:length(this.Data)
					measurementtime = datetime(this.Data(i).MesMetadata(1).MeasurementDate, 'InputFormat', 'yyyy.MM.dd. HH:mm:ss,SSS');
					timefromstart(i) = minutes(measurementtime - measurementstart);

					plvg = this.Data(i).PhaseLock(this.Data(i).Glia, this.Data(i).Glia);
					plvg = tril(plvg);
					plvg = plvg(plvg>0);
					plvgMean(i) = mean(plvg(:));
					plvgSem(i) = std(plvg(:))/sqrt(length(plvg(:)));

					plvn = this.Data(i).PhaseLock(this.Data(i).Neuron, this.Data(i).Neuron);
					plvn = tril(plvn);
					plvn = plvn(plvn>0);
					plvnMean(i) = mean(plvn(:));
					plvnSem(i) = std(plvn(:))/sqrt(length(plvn(:))); 

					plvgn = this.Data(i).PhaseLock(this.Data(i).Glia, this.Data(i).Neuron);
					plvgn = tril(plvgn);
					plvgn = plvgn(plvgn>0);
					plvgnMean(i) = mean(plvgn(:));
					plvgnSem(i) = std(plvgn(:))/sqrt(length(plvgn(:))); 
				end
				value = table(timefromstart, plvgMean, plvgSem, plvnMean, plvnSem, plvgnMean, plvgnSem);
			end
		end

		function value = get.SamplingFrequency(this)
			if ~isempty(this.Data)
				value = [this.Data.SamplingFrequency]';
			end
		end

		function value = get.SWActiveCellRatio(this)
			if ~isempty(this.Data) && ~isempty([this.Data.SWAanalytics])
				timefromstart = nan(length(this.Data), 1);
				activecellratio = nan(length(this.Data), 1);
				activecellratioNeuron = nan(length(this.Data), 1);
				activecellratioGlia = nan(length(this.Data), 1);
				averageMaxCfs = nan(length(this.Data), 1);
				averageMaxCfsNeuron = nan(length(this.Data), 1);
				averageMaxCfsGlia = nan(length(this.Data), 1);
				measurementstart = datetime(this.Data(1).MesMetadata(1).MeasurementDate, 'InputFormat', 'yyyy.MM.dd. HH:mm:ss,SSS');
				for i = 1:length(this.Data)
					measurementtime = datetime(this.Data(i).MesMetadata(1).MeasurementDate, 'InputFormat', 'yyyy.MM.dd. HH:mm:ss,SSS');
					timefromstart(i) = minutes(measurementtime - measurementstart);
					
					activecellratio(i) = sum(this.Data(i).SWAanalytics.activecellsMaxMinRatio) / length(this.Data(i).SWAanalytics.activecellsMaxMinRatio) * 100;
					activecellratioNeuron(i) = sum(this.Data(i).SWAanalytics.activecellsMaxMinRatio(this.Data(i).Neuron)) / length(this.Data(i).SWAanalytics.activecellsMaxMinRatio(this.Data(i).Neuron)) * 100;
					activecellratioGlia(i) = sum(this.Data(i).SWAanalytics.activecellsMaxMinRatio(this.Data(i).Glia)) / length(this.Data(i).SWAanalytics.activecellsMaxMinRatio(this.Data(i).Glia)) * 100;
					averageMaxCfs(i) = mean(this.Data(i).SWAanalytics.maxcfs);
					averageMaxCfsNeuron(i) = mean(this.Data(i).SWAanalytics.maxcfs(this.Data(i).Neuron));
					averageMaxCfsGlia(i) = mean(this.Data(i).SWAanalytics.maxcfs(this.Data(i).Glia));
				end
				value = table(timefromstart, activecellratio, activecellratioNeuron, activecellratioGlia, averageMaxCfs, averageMaxCfsNeuron, averageMaxCfsGlia);
			end
		end
        
        % Simple methods
		function autoClassifyCells(this)
            if ~isempty(this.Data)
				for iFile = 1:size(this.Data, 1)
					disp(this.Data(iFile).MesImageIndex);
					this.Data(iFile).autoClassifyCells;
				end
            end
		end
		
		function calculateCellCoordinates(this)
			if ~isempty(this.Data)
				for iFile = 1:size(this.Data, 1)
					this.Data(iFile).calculateCellCoordinates;
				end
			end
		end
		
		function calculateCrossCorrelation(this)
			if ~isempty(this.Data)
				for iFile = 1:size(this.Data, 1)
					disp(this.Data(iFile).MesImageIndex);
					this.Data(iFile).calculateCrossCorrelation;
				end
			end
		end
		
		function calculatePhaseLock(this, frequencyRange)
			if ~isempty(this.Data)
				for iFile = 1:size(this.Data, 1)
					disp(this.Data(iFile).MesImageIndex);
					this.Data(iFile).calculatePhaselock(frequencyRange);
				end
			end
		end
		
		function calculateSWAanalytics(this)
			if ~isempty(this.Data)
				for iFile = 1:size(this.Data, 1)
					disp(this.Data(iFile).MesImageIndex);
					this.Data(iFile).calculateSWAanalytics;
				end
			end
		end
		
		function exportCells2DB(this)
            if ~isempty(this.Data)
				for iFile = 1:size(this.Data, 1)
					disp(this.Data(iFile).MesImageIndex);
					this.Data(iFile).exportCells2DB;
				end
            end
		end
		
		function importCellAnnotation(this)
            if ~isempty(this.Data)
				for iFile = 1:size(this.Data, 1)
					disp(this.Data(iFile).MesImageIndex);
					this.Data(iFile).importCellAnnotation;
				end
            end
		end
                
		function reportCellData(this)
            if ~isempty(this.Data)
				for iFile = 1:size(this.Data, 1)
					disp(this.Data(iFile).MesImageIndex);
					this.Data(iFile).reportCellData;
				end
            end
		end
				
        function showRefImages(this)
            if ~isempty(this.Data)
				figure;
                montage(cat(4, this.Data.RefImage));
                spaceplots;
            end
        end

		function showRegisteredCell(this, cellnum) 
            if ~isempty(this.Cells)
				refs = cell(size(this.Cells, 2), 1);
				cells = cell(size(this.Cells, 2), 1);
				topleftX = 0;
				topleftY = 0;
				boxSize = 50;
				for iFile = 1:size(this.Cells, 2)
					if this.Cells(cellnum, iFile) > 0
						cellCoordinates = this.Data(iFile).CellCoordinates(this.Cells(cellnum, iFile),:);
						topleftX = round(cellCoordinates.centerX - boxSize / 2);
						topleftY = round((512 - cellCoordinates.centerY) - boxSize / 2);
						refs{iFile} = imoverlay(this.Data(iFile).RefImage, this.Data(iFile).ROIs2D == this.Cells(cellnum, iFile));
						cells{iFile} = imcrop(imoverlay(this.Data(iFile).RefImage, bwperim(this.Data(iFile).ROIs2D == this.Cells(cellnum, iFile))), [topleftX, topleftY, boxSize, boxSize]);
					elseif topleftX > 0 || topleftY > 0
						cells{iFile} = imcrop(this.Data(iFile).RefImage, [topleftX, topleftY, boxSize, boxSize]);
					end
				end
				figure;
                montage(refs);
                spaceplots;
				figure;
                montage(cells);
                spaceplots;
            end
        end

		% Complex methods
        alignCells(this)
        loadDataFromFolder(this, folderpath)
		reportFrequencyDistribution(this)
		reportWavelets(this)
		registerCells(this, newFieldStarts)
    end
end 