%**************************************************************************
%This function determines the shims required to straighten the X and Y
%trajectories.
%
%Input:
%dat_file, data file
%plt_file, plot file
%param, parameter structure
%shim_param, shim parameter structure
%field, magnetic field structure
%traj, trajectory structure
%
%Output:
%seg_traj, structure containing the segmented trajectory information
%   x_seg               %Structure containing the x segmented trajectory
%   y_seg               %Structure containing the y segmented trajectory
%x_seg, y_seg
%   traj_name           %'X' or 'Y'
%   num_seg             %Number of segments
%   z_start             %Z position of the start of each segment
%   z_end               %Z position of the end of each segment
%   traj_slope_orig     %Trajectory slope of the segment of the original trajectory
%   traj_start_orig     %Trajectory position at the start of the segment of the original trajectory
%   traj_end_orig       %Trajectory position at the end of the segment of the original trajectory
%   shim_slope          %Shim at each segment, effect on slope
%   shim_bl             %Shim at each segment, integrated field strength
%   traj_slope_shimmed  %Trajectory slope of the segment after shimming
%   traj_start_shimmed  %Trajectory position at the start of the segment after shimming
%   traj_end_shimmed    %Trajectory position at the end of the segment after shimming
%
%traj_shim, structure containing the trajectory shim information
%   x_shim              %Structure containing the x trajectory shim information
%   y_shim              %Structure containing the y trajectory shim information
%x_shim, structure containing the x-trajectory shim information
%   num_shim            %Number of shims
%   pole_num            %Pole number to place the shim
%   pole_z_pos          %z position of the pole
%   pole_by_sign        %Sign of the field in the gap at the pole_num location
%   shim_slope          %Shim effect on trajectory slope
%   shim_bl             %Shim integrated field strength
%   shim_type           %Shim type (types given in parameter file)
%   shim_dim            %Shim physical dimension
%   shim_d_dim          %Shim physical dimension change for pre-existing shims
%y_shim, structure containing the y-trajectory shim information (The shim uses two poles.)
%   num_shim            %Number of shims
%   pole_1_num          %Pole number of upstream pole in shim
%   pole_2_num          %Pole number of downstream pole in shim
%   pole_1_z_pos        %Z position of upstream pole in shim
%   pole_2_z_pos        %Z position of downstream pole in shim
%   pole_1_by_sign      %Sign of the field at the upstream pole
%   pole_2_by_sign      %Sign of the field at the downstream pole
%   pole_1_loc          %Location of shim on upstream pole, +1 upper, -1 lower
%   pole_2_loc          %Location of shim on downstream pole, +1 upper, -1 lower
%   shim_slope          %Shim effect on trajectory slope
%   shim_bl             %Shim integrated field strength
%   shim_type           %Shim type
%   shim_dim            %Shim physical dimension
%   shim_d_dim          %Shim physical dimension change for pre-existing shims
%
%Zachary Wolf
%12/28/05

function [seg_traj, traj_shim] = pid_shim_traj(dat_file, plt_file, param, shim_param, field, traj)

%Parameters
traj_num_seg = shim_param.traj_num_seg;

%Extract the required trajectory information
z = traj.z;
x = traj.x;
x_filt = traj.x_filt;
x_p_filt = traj.x_p_filt;
y = traj.y;
y_filt = traj.y_filt;
y_p_filt = traj.y_p_filt;

%Divide the trajectory into segments and fit a line to each segment
x_seg = traj_shim_seg_traj_init('X', traj_num_seg, z, x_filt);
y_seg = traj_shim_seg_traj_init('Y', traj_num_seg, z, y_filt);

%Plot the segmented fit and compare to the original trajectory
traj_shim_plot_seg_traj(plt_file, param, z, x, x_filt, x_seg);
traj_shim_plot_seg_traj(plt_file, param, z, y, y_filt, y_seg);

%Plot the segmented fit and compare to the filtered trajectory and slope
traj_shim_plot_seg_traj_slope(plt_file, param, z, x_filt, x_p_filt, x_seg);
traj_shim_plot_seg_traj_slope(plt_file, param, z, y_filt, y_p_filt, y_seg);

%First pass, one shim per segment -----

