/* ************************************************************** */ /* * Module BTWIRE * This module contains functions to determine the transverse fields * along a wire. A current pulse is applied to the wire and the * motion of the wire is recorded. Calibration magnets are required * at the beginning and end of the region of interest. * * Zachary Wolf * 4/9/02 */ /* ************************************************************** */ /* INCLUDES */ #include #include #include #include #include "iaux.h" #include "tds754d.h" #include "btwire.h" #include "btwireui.h" /* ************************************************************** */ /* PRIVATE PARAMETERS */ static char log_file[BTWIRE_MAX_NUM_CHAR]; static char dat_file[BTWIRE_MAX_NUM_CHAR]; static char plt_file[BTWIRE_MAX_NUM_CHAR]; static struct btwire_param_struct btwire_param; /* ************************************************************** */ /* PRIVATE GLOBAL VARIABLES */ static int tds754d_ID; static char msg[BTWIRE_MAX_NUM_CHAR]; /* ************************************************************** */ /* PRIVATE FUNCTIONS */ void btwire_error(char* message); int btwire_check_param(void); void btwire_find_calib_magnet(char name[], long int num_samp, double t[], double dvdt[], long int* index); void btwire_analyze_calib_magnet(long int num_samp, double t[], double dvdt[], long int index_nom, long int* index_calib_magnet, double* t_calib_magnet, double* dvdt_calib_magnet); void btwire_log_calib_magnet(struct btwire_calib_struct btwire_calib); void btwire_log_smooth_samp(long int num_samp, double t[], double y[], double y_smooth[]); void btwire_log_calc_dvdt_vs_t(long int num_samp, double t[], double v[], double dvdt[]); void btwire_log_analyze_calib_magnet(int num_samp, double t[], double dvdt[], double dvdt_fit[]); /* ************************************************************** */ /* PUBLIC FUNCTIONS */ /* ************************************************************** */ /* * btwire_init * This function is used to initialize the Btwire system. * * Zachary Wolf * 4/9/02 */ void btwire_init(char log_file_in[], char dat_file_in[], char plt_file_in[], struct btwire_param_struct btwire_param_in) { /* Declare variables */ int err; long int record_length = BTWIRE_RECORD_LENGTH; /* Save parameters for future use */ strcpy(log_file, log_file_in); strcpy(dat_file, dat_file_in); strcpy(plt_file, plt_file_in); btwire_param = btwire_param_in; /* Check all parameter values to find any problems */ err = btwire_check_param(); if (err != 0) { btwire_error("Problem with parameter values"); return; } /* Initialize the required hardware */ if (btwire_param.config == BTWIRE_TDS754D) { tds754d_init(btwire_param.board_addr, btwire_param.tds754d_addr, &tds754d_ID); tds754d_factory_setup(tds754d_ID); tds754d_set_vert_chan_select(tds754d_ID, btwire_param.chan_x_wire_pos_sensor, ON); tds754d_set_vert_chan_select(tds754d_ID, btwire_param.chan_y_wire_pos_sensor, ON); tds754d_set_vert_chan_select(tds754d_ID, btwire_param.chan_wire_current_sensor, ON); tds754d_set_vert_coupling(tds754d_ID, btwire_param.chan_x_wire_pos_sensor, AC); tds754d_set_vert_coupling(tds754d_ID, btwire_param.chan_y_wire_pos_sensor, AC); tds754d_set_vert_coupling(tds754d_ID, btwire_param.chan_wire_current_sensor, DC); tds754d_set_vert_scale(tds754d_ID, btwire_param.chan_x_wire_pos_sensor, btwire_param.scale_x_wire_pos_sensor); tds754d_set_vert_scale(tds754d_ID, btwire_param.chan_y_wire_pos_sensor, btwire_param.scale_y_wire_pos_sensor); tds754d_set_vert_scale(tds754d_ID, btwire_param.chan_wire_current_sensor, btwire_param.scale_wire_current_sensor); tds754d_set_vert_position(tds754d_ID, btwire_param.chan_x_wire_pos_sensor, 1.); tds754d_set_vert_position(tds754d_ID, btwire_param.chan_y_wire_pos_sensor, 0.); tds754d_set_vert_position(tds754d_ID, btwire_param.chan_wire_current_sensor, -3.); tds754d_set_horiz_record_length(tds754d_ID, record_length); tds754d_set_horiz_fit_to_screen(tds754d_ID); tds754d_set_horiz_scale(tds754d_ID, btwire_param.scale_horizontal / (record_length / 500)); tds754d_set_horiz_trigger_position(tds754d_ID, 10); /* trigger position 10% of record */ tds754d_set_trig_mode(tds754d_ID, NORM); if (btwire_param.chan_wire_current_sensor == 3) tds754d_set_trig_edge(tds754d_ID, CH3, TDC, RISE); else btwire_error("Unexpected configuration"); tds754d_set_trig_level(tds754d_ID, 5. * btwire_param.wire_current_sensor_v_per_a); /* trigger at 5 A */ tds754d_set_acq_mode(tds754d_ID, AVERAGE); tds754d_set_acq_num_ave(tds754d_ID, BTWIRE_NUM_AVE); } else { btwire_error("Unknown BTWIRE system configuration"); return; } /* Done */ return; } /* ************************************************************** */ /* * btwire_get_bt_vs_z * This function gets the transverse fields along the wire. * * Input: * record_results, n = no record, only update the user interface, y = yes, record results * * Output: * num_samp, number of samples in the waveform * z[0 to num_samp - 1], z position of each sample relative to the wire position detectors (m) * b_x[0 to num_samp - 1], x component of the transverse field along the wire (T) * b_y[0 to num_samp - 1], y component of the transverse field along the wire (T) * * Zachary Wolf * 6/10/02 */ void btwire_get_bt_vs_z(char record_results, long int* num_samp, double z[], double b_x[], double b_y[]) { /* Declare all variables */ double t[BTWIRE_MAX_NUM_SAMP]; double v_w_x[BTWIRE_MAX_NUM_SAMP]; double v_w_y[BTWIRE_MAX_NUM_SAMP]; double v_smooth_w_x[BTWIRE_MAX_NUM_SAMP]; double v_smooth_w_y[BTWIRE_MAX_NUM_SAMP]; double dvdt_rough_w_x[BTWIRE_MAX_NUM_SAMP]; double dvdt_rough_w_y[BTWIRE_MAX_NUM_SAMP]; double dvdt_smooth_w_x[BTWIRE_MAX_NUM_SAMP]; double dvdt_smooth_w_y[BTWIRE_MAX_NUM_SAMP]; double dvdt_w_x[BTWIRE_MAX_NUM_SAMP]; double dvdt_w_y[BTWIRE_MAX_NUM_SAMP]; struct btwire_calib_struct btwire_calib; int ok; /* Message */ printf("\nMeasuring Bt...\n"); /* Get the voltage samples */ remeasure: btwire_get_v_vs_t(num_samp, t, v_w_x, v_w_y); /* Update the user interface */ btwireui_clear_v_vs_t(); btwireui_update_v_vs_t(*num_samp, t, v_w_x, v_w_y); /* Smooth the data before taking the derivative */ btwire_smooth_samp(*num_samp, t, v_w_x, v_smooth_w_x); btwire_smooth_samp(*num_samp, t, v_w_y, v_smooth_w_y); /* Calculate the voltage derivatives */ btwire_calc_dvdt_vs_t(*num_samp, t, v_smooth_w_x, dvdt_rough_w_x); btwire_calc_dvdt_vs_t(*num_samp, t, v_smooth_w_y, dvdt_rough_w_y); /* Smooth the voltage derivatives */ btwire_smooth_samp(*num_samp, t, dvdt_rough_w_x, dvdt_smooth_w_x); btwire_smooth_samp(*num_samp, t, dvdt_rough_w_y, dvdt_smooth_w_y); /* Remove the current pulse */ btwire_remove_current_pulse(*num_samp, t, dvdt_smooth_w_x, dvdt_w_x); btwire_remove_current_pulse(*num_samp, t, dvdt_smooth_w_y, dvdt_w_y); /* Update the user interface */ btwireui_clear_dvdt_vs_t(); btwireui_update_dvdt_vs_t(*num_samp, t, dvdt_w_x, dvdt_w_y); /* Calibrate the system using the calibration magnets */ btwire_get_calib(*num_samp, t, dvdt_w_x, dvdt_w_y, &btwire_calib); /* Calculate the transverse fields */ btwire_calc_bt_vs_z(*num_samp, t, dvdt_w_x, dvdt_w_y, btwire_calib, z, b_x, b_y); /* Update the user interface */ btwireui_clear_bt_vs_z(); btwireui_update_bt_vs_z(*num_samp, z, b_x, b_y); /* Mark the calibration magnets on the user interface */ btwireui_mark_calib_magnet_v_vs_t(t[btwire_calib.index_calib_magnet_bx1], v_w_y[btwire_calib.index_calib_magnet_bx1]); btwireui_mark_calib_magnet_v_vs_t(t[btwire_calib.index_calib_magnet_bx2], v_w_y[btwire_calib.index_calib_magnet_bx2]); btwireui_mark_calib_magnet_v_vs_t(t[btwire_calib.index_calib_magnet_by1], v_w_x[btwire_calib.index_calib_magnet_by1]); btwireui_mark_calib_magnet_v_vs_t(t[btwire_calib.index_calib_magnet_by2], v_w_x[btwire_calib.index_calib_magnet_by2]); btwireui_mark_calib_magnet_dvdt_vs_t(t[btwire_calib.index_calib_magnet_bx1], dvdt_w_y[btwire_calib.index_calib_magnet_bx1]); btwireui_mark_calib_magnet_dvdt_vs_t(t[btwire_calib.index_calib_magnet_bx2], dvdt_w_y[btwire_calib.index_calib_magnet_bx2]); btwireui_mark_calib_magnet_dvdt_vs_t(t[btwire_calib.index_calib_magnet_by1], dvdt_w_x[btwire_calib.index_calib_magnet_by1]); btwireui_mark_calib_magnet_dvdt_vs_t(t[btwire_calib.index_calib_magnet_by2], dvdt_w_x[btwire_calib.index_calib_magnet_by2]); btwireui_mark_calib_magnet_bt_vs_z(z[btwire_calib.index_calib_magnet_bx1], b_x[btwire_calib.index_calib_magnet_bx1], z[btwire_calib.index_calib_magnet_by1], b_y[btwire_calib.index_calib_magnet_by1]); btwireui_mark_calib_magnet_bt_vs_z(z[btwire_calib.index_calib_magnet_bx2], b_x[btwire_calib.index_calib_magnet_bx2], z[btwire_calib.index_calib_magnet_by2], b_y[btwire_calib.index_calib_magnet_by2]); /* Perform some checks */ ok = 1; if (btwire_calib.bt_calib_magnet_bx1 < .0001) {printf("Problem with the Bx1 calibration magnet.\n"); ok = 0;} if (btwire_calib.bt_calib_magnet_bx2 < .0001) {printf("Problem with the Bx2 calibration magnet.\n"); ok = 0;} if (btwire_calib.bt_calib_magnet_by1 < .0001) {printf("Problem with the By1 calibration magnet.\n"); ok = 0;} if (btwire_calib.bt_calib_magnet_by2 < .0001) {printf("Problem with the By2 calibration magnet.\n"); ok = 0;} if (fabs((btwire_calib.z_calib_factor_bx1_bx2 - btwire_calib.z_calib_factor_by1_by2) / (btwire_calib.z_calib_factor_bx1_bx2 + btwire_calib.z_calib_factor_by1_by2) / 2.) > .1) {printf("Problem with z_calib_factor.\n"); ok = 0;} if (fabs(btwire_param.zpos_calib_magnet_bx1 - t[btwire_calib.index_calib_magnet_bx1] * (btwire_calib.z_calib_factor_bx1_bx2 + btwire_calib.z_calib_factor_by1_by2) / 2.) > .02) {printf("Problem with calculated Z for x1 calibration magnet.\n"); ok = 0;} if (fabs(btwire_param.zpos_calib_magnet_bx2 - t[btwire_calib.index_calib_magnet_bx2] * (btwire_calib.z_calib_factor_bx1_bx2 + btwire_calib.z_calib_factor_by1_by2) / 2.) > .02) {printf("Problem with calculated Z for x2 calibration magnet.\n"); ok = 0;} if (fabs(btwire_param.zpos_calib_magnet_by1 - t[btwire_calib.index_calib_magnet_by1] * (btwire_calib.z_calib_factor_bx1_bx2 + btwire_calib.z_calib_factor_by1_by2) / 2.) > .02) {printf("Problem with calculated Z for y1 calibration magnet.\n"); ok = 0;} if (fabs(btwire_param.zpos_calib_magnet_by2 - t[btwire_calib.index_calib_magnet_by2] * (btwire_calib.z_calib_factor_bx1_bx2 + btwire_calib.z_calib_factor_by1_by2) / 2.) > .02) {printf("Problem with calculated Z for y2 calibration magnet.\n"); ok = 0;} if (ok != 1) { printf("Remeasure...\n"); goto remeasure; } /* Record the resuts */ if (record_results == 'y') { /* Record the calibration results */ btwire_dat_calib(btwire_calib); /* Plot all data */ btwire_plt_all(*num_samp, t, v_w_x, v_w_y, v_smooth_w_x, v_smooth_w_y, dvdt_w_x, dvdt_w_y, z, b_x, b_y); } /* Message */ printf("Done measuring Bt.\n"); /* Done */ return; } /* ************************************************************** */ /* * btwire_get_v_vs_t * This function gets the voltages from the x and y wire position * sensors. * * Output: * num_samp, number of samples in the waveform * t[0 to num_samp - 1], time of each sample relative to the trigger (sec) * v_w_x[0 to num_samp - 1], voltage samples from the wire x-position sensor (V) * v_w_y[0 to num_samp - 1], voltage samples from the wire y-position sensor (V) * * Zachary Wolf * 5/22/02 */ void btwire_get_v_vs_t(long int* num_samp, double t[], double v_w_x[], double v_w_y[]) { /* Declare variables */ int err; double delta_t, t_cal_mag_1, t_cal_mag_2; /* debug */ double b_earth, b_cal_mag; /* debug */ long int i, i_trig, i_cal_mag_1, i_cal_mag_2; /* debug */ double di_length_cal_mag; /* debug */ /* Check all module lever parameter values */ err = btwire_check_param(); if (err != 0) { btwire_error("btwire_get_v_vs_t: Problem with parameter values"); return; } /* Debug */ #ifdef DUMMY_DEVICES *num_samp = BTWIRE_RECORD_LENGTH; i_trig = 0.1 * *num_samp; /* trigger at 10% of the record length */ delta_t = btwire_param.scale_horizontal * 10. / *num_samp; t_cal_mag_1 = btwire_param.zpos_calib_magnet_bx1 / btwire_param.nominal_wave_speed; t_cal_mag_2 = btwire_param.zpos_calib_magnet_bx2 / btwire_param.nominal_wave_speed; i_cal_mag_1 = i_trig + t_cal_mag_1 / delta_t; i_cal_mag_2 = i_trig + t_cal_mag_2 / delta_t; t[0] = (0 - i_trig) * delta_t; v_w_x[0] = 0.; v_w_y[0] = 0.; b_earth = .00005; b_cal_mag = .0014; di_length_cal_mag = .005 / (btwire_param.zpos_calib_magnet_bx2 - btwire_param.zpos_calib_magnet_bx1) / (i_cal_mag_2 - i_cal_mag_1); for (i = 1; i < *num_samp; i++) { t[i] = (i - i_trig) * delta_t; v_w_x[i] = v_w_x[i-1] + b_earth + b_cal_mag * di_length_cal_mag / sqrt(pow(i - i_cal_mag_1, 2) + pow(di_length_cal_mag, 2)) + b_cal_mag * di_length_cal_mag / sqrt(pow(i - i_cal_mag_2, 2) + pow(di_length_cal_mag, 2)); v_w_y[i] = v_w_y[i-1] + .7 * b_earth + b_cal_mag * di_length_cal_mag / sqrt(pow(i - i_cal_mag_1, 2) + pow(di_length_cal_mag, 2)) + b_cal_mag * di_length_cal_mag / sqrt(pow(i - i_cal_mag_2, 2) + pow(di_length_cal_mag, 2)); } return; #endif /* Get the voltages from the wire position sensors */ if (btwire_param.config == BTWIRE_TDS754D) { tds754d_get_waveform(tds754d_ID, btwire_param.chan_x_wire_pos_sensor, num_samp, t, v_w_x); tds754d_get_waveform(tds754d_ID, btwire_param.chan_y_wire_pos_sensor, num_samp, t, v_w_y); } else { btwire_error("Unknown BTWIRE system configuration"); return; } /* Check num_samp */ if (*num_samp > BTWIRE_MAX_NUM_SAMP) btwire_error("btwire_get_v_vs_t: num_samp > BTWIRE_MAX_NUM_SAMP"); /* Done */ return; } /* ************************************************************** */ /* * btwire_smooth_samp * This function smooths the input data. * * Input: * num_samp, number of samples in the waveform * t[0 to num_samp - 1], time of each sample relative to the trigger (sec) * y[0 to num_samp - 1], input samples (V, V/s, ...) * * Output: * y_smooth[0 to num_samp - 1], smoothed samples (V, V/s, ...) * * Zachary Wolf * 6/22/02 */ void btwire_smooth_samp(long int num_samp, double t[], double y[], double y_smooth[]) { /* Declare variables */ int err; long int i; int j, k; int num_samp_in_fit = BTWIRE_NUM_SAMP_IN_FIT_SMOOTH; double t_samp_for_fit[BTWIRE_NUM_SAMP_IN_FIT_SMOOTH]; double y_samp_for_fit[BTWIRE_NUM_SAMP_IN_FIT_SMOOTH]; int num_samp_one_side; double z[BTWIRE_NUM_SAMP_IN_FIT_SMOOTH]; double coef[10]; double mse; int order, o; /* Calculate the number of samples for the fit on each side of the sample of interest */ num_samp_one_side = (num_samp_in_fit - 1) / 2; /* Fit a range of the data centered on each sample */ /* Use the fit to fill smoothed data at the beginning and end of the array */ for (i = num_samp_one_side; i < num_samp - num_samp_one_side; i++) { for (j = -num_samp_one_side; j <= num_samp_one_side; j++) { t_samp_for_fit[j + num_samp_one_side] = t[i + j]; y_samp_for_fit[j + num_samp_one_side] = y[i + j]; } /* Running average */ y_smooth[i] = 0.; for (k = 0; k < 2 * num_samp_one_side + 1; k++) y_smooth[i] += y_samp_for_fit[k]; y_smooth[i] = y_smooth[i] / (2 * num_samp_one_side + 1); if (i == num_samp_one_side) { for (k = 0; k < i; k++) y_smooth[k] = y_smooth[i]; } if (i == num_samp - num_samp_one_side - 1) { for (k = i + 1; k < num_samp; k++) y_smooth[k] = y_smooth[i]; } /* Linear fit */ /* PolyFit(t_samp_for_fit, y_samp_for_fit, 2 * num_samp_one_side + 1, 1, z, coef, &mse); y_smooth[i] = coef[0] + coef[1] * t[i]; if (i == num_samp_one_side) { for (k = 0; k < i; k++) y_smooth[k] = coef[0] + coef[1] * t[k]; } if (i == num_samp - num_samp_one_side - 1) { for (k = i + 1; k < num_samp; k++) y_smooth[k] = coef[0] + coef[1] * t[k]; } */ /* Polynomial fit */ /* order = 2; PolyFit(t_samp_for_fit, y_samp_for_fit, 2 * num_samp_one_side + 1, order, z, coef, &mse); y_smooth[i] = coef[0]; for (o = 1; o <= order; o++) y_smooth[i] += coef[o] * pow(t[i], o); if (i == num_samp_one_side) { for (k = 0; k < i; k++) { y_smooth[k] = coef[0]; for (o = 1; o <= order; o++) y_smooth[k] += coef[o] * pow(t[k], o); } } if (i == num_samp - num_samp_one_side - 1) { for (k = i + 1; k < num_samp; k++) { y_smooth[k] = coef[0]; for (o = 1; o <= order; o++) y_smooth[k] += coef[o] * pow(t[k], o); } } */ } /* Log the result */ btwire_log_smooth_samp(num_samp, t, y, y_smooth); /* Done */ return; } /* ************************************************************** */ /* * btwire_calc_dvdt_vs_t * This function calculates the voltage derivative * using a polynomial fit to a small range of the data. * * Input: * num_samp, number of samples in the waveform * t[0 to num_samp - 1], time of each sample relative to the trigger (sec) * v[0 to num_samp - 1], voltage samples from the wire position sensor (V) * * Output: * dvdt[0 to num_samp - 1], fitted voltage derivative samples (V/s) * * Zachary Wolf * 6/20/02 */ void btwire_calc_dvdt_vs_t(long int num_samp, double t[], double v[], double dvdt[]) { /* Declare variables */ int err; long int i; int j, k; int num_samp_in_fit = BTWIRE_NUM_SAMP_IN_FIT_DERIV; double t_samp_for_fit[BTWIRE_NUM_SAMP_IN_FIT_DERIV]; double v_samp_for_fit[BTWIRE_NUM_SAMP_IN_FIT_DERIV]; int num_samp_one_side; double z[BTWIRE_NUM_SAMP_IN_FIT_DERIV]; double coef[10]; double mse; /* Calculate the number of samples for the fit on each side of the sample of interest */ num_samp_one_side = (num_samp_in_fit - 1) / 2; /* Fit a range of the data centered on each sample */ /* Use the fit for the beginning and end of the array */ for (i = num_samp_one_side; i < num_samp - num_samp_one_side; i++) { for (j = -num_samp_one_side; j <= num_samp_one_side; j++) { t_samp_for_fit[j + num_samp_one_side] = t[i + j]; v_samp_for_fit[j + num_samp_one_side] = v[i + j]; } //PolyFit(t_samp_for_fit, v_samp_for_fit, num_samp_in_fit, 2, z, coef, &mse); //dvdt[i] = coef[1] + 2. * coef[2] * t[i]; PolyFit(t_samp_for_fit, v_samp_for_fit, 2 * num_samp_one_side + 1, 1, z, coef, &mse); dvdt[i] = coef[1]; if (i == num_samp_one_side) { for (k = 0; k < i; k++) dvdt[k] = coef[1]; } if (i == num_samp - num_samp_one_side - 1) { for (k = i + 1; k < num_samp; k++) dvdt[k] = coef[1]; } } /* Log the result */ btwire_log_calc_dvdt_vs_t(num_samp, t, v, dvdt); /* Done */ return; } /* ************************************************************** */ /* * btwire_remove_current_pulse * This function removes the noisy data points in the * samples which come from the current pulse. * * Input: * num_samp, number of samples in the waveform * t[0 to num_samp - 1], time of each sample relative to the trigger (sec) * y[0 to num_samp - 1], noisy samples (V, V/s, ...) * * Output: * y_no_pulse[0 to num_samp - 1], samples with the current pulse removed (V, V/s, ...) * * Zachary Wolf * 6/20/02 */ void btwire_remove_current_pulse(long int num_samp, double t[], double y[], double y_no_pulse[]) { /* Declare variables */ long int i; /* Remove data before the trigger and during the current pulse */ for (i = 0; i < num_samp; i++) { if (t[i] < BTWIRE_TIME_CUTOFF_TO_REMOVE_CURRENT_PULSE) y_no_pulse[i] = 0.; else y_no_pulse[i] = y[i]; } /* Done */ return; } /* ************************************************************** */ /* * btwire_get_calib * This function uses the calibration magnets to calculate all * calibration factors. * * Input: * num_samp, number of samples in the waveform * t[0 to num_samp - 1], time of each sample relative to the trigger (sec) * dvdt_w_x[0 to num_samp - 1], voltage derivative samples from the wire x-position sensor (V/s) * dvdt_w_y[0 to num_samp - 1], voltage derivative samples from the wire y-position sensor (V/s) * * Output: * btwire_calib, structure containing information about the calibration magnets and calibration factors * * Zachary Wolf * 6/10/02 */ void btwire_get_calib(long int num_samp, double t[], double dvdt_w_x[], double dvdt_w_y[], struct btwire_calib_struct* btwire_calib) { /* Declare variables */ int err; long int index_nom_bx1, index_nom_bx2, index_nom_by1, index_nom_by2; /* Check all module lever parameter values */ err = btwire_check_param(); if (err != 0) { btwire_error("btwire_get_calib: Problem with parameter values"); return; } /* Calculate the field in the calibration magnets */ iaux_get_current(&(btwire_calib->imag_calib_magnet)); btwire_calib->bt_calib_magnet_bx1 = btwire_param.bx_per_a_calib_magnet_bx1 * btwire_calib->imag_calib_magnet; btwire_calib->bt_calib_magnet_bx2 = btwire_param.bx_per_a_calib_magnet_bx2 * btwire_calib->imag_calib_magnet; btwire_calib->bt_calib_magnet_by1 = btwire_param.by_per_a_calib_magnet_by1 * btwire_calib->imag_calib_magnet; btwire_calib->bt_calib_magnet_by2 = btwire_param.by_per_a_calib_magnet_by2 * btwire_calib->imag_calib_magnet; /* Find the calibration magnets */ btwire_find_calib_magnet("bx1", num_samp, t, dvdt_w_y, &index_nom_bx1); btwire_find_calib_magnet("bx2", num_samp, t, dvdt_w_y, &index_nom_bx2); btwire_find_calib_magnet("by1", num_samp, t, dvdt_w_x, &index_nom_by1); btwire_find_calib_magnet("by2", num_samp, t, dvdt_w_x, &index_nom_by2); /* Analyze the calibration magnets to get the signal arrival time, dv/dt, and to refine the index position */ btwire_analyze_calib_magnet(num_samp, t, dvdt_w_y, index_nom_bx1, &(btwire_calib->index_calib_magnet_bx1), &(btwire_calib->t_calib_magnet_bx1), &(btwire_calib->dvdty_calib_magnet_bx1)); btwire_analyze_calib_magnet(num_samp, t, dvdt_w_y, index_nom_bx2, &(btwire_calib->index_calib_magnet_bx2), &(btwire_calib->t_calib_magnet_bx2), &(btwire_calib->dvdty_calib_magnet_bx2)); btwire_analyze_calib_magnet(num_samp, t, dvdt_w_x, index_nom_by1, &(btwire_calib->index_calib_magnet_by1), &(btwire_calib->t_calib_magnet_by1), &(btwire_calib->dvdtx_calib_magnet_by1)); btwire_analyze_calib_magnet(num_samp, t, dvdt_w_x, index_nom_by2, &(btwire_calib->index_calib_magnet_by2), &(btwire_calib->t_calib_magnet_by2), &(btwire_calib->dvdtx_calib_magnet_by2)); /* Calculate the Bt / dv/dt calibration factors */ /* bx1 / dvdt_y */ if (btwire_calib->dvdty_calib_magnet_bx1 == 0.) btwire_calib->bt_calib_factor_bx1_dvdty = 0.; else btwire_calib->bt_calib_factor_bx1_dvdty = btwire_calib->bt_calib_magnet_bx1 / btwire_calib->dvdty_calib_magnet_bx1; /* bx2 / dvdt_y */ if (btwire_calib->dvdty_calib_magnet_bx2 == 0.) btwire_calib->bt_calib_factor_bx2_dvdty = 0.; else btwire_calib->bt_calib_factor_bx2_dvdty = btwire_calib->bt_calib_magnet_bx2 / btwire_calib->dvdty_calib_magnet_bx2; /* by1 / dvdt_x */ if (btwire_calib->dvdtx_calib_magnet_by1 == 0.) btwire_calib->bt_calib_factor_by1_dvdtx = 0.; else btwire_calib->bt_calib_factor_by1_dvdtx = btwire_calib->bt_calib_magnet_by1 / btwire_calib->dvdtx_calib_magnet_by1; /* by2 / dvdt_x */ if (btwire_calib->dvdtx_calib_magnet_by2 == 0.) btwire_calib->bt_calib_factor_by2_dvdtx = 0.; else btwire_calib->bt_calib_factor_by2_dvdtx = btwire_calib->bt_calib_magnet_by2 / btwire_calib->dvdtx_calib_magnet_by2; /* Save the z positions of the calibration magnets in the calib structure */ btwire_calib->zpos_calib_magnet_bx1 = btwire_param.zpos_calib_magnet_bx1; btwire_calib->zpos_calib_magnet_bx2 = btwire_param.zpos_calib_magnet_bx2; btwire_calib->zpos_calib_magnet_by1 = btwire_param.zpos_calib_magnet_by1; btwire_calib->zpos_calib_magnet_by2 = btwire_param.zpos_calib_magnet_by2; /* Calculate the z / t calibration factors */ btwire_calib->z_calib_factor_bx1_bx2 = (btwire_calib->zpos_calib_magnet_bx2 - btwire_calib->zpos_calib_magnet_bx1) / (btwire_calib->t_calib_magnet_bx2 - btwire_calib->t_calib_magnet_bx1); btwire_calib->z_calib_factor_by1_by2 = (btwire_calib->zpos_calib_magnet_by2 - btwire_calib->zpos_calib_magnet_by1) / (btwire_calib->t_calib_magnet_by2 - btwire_calib->t_calib_magnet_by1); /* Log the results */ btwire_log_calib_magnet(*btwire_calib); /* Done */ return; } /* ************************************************************** */ /* * btwire_calc_bt_vs_z * This function calculates the transverse fields along the wire. * * Input: * num_samp, number of samples in the waveform * t[0 to num_samp - 1], time of each sample relative to the trigger (sec) * dvdt_w_x[0 to num_samp - 1], voltage derivative samples from the wire x-position sensor (V/s) * dvdt_w_y[0 to num_samp - 1], voltage derivative samples from the wire y-position sensor (V/s) * btwire_calib, structure containing information about the calibration magnets and calibration factors * * Output: * z[0 to num_samp - 1], z position of each sample relative to the wire position detectors (m) * b_x[0 to num_samp - 1], x component of the transverse field along the wire (T) * b_y[0 to num_samp - 1], y component of the transverse field along the wire (T) * * Zachary Wolf * 6/10/02 */ void btwire_calc_bt_vs_z(long int num_samp, double t[], double dvdt_w_x[], double dvdt_w_y[], struct btwire_calib_struct btwire_calib, double z[], double b_x[], double b_y[]) { /* Declare variables */ int err; long int i; double K1, K2, I1, I2; /* Check all module lever parameter values */ err = btwire_check_param(); if (err != 0) { btwire_error("btwire_calc_bt_vs_z: Problem with parameter values"); return; } /* Calculate b_x */ K1 = btwire_calib.bt_calib_factor_bx1_dvdty; K2 = btwire_calib.bt_calib_factor_bx2_dvdty; I1 = btwire_calib.index_calib_magnet_bx1; I2 = btwire_calib.index_calib_magnet_bx2; for (i = 0; i < num_samp; i++) { b_x[i] = (K1 + ((K2 - K1) / (I2 - I1)) * (i - I1)) * dvdt_w_y[i]; } /* Calculate b_y */ K1 = btwire_calib.bt_calib_factor_by1_dvdtx; K2 = btwire_calib.bt_calib_factor_by2_dvdtx; I1 = btwire_calib.index_calib_magnet_by1; I2 = btwire_calib.index_calib_magnet_by2; for (i = 0; i < num_samp; i++) { b_y[i] = (K1 + ((K2 - K1) / (I2 - I1)) * (i - I1)) * dvdt_w_x[i]; } /* Calculate z */ K1 = btwire_calib.z_calib_factor_bx1_bx2; K2 = btwire_calib.z_calib_factor_by1_by2; for (i = 0; i < num_samp; i++) { z[i] = ((K1 + K2) / 2.) * t[i]; } /* Done */ return; } /* ************************************************************** */ /* * btwire_dat_bt_vs_z * This function writes the results of a transverse field measurement * to the data file. * * Input: * num_samp, number of samples in the waveform * z[0 to num_samp - 1], z position of each sample relative to the wire position detectors (m) * b_x[0 to num_samp - 1], x component of the transverse field along the wire (T) * b_y[0 to num_samp - 1], y component of the transverse field along the wire (T) * * Zachary Wolf * 6/4/02 */ void btwire_dat_bt_vs_z(long int num_samp, double z[], double b_x[], double b_y[]) { /* Declare variables */ FILE* file_ptr; long int i; /* Open the dat file */ file_ptr = fopen(dat_file, "a"); if (file_ptr == NULL) { printf("btwire_dat_bt_vs_z: Unable to open dat file\n"); return; } /* Write a header */ fprintf(file_ptr, "\n"); fprintf(file_ptr, " Transverse Field Strength vs Z\n"); fprintf(file_ptr, "\n"); fprintf(file_ptr, " Z Bx By \n"); fprintf(file_ptr, " (m) (T) (T) \n"); fprintf(file_ptr, " --------- --------- ---------\n"); /* Write the data */ for (i = 0; i < num_samp; i++) fprintf(file_ptr, " %9.6f %9.6f %9.6f\n", z[i], b_x[i], b_y[i]); /* Close the dat file */ fclose(file_ptr); /* Done */ return; } /* ************************************************************** */ /* * btwire_dat_calib * This function writes the results of the transverse field measurement * calibration to the data file. * * Input: * btwire_calib, structure containing information about the calibration magnets and calibration factors * * Zachary Wolf * 6/4/02 */ void btwire_dat_calib(struct btwire_calib_struct btwire_calib) { /* Declare variables */ FILE* file_ptr; /* Open the dat file */ file_ptr = fopen(dat_file, "a"); if (file_ptr == NULL) { printf("btwire_dat_calib: Unable to open dat file\n"); return; } /* Write a header */ fprintf(file_ptr, "\n"); fprintf(file_ptr, "Transverse Field Calibration Results:\n"); /* Write the data */ fprintf(file_ptr, "Calibration magnet current, Imag_calib_magnet = %f A\n", btwire_calib.imag_calib_magnet); fprintf(file_ptr, "Transverse field in each calibration magnet:\n"); fprintf(file_ptr, " B_x1 = %f T\n", btwire_calib.bt_calib_magnet_bx1); fprintf(file_ptr, " B_x2 = %f T\n", btwire_calib.bt_calib_magnet_bx2); fprintf(file_ptr, " B_y1 = %f T\n", btwire_calib.bt_calib_magnet_by1); fprintf(file_ptr, " B_y2 = %f T\n", btwire_calib.bt_calib_magnet_by2); fprintf(file_ptr, "Data index of each calibration magnet:\n"); fprintf(file_ptr, " I_bx1 = %i\n", btwire_calib.index_calib_magnet_bx1); fprintf(file_ptr, " I_bx2 = %i\n", btwire_calib.index_calib_magnet_bx2); fprintf(file_ptr, " I_by1 = %i\n", btwire_calib.index_calib_magnet_by1); fprintf(file_ptr, " I_by2 = %i\n", btwire_calib.index_calib_magnet_by2); fprintf(file_ptr, "Calibration factor, Bt_calib_factor_bx1_dvdty = %f T/V/s\n", btwire_calib.bt_calib_factor_bx1_dvdty); fprintf(file_ptr, "Calibration factor, Bt_calib_factor_bx2_dvdty = %f T/V/s\n", btwire_calib.bt_calib_factor_bx2_dvdty); fprintf(file_ptr, "Calibration factor, Bt_calib_factor_by1_dvdtx = %f T/V/s\n", btwire_calib.bt_calib_factor_by1_dvdtx); fprintf(file_ptr, "Calibration factor, Bt_calib_factor_by2_dvdtx = %f T/V/s\n", btwire_calib.bt_calib_factor_by2_dvdtx); fprintf(file_ptr, "Calibration factor, Z_calib_factor_bx1_bx2 = %f m/s\n", btwire_calib.z_calib_factor_bx1_bx2); fprintf(file_ptr, "Calibration factor, Z_calib_factor_by1_by2 = %f m/s\n", btwire_calib.z_calib_factor_by1_by2); /* Close the dat file */ fclose(file_ptr); /* Done */ return; } /* ************************************************************** */ /* * btwire_plt_bt_vs_z * This function writes the results of a transverse field measurement * to the plot file. * * Input: * num_samp, number of samples in the waveform * z[0 to num_samp - 1], z position of each sample relative to the wire position detectors (m) * b_x[0 to num_samp - 1], x component of the transverse field along the wire (T) * b_y[0 to num_samp - 1], y component of the transverse field along the wire (T) * * Zachary Wolf * 6/4/02 */ void btwire_plt_bt_vs_z(long int num_samp, double z[], double b_x[], double b_y[]) { /* Declare variables */ FILE* file_ptr; long int i; /* Open the dat file */ file_ptr = fopen(plt_file, "a"); if (file_ptr == NULL) { printf("btwire_plt_bt_vs_z: Unable to open plt file\n"); return; } /* Write a header */ fprintf(file_ptr, ";z (m), Bx (T), By (T)\n"); /* Write the data */ for (i = 0; i < num_samp; i++) fprintf(file_ptr, "%9.6f %9.6f %9.6f\n", z[i], b_x[i], b_y[i]); /* Close the plt file */ fclose(file_ptr); /* Done */ return; } /* ************************************************************** */ /* * btwire_plt_all * This function writes all results of a transverse field measurement * to the plot file. * * Input: * num_samp, number of samples in the waveform * t[0 to num_samp - 1], time of each sample relative to the trigger (sec) * v_w_x[0 to num_samp - 1], voltage samples from the wire x-position sensor (V) * v_w_y[0 to num_samp - 1], voltage samples from the wire y-position sensor (V) * v_smooth_w_x[0 to num_samp - 1], fitted voltage samples from the wire x-position sensor (V) * v_smooth_w_y[0 to num_samp - 1], fitted voltage samples from the wire y-position sensor (V) * dvdt_w_x[0 to num_samp - 1], fitted voltage derivative samples from the wire x-position sensor (V/s) * dvdt_w_y[0 to num_samp - 1], fitted voltage derivative samples from the wire y-position sensor (V/s) * z[0 to num_samp - 1], z position of each sample relative to the wire position detectors (m) * b_x[0 to num_samp - 1], x component of the transverse field along the wire (T) * b_y[0 to num_samp - 1], y component of the transverse field along the wire (T) * * Zachary Wolf * 6/4/02 */ void btwire_plt_all(long int num_samp, double t[], double v_w_x[], double v_w_y[], double v_smooth_w_x[], double v_smooth_w_y[], double dvdt_w_x[], double dvdt_w_y[], double z[], double b_x[], double b_y[]) { /* Declare variables */ FILE* file_ptr; long int i; /* Open the dat file */ file_ptr = fopen(plt_file, "a"); if (file_ptr == NULL) { printf("btwire_plt_all: Unable to open plt file\n"); return; } /* Write a header */ fprintf(file_ptr, ";t (sec), v_w_x (V), v_w_y (V), v_smooth_w_x (V), v_smooth_w_y (V), dvdt_w_x (V/s), dvdt_w_y (V/s), z (m), Bx (T), By (T)\n"); /* Write the data */ for (i = 0; i < num_samp; i++) fprintf(file_ptr, "%12.9f %9.6f %9.6f %9.6f %9.6f %9.3f %9.3f %9.6f %9.6f %9.6f\n", t[i], v_w_x[i], v_w_y[i], v_smooth_w_x[i], v_smooth_w_y[i], dvdt_w_x[i], dvdt_w_y[i], z[i], b_x[i], b_y[i]); /* Close the plt file */ fclose(file_ptr); /* Done */ return; } /* ************************************************************** */ /* * btwire_exit * This function is used to exit the Btwire system. * * Zachary Wolf * 6/6/02 */ void btwire_exit(void) { /* Exit all devices */ if (btwire_param.config == BTWIRE_TDS754D) { tds754d_exit(tds754d_ID); } else { btwire_error("Unknown Btwire configuration"); return; } /* Done */ return; } /* ************************************************************** */ /* INTERNAL FUNCTIONS */ /* ************************************************************** */ /* * btwire_error * This function handles errors for the Btwire module. * * Input: * message, string to display in standard I/O * * Zachary Wolf * 10/11/98 */ void btwire_error(char* message) { /* Declare variables */ char buf[80]; /* Notify the operator of the error */ printf("\nERROR: %s\n", message); Beep(); Delay(.5); Beep(); /* Terminate the program if the operator desires */ printf("Press ENTER to continue.\nPress any key then ENTER to terminate program.\n"); fgets(buf, 80, stdin); if (buf[0] == '\n') return; else exit(0); } /* ************************************************************** */ /* * btwire_check_param * This function checks that all required parameters have been assigned * appropriate values. * * Output: * err, 0 = no error, non-zero = error * * Zachary Wolf * 6/4/02 */ int btwire_check_param() { /* log_file */ if (CompareStrings(log_file, 0, "", 0, 0) == 0) { btwire_error("btwire_check_param: Log file not defined."); return -1; } /* dat_file */ if (CompareStrings(dat_file, 0, "", 0, 0) == 0) { btwire_error("btwire_check_param: Magnet strength dat file not defined."); return -1; } /* plt_file */ if (CompareStrings(plt_file, 0, "", 0, 0) == 0) { btwire_error("btwire_check_param: Magnet strength plt file not defined."); return -1; } /* board_addr */ /* taken care of by hardware functions */ /* tds754d_addr */ /* taken care of by hardware functions */ /* config */ /* OK, enum */ /* chan_x_wire_pos_sensor */ if (btwire_param.chan_x_wire_pos_sensor < 1 || btwire_param.chan_x_wire_pos_sensor > 4) { btwire_error("btwire_check_param: chan_x_wire_pos_sensor is invalid"); return -1; } /* chan_y_wire_pos_sensor */ if (btwire_param.chan_y_wire_pos_sensor < 1 || btwire_param.chan_y_wire_pos_sensor > 4) { btwire_error("btwire_check_param: chan_y_wire_pos_sensor is invalid"); return -1; } /* chan_wire_current_sensor */ if (btwire_param.chan_wire_current_sensor < 1 || btwire_param.chan_wire_current_sensor > 4) { btwire_error("btwire_check_param: chan_wire_current_sensor is invalid"); return -1; } /* scale_x_wire_pos_sensor */ if (btwire_param.scale_x_wire_pos_sensor < .001 || btwire_param.scale_x_wire_pos_sensor > 10.) { btwire_error("btwire_check_param: scale_x_wire_pos_sensor is invalid"); return -1; } /* scale_y_wire_pos_sensor */ if (btwire_param.scale_y_wire_pos_sensor < .001 || btwire_param.scale_y_wire_pos_sensor > 10.) { btwire_error("btwire_check_param: scale_y_wire_pos_sensor is invalid"); return -1; } /* scale_wire_current_sensor */ if (btwire_param.scale_wire_current_sensor < .001 || btwire_param.scale_wire_current_sensor > 10.) { btwire_error("btwire_check_param: scale_wire_current_sensor is invalid"); return -1; } /* scale_horizontal */ if (btwire_param.scale_horizontal < 1.e-10 || btwire_param.scale_horizontal > 10.) { btwire_error("btwire_check_param: scale_horizontal is invalid"); return -1; } /* wire_current_sensor_v_per_a */ if (btwire_param.wire_current_sensor_v_per_a < 1.e-5 || btwire_param.wire_current_sensor_v_per_a > 1.) { btwire_error("btwire_check_param: wire_current_sensor_v_per_a is invalid"); return -1; } /* bx_per_a_calib_magnet_bx1 */ if (btwire_param.bx_per_a_calib_magnet_bx1 < 1.e-4 || btwire_param.bx_per_a_calib_magnet_bx1 > 1.e-2) { btwire_error("btwire_check_param: bx_per_a_calib_magnet_bx1 is invalid"); return -1; } /* by_per_a_calib_magnet_by1 */ if (btwire_param.by_per_a_calib_magnet_by1 < 1.e-4 || btwire_param.by_per_a_calib_magnet_by1 > 1.e-2) { btwire_error("btwire_check_param: by_per_a_calib_magnet_by1 is invalid"); return -1; } /* bx_per_a_calib_magnet_bx2 */ if (btwire_param.bx_per_a_calib_magnet_bx2 < 1.e-4 || btwire_param.bx_per_a_calib_magnet_bx2 > 1.e-2) { btwire_error("btwire_check_param: bx_per_a_calib_magnet_bx2 is invalid"); return -1; } /* by_per_a_calib_magnet_by2 */ if (btwire_param.by_per_a_calib_magnet_by2 < 1.e-4 || btwire_param.by_per_a_calib_magnet_by2 > 1.e-2) { btwire_error("btwire_check_param: by_per_a_calib_magnet_by2 is invalid"); return -1; } /* zpos_calib_magnet_bx1 */ if (btwire_param.zpos_calib_magnet_bx1 < 0.01 || btwire_param.zpos_calib_magnet_bx1 > 10.) { btwire_error("btwire_check_param: zpos_calib_magnet_bx1 is invalid"); return -1; } /* zpos_calib_magnet_bx2 */ if (btwire_param.zpos_calib_magnet_bx2 < btwire_param.zpos_calib_magnet_bx1 || btwire_param.zpos_calib_magnet_bx2 > 10.) { btwire_error("btwire_check_param: zpos_calib_magnet_bx2 is invalid"); return -1; } /* zpos_calib_magnet_by1 */ if (btwire_param.zpos_calib_magnet_by1 < 0.01 || btwire_param.zpos_calib_magnet_by1 > 10.) { btwire_error("btwire_check_param: zpos_calib_magnet_by1 is invalid"); return -1; } /* zpos_calib_magnet_by2 */ if (btwire_param.zpos_calib_magnet_by2 < btwire_param.zpos_calib_magnet_by1 || btwire_param.zpos_calib_magnet_by2 > 10.) { btwire_error("btwire_check_param: zpos_calib_magnet_by2 is invalid"); return -1; } /* nominal_wave_speed */ if (btwire_param.nominal_wave_speed < 0. || btwire_param.nominal_wave_speed > 1000.) { btwire_error("btwire_check_param: nominal_wave_speed is invalid"); return -1; } /* show_ui */ /* OK, enum */ /* If we made it this far, all parameters have values */ return 0; } /* ************************************************************** */ /* * btwire_find_calib_magnet * This function finds the specified calibration magnet. * It finds the peak in the signal corresponding to the * transverse field strength at z locations near the * nominal calibration magnet position. * * Input: * name, calibration magnet name * num_samp, number of samples in the waveform * t[0 to num_samp - 1], time of each sample (sec) * dvdt[0 to num_samp - 1], voltage derivative samples, proportional to field strength (V/s) * * Output: * index, sample number corresponding to the center of the first calibration magnet * * Zachary Wolf * 6/7/02 */ void btwire_find_calib_magnet(char name[], long int num_samp, double t[], double dvdt[], long int* index) { /* Declare variables */ double t_nom; double t_diff_min; long int index_nom; double z_range = BTWIRE_Z_RANGE_TO_FIND_CALIB_MAGNET; double t_range; int i_range; long int i; double dvdt_max; /* Find the nominal time that the signal reached the detector */ if (strcmp(name, "bx1") == 0) t_nom = btwire_param.zpos_calib_magnet_bx1 / btwire_param.nominal_wave_speed; else if (strcmp(name, "bx2") == 0) t_nom = btwire_param.zpos_calib_magnet_bx2 / btwire_param.nominal_wave_speed; else if (strcmp(name, "by1") == 0) t_nom = btwire_param.zpos_calib_magnet_by1 / btwire_param.nominal_wave_speed; else if (strcmp(name, "by2") == 0) t_nom = btwire_param.zpos_calib_magnet_by2 / btwire_param.nominal_wave_speed; else btwire_error("btwire_find_calib_magnet: unknown calibration magnet"); /* Find the nominal index of the calibration magnet */ t_diff_min = fabs(t_nom - t[0]); index_nom = 0; for (i = 0; i < num_samp; i++) { if (fabs(t_nom - t[i]) < t_diff_min) { t_diff_min = fabs(t_nom - t[i]); index_nom = i; } } /* Look for the calibration magnet in a range about the nominal position */ t_range = z_range / btwire_param.nominal_wave_speed; i_range = t_range / (t[1] - t[0]); /* Find the peak in the dvdt signal in the specified range */ dvdt_max = 0.; for (i = index_nom - i_range / 2; i <= index_nom + i_range / 2; i++) { if (fabs(dvdt[i]) > dvdt_max) { dvdt_max = fabs(dvdt[i]); *index = i; } } /* Check that the peak is in the middle of the range */ if (*index == index_nom - i_range / 2 || *index == index_nom + i_range / 2) btwire_error("btwire_find_calib_magnet: could not find peak within allowed range"); /* Done */ return; } /* ************************************************************** */ /* * btwire_analyze_calib_magnet * This function calculates dv/dt in the calibration magnet * and the arrival time of the signal from the calibration magnet. * The index of the calibration magnet is also refined. * * Input: * num_samp, number of samples in the waveform * t[0 to num_samp - 1], time of each sample relative to the trigger (sec) * dvdt[0 to num_samp - 1], voltage derivative samples from the wire position sensor (V/s) * index_nom, nominal index position * * Output: * index_calib_magnet, index giving the location of the calibration magnet in the array * t_calib_magnet, signal arrival time from the calibration magnet * dvdt_calib_magnet, dv/dt in the calibration magnet * * Zachary Wolf * 9/10/02 */ void btwire_analyze_calib_magnet(long int num_samp, double t[], double dvdt[], long int index_nom, long int* index_calib_magnet, double* t_calib_magnet, double* dvdt_calib_magnet) { /* Declare variables */ double length_to_fit = BTWIRE_LENGTH_OF_CALIB_MAGNET_FOR_DVDT; double time_to_fit; int num_samp_each_side; int num_samp_in_fit; int i; double t_in_fit[500]; double dvdt_in_fit[500]; int order; double z[500]; double coef[10]; double mse; double dvdt_max; int index; /* Debug */ //printf("btwire_analyze_calib_magnet: debug\n"); //*index_calib_magnet = index_nom; //*t_calib_magnet = t[index_nom]; //*dvdt_calib_magnet = dvdt[index_nom]; //return; /* Determine how many samples to fit */ time_to_fit = length_to_fit / btwire_param.nominal_wave_speed; num_samp_each_side = time_to_fit / (t[1] - t[0]) / 2.; /* Check */ if (index_nom - num_samp_each_side < 0 || index_nom + num_samp_each_side > num_samp - 1) { btwire_error("btwire_analyze_calib_magnet: can not analyze calibration magnet"); *index_calib_magnet = 0; *t_calib_magnet = 0.; *dvdt_calib_magnet = 0.; return; } /* Fill arrays with the samples to fit */ num_samp_in_fit = (2 * num_samp_each_side + 1); if (num_samp_in_fit > 500) { btwire_error("Can not find dv/dt in calibration magnet"); *index_calib_magnet = index_nom; *t_calib_magnet = 0.; *dvdt_calib_magnet = 0.; return; } for (i = -num_samp_each_side; i <= num_samp_each_side; i++) { t_in_fit[num_samp_each_side + i] = t[index_nom + i]; dvdt_in_fit[num_samp_each_side + i] = dvdt[index_nom + i]; } /* Get the average dv/dt in the calibration magnet */ //*dvdt_calib_magnet = 0; //for (i = -num_samp_each_side; i <= num_samp_each_side; i++) *dvdt_calib_magnet += dvdt[index_nom + i]; //*dvdt_calib_magnet = *dvdt_calib_magnet / (2 * num_samp_each_side + 1); /* Polynomial fit */ order = 2; PolyFit(t_in_fit, dvdt_in_fit, num_samp_in_fit, order, z, coef, &mse); /* Find the peak in the fitted values */ dvdt_max = 0.; for (i = 0; i < num_samp_in_fit; i++) { if (fabs(z[i]) > dvdt_max) { dvdt_max = fabs(z[i]); index = i; } } /* Check that the peak is in the middle of the range */ if (index == 0 || index == num_samp_in_fit - 1) { btwire_error("btwire_analyze_calib_magnet: could not find peak within allowed range"); *index_calib_magnet = index_nom; *t_calib_magnet = 0.; *dvdt_calib_magnet = 0.; return; } /* Set dv/dt to the peak value, calculate the index of the peak, find the time at the index value */ *index_calib_magnet = index_nom - num_samp_each_side + index; *t_calib_magnet = t_in_fit[index]; *dvdt_calib_magnet = z[index]; /* Log the results */ btwire_log_analyze_calib_magnet(num_samp_in_fit, t_in_fit, dvdt_in_fit, z); /* Done */ return; } /* ************************************************************** */ /* * btwire_log_calib_magnet * This function logs information about a calibration magnet. * * Input: * btwire_calib, structure containing information about the calibration magnets * * Zachary Wolf * 6/10/02 */ void btwire_log_calib_magnet(struct btwire_calib_struct btwire_calib) { /* Declare variables */ FILE* file_ptr; /* Open the log file */ file_ptr = fopen(log_file, "a"); if (file_ptr == NULL) { btwire_error("Unable to open log file"); return; } /* Write the measured values to the log file */ fprintf(file_ptr, "%s Calibration Magnet Calculations\n", TimeStr()); fprintf(file_ptr, " Magnet: %s\n", "BX1"); fprintf(file_ptr, " imag = %f A\n", btwire_calib.imag_calib_magnet); fprintf(file_ptr, " bt = %f T\n", btwire_calib.bt_calib_magnet_bx1); fprintf(file_ptr, " index = %i\n", btwire_calib.index_calib_magnet_bx1); fprintf(file_ptr, " dV/dt = %f V/s\n", btwire_calib.dvdty_calib_magnet_bx1); fprintf(file_ptr, " calib_factor bt/dvdt = %e T/V/s\n", btwire_calib.bt_calib_factor_bx1_dvdty); fprintf(file_ptr, " zpos = %f m\n", btwire_calib.zpos_calib_magnet_bx1); fprintf(file_ptr, " t = %f sec\n", btwire_calib.t_calib_magnet_bx1); fprintf(file_ptr, " calib_factor z/t = %f m/s\n", btwire_calib.z_calib_factor_bx1_bx2); fprintf(file_ptr, " Magnet: %s\n", "BX2"); fprintf(file_ptr, " imag = %f A\n", btwire_calib.imag_calib_magnet); fprintf(file_ptr, " bt = %f T\n", btwire_calib.bt_calib_magnet_bx2); fprintf(file_ptr, " index = %i\n", btwire_calib.index_calib_magnet_bx2); fprintf(file_ptr, " dV/dt = %f V/s\n", btwire_calib.dvdty_calib_magnet_bx2); fprintf(file_ptr, " calib_factor bt/dvdt = %e T/V/s\n", btwire_calib.bt_calib_factor_bx2_dvdty); fprintf(file_ptr, " zpos = %f m\n", btwire_calib.zpos_calib_magnet_bx2); fprintf(file_ptr, " t = %f sec\n", btwire_calib.t_calib_magnet_bx2); fprintf(file_ptr, " calib_factor z/t = %f m/s\n", btwire_calib.z_calib_factor_bx1_bx2); fprintf(file_ptr, " Magnet: %s\n", "BY1"); fprintf(file_ptr, " imag = %f A\n", btwire_calib.imag_calib_magnet); fprintf(file_ptr, " bt = %f T\n", btwire_calib.bt_calib_magnet_by1); fprintf(file_ptr, " index = %i\n", btwire_calib.index_calib_magnet_by1); fprintf(file_ptr, " dV/dt = %f V/s\n", btwire_calib.dvdtx_calib_magnet_by1); fprintf(file_ptr, " calib_factor bt/dvdt = %e T/V/s\n", btwire_calib.bt_calib_factor_by1_dvdtx); fprintf(file_ptr, " zpos = %f m\n", btwire_calib.zpos_calib_magnet_by1); fprintf(file_ptr, " t = %f sec\n", btwire_calib.t_calib_magnet_by1); fprintf(file_ptr, " calib_factor z/t = %f m/s\n", btwire_calib.z_calib_factor_by1_by2); fprintf(file_ptr, " Magnet: %s\n", "BY2"); fprintf(file_ptr, " imag = %f A\n", btwire_calib.imag_calib_magnet); fprintf(file_ptr, " bt = %f T\n", btwire_calib.bt_calib_magnet_by2); fprintf(file_ptr, " index = %i\n", btwire_calib.index_calib_magnet_by2); fprintf(file_ptr, " dV/dt = %f V/s\n", btwire_calib.dvdtx_calib_magnet_by2); fprintf(file_ptr, " calib_factor bt/dvdt = %e T/V/s\n", btwire_calib.bt_calib_factor_by2_dvdtx); fprintf(file_ptr, " zpos = %f m\n", btwire_calib.zpos_calib_magnet_by2); fprintf(file_ptr, " t = %f sec\n", btwire_calib.t_calib_magnet_by2); fprintf(file_ptr, " calib_factor z/t = %f m/s\n", btwire_calib.z_calib_factor_by1_by2); /* Close the log file */ fclose(file_ptr); /* Done */ return; } /* ************************************************************** */ /* * btwire_log_smooth_samp * This function logs the original samples and the smoothed samples. * * Input: * num_samp, number of samples in the waveform * t[0 to num_samp - 1], time of each sample relative to the trigger (sec) * y[0 to num_samp - 1], input samples (V, V/s, ...) * y_smooth[0 to num_samp - 1], smoothed samples (V, V/s, ...) * * Zachary Wolf * 8/29/02 */ void btwire_log_smooth_samp(long int num_samp, double t[], double y[], double y_smooth[]) { /* Declare variables */ FILE* file_ptr; long int i; /* Open the log file */ file_ptr = fopen("smooth_samp.dat", "w"); if (file_ptr == NULL) { btwire_error("Unable to open smooth_samp file"); return; } /* Write the measured values to the file */ fprintf(file_ptr, "%%t (sec), y (V, V/s, ...), y_smooth (V, V/s, ...)\n"); for (i = 0; i < num_samp; i++) fprintf(file_ptr, "%10.7f %12.8f %12.8f\n", t[i], y[i], y_smooth[i]); /* Close the log file */ fclose(file_ptr); /* Done */ return; } /* ************************************************************** */ /* * btwire_log_calc_dvdt_vs_t * This function logs results from the derivative calculation. * * Input: * num_samp, number of samples in the waveform * t[0 to num_samp - 1], time of each sample relative to the trigger (sec) * v[0 to num_samp - 1], voltage samples (V) * dvdt[0 to num_samp - 1], derivative of the voltage samples (V/s) * * Zachary Wolf * 8/29/02 */ void btwire_log_calc_dvdt_vs_t(long int num_samp, double t[], double v[], double dvdt[]) { /* Declare variables */ FILE* file_ptr; long int i; /* Open the log file */ file_ptr = fopen("calc_dvdt_vs_t.dat", "w"); if (file_ptr == NULL) { btwire_error("Unable to open calc_dvdt_vs_t file"); return; } /* Write the measured values to the file */ fprintf(file_ptr, "%%t (sec), v (V), dvdt (V/s)\n"); for (i = 0; i < num_samp; i++) fprintf(file_ptr, "%10.7f %16.8f %16.8f\n", t[i], v[i], dvdt[i]); /* Close the log file */ fclose(file_ptr); /* Done */ return; } /* ************************************************************** */ /* * btwire_log_analyze_calib_magnet * This function logs the dvdt values used to get dvdt * in the calibration magnet. * * Input: * num_samp, number of samples in the waveform * t[0 to num_samp - 1], time of each sample relative to the trigger (sec) * dvdt[0 to num_samp - 1], derivative of the voltage samples (V/s) * dvdt_fit[0 to num_samp - 1], fitted derivative of the voltage samples (V/s) * * Zachary Wolf * 9/10/02 */ void btwire_log_analyze_calib_magnet(int num_samp, double t[], double dvdt[], double dvdt_fit[]) { /* Declare variables */ FILE* file_ptr; long int i; /* Open the log file */ file_ptr = fopen("analyze_calib_magnet.dat", "w"); if (file_ptr == NULL) { btwire_error("Unable to open dvdt_in_calib_magnet file"); return; } /* Write the measured values to the file */ fprintf(file_ptr, "%%t (sec), dvdt (V/s), dvdt_fit (V/s)\n"); for (i = 0; i < num_samp; i++) fprintf(file_ptr, "%10.7f %16.8f %16.8f\n", t[i], dvdt[i], dvdt_fit[i]); /* Close the log file */ fclose(file_ptr); /* Done */ return; }