%**************************************************************************
%This program takes the voltages measured by the Hall elements and applies
%the calibration to each voltage to get the measured fields.  It then
%corrects for the angle error of each Hall element.  The overall probe
%orientation, 'X' or 'Y', is corrected so the output fields are given in
%the global coordinate system.
%
%Input:
%param, program parameter structure
%dat_file, file to write data to
%plt_file, file to send plots to
%zmm, z-position of the probe package (m)
%vx1mm, measured voltage from the Bx sensor of probe 1 (V)
%vy1mm, measured voltage from the By sensor of probe 1 (V)
%vz1mm, measured voltage from the Bz sensor of probe 1 (V)
%vx2mm, measured voltage from the Bx sensor of probe 2 (V)
%vy2mm, measured voltage from the By sensor of probe 2 (V)
%vz2mm, measured voltage from the Bz sensor of probe 2 (V)
%
%Output:
%b_meas, structure containing measurement information and calculated fields
% b_meas.zm = zm;
% b_meas.vx1m = vx1m;
% b_meas.vy1m = vy1m;
% b_meas.vz1m = vz1m;
% b_meas.vx2m = vx2m;
% b_meas.vy2m = vy2m;
% b_meas.vz2m = vz2m;
% b_meas.zv = zv;
% b_meas.vx1 = vx1;
% b_meas.vy1 = vy1;
% b_meas.vz1 = vz1;
% b_meas.vx2 = vx2;
% b_meas.vy2 = vy2;
% b_meas.vz2 = vz2;
% b_meas.z = z;
% b_meas.bx1 = bx1;
% b_meas.by1 = by1;
% b_meas.bz1 = bz1;
% b_meas.bx2 = bx2;
% b_meas.by2 = by2;
% b_meas.bz2 = bz2;
%
%Zachary Wolf
%9/19/13

function [b_meas] = hall2_anal_calib_meas(param, dat_file, plt_file, zmm, vx1mm, vy1mm, vz1mm, vx2mm, vy2mm, vz2mm)

%Plot the voltage measurements
halln_meas_plot_vxyzm_vs_zm(plt_file, 'Probe 1, Raw', zmm, vx1mm, vy1mm, vz1mm);
halln_meas_plot_vxyzm_vs_zm(plt_file, 'Probe 2, Raw', zmm, vx2mm, vy2mm, vz2mm);
% halln_meas_plot_vxyzm_vs_zm(plt_file, 'Probe 1, Raw, Exit To Entrance', zmm, vx1mm, vy1mm, vz1mm);
% halln_meas_plot_vxyzm_vs_zm(plt_file, 'Probe 2, Raw, Exit To Entrance', zmm, vx2mm, vy2mm, vz2mm);

%The measurements are made from the exit end to the entrance end, reverse the order
%The 2015 measurements are done from the entrance to the exit, do not reverse the order
% zm = fliplr(zmm);
% zm = -abs(zm);  %Don't use the - sign put in by the measurement program
% vx1m = fliplr(vx1mm);
% vy1m = fliplr(vy1mm);
% vz1m = fliplr(vz1mm);
% vx2m = fliplr(vx2mm);
% vy2m = fliplr(vy2mm);
% vz2m = fliplr(vz2mm);
% 
% %In the 2015 repeat measurements, the order is correct so no flip is required
% %The signs of Vx and Vz are reversed compared to the calibrations, correct here
% zm = zmm;
% vx1m = -vx1mm;
% vy1m = vy1mm;
% vz1m = -vz1mm;
% vx2m = -vx2mm;
% vy2m = vy2mm;
% vz2m = -vz2mm;

%In the 2015 new measurements, the order is correct so no flip is required
zm = zmm;
vx1m = vx1mm;
vy1m = vy1mm;
vz1m = vz1mm;
vx2m = vx2mm;
vy2m = vy2mm;
vz2m = vz2mm;

%Define the ranges of data in the measurement arrays
num_zero_gauss_meas = param.num_zero_gauss_meas;
num_meas = length(vx1m);
zero_ini_range = 1 : num_zero_gauss_meas;
zero_fin_range = num_meas - num_zero_gauss_meas + 1 : num_meas;
meas_range = num_zero_gauss_meas + 1 : num_meas - num_zero_gauss_meas;

%Find the z-values in the undulator
zv = zm(meas_range) - zm(meas_range(1));  %Start at 0

%Remove offsets from probe 1 before applying calibrations
vx1_zero_ini = mean(vx1m(zero_ini_range));
vy1_zero_ini = mean(vy1m(zero_ini_range));
vz1_zero_ini = mean(vz1m(zero_ini_range));
vx1_zero_fin = mean(vx1m(zero_fin_range));
vy1_zero_fin = mean(vy1m(zero_fin_range));
vz1_zero_fin = mean(vz1m(zero_fin_range));
vx1 = vx1m(meas_range) - (vx1_zero_ini + (vx1_zero_fin - vx1_zero_ini) * zv / zv(end));  %Linear offset correction, zv starts at 0
vy1 = vy1m(meas_range) - (vy1_zero_ini + (vy1_zero_fin - vy1_zero_ini) * zv / zv(end));  %Linear offset correction
vz1 = vz1m(meas_range) - (vz1_zero_ini + (vz1_zero_fin - vz1_zero_ini) * zv / zv(end));  %Linear offset correction

