Quiver plot of coordinate error with wrong arrow lengths

39 visualizzazioni (ultimi 30 giorni)
Andy il 23 Mag 2024 alle 19:29
Commentato: Voss il 24 Mag 2024 alle 17:08
I'm working on a quiver plot that represents coordinate error in images.
However, the magnitude of the vectors is not being represented correctly: for example, some small erros are being draw as bigger lines.
The magnitudes seems to be calculated correctly, but 'idx' is always 0 or 1, although there are 4 magnitude classes; also, the lengths of arrows are wrong in the figures.
I'm plotting 5 figures, but magnitude thresholds are calculated considering the set of images to generate a common legend.
% data
% calculate magnitude
magnitude1 = sqrt(errorx1.^2+errory1.^2);
magnitude2 = sqrt(errorx2.^2+errory2.^2);
magnitude3 = sqrt(errorx3.^2+errory3.^2);
magnitude4 = sqrt(errorx4.^2+errory4.^2);
magnitude5 = sqrt(errorx5.^2+errory5.^2);
magnitude_total = [];
magnitudes = {magnitude1, magnitude2, magnitude3, magnitude4, magnitude5};
% concatenate values of magnitude in one array
for i = 1:length(magnitudes)
magnitude_total = vertcat(magnitude_total, magnitudes{i});
end
% calculate min and max magnitude
mag_res = 0.05;
magnitudelim = [ ...
floor(min(magnitude_total)/mag_res) ...
ceil(max(magnitude_total)/mag_res) ...
]*mag_res;
% define a color map
n_colors = 4;
cmap = jet(n_colors);
% calculate the magnitude thresholds
mthresholds = linspace(magnitudelim(1),magnitudelim(2),n_colors+1);
% plot function
function plot_image(x, y, errorx, errory, magnitude, mthresholds, cmap, magnitudelim, n_colors, img_title)
figure
hold on
% for each color, find the indicies of the magnitudes at this color level
for ii = 1:n_colors
idx = magnitude >= mthresholds(ii) & magnitude < mthresholds(ii+1);
% generate an arrow of the corresponding color
quiver(x(idx), y(idx), errorx(idx), errory(idx), 0.5, 'Color', cmap(ii,:));
end
% set up the colorbar
colormap(cmap);
colorbar();
caxis(magnitudelim);
xlim([0 2836])
ylim([0 2778])
title(img_title);
hold off
end
% plot all figures
plot_image(x1, y1, errorx1, errory1, magnitude1, mthresholds, cmap, magnitudelim, n_colors, '570nm');
plot_image(x2, y2, errorx2, errory2, magnitude2, mthresholds, cmap, magnitudelim, n_colors, '525nm');
plot_image(x3, y3, errorx3, errory3, magnitude3, mthresholds, cmap, magnitudelim, n_colors, '850nm');
plot_image(x4, y4, errorx4, errory4, magnitude4, mthresholds, cmap, magnitudelim, n_colors, '490nm');
plot_image(x5, y5, errorx5, errory5, magnitude5, mthresholds, cmap, magnitudelim, n_colors, '550nm');
1 CommentoMostra -1 commenti meno recentiNascondi -1 commenti meno recenti
Voss il 24 Mag 2024 alle 15:36
By the way, here is a more succinct version, which uses readtable instead of xlsread (which is no longer recommended) and uses arrays (cell arrays, tables) instead of sequences of numbered variables (x1, x2, x3, ...):
sheet_names = sheetnames('DSC03765.xlsx');
N = numel(sheet_names);
C = cell(1,N);
for ii = 1:N
% rename table variables
T = renamevars(T,1:width(T),{'x','y','foo','bar','errorx','errory'});
% calculate magnitude
T.magnitude = sqrt(T.errorx.^2+T.errory.^2);
% store table in cell array
C{ii} = T;
end
% concatenate values of magnitude in one array
magnitude_total = vertcat(C{:}).magnitude;
% calculate min and max magnitude
mag_res = 0.05;
magnitudelim = [ ...
floor(min(magnitude_total)/mag_res) ...
ceil(max(magnitude_total)/mag_res) ...
]*mag_res;
% define a color map
n_colors = 4;
cmap = jet(n_colors);
% calculate the magnitude thresholds
mthresholds = linspace(magnitudelim(1),magnitudelim(2),n_colors+1);
nm = [570 525 850 490 550];
common_scale_factor = 50;
for ii = 1:numel(C)
plot_image(C{ii}.x, C{ii}.y, common_scale_factor*C{ii}.errorx, common_scale_factor*C{ii}.errory, ...
C{ii}.magnitude, mthresholds, cmap, magnitudelim, n_colors, nm(ii));
end
% plot function
function plot_image(x, y, errorx, errory, magnitude, mthresholds, cmap, magnitudelim, n_colors, nm)
figure
hold on
% for each color, find the indicies of the magnitudes at this color level
for ii = 1:n_colors
idx = magnitude >= mthresholds(ii) & magnitude < mthresholds(ii+1);
% generate an arrow of the corresponding color
quiver(x(idx), y(idx), errorx(idx), errory(idx), 'off', 'Color', cmap(ii,:));
end
% set up the colorbar
colormap(cmap);
colorbar();
caxis(magnitudelim);
xlim([0 2836])
ylim([0 2778])
title(sprintf('%d nm',nm));
hold off
end

