How to use quiver correctly?

41 views (last 30 days)
Jin Hung
Jin Hung on 6 Oct 2022
Commented: William Rose on 7 Oct 2022
I have data include speed,direction(0-360 degree) and time series.((see attached 'quiver_input.csv')
I do not know how to apply quiver to my current data correctly.
I use the code as below:
filename = 'quiver_input.csv';
delimiter = ',';
startRow = 1;
formatSpec = '%s%f%f%f%[^\n\r]';
fileID = fopen(filename,'r');
dataArray = textscan(fileID, formatSpec, 'Delimiter', delimiter, 'EmptyValue' ,NaN,'headerlines', startRow-1,'ReturnOnError', false);
fclose(fileID);
WDate = datenum(dataArray{1});
Spd = dataArray{2};
Dir=dataArray{3};
Spd(isnan(Spd)) = 0;
Dir(isnan(Dir)) = 0;
t = WDate;
u = Spd.*cos(Dir);
v = Spd.*sin(Dir);
q = quiver(t,t*0,u,v);
The stick plot is not correect.(see attached 'quiver_output.png')
All help would be greatly appreciated. Jin

Answers (3)

KSSV
KSSV on 6 Oct 2022
T = readtable('https://in.mathworks.com/matlabcentral/answers/uploaded_files/1147075/quiver_input.csv') ;
WDate = datenum(T.(1));
Spd = T.(2) ;
Dir = T.(3) ;
Spd(isnan(Spd)) = 0;
Dir(isnan(Dir)) = 0;
t = WDate;
u = Spd.*cosd(Dir);
v = Spd.*sind(Dir);
q = quiver(t,t*0,u,v);
  6 Comments
William Rose
William Rose on 6 Oct 2022
I use v=wspd*cosd(wdir) because in quiver, v is the y component (up down) and u is the x component (right left). When wdir=0, I want a vector with u=0, v=wdir, i.e. a straight up vector. When wdir=90, I want a u=wdir, v=0, i.e. vector pointing right.
The basic issue is that compasses have 0 degrees on the y axis, but our convention for measuring angles on the plane is put zero on the +x axis.

Sign in to comment.


William Rose
William Rose on 6 Oct 2022
The code below makes a plot like the plot you posted, which you said you want to mimic.
This code does not use quiver, because of the problems with quiver which I demonstrated in my previous answer.
%T = readtable('quiver_input.csv');
T = readtable('quiver_input2.csv'); %shorter file for testing
Spd = T.(2) ;
Dir = T.(3) ;
N=length(Spd); %number of values
Spd(isnan(Spd)) = 0;
Dir(isnan(Dir)) = 0;
u = Spd.*sind(Dir);
v = Spd.*cosd(Dir);
subplot(211), plot(T.(1),Spd,'-b'); ylabel('Speed')
subplot(212), plot(T.(1),Dir,'b.'); ylabel('Direction'); ylim([0 360])
figure;
t = tiledlayout(1,1);
ax1 = axes(t);
%The next plot is made to generate an x-axis. The data is not important.
plot(ax1,T.(1),zeros(size(T.(1))),'-w') %white for invisible data
ax1.YAxisLocation = 'right'; %y-axis 1 on right
ax1.YColor = 'w'; %white to hide y-axis 1
ax1.XColor = 'k'; %x-axis 1 is at bottom and is black
ax2 = axes(t); %create a second pair of axes
% Choose xaxmax to get approximately equal scaling for u and v.
% The factor 2.4 below is derived as follows:
% I expect the y range (for v values) to be 2*max(abs(v)), because I expect the
% most negative and most positive v values will be apprximately equal,
% for a large wind sample. I want x range ~= 1.2 times yrange,
% because Matlab plots seem to be about 20% longer than tall. Therefore this
% choice for xmax will give approximately equal scaling to x and y.
% This will cause wind vectors to be plotted at their true angles.
% I will use axis equal to to make sure the scalin is exactly equal.
% This initial guess for x range gets me in the right ballpark.
xaxmax=2.4*max(abs(v));
x=0:xaxmax/(N-1):xaxmax; %N equally spaced values
for i=1:N %loop to plot the wind arrows
plot([x(i),x(i)+u(i)],[0,v(i)],'-k')
hold on
end
axis equal %assure u,v have equal scaling
xlim([0,xaxmax]); %range of x values must line up with date-times
ax2.XAxisLocation = 'top'; %x axis 2 on top
ax2.XColor = 'w'; %white to hide x-axis 2
ax2.YAxisLocation = 'left'; %y axis 2 at left, color=black by default
ax1.Box = 'off';
ax2.Box = 'off';
ylabel('Wind Speed')
I have used ideas from this page and this page.
Compare the wind speed and direction in the top pair of plots to the wind vectors in the bottom plot. They are consistent.
Wind vectors at the left and right edges may be cut off. A possible cure for this would be to add some wind values of zero for dates before and dates after the date range plotted, before making the plot. This would expand the plotting region horizontally and result in less cut off at left and right edges.
  7 Comments
William Rose
William Rose on 7 Oct 2022
I see from the web page address for the plot that you are at NTU. Please send me a secure email by clicking on the envelope that will appear in the pop-up window when you click on the "WR" circle for my posts.

Sign in to comment.


William Rose
William Rose on 6 Oct 2022
I am mostly copying the code of @KSSV. I am trying to make a plot like the oe you want to mimic. @KSSV's code gives an arrow that points right (+x) when the direction is 0, and points up (+y) when the direction is 90. I want the opposite, so I have flipped cosd and sind. I use axis equal to prevent unequal scaling of u and v. I turn off arrowheads, since the plot you shared did not have arrowheads.
T = readtable('quiver_input.csv') ;
wdate = datenum(T.(1));
Spd = T.(2) ;
Dir = T.(3) ;
Spd(isnan(Spd)) = 0;
Dir(isnan(Dir)) = 0;
t = wdate;
u = Spd.*sind(Dir);
v = Spd.*cosd(Dir);
subplot(311)
quiver(t,t*0,u,v,'ShowArrowHead',0);
axis equal
subplot(312)
quiver(t,t*0,1e3*u,1e3*v,'ShowArrowHead',0);
axis equal %bigger wind
subplot(313)
quiver(t,t*0,u,v,1,'ShowArrowHead',0);
axis equal %turn off autoscale
None of the three plots above are aceptable, because the arrows are too short to see, and because the y-axis scale does not correctly indicate wind speed. I also tried using yyaxis right before quiver, to put the (incorrect) y axis on the right. I was hoping that then I could add an axis to correctly indicate wind speed on the left. But when you use yyaxis right and/or yyaxis left, the axis equal command does not work.

Tags

Products


Release

R2022b

Community Treasure Hunt

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

Start Hunting!

Translated by