%Remove offsets from probe 2 before applying calibrations
vx2_zero_ini = mean(vx2m(zero_ini_range));
vy2_zero_ini = mean(vy2m(zero_ini_range));
vz2_zero_ini = mean(vz2m(zero_ini_range));
vx2_zero_fin = mean(vx2m(zero_fin_range));
vy2_zero_fin = mean(vy2m(zero_fin_range));
vz2_zero_fin = mean(vz2m(zero_fin_range));
vx2 = vx2m(meas_range) - (vx2_zero_ini + (vx2_zero_fin - vx2_zero_ini) * zv / zv(end));  %Linear offset correction, zv starts at 0
vy2 = vy2m(meas_range) - (vy2_zero_ini + (vy2_zero_fin - vy2_zero_ini) * zv / zv(end));  %Linear offset correction
vz2 = vz2m(meas_range) - (vz2_zero_ini + (vz2_zero_fin - vz2_zero_ini) * zv / zv(end));  %Linear offset correction

%Plot the offset voltage samples
halln_meas_plot_vxyz_offset(plt_file, 'Probe 1, Before', vx1m(zero_ini_range), vy1m(zero_ini_range), vz1m(zero_ini_range));
halln_meas_plot_vxyz_offset(plt_file, 'Probe 1, After', vx1m(zero_fin_range), vy1m(zero_fin_range), vz1m(zero_fin_range));
halln_meas_plot_vxyz_offset(plt_file, 'Probe 2, Before', vx2m(zero_ini_range), vy2m(zero_ini_range), vz2m(zero_ini_range));
halln_meas_plot_vxyz_offset(plt_file, 'Probe 2, After', vx2m(zero_fin_range), vy2m(zero_fin_range), vz2m(zero_fin_range));

%Write the offset voltages to the data file
hall2_meas_dat_vxyz_offset(dat_file, 'Probe 1, Entrance End', vx1_zero_ini, vy1_zero_ini, vz1_zero_ini);
hall2_meas_dat_vxyz_offset(dat_file, 'Probe 1,     Exit End', vx1_zero_fin, vy1_zero_fin, vz1_zero_fin);
hall2_meas_dat_vxyz_offset(dat_file, 'Probe 2, Entrance End', vx2_zero_ini, vy2_zero_ini, vz2_zero_ini);
hall2_meas_dat_vxyz_offset(dat_file, 'Probe 2,     Exit End', vx2_zero_fin, vy2_zero_fin, vz2_zero_fin);

%Plot the voltages from the two probes
halln_meas_plot_vx1vx2_vs_z(plt_file, zv, vx1, vx2);
halln_meas_plot_vy1vy2_vs_z(plt_file, zv, vy1, vy2);
halln_meas_plot_vz1vz2_vs_z(plt_file, zv, vz1, vz2);

%Apply the calibrations to probe 1
%msgbox('Using nominal calibrations', 'Warning');
%load(param.probe1_bx_calib_file, 'calib');
%p = calib.fit_coef_bvsvoc_no_out;
%p = [1/5, 0];
p = hall_calib_read_hall_calib_ini(param.probe1_bx_calib_file);
bx1 = polyval(p, vx1);
hall2_meas_dat_calib(dat_file, 'Probe 1 Bx', p);
%load(param.probe1_by_calib_file, 'calib');
%p = calib.fit_coef_bvsvoc_no_out;
%p = [1/5, 0];
p = hall_calib_read_hall_calib_ini(param.probe1_by_calib_file);
by1 = polyval(p, vy1);
hall2_meas_dat_calib(dat_file, 'Probe 1 By', p);
bz1 = (1 / 5) * vz1;
hall2_meas_dat_calib(dat_file, 'Probe 1 Bz', [1/5, 0]);

%Apply the calibrations to probe 2
%load(param.probe2_bx_calib_file, 'calib');
%p = calib.fit_coef_bvsvoc_no_out;
%p = [1/5, 0];
p = hall_calib_read_hall_calib_ini(param.probe2_bx_calib_file);
bx2 = polyval(p, vx2);
hall2_meas_dat_calib(dat_file, 'Probe 2 Bx', p);
%load(param.probe2_by_calib_file, 'calib');
%p = calib.fit_coef_bvsvoc_no_out;
%p = [1/5, 0];
p = hall_calib_read_hall_calib_ini(param.probe2_by_calib_file);
by2 = polyval(p, vy2);
hall2_meas_dat_calib(dat_file, 'Probe 2 By', p);
bz2 = (1 / 5) * vz2;
hall2_meas_dat_calib(dat_file, 'Probe 2 Bz', [1/5, 0]);