Accedi per commentare.

Risposta accettata

Voss il 24 Mag 2024 alle 15:11
Modificato: Voss il 24 Mag 2024 alle 15:12
"some small erros are being draw as bigger lines"
That's because each quiver plot scales its own arrows' lengths independently of any other quiver plots.
Using a scale factor of 0.5 means each quiver plot's arrows are half as long as they would be if they were automatically scaled not to overlap, as described in the documentation,
• When scale is a positive number, the quiver function automatically adjusts the lengths of arrows so they do not overlap, then stretches them by a factor of scale. For example, a scale of 2 doubles the length of arrows, and a scale of 0.5 halves the length of arrows.
But this implies nothing about the relative length of one quiver plot's arrows compared to another quiver plot's arrows. Since each quiver plot's arrow lengths are scaled independently, it's impossible to enforce any relationship between multiple quiver plots' arrow lengths when using automatic scaling.
However, you can turn automatic scaling off, and manually apply a scale factor to the arrow magnitudes (i.e., multiply the U and V by some factor before sending them to quiver). Using the same factor for all quiver plots will scale them all together. See the variable common_scale_factor below, and adjust it until the plots look like what you want.
% data
% calculate magnitude
magnitude1 = sqrt(errorx1.^2+errory1.^2);
magnitude2 = sqrt(errorx2.^2+errory2.^2);
magnitude3 = sqrt(errorx3.^2+errory3.^2);
magnitude4 = sqrt(errorx4.^2+errory4.^2);
magnitude5 = sqrt(errorx5.^2+errory5.^2);
magnitude_total = [];
magnitudes = {magnitude1, magnitude2, magnitude3, magnitude4, magnitude5};
% concatenate values of magnitude in one array
for i = 1:length(magnitudes)
magnitude_total = vertcat(magnitude_total, magnitudes{i});
end
% calculate min and max magnitude
mag_res = 0.05;
magnitudelim = [ ...
floor(min(magnitude_total)/mag_res) ...
ceil(max(magnitude_total)/mag_res) ...
]*mag_res;
% define a color map
n_colors = 4;
cmap = jet(n_colors);
% calculate the magnitude thresholds
mthresholds = linspace(magnitudelim(1),magnitudelim(2),n_colors+1);
% plot function
function plot_image(x, y, errorx, errory, magnitude, mthresholds, cmap, magnitudelim, n_colors, img_title)
figure
hold on
common_scale_factor = 50;
% for each color, find the indicies of the magnitudes at this color level
for ii = 1:n_colors
idx = magnitude >= mthresholds(ii) & magnitude < mthresholds(ii+1);
% generate an arrow of the corresponding color
quiver(x(idx), y(idx), common_scale_factor*errorx(idx), common_scale_factor*errory(idx), 'off', 'Color', cmap(ii,:));
end
% set up the colorbar
colormap(cmap);
colorbar();
caxis(magnitudelim);
xlim([0 2836])
ylim([0 2778])
title(img_title);
hold off
end
% plot all figures
plot_image(x1, y1, errorx1, errory1, magnitude1, mthresholds, cmap, magnitudelim, n_colors, '570nm');
plot_image(x2, y2, errorx2, errory2, magnitude2, mthresholds, cmap, magnitudelim, n_colors, '525nm');
plot_image(x3, y3, errorx3, errory3, magnitude3, mthresholds, cmap, magnitudelim, n_colors, '850nm');
plot_image(x4, y4, errorx4, errory4, magnitude4, mthresholds, cmap, magnitudelim, n_colors, '490nm');
plot_image(x5, y5, errorx5, errory5, magnitude5, mthresholds, cmap, magnitudelim, n_colors, '550nm');
(For the other question, "'idx' is always 0 or 1" because idx is a logical vector, which is used for (logical) indexing.)
2 CommentiMostra NessunoNascondi Nessuno
Andy il 24 Mag 2024 alle 16:58
Oh, I see now.
I thought there was proportionality between each other lengths.
This was very helpful, I really appreciate it. Thanks!
Voss il 24 Mag 2024 alle 17:08
You're welcome! Any questions, let me know. Otherwise, please "Accept" this answer. Thanks!

Accedi per commentare.

Categorie

Scopri di più su Vector Fields in Help Center e File Exchange

R2024a

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by