function [  ] = TERHARDT_SweepLowToHigh5DecreasingHarmonics_100_InputPerBasetone(  )
clc;
tic;
pause on;
format long;

% PSP(1..Layers,1..NeuronsPerLayer) = post synaptic potential magnitude
% Axon(1..Layers,1..NeuronsPerLayer) = the axon signal magnitude
% W(1..LayersSource,1..NeuronsPerLayer,1..LayersDestination,1..NeuronsPerLayerDestination) = synaptic weights
% Input(1..Samples,1..NeuronsPerLayer) = Magnitude of the input signals (harmonics' amplitudes)
%   Layer 1: "thalamic" neurons = sums up the sensory + cortical signals
%   Layer 2: "cortical" neurons = their synaptic weights are Hebbian (featuring learning)
%           - sensory + cortical axons feed into thalamic neurons for the
%           recurrent network
%       FqMin is the frequency of the lowest tone used here
%       FqMax = FqMin * 2^(x*interNNdistanceInSemitones*/12)
%       FqMax/FqMin = 2^(x*interNNdistanceInSemitones/12)
%       log(FqMax/FqMin)=x*interNNdistanceInSemitones/12
%       x=12*log2(FqMax/FqMin)/interNNdistanceInSemitones
%       NeuronsPerLayer=x

loops='N'; % put Y for the recurrent neural network

for Sweeps=10:10
    for RepetitionsForEachBaseTone=10:10
        
        Octaves=10; % octve span between FqMin and FqMax
        InterNeuronalSemiToneDistance=1/100;
        NeuronsPerSemiTone = floor(1/InterNeuronalSemiToneDistance);
                
        % ############### Initialization start #################################
        
        Tones =          ['C' '#' 'D' '#' 'E' 'F' '#' 'G' '#' 'A' '#' 'H' ];
        TonesFilenames = ['C' 'c' 'D' 'd' 'E' 'F' 'f' 'G' 'g' 'A' 'a' 'H' ];
        PureTones =      ['C '; 'C#'; 'D '; 'D#'; 'E '; 'F '; 'F#'; 'G '; 'G#'; 'A '; 'A#'; 'H ' ];
        PureTonesFilenames = ['C '; 'CC'; 'D '; 'DD'; 'E '; 'F '; 'FF'; 'G '; 'GG'; 'A '; 'AA'; 'H ' ];
        
        %LayerThalamic=1;
        LayerCortical=1;
        Layers=1;
        FqMin=16.351597831287400000; % Hz === the lowest C
        
        FqMax=FqMin*2^(Octaves); % Hz
        NeuronsPerLayer=floor(12*log2(FqMax/FqMin)/InterNeuronalSemiToneDistance);
        Fq=FqMin*2.^((0:NeuronsPerLayer-1)*InterNeuronalSemiToneDistance/12);
        
        PSP=zeros(1,NeuronsPerLayer); % Annulate short-time memory
        Axon=zeros(1,NeuronsPerLayer); % Annulate last-sample activity       
        
        BaseTones=floor(size(Fq,2));
        Input=zeros(NeuronsPerLayer,BaseTones);
        Eye=eye(NeuronsPerLayer);
        InvEye=1-Eye;
        W=eye(NeuronsPerLayer);
        % ############### Initialization end #################################
        
        
        % ############### GENERATE INPUTS start ##############################
        if NeuronsPerSemiTone ~= floor(1/InterNeuronalSemiToneDistance)
            error(strcat('The number of neurons per semitone must be an integer.'));
        end
%         if NeuronsPerSemiTone/2 == floor(NeuronsPerSemiTone/2)
%             error(strcat('The number of neurons per semitone must be an odd number.'));
%         end
        tempTones=Tones;
        tempTonesFilenames=TonesFilenames;
        tempPureTones=PureTones;
        ToneOctave = zeros(1,Octaves*size(Tones,2)*NeuronsPerSemiTone);
        ToneName = tempPureTones;
        ToneNeuron = zeros(1,Octaves*size(Tones,2)*NeuronsPerSemiTone);
        for o=1:Octaves
            for k=1:size(Tones,2)
                toneBaseIndex=(o-1)*size(Tones,2)*NeuronsPerSemiTone+(k-1)*NeuronsPerSemiTone;
                tempTones(toneBaseIndex+1)=Tones(k);
                tempTonesFilenames(toneBaseIndex+1)=TonesFilenames(k);
                ToneOctave(toneBaseIndex+1)=o;
                ToneName(toneBaseIndex+1,:)=PureTones(k,:);
                ToneNeuron(toneBaseIndex+1)=1;
                for n=2:NeuronsPerSemiTone
                    tempTones(toneBaseIndex+n)='.';
                    ToneOctave(toneBaseIndex+n)=o;
                    ToneName(toneBaseIndex+n,:)=PureTones(k,:);
                    ToneNeuron(toneBaseIndex+n)=n;
                end
            end
        end
        neuronShift=floor(NeuronsPerSemiTone/2);
        ShiftedToneOctave=ToneOctave;
        ShiftedToneName=ToneName;
        ShiftedToneNeuron=ToneNeuron;
        for i=1:size(ToneOctave,2)-neuronShift
            ShiftedToneOctave(i)=ToneOctave(i+neuronShift);
            ShiftedToneName(i,:)=ToneName(i+neuronShift,:);
            ShiftedToneNeuron(i)=ToneNeuron(i+neuronShift);
        end
        for i=size(ToneOctave,2)-neuronShift+1:size(ToneOctave,2)
            ShiftedToneOctave(i)=ToneOctave(i)+1;
            ShiftedToneName(i,:)=ToneName(i-(size(ToneOctave,2)-neuronShift),:);
            ShiftedToneNeuron(i)=ToneNeuron(i-(size(ToneOctave,2)-neuronShift));
        end
        
        decreaseRatio=0.9;
        HarmonicMultipleOfF0 =  [1          2              3                  4                   5]; %                   6                    7                  8 ];%           6];
        HarmonicMagnitude =     [1         decreaseRatio   decreaseRatio^2	  decreaseRatio^3     decreaseRatio^4]; %     decreaseRatio^5      decreaseRatio^6    decreaseRatio^7];%	0.382066277];
        HarmonicBandNumber=HarmonicMultipleOfF0*0;
        

        % bind to the most resonant band (by finding the lowest difference
        % between the frequencies)
        maxFq=Fq(size(Fq,2));
        for harmonic=1:size(HarmonicMultipleOfF0,2)
            if Fq(1)*HarmonicMultipleOfF0(harmonic)<maxFq
                closest=1;
                for f=1:size(Fq,2)
                    if ( abs(Fq(1)*HarmonicMultipleOfF0(harmonic)-Fq(f)) < abs(Fq(1)*HarmonicMultipleOfF0(harmonic)-Fq(closest)) )
                        closest=f;
                    end
                end
                HarmonicBandNumber(harmonic)=closest;
            else
                error(strcat('The number of harmonics cannot be bigger than all the octaves span. Lower the number of harmonics to : ',num2str(harmonic-1)));
            end
        end
        
        Harmonics = size(HarmonicBandNumber,2);
        if(Harmonics~=size(HarmonicMagnitude,2))
            error(strcat('The HarmonicSemiToneDistanceFromF0 and HarmonicMagnitude arrays must have same dimensions.'));
        end
        for baseTone=1:BaseTones
            F0=(baseTone-1)+1; % The Input Set index defines the F0 (are equal)
            for harmonic=1:Harmonics
                if F0+HarmonicBandNumber(harmonic)-1 <= NeuronsPerLayer                    
                    Input(F0+HarmonicBandNumber(harmonic)-1,baseTone)=HarmonicMagnitude(harmonic);
                end
            end
        end
        
        % ############### GENERATE INPUTS end ##############################
        
        
        if strcmp(loops,'Y')
            wDataFilename=strcat('W-S',num2str(Sweeps),'-R',num2str(RepetitionsForEachBaseTone),'-LOOPS-DATA.mat');
        else
            wDataFilename=strcat('W-S',num2str(Sweeps),'-R',num2str(RepetitionsForEachBaseTone),'-DATA.mat');
        end
        % WDATA contains snapshot of W (synaptic weights) taken at each
        % repetition
        %WDATA=zeros(InputSeries,InputSets,InputRepetitionsPerSet,NeuronsPerLayer,NeuronsPerLayer);
        firstTime=1;
        
       % load('Resolution_100_perSemiTone-5_harmonics_sweep-7.mat');
       
        
        for sweep=1:Sweeps
            disp(strcat('Rendering Input Sweep=',num2str(sweep),' of total= ',num2str(Sweeps)));
            for baseTone=1:BaseTones
                disp(strcat('       Rendering Input Set=',num2str(baseTone),' of total= ',num2str(BaseTones)));
                PSP=0*PSP; % Annulate short-time memory
                Axon=0.*Axon;
                
                for repetition=1:RepetitionsForEachBaseTone
                    %disp(strcat('             Rendering Input Repetitaion=',num2str(repetition),' of total= ',num2str(RepetitionsForEachBaseTone)));
                    % ##################### Activity Rule - start ########
                    % Layer 2 - cortical                   
                    PSP=Input(:,baseTone)'; %*W;
                    
                    % Normalize                  
                    maxInLayer=max(PSP(LayerCortical,1:NeuronsPerLayer));
                    if (maxInLayer>1)
                        PSP(LayerCortical,1:NeuronsPerLayer)=PSP(LayerCortical,1:NeuronsPerLayer)./maxInLayer;
                    end

                    % ##################### Activity Rule - end ########
                    
                    % ##################### Activation Rule - start #####
                    Axon=PSP;
                    % ##################### Activation Rule - end #######
                                       
                    % ##################### Learning Rule - start #######
                    W=W+0.001*Input(:,baseTone)*Axon;
                                       
                    % Normalize W
                    maxW  = max(W(:));
                    if (maxW>0.1)
                        W = W./maxW;
                    end
                    % ##################### Learning Rule - end #######
                                      
                end
                

            end
            
            
            
                    plotOctaves=1;
                    i=12*4*NeuronsPerSemiTone+1;   j=i+ plotOctaves*12*NeuronsPerSemiTone+1;
                    w=W.*InvEye; w=w+Eye*1.2*max(w(i,:)); 
                    if firstTime==1
                       firstTime=0; 
                        figure1 = figure('Color',[1 1 1]);
                        % Create axes
                        axes1 = axes('Parent',figure1,'YTick',zeros(1,0),...
                            'XTickLabel',ShiftedToneName(i:j,:),...
                            'XTick',1:12*NeuronsPerSemiTone);
    %                     axes1 = axes('Parent',figure1,'YTick',zeros(1,0),...
    %                         'XTickLabel',{'C4','C#4','D4','D#4','E4','F4','F#4','G4','G#4','A4','A#4','H4','C5'},...
    %                         'XTick',[1 2 3 4 5 6 7 8 9 10 11 12 13]);                    

                        box(axes1,'on');
                        hold(axes1,'all');
                    end 
                
                    % Uncomment next row to get single octave graph for C4    
                    bar(log(1+w(i,i:j)),'FaceColor',[0 0 0]);   
                
                
          pause(1/100000); 
            InputFileName = strcat('Resolution_',num2str(NeuronsPerSemiTone),'_perSemiTone-',num2str(size(HarmonicMultipleOfF0,2)),'_harmonics_sweep-',num2str(sweep));
            InputFileName = strcat(InputFileName,'.mat');
            disp(strcat('Data file: ',InputFileName));         
          save(InputFileName,'W');
            
        end
