classdef classMapSet < handle
    %> classMapSet (derived from handle) defines a class for two dimensional RIXS maps 
    %> this class serves the purpose to handle and convert the RIXSmap created by the CreateResonantSpectra() function in QUANTY.
    %> Properties of this class are public (direct RW access)

    %> @file classMapSet.m
    %> @author Patric Zimmermann, 04/2016, Utrecht University
 
    % ------------------------------------------------------------------------------------------------------   
    properties   % (GetAccess = 'public', SetAccess = 'private')         % public read access, but private write access.   
        %> info string, generic use
        info         = '';
        baseName     = '';
        mapFolder    = '';

        %> offsetX,offsetY (default: 0.0) can be used to correct energy callaibration of for any shift of the spectrum.
        offsetIn  = 0.0;
        offsetOut = 0.0;   
        %> variable for X values (e.g. Incident / XAS energy)
        energyIn  = [];
        %> variable for Y values (e.g. Emission energy / energy transfer) 
        energyOut = [];    
        %> variable for lcp RIXS map  
        lcpMap    = [];
        %> variable for rcp RIXS map  
        rcpMap    = [];
        %> variable for sum RIXS map  
        sumMap    = [];
        %> variable for mcd RIXS map  
        mcdMap    = [];       
        
        % cell array with the maps    will become a struct:   mapData{1}.mapRe   or mapData{2}.mapIm
        rawMaps = {};

        % lcp XAS energy in
        lcpEin = [];
        % lcp XAS Absorption (Im part)
        lcpXAS = [];
        
        % rcp XAS energy in
        rcpEin = [];
        % rcp XAS Absorption (Im part)
        rcpXAS = [];  
        
        % sum XAS Absorption (Im part)
        sumXAS = [];  
        % mcd XAS Absorption (Im part)
        mcdXAS = [];  
        
        
        
        para = 0;        % variable to hold a [parameter struct
        
        % variables for the arrays for expecation values if the _valuesGS files exist
        valuesLegend = [];
        valuesGS = [];
        valuesIS = [];
        valuesFS = [];
        
        % variables for the arrays for energy level diagram 
        eld_headers = [];
        eld_cfValues = [];
        eld_valData = [];
       
    end
    
%     properties (Access = 'private')         
%         indexL = 0;       % should be set with the index of the mapData cell for LCP
%         indexR = 0;       % index for RCP                   
%     end
    % ------------------------------------------------------------------------------------------------------

    % ------------------------------------------------------------------------------------------------------
    methods
        % ----------------------------------------------------------------------------
        %> Constructor for classMapSet
        function thisObj = classMapSet(vargin)
            if nargin == 1
            	display([' *******   classMapSet constructor 1 ************ '])               
%                 thisObj
%                 vargin
%                 thisObj.XX = vargin{1};
%                 thisObj.YY = vargin{2};
%                 if isstr(vargin)
%                     thisObj.info = vargin;                            % 1 arg only -> info strings                      
%                 end 
                
                thisObj.importQuantyMaps(vargin);                        % import the RAW mapfiles (.txt)   
           
            else
                display(['default constructor classMapSet (empty)'])
                % thisObj;   
            end
        end % constructor
        % ----------------------------------------------------------------------------
        % DE-Constuctor / Destructor
        function delete(thisObj)
            debugMsg([' !!! DESTRUCTOR classMapSet !!! Deleting Object'],0)
            rawMaps = {};
            delete(thisObj);
            
        end
        % ----------------------------------------------------------------------------
        % ----------------------------------------------------------------------------
 
        % ----------------------------------------------------------------------------
        % ----------------------------------------------------------------------------
        function importQuantyMaps(thisObj, specFiles)

            specFiles
            
            if length(specFiles) > 0
                % ----------------------------------------------
                [thisPath, thisFName, thisExt] = fileparts(specFiles{1});               % assuming all mapfiles in list are in same folder
                clear thisName thisExt
%                 thisPath
                % store path to current mapFolder 
                thisObj.mapFolder = [thisPath filesep];
                % ----------------------------------------------
                % get baseName from para file and store in object
                dirLS = dir([thisPath filesep '*_para.mat'])               % use _parafile as basename finder. (Exp files exist only when made here, and the the para file should exist too)
                
%                	dir([thisPath filesep])                                 % debug
                
                thisObj.baseName = char(dirLS.name(1:end-9));                      % substract '*_para.mat'   (9character)
                % ----------------------------------------------
                % load here the para.mat file, give para to readQuantyRIXSmap
                paraFName =  fullfile(thisPath, dirLS.name);     
                if exist(paraFName) == 2                % 2 for file
                    debugMsg( ' ', 0 )
                    debugMsg( ['Loading parameter from matlab file: ' paraFName], 0 )
                    load(paraFName,'para')
                else
                     para = 0;
                end
%                 para                       % debug info  

                % --------------------------------------------------------------------------------------------
                % --------------------------------------------------------------------------------------------                
                for j=1:length(specFiles)
                    [thisPath, thisName, thisExt] = fileparts(specFiles{j});
                    thisPath  = [thisPath filesep]
                    thisFName = [thisName thisExt]
                    debugMsg([' ***** Importing Spectrum ' thisFName ' ***** ' ],0)
                    % --------------------------------------------------------------------------------------------
                   
                    thisPath
                    strEnd = thisFName(end-11:end)
                    
                    
                    if strcmp(thisFName(end-11:end),'XAS-Spec.txt')
                        % read ASCII Quanty XAS 
                        specData  = readQuantyXASSpec( [thisPath thisFName], para )
                        % ----------------------------------------------
                        % store the mapfile name in mapData
                        specData.filename = thisFName;
                        % ----------------------------------------------     
                        if strfind(upper(thisFName),'LCP') > 0                        % check for LCP in name                        
                            % LCP FOUND
                            thisObj.lcpEin = specData.energyIn
                            thisObj.lcpXAS = specData.map_Im;                % store in lcpMap

                        elseif strfind(upper(thisFName),'RCP') > 0                    % check for RCP in name
                             % RCP FOUND
                            thisObj.rcpEin = specData.energyIn
                            thisObj.rcpXAS = specData.map_Im;                % store in lcpMap

                        end
                        % ----------------------------------------------
                        % check if LCP and RCP are loaded, then assign SUM and MCD
                        thisObj = checkLR(thisObj);
                        % ----------------------------------------------   
                                               
                        thisObj.para      = specData.para;            % contents of the _para.mat file
                        clear specData                      
    
                    % --------------------------------------------------------------------------------------------    
                    elseif strcmp(thisFName(end-7:end),'Spec.txt')
                        % read the ascii map data created by Quanty and store in rawMaps
                        mapData = readQuantyRIXSmap( [specFiles{j}], para ) ;  
                        % ----------------------------------------------
                        % store the mapfile name in mapData
                        mapData.filename = thisFName;
                        % ----------------------------------------------                   
                        if strfind(upper(thisFName),'LCP') > 0                        % check for LCP in name                        
                            % LCP FOUND
                            thisObj.lcpMap = mapData.map_Im;                % store in lcpMap

                        elseif strfind(upper(thisFName),'RCP') > 0                    % check for RCP in name
                             % RCP FOUND
                            thisObj.rcpMap = mapData.map_Im;                % store in rcpMap      

                        else    
                            thisObj.rawMaps{j}.mapRe = mapData.map_Re;
                            thisObj.rawMaps{j}.mapIm = mapData.map_Im;
                            thisObj.rawMaps{j}.filename = thisFName;           % add file name to struct                          
                        end    
                        % ----------------------------------------------
                        % check if LCP and RCP are loaded, then assign SUM and MCD
                        thisObj = checkLR(thisObj);
                        % ----------------------------------------------   
                        
                        % --------------------------------------------------------------------------------------------                
                        % NOTE: mapData will here be over written each time of the loop (shoud not cause trouble)
                        % parameter file is identical for all submaps, and energies are the same too
                        thisObj.energyIn  = mapData.energyIn;
                        thisObj.energyOut = mapData.energyOut;
                        thisObj.para      = mapData.para;            % contents of the _para.mat file
                        clear mapData
                        % --------------------------------------------------------------------------------------------                       
                    end
                    % --------------------------------------------------------------------------------------------
                    
                end
                clear j  thisName thisExt

                
                % --------------------------------------------------------------------------------------------                
                % check if Expectation txt files exists (should always exist for maps calculated here)
                fName_OPvals = fullfile(thisPath, [ thisObj.baseName '-OPvals.txt' ] ) ;                                % load OP vals if exists
                thisObj.importValueTXT(fName_OPvals);
                % --------------------------------------------------------------------------------------------                
                % --------------------------------------------------------------------------------------------                
                % check if Values for CF diagram exists 
                fName_ELDiagram = fullfile(thisPath, [ thisObj.baseName '-Diagram.txt' ] ) ;                           % load CF diagram if exists             
                thisObj.importELDiagram(fName_ELDiagram);
                % --------------------------------------------------------------------------------------------                
                % --------------------------------------------------------------------------------------------                
            end
            clear mapData dirLS fName_OPvals mapFiles
                        
        end   
        % ----------------------------------------------------------------------------
        function importValueTXT(thisObj, opsFile)
            
            % ----------------------------------------------
            % get and set basename
            if iscell(opsFile)
                opsFile = opsFile{1};
            end
    
            if exist(opsFile) == 2
                [thisPath, thisName, thisExt] = fileparts(opsFile);
                clear thisExt

                % store path to current mapFolder 
                thisObj.mapFolder = [thisPath filesep];

                thisObj.baseName = thisName(1:end-7);            % RIXS1s2p-OPvals.txt, but NO EXTENSION (removed last 7 chars: '-OPvals' )         
                % ----------------------------------------------
                % <E>  <S^2>  <L^2>  <J^2>  <l.s>  <F[2]> <F[4]>  <Nx2y2>  <Nz2>  <Nxy>  <Nxzyz>  
                [header, tmpGS, tmpIS, tmpFS] = readExpectValues( opsFile );    % checks if file exists

                thisObj.valuesLegend = header;                     %

                thisObj.valuesGS = tmpGS;
                thisObj.valuesIS = tmpIS;
                thisObj.valuesFS = tmpFS;
                clear tmpGS tmpIS tmpFS header
            else
                disp('No Observable File found.')
            end    
        end    
        % ----------------------------------------------------------------------------
%         function importCFDiagram(thisObj, opsFile)
        function importELDiagram(thisObj, eldFile)
            
            % ----------------------------------------------
            % get and set basename
            if iscell(eldFile)
                eldFile = eldFile{1};
            end

            if exist(eldFile) == 2            
                [thisPath, thisName, thisExt] = fileparts(eldFile);
                clear thisExt

                % store path to current mapFolder 
                thisObj.mapFolder = [thisPath filesep];

                thisObj.baseName = thisName(1:end-10);            % RIXS1s2p-OPvals.txt, but NO EXTENSION (removed last 7 chars: '-OPvals' )         
                % ----------------------------------------------

                [headers, cfValues, valData ] = readELDiagramValues( eldFile );

                thisObj.eld_headers  = headers;
                thisObj.eld_cfValues = cfValues;
                thisObj.eld_valData  = valData;

    %             sz_headDq = size(headers{1})
    %             sz_valsDq = size(valData{1})            

                clear headers cfValues valData
            else
                disp('No Energy Level Diagram File found.')
            end             
            
        end    
        % ----------------------------------------------------------------------------                
        function saveMapData(thisObj)
            % ------------------------------------------------------------
            % check or create ./mat/ folder
            matFolder = [thisObj.mapFolder 'mat' filesep];
            if not(exist(matFolder) == 7)            % 7 = folder exists 
                mkdir(matFolder)
            end  
            % ------------------------------------------------------------      
            fullSaveName = fullfile(matFolder, [thisObj.baseName '_mapDataRAW.mat' ]);
            
%             debugMsg( [' saving mapData to file: ' fullSaveName], 1 )
            disp( [' saving mapData to file: ' fullSaveName] )
            
            mapData.info = thisObj.info;
            mapData.XX   = thisObj.energyIn  + thisObj.offsetIn;
            mapData.YY   = thisObj.energyOut + thisObj.offsetOut;
            
            mapData.LCP = thisObj.lcpMap;
            mapData.RCP = thisObj.rcpMap;
            mapData.SUM = thisObj.lcpMap + thisObj.rcpMap;
            mapData.MCD = thisObj.lcpMap - thisObj.rcpMap;
            
            mapData.para = thisObj.para;
            
            save(fullSaveName,'mapData')
            % ------------------------------------------------------------
        end
        % ----------------------------------------------------------------------------
        % ----------------------------------------------------------------------------                
        function saveMapDataLCP(thisObj)
            % ------------------------------------------------------------
            % check or create ./mat/ folder
            matFolder = [thisObj.mapFolder 'mat' filesep];
            if not(exist(matFolder) == 7)            % 7 = folder exists 
                mkdir(matFolder)
            end  
            % ------------------------------------------------------------      
            fullSaveName = fullfile(matFolder, [thisObj.baseName '_mapDataLCP.mat' ]);
            
%             debugMsg( [' saving mapData to file: ' fullSaveName], 1 )
            disp( [' saving mapData to file: ' fullSaveName] )
            
            mapData.info = thisObj.info;
            mapData.XX   = thisObj.energyIn  + thisObj.offsetIn;
            mapData.YY   = thisObj.energyOut + thisObj.offsetOut;
            
            mapData.LCP = thisObj.lcpMap;
            
            mapData.para = thisObj.para;
            
            save(fullSaveName,'mapData')
            % ------------------------------------------------------------
        end
        % ----------------------------------------------------------------------------
        % ----------------------------------------------------------------------------                
        function saveMapDataRCP(thisObj)
            % ------------------------------------------------------------
            % check or create ./mat/ folder
            matFolder = [thisObj.mapFolder 'mat' filesep];
            if not(exist(matFolder) == 7)            % 7 = folder exists 
                mkdir(matFolder)
            end  
            % ------------------------------------------------------------      
            fullSaveName = fullfile(matFolder, [thisObj.baseName '_mapDataRCP.mat' ]);
            
%             debugMsg( [' saving mapData to file: ' fullSaveName], 1 )
            disp( [' saving mapData to file: ' fullSaveName] )
            
            mapData.info = thisObj.info;
            mapData.XX   = thisObj.energyIn  + thisObj.offsetIn;
            mapData.YY   = thisObj.energyOut + thisObj.offsetOut;
            
            mapData.RCP = thisObj.rcpMap;
            
            mapData.para = thisObj.para;
            
            save(fullSaveName,'mapData')
            % ------------------------------------------------------------
        end
        % ----------------------------------------------------------------------------

        
        % ----------------------------------------------------------------------------                
        function saveOPvalData(thisObj)
            % ------------------------------------------------------------
            % check or create ./mat/ folder            
            matFolder = [thisObj.mapFolder 'mat' filesep];
            if not(exist(matFolder) == 7)            % 7 = folder exists 
                mkdir(matFolder)
            end  
            % ------------------------------------------------------------
            fullSaveName = fullfile(matFolder, [thisObj.baseName '_OPvalData.mat' ]);
            
%             debugMsg( [' saving OPvalData to file: ' fullSaveName], 1 )
            disp( [' saving OPvalData to file: ' fullSaveName] )
            
            opValsData.info = thisObj.info;            
            opValsData.valuesLegend = thisObj.valuesLegend;                     %

            opValsData.valuesGS = thisObj.valuesGS;
            opValsData.valuesIS = thisObj.valuesIS;
            opValsData.valuesFS = thisObj.valuesFS;
            
            opValsData.para = thisObj.para;
            
            save(fullSaveName,'opValsData')
            
        end
        % ----------------------------------------------------------------------------
                
        % ----------------------------------------------------------------------------                
        function saveELDData(thisObj)
            % ------------------------------------------------------------
            % check or create ./mat/ folder            
            matFolder = [thisObj.mapFolder 'mat' filesep];
            if not(exist(matFolder) == 7)            % 7 = folder exists 
                mkdir(matFolder)
            end  
            % ------------------------------------------------------------
            fullSaveName = fullfile(matFolder, [thisObj.baseName '_eldData.mat' ]);
            
%             debugMsg( [' saving mapData to file: ' fullSaveName], 1 )
            disp( [' saving mapData to file: ' fullSaveName] )
            
            eldData.info = thisObj.info;            
            eldData.eld_headers = thisObj.eld_headers;
            eldData.eld_cfValues   = thisObj.eld_cfValues;
            eldData.eld_valData   = thisObj.eld_valData;
            
            eldData.para = thisObj.para;
            
            save(fullSaveName,'eldData')
            
        end
        % ----------------------------------------------------------------------------
        
        
        
        % ----------------------------------------------------------------------------
    end
    % ------------------------------------------------------------------------------------------------------
    
    
    % ------------------------------------------------------------------------------------------------------
    methods (Access = 'private')       % grants only member functions of this class access
        % ----------------------------------------------------------------------------
        function thisObj = checkLR( thisObj )           
            % ----------------------------------------------------------------------------
            if (length(thisObj.lcpMap) > 0) && (length(thisObj.rcpMap) > 0)                
                if size(thisObj.lcpMap) == size(thisObj.rcpMap)
                    thisObj.sumMap = thisObj.lcpMap + thisObj.rcpMap;
                    thisObj.mcdMap = thisObj.lcpMap - thisObj.rcpMap; 
                else                   
                    disp([' !!! WARNING !!! LCP and RCP size dont match for RIXS! - in classMapSet:checkLR()  '])
                    updateStatus([' !!! WARNING !!! RIXS LCP and RCP size not matching! '])
                end               
            end  
            % ----------------------------------------------------------------------------
 
            % ----------------------------------------------------------------------------
            if (length(thisObj.lcpXAS) > 0) && (length(thisObj.rcpXAS) > 0)                
                if size(thisObj.lcpXAS) == size(thisObj.rcpXAS)
                    thisObj.sumXAS = thisObj.lcpXAS + thisObj.rcpXAS;
                    thisObj.mcdXAS = thisObj.lcpXAS - thisObj.rcpXAS; 
                else                   
                    disp([' !!! WARNING !!! LCP and RCP size dont match for XAS! - in classMapSet:checkLR()  '])
                    updateStatus([' !!! WARNING !!! XAS LCP and RCP size not matching! '])
                end               
            end  
            % ----------------------------------------------------------------------------        
        end
        % ----------------------------------------------------------------------------     
        
        
    end % methods (SetAccess = private)
     
end % classdef