%Calculate the shim slopes required to straighten the trajectory
[x_seg.shim_slope] = traj_shim_calc_shim_slope(x_seg.num_seg, x_seg.z_start, x_seg.z_end, x_seg.traj_end_orig);
[y_seg.shim_slope] = traj_shim_calc_shim_slope(y_seg.num_seg, y_seg.z_start, y_seg.z_end, y_seg.traj_end_orig);

%Calculate the integrated field strength of each shim
[x_seg.shim_bl] = traj_shim_calc_shim_bl(x_seg.traj_name, param.gamma, x_seg.shim_slope);
[y_seg.shim_bl] = traj_shim_calc_shim_bl(y_seg.traj_name, param.gamma, y_seg.shim_slope);

%Update the shimmed trajectory
[x_seg] = traj_shim_update_shim_traj(x_seg);
[y_seg] = traj_shim_update_shim_traj(y_seg);

%Plot the original and the shimmed trajectory
traj_shim_plot_traj_orig_shim(plt_file, param, x_seg);
traj_shim_plot_traj_orig_shim(plt_file, param, y_seg);

%Second pass, add end shims, combine shims into undulator center -----

%Add small segments for the end shims and the end of undulator center shims
x_seg = traj_shim_add_end_shim_seg(param, shim_param, field.z_peak, x_seg);
y_seg = traj_shim_add_end_shim_seg(param, shim_param, field.z_peak, y_seg);

%Plot the shimmed trajectory
%traj_shim_plot_traj_shim(plt_file, param, x_seg);
%traj_shim_plot_traj_shim(plt_file, param, y_seg);

%Combine shims so they are in the undulator center
[x_seg.shim_slope] = traj_shim_calc_shim_combo_ctr(param, shim_param, field.z_peak, x_seg.num_seg, x_seg.z_start, x_seg.z_end, x_seg.shim_slope);
[y_seg.shim_slope] = traj_shim_calc_shim_combo_ctr(param, shim_param, field.z_peak, y_seg.num_seg, y_seg.z_start, y_seg.z_end, y_seg.shim_slope);

%Calculate the integrated field strength of each shim
[x_seg.shim_bl] = traj_shim_calc_shim_bl(x_seg.traj_name, param.gamma, x_seg.shim_slope);
[y_seg.shim_bl] = traj_shim_calc_shim_bl(y_seg.traj_name, param.gamma, y_seg.shim_slope);

%Update the shimmed trajectory
[x_seg] = traj_shim_update_shim_traj(x_seg);
[y_seg] = traj_shim_update_shim_traj(y_seg);

%Plot the shimmed trajectory
%traj_shim_plot_traj_shim(plt_file, param, x_seg);
%traj_shim_plot_traj_shim(plt_file, param, y_seg);

%Third pass, combine shims to reduce their number -----

%Combine shims to reduce their number
[x_seg.shim_slope] = traj_shim_calc_shim_combo(param, shim_param, field.z_peak, x_seg.num_seg, x_seg.z_start, x_seg.z_end, x_seg.shim_slope);
[y_seg.shim_slope] = traj_shim_calc_shim_combo(param, shim_param, field.z_peak, y_seg.num_seg, y_seg.z_start, y_seg.z_end, y_seg.shim_slope);

%Calculate the integrated field strength of each shim
[x_seg.shim_bl] = traj_shim_calc_shim_bl(x_seg.traj_name, param.gamma, x_seg.shim_slope);
[y_seg.shim_bl] = traj_shim_calc_shim_bl(y_seg.traj_name, param.gamma, y_seg.shim_slope);

%Update the shimmed trajectory
[x_seg] = traj_shim_update_shim_traj(x_seg);
[y_seg] = traj_shim_update_shim_traj(y_seg);

%Plot the shimmed trajectory
%traj_shim_plot_traj_shim(plt_file, param, x_seg);
%traj_shim_plot_traj_shim(plt_file, param, y_seg);

%Fourth pass, make the trajectory go to zero at the shim locations -----