%         disp('Saving data, please be patient, may take few minutes...');
%         save(wDataFilename,'WDATA');
        disp('Still data, please be patient...');
        %clear('WDATA');
        disp('Almost done, please be patient...');
        clear('figure1');
        %save(InputFileName);
        toc;


       
        
    end;
end;

% % ############ SHOW GRAPH FOR INTERVALS IN C4-C5 OCTAVE - START ##########
% disp('Preparing graphics, please be patient...');
% %InputFileName='Data-Series10-Reps10.mat';
% %load(InputFileName);
% i=12*4+1; j=i+1;              
% w=W.*InvEye; w=w+Eye*1.2*max(w(i,:)); 
% figure1 = figure('Color',[1 1 1]);
% % Create axes
% axes1 = axes('Parent',figure1,'YTick',zeros(1,0),...
%     'XTickLabel',{'C4','C#4','D4','D#4','E4','F4','F#4','G4','G#4','A4','A#4','H4','C5'},...
%     'XTick',[1 2 3 4 5 6 7 8 9 10 11 12 13]);
% box(axes1,'on');
% hold(axes1,'all');
% % Create bar
% minNonZero=9999999999;
% for k=0:12
%     if minNonZero>w(i,49+k)
%         if w(i,49+k)>0
%             minNonZero=w(i,49+k);
%         end
%     end
% end
% 
% w(i,49:49+12)'
% 
% % Uncomment next row to get the graph that spans multiple octaves around C4
% %bar((1+w(i,12:12+6*12)/minNonZero),'FaceColor',[0 0 0]);
% 
% % Uncomment next row to get single octave graph for C4
% bar(w(i,49:49+12),'FaceColor',[0 0 0]);
% 
% % Uncomment next row to get single octave graph for C4, log magnitudes
% %bar(log(1+w(i,49:49+12)/minNonZero),'FaceColor',[0 0 0]);
% 
% 
% annotation(figure1,'textbox',...
%     [0.131524008350731 0.941567567567568 0.775574112734864 0.0506756756756757],...
%     'Interpreter','none',...
%     'String',{''},...
%     'FitBoxToText','off',...
%     'LineStyle','none');
% % ############ SHOW GRAPH FOR INTERVALS IN C4-C5 OCTAVE - END ##########

disp('############ END #############');
disp('############ END #############');
disp('    Data...mat files are created for each run of max series and max reps.');
disp('    In Data...mat files find WDATA vector containing snapshots of the');
disp('    W matrix taken at each time cycle.');
disp('############ END #############');
disp('############ END #############');

end

