%--------------------------------------------------------------------------
% function [fake_map] =
% FT_create_synthetic_zernike_map(zc,option,real_size,grid_size,r,mapname)
%
% A function for Matlab which computes a 'synthetic', or 'fake', map from a
% sum of Zernike polynomials.  The amplitudes of the Zernike polynomials
% are provided and the function can either create a surface map with these
% original amplitudes or randomly distribute the combined amplitude for all 
% the polynomials of a given order (n) between the polynomials of that 
% order.  The aim of this is to produce maps with similar spectra, but with 
% differing Zernike distributions.
%
% zc:           Structure storing the original amplitudes of the Zernike
%               polynomials, in nm.
% option:       'original': Use original amplitudes to recreate zernike
%                           map
%               'random':   Random distribution of amplitudes throughout 
%                           the orders, but the the sum of amplitudes in 
%                           each order remains the same. 
% real_size:    Size of the map [m]
% grid_size:    Size of the grid representing the map
% r:            Radius of mirror map [m]
% mapname:      Name of map
%
% fake_map:     Returned synthetic map
%
% Part of the Simtools package, http://www.gwoptics.org/simtools
% Charlotte Bond    12.04.2011
%--------------------------------------------------------------------------
%

function [fake_map] = FT_create_synthetic_zernike_map(zc,option,real_size,grid_size,r,mapname)

    baseid = 'create_synthetic_zernike_map';
    
    % Option should be 'random' or 'original'
    if (~strcmp(option,'original') && ~strcmp(option,'random'))
        result='Invalid option: option must be "original" or "random"';
        msgid=[baseid,':checkarguments']
        error(msgid,result);
    end
    
    % If option is 'random' then distribute amplitudes randomly throughout
    % zernike polynomials
    if strcmp(option,'original')
        fake_zc=zc;
    elseif strcmp(option,'random')
        [N,I]=size(zc.amp);
        nmax=N-1;
  
        temp_amps=zeros(N,I);
  
        % The sum of amplitudes in the same order should stay the same but is
        % randomly distributed over those with different m.
        for n=0:nmax
            A=sum(abs(zc.amp(n+1,1:I)))
            i=1;
            for m=-n:2:n
                temp_amps(n+1,i)=(2*rand()-1)*A;
                fake_zc.n(n+1,i)=n;
                fake_zc.m(n+1,i)=m;
                i=i+1;
          
            end
            temp_A=sum(abs(temp_amps(n+1,1:I)));
            fake_zc.amp(n+1,1:I)=(A/temp_A)*temp_amps(n+1,1:I);
            sum(abs(fake_zc.amp(n+1,1:I)))
      
        end
    end
  
  
    % Basic parameters for Zernike map
    rows=grid_size;
    cols=grid_size;
    step_size=real_size/(grid_size-1);
    x0=(cols+1)/2;
    y0=(rows+1)/2;
  
    % Elements outside the mirror set to nan
    for x=1:cols
        for y=1:rows
            R=sqrt((x-x0)^2+(y-y0)^2);
            if (R*step_size>r)
                data(y,x)=nan;
            else
                data(y,x)=1;
            end
        end
    end

    % Create new map and add Zernike polynomials to surface (surface heights
    % are in nm)
    map=FT_new_surface_map(mapname,data,0,0,x0,y0,step_size,step_size,1e-9);
    fake_map=FT_create_zernike_polynomial_map(map,fake_zc);
  
    % Recenter map
    fake_map=FT_recenter_mirror_map(fake_map);
 
end