%In 2015 the probe coordinte system is rotated compared to the laboratory coordinate system, correct here
bx1 = -bx1;
by1 = by1;
bz1 = -bz1;
bx2 = -bx2;
by2 = by2;
bz2 = -bz2;

%Plot the calibrated fields from the two probes
name = 'After V -> B Calibration';
hall2_meas_plot_bx1bx2_vs_z(plt_file, name, zv, bx1, bx2);
hall2_meas_plot_by1by2_vs_z(plt_file, name, zv, by1, by2);
hall2_meas_plot_bz1bz2_vs_z(plt_file, name, zv, bz1, bz2);

%Account for the z-offsets of probe 1
zbx1 = zv + param.probe1_param.bx_sensor.z;
zby1 = zv + param.probe1_param.by_sensor.z;
zbz1 = zv + param.probe1_param.bz_sensor.z;
bx1_zoc = spline(zbx1, bx1, zv);
by1_zoc = spline(zby1, by1, zv);
bz1_zoc = spline(zbz1, bz1, zv);

%Account for the z-offsets of probe 2
zbx2 = zv + param.probe2_param.bx_sensor.z;
zby2 = zv + param.probe2_param.by_sensor.z;
zbz2 = zv + param.probe2_param.bz_sensor.z;
bx2_zoc = spline(zbx2, bx2, zv);
by2_zoc = spline(zby2, by2, zv);
bz2_zoc = spline(zbz2, bz2, zv);

%Remove end effects
%index_array = find((zv > param.probe1_param.bz_sensor.z + .001) & (zv < zv(end) + param.probe2_param.bx_sensor.z - .001));
index_array = find((zv > param.probe2_param.bz_sensor.z + .004) & (zv < zv(end) + param.probe1_param.bx_sensor.z - .004));
z = zv(index_array);
bx1 = bx1_zoc(index_array);
by1 = by1_zoc(index_array);
bz1 = bz1_zoc(index_array);
bx2 = bx2_zoc(index_array);
by2 = by2_zoc(index_array);
bz2 = bz2_zoc(index_array);

%Plot the z-offset corrected calibrated fields from the two probes
name = 'After V -> B And Z-Offset Calibration';
hall2_meas_plot_bx1bx2_vs_z(plt_file, name, z, bx1, bx2);
hall2_meas_plot_by1by2_vs_z(plt_file, name, z, by1, by2);
hall2_meas_plot_bz1bz2_vs_z(plt_file, name, z, bz1, bz2);

%Correct for probe offset direction, 'X' or 'Y'
%Correct the measured signals for Hall element angle errors
%Note that the input bx, by, bz are calibrated signals from the elements, the output bx, by, bz are the corrected fields
[bx1, by1, bz1] = halln_meas_corr_hall_angles(param.probe2_offset_dir, param.probe1_param, bx1, by1, bz1);
[bx2, by2, bz2] = halln_meas_corr_hall_angles(param.probe2_offset_dir, param.probe2_param, bx2, by2, bz2);

%Plot the Hall element angle corrected, z-offset corrected, calibrated fields from the two probes
name = 'After V -> B And Z-Offset And Hall Element Angle Calibration';
hall2_meas_plot_bx1bx2_vs_z(plt_file, name, z, bx1, bx2);
hall2_meas_plot_by1by2_vs_z(plt_file, name, z, by1, by2);
hall2_meas_plot_bz1bz2_vs_z(plt_file, name, z, bz1, bz2);

%Plot the fields
halln_meas_plot_bxyz_vs_z(plt_file, 'Probe 1, V and Z Offset Corrected, Hall Angles Corrected', z, bx1, by1, bz1);
halln_meas_plot_bxyz_vs_z(plt_file, 'Probe 2, V and Z Offset Corrected, Hall Angles Corrected', z, bx2, by2, bz2);

%Return the results in a structure
b_meas.zm = zm;
b_meas.vx1m = vx1m;
b_meas.vy1m = vy1m;
b_meas.vz1m = vz1m;
b_meas.vx2m = vx2m;
b_meas.vy2m = vy2m;
b_meas.vz2m = vz2m;
b_meas.zv = zv;
b_meas.vx1 = vx1;
b_meas.vy1 = vy1;
b_meas.vz1 = vz1;
b_meas.vx2 = vx2;
b_meas.vy2 = vy2;
b_meas.vz2 = vz2;
b_meas.z = z;
b_meas.bx1 = bx1;
b_meas.by1 = by1;
b_meas.bz1 = bz1;
b_meas.bx2 = bx2;
b_meas.by2 = by2;
b_meas.bz2 = bz2;

%Done
