%--------------------------------------------------------------------------
% function [map_out,zc] = FT_prepare_phase_map_for_finesse(map,curvature)
%
% A Matlab function which prepares a (phase) mirror map for use in Finesse,
% using Zernike polynomials to remove effects such as offset, tilt and 
% residual curvature.  The function then saves the resulting map in the
% file format for use in Finesse, as well as creating and saving a map
% representing the aperture created by the mirror.
%
% map:          Input map to be prepared and converted for Finesse
% offset:       [x0 y0] offset to the map optical centre ([0,0] for map 
%               centre).
% curvature:    Variable which determines what curvature to remove from the
%               map.
%               'constant':     remove constant curvature (Z20 term)
%               'all':          remove constant and astigmatic curvature 
%                               (Z20 and Z22 terms)
%               'astigmatism':  remove just Z22 term
%               'none':         no curvature removal
%
% map_out:      Returned map, after preparation for Finesse
% zc:           Zernike content.  Summary of the zernike polynomials in the
%               original map.
% 
% Part of the Simtools package, http://www.gwoptics.org/simtools
% Charlotte Bond    04.05.2012
%--------------------------------------------------------------------------
%

function [map_out,zc] = FT_prepare_phase_map_for_finesse(map,offset,curvature)
    
    % TO DO: 04.05.2012
    % Add in gaussian weighting function

    baseid = 'prepare_phase_map_for_finesse';
    
    % Error messages
    if (~strcmp(curvature,'none') && ~strcmp(curvature,'astigmatism') && ...
            ~strcmp(curvature,'constant') && ~strcmp(curvature,'all'))
        msg = 'Invalid value: curvature must be "constant", "astigmatism", "all" or "none"'
        msgid = [baseid,':checkarguments']
        error(msgid,result);
    end

    % Output filenames
    basename = map.name;
    f_mapname = sprintf('%s',basename,'_for_finesse.txt');
    a_mapname = sprintf('%s',basename,'_aperture.txt');
    zc_name = sprintf('%s',basename,'_zernike_content');
    results_name = sprintf('%s',basename,'_conversion_info.txt');

    % Factor to scale map.data to nm (usually 1)
    nm_scaling = map.scaling*1e9;
    
    % Output map and temporary map
    map_out = map;
  
    disp(' --- recentering map ...');
    % Recenter map
    map_out = FT_recenter_mirror_map(map_out);
    
    % Remove invalid outside elements
    map_out = FT_remove_elements_outside_map(map_out);
    
    % Map radius in m
    real_radius = map.xstep*FT_find_map_radius(map);
  
    [y,x]=size(map.data);
    
    disp(' --- removing Zernike terms Z00, Z11 and Z20 ...')
    % Removing offset
    [map_out,zc] = FT_remove_zernike_offset_from_map(map_out);
    A(1) = nm_scaling*zc.amp(1,1);
    disp(sprintf(' --- removing offset of A00 = %g [nm] ...',A(1)))
    
    % Removing tilt -> -1 (odd polynomial), +1 (even polynomial)
    [map_out,zc] = FT_remove_zernike_tilt_from_map(map_out);
    A(2) = nm_scaling*zc.amp(2,1);
    A(3) = nm_scaling*zc.amp(2,2);
    disp(sprintf(' --- removing tilt of A11 = %g [nm] ...',sqrt(A(2)^2+A(3)^2)))
    
    A(4:6) = 0;
    if ~(strcmp(curvature,'none'))
        % Remove curvature
        [map_out,zc] = FT_remove_zernike_curvatures_from_map(map_out,curvature);
        if strcmp(curvature,'all') || strcmp(curvature,'constant')
            A(5) = nm_scaling*zc.amp(3,2);
            disp(sprintf(' --- removing curvature of A20 = %g [nm] ...',A(5)))
        end
        if strcmp(curvature,'all') || strcmp(curvature,'astigmatism')
            A(4) = nm_scaling*zc.amp(3,1);
            A(6) = nm_scaling*zc.amp(3,3);
            disp(sprintf(' --- removing astigmatism of A22 = %g [nm] ...',sqrt(A(4)^2+A(6)^2)))
        end
    end
    
    if offset(1)~=0 || offset(2)~=0
        % Add offset to mirror centre
        map_out.x0 = map_out.x0+offset(1)*1e-3/map_out.xstep;
        map_out.y0 = map_out.y0+offset(2)*1e-3/map_out.ystep;
    end
    
    % Create aperture map
    a_map = FT_create_aperture_map(map_out);
    
    % Write maps in Finesse format
    disp(sprintf(' --- saving file "%s" ...',f_mapname))
    FT_write_surface_map(f_mapname,map_out)
    disp(sprintf(' --- saving file "%s" ...',a_mapname))
    FT_write_surface_map(a_mapname,a_map)
    
    % Write results to STDOUT
    write_results(1,map_out,A,offset);

    % ... and to file
    disp(sprintf(' --- writing results to file "%s" ...',results_name));
    FT_make_backup(results_name);
    [FID, result]=fopen(results_name,'w');  
    if (FID==-1)
        msgid=[baseid,':fileopen'];
        error(msgid,result);
    end
    write_results(FID,map_out,A,offset);
    fclose(FID);
  
    % and maybe plot the result
    FT_plot_mirror_map(map_out,0);

end


function []=write_results(FID,map,A,offset);
  
    % Calculate map radius [m] and equivalent optical features (angles for
    % tilt, Rcs for curvature etc.)
    R = map.xstep*FT_find_map_radius(map);
    OF1 = FT_zernike_optical_features(A(3),R,1,1);
    OF2 = FT_zernike_optical_features(A(2),R,1,-1);
    
    % use FID=1 for stdout
    % Output conversion data
    fprintf(FID,'\n---------------------------------------------------------\n');
    fprintf(FID,'Map: %s\n',map.name);
    fprintf(FID,'Date: %s\n', datestr(now,'dd. mmmm yyyy (HH:MM:SS)'));
    fprintf(FID,'---------------------------------------------------------\n');
    fprintf(FID,'Diameter:             %3.3f cm\n',2*R*1e2);
    fprintf(FID,'Offset (Z00):         %3.1f nm\n',A(1));
    fprintf(FID,'Tilt (Z11):           %3.1f nm\n',sqrt(A(2)^2+A(3)^2));
    fprintf(FID,'(xbeta = %2.2g urad, ybeta = %2.2g urad)\n',OF1.value*1e6,OF2.value*1e6);
    if A(5)>0
        OF3 = FT_zernike_optical_features(A(5),R,2,0);
        fprintf(FID,'Curvature (Z20):      %3.1f nm\n',A(5));
        fprintf(FID,'          (Rc = %3.1f m)\n',OF3.value);
    end
    if A(4)>0 || A(6)>0
        Amps = [A(4) A(5) A(6)];
        n = [2 2 2];
        m = [-2 0 2];
        OP4 = FT_zernike_optical_features(Amps,R,n,m);
        fprintf(FID,'Astigmatism (Z22):  %3.1f nm\n',sqrt(A(4)^2+A(6)^2));
        fprintf(FID,'Curvature (Z20):    %3.1f nm\n',A(5));
        fprintf(FID,'(Rcx = %4.1f m, Rcy = %4.1f m)\n',OP4.value(1),OP4.value(2));
    end
    if offset(1)~=0 || offset(2)~=0
        fprintf(FID,'x0 offset:          %3.2f mm\n',offset(1));
        fprintf(FID,'y0 offset:          %3.2f mm\n',offset(2));
    end
    fprintf(FID,'---------------------------------------------------------\n\n');

end

