Quiver plot of coordinate error with wrong arrow lengths
2 次查看(过去 30 天)
显示 更早的评论
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
x1 = xlsread('DSC03765.xlsx',1,'A14:A614');
y1 = xlsread('DSC03765.xlsx',1,'B14:B614');
errorx1 = xlsread('DSC03765.xlsx',1,'E14:E614');
errory1 = xlsread('DSC03765.xlsx',1,'F14:F614');
x2 = xlsread('DSC03765.xlsx',2,'A14:A614');
y2 = xlsread('DSC03765.xlsx',2,'B14:B614');
errorx2 = xlsread('DSC03765.xlsx',2,'E14:E614');
errory2 = xlsread('DSC03765.xlsx',2,'F14:F614');
x3 = xlsread('DSC03765.xlsx',3,'A14:A614');
y3 = xlsread('DSC03765.xlsx',3,'B14:B614');
errorx3 = xlsread('DSC03765.xlsx',3,'E14:E614');
errory3 = xlsread('DSC03765.xlsx',3,'F14:F614');
x4 = xlsread('DSC03765.xlsx',4,'A14:A614');
y4 = xlsread('DSC03765.xlsx',4,'B14:B614');
errorx4 = xlsread('DSC03765.xlsx',4,'E14:E614');
errory4 = xlsread('DSC03765.xlsx',4,'F14:F614');
x5 = xlsread('DSC03765.xlsx',5,'A14:A614');
y5 = xlsread('DSC03765.xlsx',5,'B14:B614');
errorx5 = xlsread('DSC03765.xlsx',5,'E14:E614');
errory5 = xlsread('DSC03765.xlsx',5,'F14:F614');
% 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 个评论
Voss
2024-5-24
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
% read sheet
T = readtable('DSC03765.xlsx','Sheet',ii);
% 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
采纳的回答
Voss
2024-5-24
编辑:Voss
2024-5-24
"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
x1 = xlsread('DSC03765.xlsx',1,'A14:A614');
y1 = xlsread('DSC03765.xlsx',1,'B14:B614');
errorx1 = xlsread('DSC03765.xlsx',1,'E14:E614');
errory1 = xlsread('DSC03765.xlsx',1,'F14:F614');
x2 = xlsread('DSC03765.xlsx',2,'A14:A614');
y2 = xlsread('DSC03765.xlsx',2,'B14:B614');
errorx2 = xlsread('DSC03765.xlsx',2,'E14:E614');
errory2 = xlsread('DSC03765.xlsx',2,'F14:F614');
x3 = xlsread('DSC03765.xlsx',3,'A14:A614');
y3 = xlsread('DSC03765.xlsx',3,'B14:B614');
errorx3 = xlsread('DSC03765.xlsx',3,'E14:E614');
errory3 = xlsread('DSC03765.xlsx',3,'F14:F614');
x4 = xlsread('DSC03765.xlsx',4,'A14:A614');
y4 = xlsread('DSC03765.xlsx',4,'B14:B614');
errorx4 = xlsread('DSC03765.xlsx',4,'E14:E614');
errory4 = xlsread('DSC03765.xlsx',4,'F14:F614');
x5 = xlsread('DSC03765.xlsx',5,'A14:A614');
y5 = xlsread('DSC03765.xlsx',5,'B14:B614');
errorx5 = xlsread('DSC03765.xlsx',5,'E14:E614');
errory5 = xlsread('DSC03765.xlsx',5,'F14:F614');
% 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');
2 个评论
Voss
2024-5-24
You're welcome! Any questions, let me know. Otherwise, please "Accept" this answer. Thanks!
更多回答(0 个)
另请参阅
类别
在 Help Center 和 File Exchange 中查找有关 Vector Fields 的更多信息
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!