%Adjust the combined shims to minimize walkoff
[x_seg.shim_slope] = traj_shim_calc_shim_combo_adj(param, shim_param.x_traj_end_shim_pole_num, field.z_peak, x_seg.num_seg, x_seg.z_start, x_seg.z_end, x_seg.shim_slope, x_seg.traj_start_shimmed);
[y_seg.shim_slope] = traj_shim_calc_shim_combo_adj(param, shim_param.y_traj_end_shim_pole_num, field.z_peak, y_seg.num_seg, y_seg.z_start, y_seg.z_end, y_seg.shim_slope, y_seg.traj_start_shimmed);

%Calculate the integrated field strength of each shim
[x_seg.shim_bl] = traj_shim_calc_shim_bl(x_seg.traj_name, param.gamma, x_seg.shim_slope);
[y_seg.shim_bl] = traj_shim_calc_shim_bl(y_seg.traj_name, param.gamma, y_seg.shim_slope);

%Update the shimmed trajectory
[x_seg] = traj_shim_update_shim_traj(x_seg);
[y_seg] = traj_shim_update_shim_traj(y_seg);

%Plot the shimmed trajectory
%traj_shim_plot_traj_shim(plt_file, param, x_seg);
%traj_shim_plot_traj_shim(plt_file, param, y_seg);

%Fifth pass, distribute shims which are too large, combine shims which are too small -----

%Distribute shims
[x_seg.shim_slope] = traj_shim_calc_shim_combo_dist(param, shim_param.x_traj_end_shim_pole_num, shim_param.x_traj_shim_par, field.z_peak, x_seg.num_seg, x_seg.z_start, x_seg.z_end, x_seg.shim_slope);
[y_seg.shim_slope] = traj_shim_calc_shim_combo_dist(param, shim_param.y_traj_end_shim_pole_num, shim_param.y_traj_shim_par, field.z_peak, y_seg.num_seg, y_seg.z_start, y_seg.z_end, y_seg.shim_slope);

%Calculate the integrated field strength of each shim
[x_seg.shim_bl] = traj_shim_calc_shim_bl(x_seg.traj_name, param.gamma, x_seg.shim_slope);
[y_seg.shim_bl] = traj_shim_calc_shim_bl(y_seg.traj_name, param.gamma, y_seg.shim_slope);

%Update the shimmed trajectory
[x_seg] = traj_shim_update_shim_traj(x_seg);
[y_seg] = traj_shim_update_shim_traj(y_seg);

%Plot the shimmed trajectory
traj_shim_plot_traj_shim(plt_file, param, x_seg);
traj_shim_plot_traj_shim(plt_file, param, y_seg);

%Locate shims, determine shim dimensions -----

%Locate the shims explicitly
x_shim = traj_shim_calc_x_traj_shim_loc(shim_param, field.z_peak, field.by_peak, x_seg.num_seg, x_seg.z_start, x_seg.z_end, x_seg.shim_slope, x_seg.shim_bl);
y_shim = traj_shim_calc_y_traj_shim_loc(shim_param, field.z_peak, field.by_peak, y_seg.num_seg, y_seg.z_start, y_seg.z_end, y_seg.shim_slope, y_seg.shim_bl);

%Determine the shim type and dimensions
[x_shim.shim_type, x_shim.shim_dim] = traj_shim_calc_shim_dim(shim_param.x_traj_shim_par, x_shim.num_shim, x_shim.shim_slope, x_shim.shim_type);
[y_shim.shim_type, y_shim.shim_dim] = traj_shim_calc_shim_dim(shim_param.y_traj_shim_par, y_shim.num_shim, y_shim.shim_slope, y_shim.shim_type);

%If a shim already exists at the location, calculate the change in the shim to get the slope change 
[x_shim.shim_d_dim] = traj_shim_calc_x_traj_shim_d_dim(shim_param.x_traj_shim_par, x_shim.num_shim, x_shim.pole_by_sign, x_shim.shim_slope);
[y_shim.shim_d_dim] = traj_shim_calc_y_traj_shim_d_dim(shim_param.y_traj_shim_par, y_shim.num_shim, y_shim.shim_slope);

%Results -----

%Write a table of required shims to the data file
traj_shim_dat_traj_shim(dat_file, shim_param, x_shim, y_shim);

%Return the X and Y segmented trajectories
seg_traj.x_seg = x_seg;
seg_traj.y_seg = y_seg;

%Return the X and Y trajectory shim structures
traj_shim.x_shim = x_shim;
traj_shim.y_shim = y_shim;

%Done
