Skip to content
Permalink
master
Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
Go to file
 
 
Cannot retrieve contributors at this time
executable file 1311 lines (1149 sloc) 52.3 KB
% script to evaulate the cramer-rao lower bound for bos images of
% supersonic flow over a wedge and compare theoretical estimates to
% experiment.
clear
close all
clc
rmpath('/scratch/shannon/a/lrajendr/Software/prana');
restoredefaultpath;
% addpath ../prana-master/
% addpath /scratch/shannon/c/aether/Projects/BOS/error-analysis/analysis/src/error-analysis-codes/helper-codes/mCodes/
% addpath /scratch/shannon/c/aether/Projects/BOS/error-analysis/analysis/src/error-analysis-codes/post-processing-codes/
% addpath ../error-analysis-codes/ptv-codes/
addpath(genpath('/scratch/shannon/c/aether/Projects/BOS/general-codes/matlab-codes/'));
% addpath /scratch/shannon/a/lrajendr/Software/general-mCodes/
addpath /scratch/shannon/a/lrajendr/Software/cbrewer/
addpath ../dot-tracking-package/
% addpath
dbstop if error
logical_string = {'False'; 'True'};
%% experiment settings
% --------------------------
% wind tunnel settings
% --------------------------
% chamber pressure (psig) - from read out near tunnel
pressure = 55;
% stagnation temperature (deg. C)
T0 = 20.5;
% atmospheric pressure (psi)
p_a = 14.7;
% psi to pascal conversion
psi_to_pa = 6894.76;
% gas constant for air (J/kg-K)
R = 287;
% specific heat ratio
gamm = 1.4;
% upstream mach number
M1 = 2.56; %2.4;
% upstream stagnation density (kg/m^3)
% rho_01 = 3 * 1.225;
rho_01 = (pressure + p_a) * psi_to_pa/(R * (273.15 + T0));
% --------------------------
% wedge settings
% --------------------------
% location of wedge tip (from looking at the correlation vector field)
x0 = 865; %897; %846; %1066; %830; %1392 - 830;
y0 = 631; %406; %421; %396; %492;
% location of wedge shoulder (pix.)
xs = 360;
ys = 545; %480;
% angle of the wedge shoulder (deg.)
shoulder_angle = 0;
% wedge half angle (deg.)
wedge_angle = 10; %1/5;
% --------------------------
% dot pattern settings
% --------------------------
% geoemtric dot diameter (um)
d_geo = 0;
% dot size (pix.)
dot_size_pixels = 3;
% expected dot spacing in the image plane (pix.)
dot_spacing = 6;
% % distance between dot pattern and density gradient field (m)
% Z_D = 1 * 0.0254;
% % thickness of the density gradient field/wind-tunnel (m)
% Z_g = 1 * 0.0254;
% --------------------------
% imaging settings
% --------------------------
% lens model
lens_model = 'thin-lens'; %'apparent';
% magnification (um/pix.)
magnification = 10^4/180; %33;
% number of pixels on the camera sensor
y_pixel_number = 512;
x_pixel_number = 1024;
% size of a pixel on the camera sensor (um)
pixel_pitch = 20.8;
% f-number of the camera aperture
f_number = 22;
% focal length of the camera lens (mm)
focal_length = 105;
% image noise level (%)
noise_gray_level = 0.05;
% --------------------------
% density gradient settings
% --------------------------
% algorithm used for ray tracing
ray_tracing_algorithm = 'rk4';
% distance between dot pattern and density gradient field (mm)
Z_D = 1 * 0.0254 * 1e3;
% thickness of the density gradient field/wind-tunnel (mm)
Z_g = 1 * 0.0254 * 1e3;
% distance between density gradietns and camera lens (mm)
Z_A = (10.5*0.0254*1e3 + Z_g/2);
% distance between dot pattern and camera lens (mm)
z_obj = Z_A + Z_D;
% distance between dot pattern and far end of density field (mm)
zmax = Z_D + Z_g/2.0;
% distance between dot pattern and near end of density field (mm)
zmin = Z_D - Z_g/2.0;
% number of grid points along x
nx = 234; %700; %113;
% number of grid points along y
ny = 84; %251; %41;
% number of grid points along z
nz = 51;
%% processing settings
% ------------------------
% read/write settings
% ------------------------
% top level directory containing images
top_image_directory = fullfile('/scratch/shannon/c/aether/Projects/BOS/crlb/analysis/data/images/synthetic/wedge/regular-overlap=False/', lens_model, [num2str(x_pixel_number, '%d') 'x' num2str(y_pixel_number, '%d')], ...
ray_tracing_algorithm, ['zobj' num2str(floor(z_obj), '%d') '-zmin' num2str(floor(zmin), '%d') '-zmax' num2str(floor(zmax), '%d') '-nx' num2str(nx, '%d') '-ny' num2str(ny, '%d') '-nz' num2str(nz, '%d')], ...
['f=' num2str(focal_length, '%d') 'mm_f' num2str(f_number, '%02d') '_l_p=' num2str(floor(pixel_pitch), '%02d') 'um'], ['dg=' num2str(d_geo, '%d') 'um_dp=' num2str(dot_size_pixels, '%.2f') 'pix_spacing=' num2str(dot_spacing, '%.2f') 'pix'], 'noise00');
% top level directory to store the results
top_results_directory = fullfile('/scratch/shannon/c/aether/Projects/BOS/crlb/analysis/results/synthetic/wedge/regular-overlap=False/', lens_model, [num2str(x_pixel_number, '%d') 'x' num2str(y_pixel_number, '%d')], ...
ray_tracing_algorithm, ['zobj' num2str(floor(z_obj), '%d') '-zmin' num2str(floor(zmin), '%d') '-zmax' num2str(floor(zmax), '%d') '-nx' num2str(nx, '%d') '-ny' num2str(ny, '%d') '-nz' num2str(nz, '%d')], ...
['f=' num2str(focal_length, '%d') 'mm_f' num2str(f_number, '%02d') '_l_p=' num2str(floor(pixel_pitch), '%02d') 'um'], ['dg=' num2str(d_geo, '%d') 'um_dp=' num2str(dot_size_pixels, '%.2f') 'pix_spacing=' num2str(dot_spacing, '%.2f') 'pix'], ['noise' num2str(floor(noise_gray_level*1000), '%03d')]);
% ----------------------------
% general processing settings
% ----------------------------
% perform background subtraction? (true/false)
background_subtraction = false;
% peform image masking? (true/false)
image_masking = false;
% perform median filtering of dot positions across time series before
% calculating position estimation variance? (true/false)
median_filtering = false;
% number of trials to calculate position estimation variance
num_trials = 1e3;
% buffer to remove points close to boundaries
left_boundary_buffer = 200;
right_boundary_buffer = 200;
top_boundary_buffer = 100;
bottom_boundary_buffer = 100;
% ------------------------
% calibration settings
% ------------------------
% directory containing calibration images
calibration_directory = fullfile(top_image_directory, 'calibration-crlb');
% camera model
camera_model = 'thin-lens';
% order of the z term in the polynomial mapping function (x and y are
% cubic).
order_z = 1;
% offset in the co-ordinate system of the sensor for synthetic images
% (pix.)
starting_index_x = -1; %0;
starting_index_y = 0; %1;
% ------------------------
% identification settings
% ------------------------
% expected dot diameter in the image plane (pix.)
dot_diameter = dot_size_pixels; % 1.5 * dot_size_pixels;
% minimum expected area for a group of pixels to be identified as a dot
% (pix.^2)
min_area = 9; %dot_diameter^2 * 0.5;
% subpixel fit to used for centroid estimation
subpixel_fit = 'clsg';
% use intensity weighted centroid estimates if gaussian fits fail?
% (true/false)
default_iwc = true;
% weights for area, intensity and distance to be used for multi-parametric
% identification
W_area = 1;
W_intensity = 1;
W_distance = 1;
% -------------------
% tracking settings
% -------------------
% intensity, distance and diameter weights for multi-parametric tracking
weights = [1, 1, 1];
% search radius for nearest neighbor tracking (pix.)
s_radius = 2;
% -------------------
% plot settings
% -------------------
% save figures? (true/false)
save_figures = true;
% plot error histograms for the position estimation variance calculation?
% (true/false)
plot_error_histogram = false;
% min color level for position standard deviation (pix.)
global_cmin = 0.02; %1;
% max color level for position standard deviation (pix.)
global_cmax = 0.05; %7;
% factor to scale the displacements for quiver plots
scale_factor = 0.05;
% extract line colors
colors = lines(3);
%% directory info
% directory containing for the current case
current_image_directory = fullfile(top_image_directory, '1');
% directory to store results for the current case
current_results_directory = fullfile(top_results_directory, ['bg_subtraction=' logical_string{background_subtraction + 1} '_median_filtering=' logical_string{median_filtering+1}], [subpixel_fit '-ell']);
mkdir_c(current_results_directory);
% directory to store figures for the current case
figure_save_directory = fullfile(current_results_directory, 'figures');
mkdir_c(figure_save_directory);
%% calculate reference dot location from dot positions
% load parameters for a sample image
image_generation_parameters = load(fullfile(top_image_directory, '1', 'parameters.mat'));
% load dot positions for a sample image
positions = load(fullfile(top_image_directory, '1', 'positions.mat'));
% calculate reference dot locations on the image plane based on the
% expected locations on the object plane and the camera mapping function.
fprintf('calculating reference dot locations\n');
pos_ref_dots.x = positions.x;
pos_ref_dots.y = positions.y;
[pos_ref_dots.x, pos_ref_dots.y] = calculate_reference_dot_locations_new(positions, image_generation_parameters, camera_model, [], [], starting_index_x, starting_index_y);
% flip the y co-ordinates of the dots to account for the image being
% flipped upside down
pos_ref_dots.y = image_generation_parameters.camera_design.y_pixel_number - pos_ref_dots.y;
% remove points outside FOV
% indices = pos_ref_dots.x < 1 | pos_ref_dots.x > image_generation_parameters.camera_design.x_pixel_number-1 | pos_ref_dots.y < 1 | pos_ref_dots.y > image_generation_parameters.camera_design.y_pixel_number-1;
indices = pos_ref_dots.x < left_boundary_buffer | ...
pos_ref_dots.x > image_generation_parameters.camera_design.x_pixel_number - right_boundary_buffer | ...
pos_ref_dots.y < top_boundary_buffer | ...
pos_ref_dots.y > image_generation_parameters.camera_design.y_pixel_number - bottom_boundary_buffer;
pos_ref_dots.x(indices) = [];
pos_ref_dots.y(indices) = [];
num_dots_ref = numel(pos_ref_dots.x); % - sum(indices);
% remove dots in masked regions. first set dots in masked region to be NaN
if image_masking
for dot_index = 1:num_dots_ref
if mask(round(pos_ref_dots.y(dot_index)), round(pos_ref_dots.x(dot_index))) == 0
pos_ref_dots.x(dot_index) = NaN;
pos_ref_dots.y(dot_index) = NaN;
end
end
% find and remove NaN indices
nan_indices = isnan(pos_ref_dots.x) | isnan(pos_ref_dots.y);
pos_ref_dots.x(nan_indices) = [];
pos_ref_dots.y(nan_indices) = [];
end
%% calculate dot positions from light rays
% load light ray data
ray_data = load_lightray_data_03(current_image_directory);
% extract final positions and directions of light rays for each dot
% (pix.)
[x1, y1] = pos_to_xy_pix_04(ray_data{1}.pos.x, ray_data{1}.pos.y, image_generation_parameters, -1, -0.5);
[x2, y2] = pos_to_xy_pix_04(ray_data{2}.pos.x, ray_data{2}.pos.y, image_generation_parameters, -1, -0.5);
[pos_ref_rays_1.x, pos_ref_rays_1.y] = calculate_centroids_from_lightrays_06(x1, y1, image_generation_parameters.bos_pattern.particle_number_per_grid_point * image_generation_parameters.bos_pattern.lightray_number_per_particle);
[pos_ref_rays_2.x, pos_ref_rays_2.y] = calculate_centroids_from_lightrays_06(x2, y2, image_generation_parameters.bos_pattern.particle_number_per_grid_point * image_generation_parameters.bos_pattern.lightray_number_per_particle);
% remove nan values
nan_indices = isnan(pos_ref_rays_1.x) | isnan(pos_ref_rays_1.y) | isnan(pos_ref_rays_2.x) | isnan(pos_ref_rays_2.y);
pos_ref_rays_1.x(nan_indices) = [];
pos_ref_rays_1.y(nan_indices) = [];
pos_ref_rays_2.x(nan_indices) = [];
pos_ref_rays_2.y(nan_indices) = [];
z_rays_ref = zeros(size(pos_ref_rays_1.x));
z_rays_grad = zeros(size(pos_ref_rays_2.x));
d_rays_ref = zeros(size(pos_ref_rays_1.x));
d_rays_grad = zeros(size(pos_ref_rays_2.x));
I_rays_ref = zeros(size(pos_ref_rays_1.x));
I_rays_grad = zeros(size(pos_ref_rays_2.x));
% run tracking
fprintf('Tracking light rays from reference to grad images\n');
[tracks_rays]=weighted_nearest_neighbor3D(pos_ref_rays_2.x, pos_ref_rays_1.x, pos_ref_rays_2.x, pos_ref_rays_2.y, pos_ref_rays_1.y, pos_ref_rays_2.y,...
z_rays_grad, z_rays_ref, z_rays_grad, d_rays_grad, d_rays_ref, I_rays_grad, I_rays_ref, weights, s_radius);
x_track_rays = tracks_rays(:,1);
y_track_rays = tracks_rays(:,3);
u_track_rays = tracks_rays(:,2) - tracks_rays(:,1);
v_track_rays = tracks_rays(:,4) - tracks_rays(:,3);
% remove boundary tracks
[x_track_rays, y_track_rays, u_track_rays, v_track_rays] = remove_boundary_points_scattered(x_track_rays, y_track_rays, u_track_rays, v_track_rays, image_generation_parameters.camera_design.x_pixel_number, image_generation_parameters.camera_design.y_pixel_number, left_boundary_buffer, right_boundary_buffer, bottom_boundary_buffer, top_boundary_buffer);
% plot tracks
figure
quiver(x_track_rays, y_track_rays, u_track_rays/scale_factor, v_track_rays/scale_factor, 'AutoScale', 'off')
annotate_image(gcf, gca);
title('Tracked Rays')
if save_figures
saveas(gcf, fullfile(figure_save_directory, 'track-rays.png'), 'png');
saveas(gcf, fullfile(figure_save_directory, 'track-rays.eps'), 'epsc');
end
%% identify dots on the images
fprintf('identifying dots in images\n');
% --------------------------
% Reference Image
% --------------------------
fprintf('Reference Image\n');
% load image
% im_ref = imread(fullfile(current_image_directory, 'bos_pattern_image_1.tif'));
fid = fopen(fullfile(current_image_directory, 'bos_pattern_image_1.bin'));
a = fread(fid, 'single');
fclose(fid);
im_ref = reshape(a, image_generation_parameters.camera_design.x_pixel_number, image_generation_parameters.camera_design.y_pixel_number);
im_ref = im_ref';
% % flip image upside down so bottom pixel is y = 1
% im_ref = flipud(im_ref);
% flip image left to right
im_ref = fliplr(im_ref);
% mask image if required
if image_masking
im_ref = double(im_ref) .* mask;
end
% subtract background if required
if background_subtraction
im_ref = im_ref - im_bg;
end
% set image pixels outside buffer to zero
im_ref(:, 1:left_boundary_buffer) = 0;
im_ref(:, image_generation_parameters.camera_design.x_pixel_number - right_boundary_buffer:end) = 0;
im_ref(1:bottom_boundary_buffer, :) = 0;
im_ref(image_generation_parameters.camera_design.y_pixel_number - top_boundary_buffer:end, :) = 0;
% identify dots on the reference image
[SIZE_ref.XYDiameter, SIZE_ref.peaks, SIZE_ref.mapsizeinfo, SIZE_ref.locxy, SIZE_ref.mapint] = combined_ID_size_apriori_10(im_ref, pos_ref_dots.x, pos_ref_dots.y, dot_diameter+2, subpixel_fit, default_iwc, min_area, W_area, W_intensity, W_distance);
% extract dot co-ordinates from sizing results
[X_ref, Y_ref, Z_ref, d_x_ref, d_y_ref, R_ref, I_ref] = extract_dot_properties_02(SIZE_ref.XYDiameter);
% remove dots outside ROI
[X_ref, Y_ref, Z_ref, d_x_ref, d_y_ref, R_ref, I_ref] = nan_dots_outside_ROI_02(X_ref, Y_ref, Z_ref, d_x_ref, d_y_ref, R_ref, I_ref, ...
left_boundary_buffer, image_generation_parameters.camera_design.x_pixel_number - right_boundary_buffer, ...
bottom_boundary_buffer, image_generation_parameters.camera_design.y_pixel_number - top_boundary_buffer);
% --------------------------
% display results
% --------------------------
figure,
imagesc(im_ref), colormap(flipud(gray))
hold on
plot(pos_ref_dots.x, pos_ref_dots.y, '*')
plot(X_ref, Y_ref, 'o')
annotate_image(gcf, gca);
xlim([left_boundary_buffer, image_generation_parameters.camera_design.x_pixel_number - right_boundary_buffer])
ylim([bottom_boundary_buffer, image_generation_parameters.camera_design.y_pixel_number - top_boundary_buffer])
set(gca, 'ydir', 'normal')
title('Reference')
%%
% --------------------------
% Gradient Image
% --------------------------
fprintf('Gradient Images\n');
% load image
fid = fopen(fullfile(current_image_directory, 'bos_pattern_image_2.bin'));
a = fread(fid, 'single');
fclose(fid);
im_grad = reshape(a, image_generation_parameters.camera_design.x_pixel_number, image_generation_parameters.camera_design.y_pixel_number);
im_grad = im_grad';
% im_grad = imread(fullfile(current_image_directory, 'bos_pattern_image_2.tif'));
% % flip image upside down so bottom pixel is y = 1
% im_grad = flipud(im_grad);
% flip image left to right
im_grad = fliplr(im_grad);
% mask image if required
if image_masking
im_grad = double(im_grad) .* mask;
end
% subtract background if required
if background_subtraction
im_grad = im_grad - im_bg;
end
% set image pixels outside buffer to zero
im_grad(:, 1:left_boundary_buffer) = 0;
im_grad(:, image_generation_parameters.camera_design.x_pixel_number - right_boundary_buffer:end) = 0;
im_grad(1:bottom_boundary_buffer, :) = 0;
im_grad(image_generation_parameters.camera_design.y_pixel_number - top_boundary_buffer:end, :) = 0;
% identify dots
[SIZE_grad.XYDiameter, SIZE_grad.peaks, SIZE_grad.mapsizeinfo, SIZE_grad.locxy, SIZE_grad.mapint] = combined_ID_size_apriori_10(im_grad, pos_ref_dots.x, pos_ref_dots.y, dot_diameter+2, subpixel_fit, default_iwc, min_area, W_area, W_intensity, W_distance);
% extract dot properties from sizing results
[X_grad, Y_grad, Z_grad, d_x_grad, d_y_grad, R_grad, I_grad] = extract_dot_properties_02(SIZE_grad.XYDiameter);
% remove dots outside ROI
[X_grad, Y_grad, Z_grad, d_x_grad, d_y_grad, R_grad, I_grad] = nan_dots_outside_ROI_02(X_grad, Y_grad, Z_grad, d_x_grad, d_y_grad, R_grad, I_grad, ...
left_boundary_buffer, image_generation_parameters.camera_design.x_pixel_number - right_boundary_buffer, ...
bottom_boundary_buffer, image_generation_parameters.camera_design.y_pixel_number - top_boundary_buffer);
% --------------------------
% display results
% --------------------------
figure,
imagesc(im_grad), colormap(flipud(gray))
hold on
plot(pos_ref_dots.x, pos_ref_dots.y, '*')
plot(X_grad, Y_grad, 'o')
annotate_image(gcf, gca);
xlim([left_boundary_buffer, image_generation_parameters.camera_design.x_pixel_number - right_boundary_buffer])
ylim([bottom_boundary_buffer, image_generation_parameters.camera_design.y_pixel_number - top_boundary_buffer])
set(gca, 'ydir', 'normal')
title('Gradient')
%% track dots to estimate displacements
s_radius = 3;
fprintf('tracking dot locations between reference image and first grad image\n');
% run tracking
[tracks_dots]=weighted_nearest_neighbor3D(X_grad, X_ref, X_grad, Y_grad, Y_ref, Y_grad,...
Z_grad, Z_ref, Z_grad, d_x_grad, d_x_ref, I_grad, I_ref, weights, s_radius);
x_track_dots = tracks_dots(:,1);
y_track_dots = tracks_dots(:,3);
u_track_dots = tracks_dots(:,2) - tracks_dots(:,1);
v_track_dots = tracks_dots(:,4) - tracks_dots(:,3);
% remove boundary tracks
[x_track_dots, y_track_dots, u_track_dots, v_track_dots] = remove_boundary_points_scattered(x_track_dots, y_track_dots, u_track_dots, v_track_dots, image_generation_parameters.camera_design.x_pixel_number, image_generation_parameters.camera_design.y_pixel_number, left_boundary_buffer, right_boundary_buffer, bottom_boundary_buffer, top_boundary_buffer);
% plot tracks
figure
quiver(x_track_dots, y_track_dots, u_track_dots/scale_factor, v_track_dots/scale_factor, 'AutoScale', 'off')
annotate_image(gcf, gca);
title('Tracked Dots')
if save_figures
saveas(gcf, fullfile(figure_save_directory, 'track-dots.png'), 'png');
saveas(gcf, fullfile(figure_save_directory, 'track-dots.eps'), 'epsc');
end
%% calculate wedge flow field
% name of file containing density data
file_name = '/scratch/shannon/c/aether/Projects/BOS/crlb/analysis/data/density-gradient-files/wedge_nx=234_ny=84_nz=51.mat';
% load data
wedge_data = load(file_name);
% extract 2D slice of density
rho = wedge_data.rho_3d(:,:,1);
% flip density field
% rho = fliplr(flipud(rho));
rho = rot90(rho, 2);
% create X,Y co-ordinate grid of density values
x_rho = image_generation_parameters.density_gradients.origin(1) + (1:image_generation_parameters.density_gradients.num_grid_points(1)) * image_generation_parameters.density_gradients.spacing(1);
y_rho = image_generation_parameters.density_gradients.origin(2) + (1:image_generation_parameters.density_gradients.num_grid_points(2)) * image_generation_parameters.density_gradients.spacing(2);
z_rho = image_generation_parameters.density_gradients.origin(3) + image_generation_parameters.density_gradients.volume_dimensions(3)/2;
% calculate magnification of the density gradient field on the image plane
M_rho = image_generation_parameters.lens_design.magnification * image_generation_parameters.lens_design.object_distance/z_rho;
% calculate co-ordinates of the density gradient field on the image plane
% (pix.)
[X_rho, Y_rho] = meshgrid(x_rho, y_rho);
X_rho = X_rho * M_rho * 1/image_generation_parameters.camera_design.pixel_pitch;
Y_rho = Y_rho * M_rho * 1/image_generation_parameters.camera_design.pixel_pitch;
% ensure that co-ordinates are positive integers
X_rho = floor(X_rho + image_generation_parameters.camera_design.x_pixel_number/2);
Y_rho = floor(Y_rho + image_generation_parameters.camera_design.y_pixel_number/2);
% calculate density gradients along x and y
rho_x = socdiff(rho, image_generation_parameters.density_gradients.spacing(1)*1e-6, 2);
rho_y = socdiff(rho, image_generation_parameters.density_gradients.spacing(2)*1e-6, 1);
% calculate second gradients of density
rho_xx = socdiff(rho_x, image_generation_parameters.density_gradients.spacing(1)*1e-6, 2);
rho_xy = socdiff(rho_x, image_generation_parameters.density_gradients.spacing(2)*1e-6, 1);
rho_yy = socdiff(rho_y, image_generation_parameters.density_gradients.spacing(1)*1e-6, 1);
% calculate factor by which the midpoint of the density gradient is
% magnified with respect to the dot pattern
magnification_factor = image_generation_parameters.lens_design.object_distance/z_rho;
% interpolate density gradients onto the tracks
rho_x_interp = interp2(X_rho, Y_rho, rho_x, x_track_dots, y_track_dots);
rho_y_interp = interp2(X_rho, Y_rho, rho_y, x_track_dots, y_track_dots);
% calculate second gradients density at the interrogation points using interpolation
rho_xx_interp = interp2(X_rho, Y_rho, rho_xx, x_track_dots, y_track_dots);
rho_yy_interp = interp2(X_rho, Y_rho, rho_yy, x_track_dots, y_track_dots);
rho_xy_interp = interp2(X_rho, Y_rho, rho_xy, x_track_dots, y_track_dots);
% gladstone dale constant (m^3/kg)
gladstone_dale = 0.225e-3;
% calculate ambient refractive index
n_0 = 1 + gladstone_dale * double(rho(end));
%% check if theoretical density gradients are aligned with the tracks
figure
quiver((x_track_dots - x_pixel_number/2) * magnification_factor + x_pixel_number/2, (y_track_dots - y_pixel_number/2) * magnification_factor + y_pixel_number/2, ...
u_track_dots * magnification_factor/scale_factor, v_track_dots * magnification_factor/scale_factor, 'AutoScale', 'off')
hold on
quiver(X_rho, Y_rho, rho_x/0.1e2, rho_y/0.1e2, 'AutoScale', 'off')
annotate_image(gcf, gca);
legend('Tracks', 'Density Gradients', 'Location', 'northoutside', 'Orientation', 'horizontal')
%% calculate position estimation variance for tracked dots
fprintf('Calculating position estimation variance with a noise level of %.2f \n', noise_gray_level*100);
num_tracks = size(tracks_dots, 1);
xc_tracked_ref = ones(num_tracks,1) * NaN;
yc_tracked_ref = ones(num_tracks,1) * NaN;
xc_tracked_grad = ones(num_tracks,1) * NaN;
yc_tracked_grad = ones(num_tracks,1) * NaN;
d_x_tracked_ref = ones(num_tracks,1) * NaN;
d_y_tracked_ref = ones(num_tracks,1) * NaN;
d_x_tracked_grad = ones(num_tracks,1) * NaN;
d_y_tracked_grad = ones(num_tracks,1) * NaN;
R_tracked_ref = ones(num_tracks,1) * NaN;
R_tracked_grad = ones(num_tracks,1) * NaN;
pos_std_x_ref = ones(num_tracks,1) * NaN;
pos_std_y_ref = ones(num_tracks,1) * NaN;
pos_std_x_grad = ones(num_tracks,1) * NaN;
pos_std_y_grad = ones(num_tracks,1) * NaN;
pos_std_x_ref_theory = ones(num_tracks,1) * NaN;
pos_std_y_ref_theory = ones(num_tracks,1) * NaN;
pos_std_x_grad_theory = ones(num_tracks,1) * NaN;
pos_std_y_grad_theory = ones(num_tracks,1) * NaN;
pos_std_x_grad_hybrid = ones(num_tracks,1) * NaN;
pos_std_y_grad_hybrid = ones(num_tracks,1) * NaN;
pos_std_x_ref_measured = ones(num_tracks,1) * NaN;
pos_std_y_ref_measured = ones(num_tracks,1) * NaN;
pos_std_x_grad_measured = ones(num_tracks,1) * NaN;
pos_std_y_grad_measured = ones(num_tracks,1) * NaN;
amplification_ratio_x = ones(num_tracks,1) * NaN;
amplification_ratio_y = ones(num_tracks,1) * NaN;
amplification_ratio_x_theory = ones(num_tracks,1) * NaN;
amplification_ratio_y_theory = ones(num_tracks,1) * NaN;
%%
% loop through all tracked dots
for track_index = 1:num_tracks
%% display progress to user
if rem(track_index, 1000) == 0
fprintf('Track number: %d\n', track_index);
end
%% extract dot index
% reference
dot_index_ref = tracks_dots(track_index, 12);
% gradient
dot_index_grad = tracks_dots(track_index, 11);
%% extract intensity profile
% reference
im_crop_ref = SIZE_ref.mapint{dot_index_ref};
% gradient
im_crop_grad = SIZE_grad.mapint{dot_index_grad};
%% extract dot centroid
% reference
xc_tracked_ref(track_index) = X_ref(dot_index_ref);
yc_tracked_ref(track_index) = Y_ref(dot_index_ref);
xc_crop_ref = xc_tracked_ref(track_index) - SIZE_ref.locxy(dot_index_ref,1) + 1;
yc_crop_ref = yc_tracked_ref(track_index) - SIZE_ref.locxy(dot_index_ref,2) + 1;
% gradient
xc_tracked_grad(track_index) = X_grad(dot_index_grad);
yc_tracked_grad(track_index) = Y_grad(dot_index_grad);
xc_crop_grad = xc_tracked_grad(track_index) - SIZE_grad.locxy(dot_index_grad,1) + 1;
yc_crop_grad = yc_tracked_grad(track_index) - SIZE_grad.locxy(dot_index_grad,2) + 1;
%% extract dot diameter
% reference
d_x_tracked_ref(track_index) = d_x_ref(dot_index_ref);
d_y_tracked_ref(track_index) = d_y_ref(dot_index_ref);
% gradient
d_x_tracked_grad(track_index) = d_x_grad(dot_index_grad);
d_y_tracked_grad(track_index) = d_y_grad(dot_index_grad);
%% extract correlation coefficient
R_tracked_ref(track_index) = R_ref(dot_index_ref);
R_tracked_grad(track_index) = R_grad(dot_index_grad);
%% calculate position estimation variance from monte-carlo
% reference
[err_var_x, err_var_y, ~, ~, ~] = ...
calculate_position_estimation_variance_monte_carlo(im_crop_ref, xc_crop_ref, yc_crop_ref, noise_gray_level, ...
num_trials, subpixel_fit, plot_error_histogram);
pos_std_x_ref(track_index) = sqrt(err_var_x);
pos_std_y_ref(track_index) = sqrt(err_var_y);
% gradient
[err_var_x, err_var_y, ~, ~, ~] = ...
calculate_position_estimation_variance_monte_carlo(im_crop_grad, xc_crop_grad, yc_crop_grad, noise_gray_level, ...
num_trials, subpixel_fit, plot_error_histogram);
pos_std_x_grad(track_index) = sqrt(err_var_x);
pos_std_y_grad(track_index) = sqrt(err_var_y);
%% calculate amplification ratio
% x
amplification_ratio_x(track_index) = pos_std_x_grad(track_index)/pos_std_x_ref(track_index);
% y
amplification_ratio_y(track_index) = pos_std_y_grad(track_index)/pos_std_y_ref(track_index);
%% calculate crlb from theory
% reference
[crlb_x, crlb_y] = calculate_crlb_bos_05(im_crop_ref, n_0, 0, 0, ...
0, 0, 0, ...
0.5 * (d_x_tracked_ref(track_index) + d_y_tracked_ref(track_index)), image_generation_parameters.lens_design.magnification, ...
image_generation_parameters.lens_design.aperture_f_number, Z_D*1e-3, Z_g*1e-3, ...
image_generation_parameters.camera_design.pixel_pitch*1e-6, noise_gray_level);
pos_std_x_ref_theory(track_index) = sqrt(crlb_x);
pos_std_y_ref_theory(track_index) = sqrt(crlb_y);
% gradient
[crlb_x, crlb_y] = calculate_crlb_bos_05(im_crop_ref, n_0, rho_x_interp(track_index), rho_y_interp(track_index), ...
rho_xx_interp(track_index), rho_xy_interp(track_index), rho_yy_interp(track_index), ...
0.5 * (d_x_tracked_ref(track_index) + d_y_tracked_ref(track_index)), image_generation_parameters.lens_design.magnification, ...
image_generation_parameters.lens_design.aperture_f_number, Z_D*1e-3, Z_g*1e-3, ...
image_generation_parameters.camera_design.pixel_pitch*1e-6, noise_gray_level);
pos_std_x_grad_theory(track_index) = sqrt(crlb_x);
pos_std_y_grad_theory(track_index) = sqrt(crlb_y);
%% calculate amplification ratio from theory
% x
amplification_ratio_x_theory(track_index) = pos_std_x_grad_theory(track_index)/pos_std_x_ref_theory(track_index);
% y
amplification_ratio_y_theory(track_index) = pos_std_y_grad_theory(track_index)/pos_std_y_ref_theory(track_index);
%% calculate crlb from measured diameter
% reference
% pos_std_x_ref_measured(track_index) = (2 * sqrt(2*pi) * noise_gray_level / sum(im_crop_ref(:)) * d_tracked_ref(track_index)^2/16); % ^ 2;
% pos_std_y_ref_measured(track_index) = (2 * sqrt(2*pi) * noise_gray_level / sum(im_crop_ref(:)) * d_tracked_ref(track_index)^2/16); % ^ 2;
pos_std_x_ref_measured(track_index) = 2 * sqrt(2*pi) * noise_gray_level / sum(im_crop_ref(:)) * ...
d_x_tracked_ref(track_index)^(3/2) * d_y_tracked_ref(track_index)^(1/2) * ...
(1 - R_tracked_ref(track_index)^2)^0.25;
pos_std_y_ref_measured(track_index) = 2 * sqrt(2*pi) * noise_gray_level / sum(im_crop_ref(:)) * ...
d_x_tracked_ref(track_index)^(1/2) * d_y_tracked_ref(track_index)^(3/2) * ...
(1 - R_tracked_ref(track_index)^2)^0.25;
% gradient
% pos_std_x_grad_measured(track_index) = (2 * sqrt(2*pi) * noise_gray_level / sum(im_crop_grad(:)) * d_tracked_grad(track_index)^2/16); % ^ 2;
% pos_std_x_grad_measured(track_index) = (2 * sqrt(2*pi) * noise_gray_level / sum(im_crop_grad(:)) * d_tracked_grad(track_index)^2/16); % ^ 2;
pos_std_x_grad_measured(track_index) = 2 * sqrt(2*pi) * noise_gray_level / sum(im_crop_grad(:)) * ...
d_x_tracked_grad(track_index)^(3/2) * d_y_tracked_grad(track_index)^(1/2) * ...
(1 - R_tracked_grad(track_index)^2)^0.25;
pos_std_y_grad_measured(track_index) = 2 * sqrt(2*pi) * noise_gray_level / sum(im_crop_grad(:)) * ...
d_x_tracked_grad(track_index)^(1/2) * d_y_tracked_grad(track_index)^(3/2) * ...
(1 - R_tracked_grad(track_index)^2)^0.25;
%% calculate crlb from theoretical ratio and measured std of reference
% x
pos_std_x_grad_hybrid(track_index) = amplification_ratio_x_theory(track_index) * pos_std_x_ref(track_index);
% y
pos_std_y_grad_hybrid(track_index) = amplification_ratio_y_theory(track_index) * pos_std_y_ref(track_index);
end
fprintf('...done\n');
%% interpolate results onto a grid
% amplfication ratio, simulation
[X_ref_grid, Y_ref_grid, amplification_ratio_x_grid, amplification_ratio_y_grid] = ...
interpolate_tracks(xc_tracked_ref, yc_tracked_ref, ...
amplification_ratio_x, amplification_ratio_y, dot_spacing);
% amplfication ratio, theory
[~, ~, amplification_ratio_x_theory_grid, amplification_ratio_y_theory_grid] = ...
interpolate_tracks(xc_tracked_ref, yc_tracked_ref, ...
amplification_ratio_x_theory, amplification_ratio_y_theory, dot_spacing);
% dot diameters, gradient
[~, ~, d_x_tracked_grad_grid, ~] = ...
interpolate_tracks(xc_tracked_ref, yc_tracked_ref, ...
d_x_tracked_grad, d_x_tracked_grad, dot_spacing);
% dot diameters, gradient
[~, ~, d_y_tracked_grad_grid, ~] = ...
interpolate_tracks(xc_tracked_ref, yc_tracked_ref, ...
d_x_tracked_grad, d_y_tracked_grad, dot_spacing);
%% calculate pdf of uncertainty
% bin levels
edges_std = linspace(0, 0.2, 100);
% simulation
[N_std_sim, ~] = histcounts([pos_std_x_grad; pos_std_y_grad], edges_std, 'Normalization', 'pdf');
% theory
[N_std_theory, ~] = histcounts([pos_std_x_grad_theory; pos_std_y_grad_theory], edges_std, 'Normalization', 'pdf');
% ratio from theory
[N_std_hybrid, ~] = histcounts([pos_std_x_grad_hybrid; pos_std_y_grad_hybrid], edges_std, 'Normalization', 'pdf');
%% calculate pdf of amplification ratio
% bin levels
edges_ratio = linspace(1, 1.5, 100);
% simulation
[N_ratio_sim, ~] = histcounts([amplification_ratio_x; amplification_ratio_y], edges_ratio, 'Normalization', 'pdf');
% theory
[N_ratio_theory, ~] = histcounts([amplification_ratio_x_theory; amplification_ratio_y_theory], edges_ratio, 'Normalization', 'pdf');
%% calculate rms of uncertainty
% simulation
rms_std_sim = rms([pos_std_x_grad; pos_std_y_grad], 'omitnan');
% theory
rms_std_theory = rms([pos_std_x_grad_theory; pos_std_y_grad_theory], 'omitnan');
% hybrid
rms_std_hybrid = rms([pos_std_x_grad_hybrid; pos_std_y_grad_hybrid], 'omitnan');
%% calculate rms of amplifcation ratio
% simulation
rms_ratio_sim = rms([amplification_ratio_x; amplification_ratio_y], 'omitnan');
% theory
rms_ratio_theory = rms([amplification_ratio_x_theory; amplification_ratio_y_theory], 'omitnan');
%% plot contour of measured diameters for gradient image
% display contours
cmin_current = dot_size_pixels;
cmax_current = dot_size_pixels + 2;
contour_levels = linspace(cmin_current, cmax_current, 100);
figure
contourf(X_ref_grid, Y_ref_grid, sqrt(d_x_tracked_grad_grid.^2 + d_y_tracked_grad_grid.^2), ...
contour_levels, 'edgecolor', 'none')
colorcet('fire', 'N', 100, 'reverse', 1);
% caxis([cmin_current, cmax_current]);
caxis([4, 6]);
colorbar
annotate_image(gcf, gca);
% axis([xmin_mask xmax_mask ymin_mask ymax_mask])
box on
title('Dot Diameters')
set(gcf, 'Position', [360 584 441 316])
if save_figures
save_figure_to_png_eps_fig(figure_save_directory, 'diameter-contour', [1, 0, 1]);
end
%% plot contour of amplification ratio magnitude from simulations
% display contours
cmin_current = 1;
cmax_current = 2;
contour_levels = linspace(cmin_current, cmax_current, 100);
figure
contourf(X_ref_grid, Y_ref_grid, sqrt(amplification_ratio_x_grid.^2 + amplification_ratio_y_grid.^2)/sqrt(2), ...
contour_levels, 'edgecolor', 'none')
colorcet('fire', 'N', 100, 'reverse', 1);
caxis([cmin_current, cmax_current]);
colorbar
annotate_image(gcf, gca);
% axis([xmin_mask xmax_mask ymin_mask ymax_mask])
box on
title('Ratio, Simulation')
set(gcf, 'Position', [360 584 441 316])
if save_figures
save_figure_to_png_eps_fig(figure_save_directory, 'amplification-ratio-contour', [1, 0, 1]);
end
%% plot contour of amplification ratio magnitude from theory
% display contours
cmin_current = 1;
cmax_current = 2;
contour_levels = linspace(cmin_current, cmax_current, 100);
figure
contourf(X_ref_grid, Y_ref_grid, sqrt(amplification_ratio_x_theory_grid.^2 + amplification_ratio_y_theory_grid.^2)/sqrt(2), ...
contour_levels, 'edgecolor', 'none')
colorcet('fire', 'N', 100, 'reverse', 1);
caxis([cmin_current, cmax_current]);
colorbar
annotate_image(gcf, gca);
% axis([xmin_mask xmax_mask ymin_mask ymax_mask])
box on
title('Ratio, Theory')
set(gcf, 'Position', [360 584 441 316])
if save_figures
save_figure_to_png_eps_fig(figure_save_directory, 'amplification-ratio-theory-contour', [1, 0, 1]);
end
%% plot scatter plot of amplification ratio magnitude
minval = 1;
maxval = 1.5;
figure
% plot(sqrt(amplification_ratio_x_theory.^2 + amplification_ratio_y_theory.^2)/sqrt(2), ...
% sqrt(amplification_ratio_x.^2 + amplification_ratio_y.^2)/sqrt(2), ...
% 'o', 'markersize', 3, 'markeredgecolor', colors(1,:), 'markerfacecolor', colors(1,:))
plot(sqrt(amplification_ratio_x_theory_grid.^2 + amplification_ratio_y_theory_grid.^2)/sqrt(2), ...
sqrt(amplification_ratio_x_grid.^2 + amplification_ratio_y_grid.^2)/sqrt(2), ...
'o', 'markersize', 3, 'markeredgecolor', colors(1,:), 'markerfacecolor', colors(1,:))
axis equal
hold on
plot([minval maxval], [minval maxval])
axis([minval maxval minval maxval])
grid on
xlabel('Theory (pix.)')
ylabel('Simulation (pix.)')
title('Amplification Ratio')
set(gcf, 'Position', [360 559 417 341]);
if save_figures
save_figure_to_png_eps_fig(figure_save_directory, 'amplification-ratio-scatter', [1, 1, 1]);
end
%% plot histograms of position uncertainty
x_max = 0.2;
y_max = 150;
figure
% simulation
plot(edges_std(1:end-1), N_std_sim, 'k');
hold on
plot(rms_std_sim * [1, 1], [0, y_max], 'k--');
% theory
plot(edges_std(1:end-1), N_std_theory, 'color', colors(1,:));
plot(rms_std_theory * [1, 1], [0, y_max], 'color', colors(1,:), 'linestyle', '--');
% hybrid
plot(edges_std(1:end-1), N_std_hybrid, 'color', colors(2,:));
plot(rms_std_hybrid * [1, 1], [0, y_max], 'color', colors(2,:), 'linestyle', '--');
xlim([0 x_max])
ylim([0 y_max])
lgd = legend('\sigma_{X_0}, Sim.', 'RMS \sigma_{X_0}, Sim.', '\sigma_{X_0}, Theory', 'RMS \sigma_{X_0}, Theory', ...
'\sigma_{X_0}, Hybrid', 'RMS \sigma_{X_0}, Hybrid');
lgd.FontSize = 10;
xlabel('\sigma_{X_0} (pix.)')
set(gcf, 'Position', [360 584 441 316])
if save_figures
save_figure_to_png_eps_fig(figure_save_directory, 'uncertainty-hist-theory-sim-hybrid', [1 1 1]);
end
%% plot histograms of amplification ratio
x_max = 1.2;
y_max = 150;
figure
plot(edges_ratio(1:end-1), N_ratio_sim, 'k');
hold on
plot(rms_ratio_sim * [1, 1], [0, y_max], 'k--');
plot(edges_ratio(1:end-1), N_ratio_theory, 'color', colors(1,:));
plot(rms_ratio_theory * [1, 1], [0, y_max], 'color', colors(1,:), 'linestyle', '--');
xlim([1 x_max])
ylim([0 y_max])
legend('AR, Sim.', 'RMS AR, Sim.', 'AR, Theory.', 'RMS AR, Theory.')
xlabel('AR')
set(gcf, 'Position', [360 584 441 316])
if save_figures
save_figure_to_png_eps_fig(figure_save_directory, 'ratio-hist-theory-sim', [1 1 1]);
end
%%
% %% create scattered interpolants
%
% % simulation, x
% F_x_sim = scatteredInterpolant(xc_tracked_ref, yc_tracked_ref, pos_std_x_grad);
% F_x_sim.Method = 'nearest';
% F_x_sim.ExtrapolationMethod = 'none';
% % simulation, y
% F_y_sim = scatteredInterpolant(xc_tracked_ref, yc_tracked_ref, pos_std_y_grad);
% F_y_sim.Method = 'nearest';
% F_y_sim.ExtrapolationMethod = 'none';
%
% % theory, x
% F_x_theory = scatteredInterpolant(xc_tracked_ref, yc_tracked_ref, pos_std_x_grad_theory);
% F_x_theory.Method = 'nearest';
% F_x_theory.ExtrapolationMethod = 'none';
%
% % theory, y
% F_y_theory = scatteredInterpolant(xc_tracked_ref, yc_tracked_ref, pos_std_y_grad_theory);
% F_y_theory.Method = 'nearest';
% F_y_theory.ExtrapolationMethod = 'none';
%
% % theory with measured diameter, x
% F_x_measured = scatteredInterpolant(xc_tracked_ref, yc_tracked_ref, pos_std_x_grad_measured);
% F_x_measured.Method = 'nearest';
% F_x_measured.ExtrapolationMethod = 'none';
%
% % theory with measured diameter, y
% F_y_measured = scatteredInterpolant(xc_tracked_ref, yc_tracked_ref, pos_std_y_grad_measured);
% F_y_measured.Method = 'nearest';
% F_y_measured.ExtrapolationMethod = 'none';
%
% %% compare standard deviation on a slice
%
% % co-ordinates on the slice
% x_slice = 200:dot_spacing:800;
% y_slice = 252 * ones(size(x_slice));
%
% % plot results
% figure
% subplot(1,2,1)
% plot(x_slice, F_x_sim(x_slice, y_slice), 'o')
% hold on
% plot(x_slice, F_x_theory(x_slice, y_slice), 'o')
% plot(x_slice, F_x_measured(x_slice, y_slice), 'o')
% ylim([0 1])
% xlabel('X (pix.)')
% ylabel('\sigma_{X_0} (pix.)')
% legend('Simulation', 'CRLB', 'CRLB - Measured')
% legend boxon
% title(['Y = ' num2str(y_slice(1)) ' pix.'])
%
% subplot(1,2,2)
% plot(x_slice, F_y_sim(x_slice, y_slice), 'o')
% hold on
% plot(x_slice, F_y_theory(x_slice, y_slice), 'o')
% ylim([0 1])
% xlabel('X (pix.)')
% ylabel('\sigma_{Y_0} (pix.)')
% legend('Simulation', 'CRLB')
% title(['Y = ' num2str(y_slice(1)) ' pix.'])
%
% set(gcf, 'Position', [64 433 1109 403])
%
% if save_figures
% saveas(gcf, fullfile(figure_save_directory, ['pos-std-comparison-slice-y=' num2str(y_slice(1)) '.png']), 'png');
% saveas(gcf, fullfile(figure_save_directory, ['pos-std-comparison-slice-y=' num2str(y_slice(1)) '.eps']), 'epsc');
% end
%%
% %% plot amplification ratio magnitude
%
% % calculate amplification ratios
% AR_x = (crlb_ratio_measured_I .* sqrt(crlb_x_ratio_measured./crlb_y_ratio_measured))';
% AR_y = (crlb_ratio_measured_I .* sqrt(crlb_y_ratio_measured./crlb_x_ratio_measured))';
%
% % interpolate results onto a grid
% [X_ref_grid, Y_ref_grid, AR_x_grid, AR_y_grid] = interpolate_tracks(X_all_ref(:,1), Y_all_ref(:,1), AR_x, AR_y, dot_spacing);
%
% % display contours
% cmin_current = 1.5;
% cmax_current = 1.9;
% contour_levels = linspace(cmin_current, cmax_current, 100);
% figure
% contourf(X_ref_grid, Y_ref_grid, sqrt(AR_x_grid.^2 + AR_y_grid.^2), contour_levels, 'edgecolor', 'none')
% colorcet('fire', 'N', 100, 'reverse', 1);
% caxis([cmin_current, cmax_current]);
% colorbar
% annotate_image(gcf, gca);
% axis([xmin_mask xmax_mask ymin_mask ymax_mask])
% box on
% title('Ratio')
% set(gcf, 'Position', [360 584 441 316])
%
% %% plot distribution of mean measured dot diameter on the image
%
% % display image
% figure
% imagesc(im_ref)
% colormap(flipud(gray))
% annotate_image(gcf, gca);
% % axis([xmin_mask xmax_mask ymin_mask ymax_mask])
% hold on
%
% plot_colored_circles(gcf, X_grad, Y_grad, d_grad, 0.75*dot_diameter, 1.5*dot_diameter, dot_diameter/2);
% set(gca, 'ydir', 'normal')
% title({'Dot Diameter - Experiment'; ['Min: ' num2str(0.75*dot_diameter, '%.2f') ' pix., Max: ' num2str(1.25*dot_diameter, '%.2f') ' pix.']})
% set(gcf, 'Position', [360 275 741 625])
% set(gcf, 'Resize', 'off')
% if save_figures
% saveas(gcf, fullfile(figure_save_directory, 'dot-diameter-exp-spatial.png'), 'png');
% saveas(gcf, fullfile(figure_save_directory, 'dot-diameter-exp-spatial.eps'), 'epsc');
% end
%
% %% plot distribution of position estimation variance on the image
%
% % ------------------------------------
% % plot circles with global color bar
% % ------------------------------------
%
% % display image
% figure
% imagesc(im_grad)
% colormap(flipud(gray))
% annotate_image(gcf, gca);
% % axis([xmin_mask xmax_mask ymin_mask ymax_mask])
% hold on
%
% plot_colored_circles(gcf, X_all, Y_all, sqrt(err_var_x_all + err_var_y_all), global_cmin, global_cmax, dot_diameter/2);
% % plot_colored_circles(gcf, X_grad, Y_grad, sqrt(err_var_x_all + err_var_y_all), cmin, cmax, dot_diameter/2);
% ylim([100 400])
% set(gca, 'ydir', 'normal')
% title({'\sigma_{X_0} - Simulation'; ['Min: ' num2str(global_cmin, '%.2f') ' pix., Max: ', num2str(global_cmax, '%.2f') ' pix.']})
% set(gcf, 'Position', [360 275 741 625])
% set(gcf, 'Resize', 'off')
% if save_figures
% saveas(gcf, fullfile(figure_save_directory, 'pos-std-exp-spatial-global.png'), 'png');
% saveas(gcf, fullfile(figure_save_directory, 'pos-std-exp-spatial-global.eps'), 'epsc');
% end
%
% % return;
% % ------------------------------------
% % plot circles with local color bar
% % ------------------------------------
%
% local_cmin = prctile(sqrt(err_var_x_all + err_var_y_all), 0.1);
% local_cmax = prctile(sqrt(err_var_x_all + err_var_y_all), 0.9);
%
% % display image
% figure
% imagesc(im_grad)
% colormap(flipud(gray))
% annotate_image(gcf, gca);
% % axis([xmin_mask xmax_mask ymin_mask ymax_mask])
% hold on
%
% plot_colored_circles(gcf, X_all, Y_all, sqrt(err_var_x_all + err_var_y_all), local_cmin, local_cmax, dot_diameter/2);
% % plot_colored_circles(gcf, X_grad, Y_grad, sqrt(err_var_x_all + err_var_y_all), cmin, cmax, dot_diameter/2);
% ylim([100 400])
% set(gca, 'ydir', 'normal')
% title({'\sigma_{X_0} - Simulation'; ['Min: ' num2str(local_cmin, '%.2f') ' pix., Max: ', num2str(local_cmax, '%.2f') ' pix.']})
% set(gcf, 'Position', [360 275 741 625])
% set(gcf, 'Resize', 'off')
% if save_figures
% saveas(gcf, fullfile(figure_save_directory, 'pos-std-exp-spatial-local.png'), 'png');
% saveas(gcf, fullfile(figure_save_directory, 'pos-std-exp-spatial-local.eps'), 'epsc');
% end
%
% %% calculate crlb
% fprintf('calculating crlb \n');
%
% % number of dots for which the crlb needs to be calculated
% num_dots = size(X_ref,1);
%
% % declare arrays to hold results
% crlb_x_all = ones(1, num_dots) * NaN;
% crlb_x_all_measured = ones(1, num_dots) * NaN;
% crlb_y_all = ones(1, num_dots) * NaN;
% rho_x_interp = ones(1, num_dots) * NaN;
% rho_y_interp = ones(1, num_dots) * NaN;
% rho_xx_interp = ones(1, num_dots) * NaN;
% rho_xy_interp = ones(1, num_dots) * NaN;
% rho_yy_interp = ones(1, num_dots) * NaN;
%
% %% loop through all dots and estimate crlb
%
% for track_index = 1:num_tracks
% %% display progress to user
% if rem(track_index, 1000) == 0
% fprintf('Track number: %d\n', track_index);
% end
%
% %% extract dot index
%
% % reference
% dot_index_ref = tracks_dots(track_index, 11);
% % gradient
% dot_index_grad = tracks_dots(track_index, 12);
%
% %% extract intensity profile
%
% % reference
% im_crop_ref = SIZE_ref.mapint{dot_index_ref};
% % gradient
% im_crop_grad = SIZE_grad.mapint{dot_index_grad};
%
% %% extract dot centroid
%
% % reference
% xc_tracked_ref(track_index) = X_ref(dot_index_ref);
% yc_tracked_ref(track_index) = Y_ref(dot_index_ref);
% xc_crop_ref = xc_tracked_ref(track_index) - SIZE_ref.locxy(dot_index_ref,1) + 1;
% yc_crop_ref = yc_tracked_ref(track_index) - SIZE_ref.locxy(dot_index_ref,2) + 1;
%
% % gradient
% xc_tracked_grad(track_index) = X_grad(dot_index_grad);
% yc_tracked_grad(track_index) = Y_grad(dot_index_grad);
% xc_crop_grad = xc_tracked_grad(track_index) - SIZE_grad.locxy(dot_index_grad,1) + 1;
% yc_crop_grad = yc_tracked_grad(track_index) - SIZE_grad.locxy(dot_index_grad,2) + 1;
%
% end
%
% for p_ref = 1:num_dots %size(X_all, 1)
% % display progress to user
% if rem(p_ref, 1000) == 0
% fprintf('Dot number: %d\n', p_ref);
% end
%
% track_index = find(tracks_dots(:,12) == p_ref);
% if isempty(track_index)
% continue;
% end
% p_grad = tracks_dots(track_index, 11);
% % extract the intensity map for this dot
% % im_crop = SIZE_ref.mapint{p_ref};
% im_crop = SIZE_grad.mapint{p_grad};
%
% % if the intensity map is blank, then continue to the next dot
% if isempty(im_crop) || sum(im_crop(:)) == 0
% continue;
% end
%
% % % extract peak intensity if it is finite
% % if isfinite(I_ref(p_ref))
% % I_max = I_ref(p_ref);
% % else
% % I_max = max(im_crop(:));
% % end
% % I_max = max(im_crop(:));
%
% % calculate first gradients of density at the interrogation points using interpolation
% rho_x_interp(p_ref) = interp2(X_rho, Y_rho, rho_x, X_ref(p_ref), Y_ref(p_ref));
% rho_y_interp(p_ref) = interp2(X_rho, Y_rho, rho_y, X_ref(p_ref), Y_ref(p_ref));
%
% % calculate second gradients density at the interrogation points using interpolation
% rho_xx_interp(p_ref) = interp2(X_rho, Y_rho, rho_xx, X_ref(p_ref), Y_ref(p_ref));
% rho_yy_interp(p_ref) = interp2(X_rho, Y_rho, rho_yy, X_ref(p_ref), Y_ref(p_ref));
% rho_xy_interp(p_ref) = interp2(X_rho, Y_rho, rho_xy, X_ref(p_ref), Y_ref(p_ref));
%
% % calculate crlb
% % [crlb_x_all(p_ref), crlb_y_all(p_ref)] = calculate_crlb_bos(im_crop, rho_xx_interp(p_ref), rho_xy_interp(p_ref), rho_yy_interp(p_ref), d_ref(p_ref), image_generation_parameters.lens_design.magnification, image_generation_parameters.lens_design.aperture_f_number, Z_D*1e-3, Z_g*1e-3, image_generation_parameters.camera_design.pixel_pitch*1e-6, noise_level);
% % [crlb_x_all(p_ref), crlb_y_all(p_ref)] = calculate_crlb_bos(im_crop, rho_xx_interp(p_ref), rho_xy_interp(p_ref), rho_yy_interp(p_ref), d_ref(p_ref), image_generation_parameters.lens_design.magnification, image_generation_parameters.lens_design.aperture_f_number, Z_D*1e-3, Z_g*1e-3, image_generation_parameters.camera_design.pixel_pitch*1e-6, noise_gray_level);
% [crlb_x_all(p_ref), crlb_y_all(p_ref)] = calculate_crlb_bos_02(im_crop, rho_x_interp(p_ref), rho_y_interp(p_ref), rho_xx_interp(p_ref), rho_xy_interp(p_ref), rho_yy_interp(p_ref), d_ref(p_ref), image_generation_parameters.lens_design.magnification, image_generation_parameters.lens_design.aperture_f_number, Z_D*1e-3, Z_g*1e-3, image_generation_parameters.camera_design.pixel_pitch*1e-6, noise_gray_level);
% crlb_x_all_measured(p_ref) = (2 * sqrt(2*pi) * noise_gray_level / sum(im_crop(:)) * d_grad(p_grad)^2/16) ^ 2;
%
% end
%
% %% plot distribution of crlb on the image
%
% % ------------------------------------
% % plot circles with global color bar
% % ------------------------------------
%
% % display the reference image
% figure
% imagesc(im_ref)
% colormap(flipud(gray))
% annotate_image(gcf, gca);
% hold on
%
% % plot position standard deviation estimated from crlb
% plot_colored_circles(gcf, X_ref(:,1), Y_ref(:,1), sqrt(crlb_x_all + crlb_y_all), global_cmin, global_cmax, dot_diameter/2);
%
% ylim([100 400])
% set(gca, 'ydir', 'normal')
% set(gcf, 'Position', [360 275 741 625])
% set(gcf, 'Resize', 'off')
% title({'\sigma_{X_0} - Theory'; ['Min: ' num2str(global_cmin, '%.2f') ' pix., Max: ', num2str(global_cmax, '%.2f') ' pix.']})
% if save_figures
% saveas(gcf, fullfile(figure_save_directory, 'pos-std-theory-spatial-global.png'), 'png');
% saveas(gcf, fullfile(figure_save_directory, 'pos-std-theory-spatial-global.eps'), 'epsc');
% end
%
% % ------------------------------------
% % plot circles with local color bar
% % ------------------------------------
%
% % calculate limits of the local color bar
% local_cmin = prctile(sqrt(crlb_x_all + crlb_y_all), 0.1);
% local_cmax = prctile(sqrt(crlb_x_all + crlb_y_all), 0.9);
%
% % display the reference image
% figure
% imagesc(im_ref)
% colormap(flipud(gray))
% annotate_image(gcf, gca);
% hold on
%
% % plot position standard deviation estimated from crlb
% plot_colored_circles(gcf, X_ref(:,1), Y_ref(:,1), sqrt(crlb_x_all + crlb_y_all), local_cmin, local_cmax, dot_diameter/2);
%
% ylim([100 400])
% set(gca, 'ydir', 'normal')
% set(gcf, 'Position', [360 275 741 625])
% set(gcf, 'Resize', 'off')
% title({'\sigma_{X_0} - Theory'; ['Min: ' num2str(local_cmin, '%.2f') ' pix., Max: ', num2str(local_cmax, '%.2f') ' pix.']})
% if save_figures
% saveas(gcf, fullfile(figure_save_directory, 'pos-std-theory-spatial-local.png'), 'png');
% saveas(gcf, fullfile(figure_save_directory, 'pos-std-theory-spatial-local.eps'), 'epsc');
% end
%
% %% match position estimation variance and crlb estimates for corresponding dots
%
% % declare arrays to hold the crlb for the matched dots
% crlb_x_matched = ones(size(tracks_dots, 1), 1) * NaN;
% crlb_x_measured_matched = ones(size(tracks_dots, 1), 1) * NaN;
% crlb_y_matched = ones(size(tracks_dots, 1), 1) * NaN;
%
% % declare arrays to hold the position estimation variance for the matched
% % dots
% pos_std_x_matched = ones(size(tracks_dots, 1), 1) * NaN;
% pos_std_y_matched = ones(size(tracks_dots, 1), 1) * NaN;
%
% % loop through all dots in the tracks and find corresponding reference and
% % gradient dots
% for dot_index = 1:size(tracks_dots, 1)
% % dot id in gradient image
% p_grad = tracks_dots(dot_index,11);
% % dot id in reference image
% p_ref = tracks_dots(dot_index,12);
%
% % if abs(tracks_dots(dot_index, 2) - 596.7) < 1
% % % flag = flag + 1
% % continue;
% % end
% if isnan(p_ref) || isnan(p_grad)
% continue;
% end
%
% % crlb for the matched dot
% crlb_x_matched(p_grad) = crlb_x_all(p_ref);
% crlb_x_measured_matched(p_grad) = crlb_x_all_measured(p_ref);
% crlb_y_matched(p_grad) = crlb_y_all(p_ref);
% % position estimation variance for the matched dot
% pos_std_x_matched(p_grad) = pos_std_x(p_grad);
% end
%
% %% plot standard deviation of experiment vs theoretial predictions
%
% colors = lines(2);
% figure
% plot(sqrt(crlb_x_matched), pos_std_x_matched, 'o', 'markersize', 3, 'markeredgecolor', colors(1,:)); %, 'markerfacecolor', colors(1,:))
% hold on
% plot(sqrt(crlb_x_measured_matched), pos_std_x_matched, 'o', 'markersize', 3, 'markeredgecolor', colors(2,:)); %, 'markerfacecolor', colors(1,:))
% axis equal
% hold on
% plot([0 1], [0 1])
% % axis([0.02 0.05 0.02 0.05])
% axis([0 1 0 1])
% grid on
% xlabel('\sigma_{X_0}, Theory (pix.)')
% ylabel('\sigma_{X_0}, Simulation (pix.)')
% legend('Theoretical Diameter', 'Measured Diameter', 'location', 'northoutside', 'Orientation', 'horizontal')
% % set(gcf, 'Position', [360 559 417 341]);
% set(gcf, 'Position', [360 388 618 512])
% % return;
% if save_figures
% saveas(gcf, fullfile(figure_save_directory, 'scatter.png'), 'png');
% saveas(gcf, fullfile(figure_save_directory, 'scatter.eps'), 'epsc');
% end
%
%% save workspace to file
workspace_save_directory = fullfile(current_results_directory, 'workspace');
if ~exist(workspace_save_directory, 'dir')
mkdir(workspace_save_directory);
end
% this is the name of the current script
script_name_full = mfilename('fullpath');
[pathstr, script_name, ext] = fileparts(script_name_full);
%%
% Get a list of all variables
allvars = whos;
% Identify the variables that ARE NOT graphics handles. This uses a regular
% expression on the class of each variable to check if it's a graphics object
tosave = cellfun(@isempty, regexp({allvars.class}, '^matlab\.(ui|graphics)\.'));
% Pass these variable names to save
% save('output.mat', allvars(tosave).name)
save(fullfile(workspace_save_directory, [script_name '.mat']), allvars(tosave).name);