2 views (last 30 days)

Show older comments

Original question: I'm trying to color a line based on the error, with levels set at 10% and 25% of the error range. The attached code predicts a response, and plots the response and prediction, along with the difference between the response and prediction, and the cumulative probability of the difference. The problem is most visible in the second plot. The colors should be in bands, red > 25%, blue > 10%, and green < 10% of error range. How can the code be corrected to show the proper colors?

Revised question:

The code below generates a figure with three plots. The top plot shows a black line for data, and a multicolor line for a 3-sec forecast of the data. The middle plot shows the error between data and forecast (data-forecast). The bottom plot shows the cumulative probability distribution of the error. What I would like to do is color the lines associated with the forecast based on the level of error. In particular, if the abs(error) is less than 10% of the error range, then the line should be green. If the abs(error) is between 10% and 25% of the error range, then the line should be blue (I have trouble seeing yellow). If the abs(error) is above 25%, then the line should be red. So, in the top plot, the forecast line should be green, blue, and red, indicating where the low is low, medium, or high. Likewise, the middle plot the line should be colored green, blue, and red, and should correspond directly with the top lines, and also the colors should appear in horizontal bands since the y-axis is error. That is, when the error (or y-axis value) is less than 10%, the line should be green. When the error is between 10% and 25%, the line should be yellow. And when the error is above 25%, the line should be red. The bottom figure is actually correct, and does show the cumulative probability colored based on error range (or the x-axis), and shows up as vertical bands.

The reason the code doesn't work is that when the line is a function of time, for the top and middle plots, then addition points need to added when the color changes. The problem now is the color lines extend into the next bands. So, in the top plot you can have a higher color appear less than a lower color, for example, at time 0.595, the blue line changes to a green line at a higher value of error, or the green line error is higher than the blue, which should not occur.

So the question is how to interpolate the forecast line (top plot) and the error line (middle plot) to add values at the times when the colors change (10% and 25% of the error range).

function line_color

%%Question about plot colors

close all; clc; clear;

load iddata9 z9

Ts = z9.Ts;

y1 = cumsum(z9.y);

model = ar(y1, 6, 'ls', 'Ts', Ts, 'IntegrateNoise', true);

[yc1,fit,x0] = compare(y1,model,6);

t1=Ts*((1:length(y1))-1);

yel_pcnt = 10;

red_pcnt = 25;

[t, y, yc, err_dist, cum_err_count, time_indx, err_time, hist_indx] = plot_3_color_line(t1,y1,yc1,yel_pcnt,red_pcnt);

c_color = {'g','b','r'};

figure; nrows = 3; ncols = 1; iplot = 0;

iplot = iplot+1; subplot(nrows,ncols,iplot);

for ic=1:3

x_indx = time_indx{ic}.indx;

x_bad_indx = find(isnan(x_indx));

x_indx(x_bad_indx)=1;

x_data = t(x_indx);

x_data(x_bad_indx) = nan;

y_data_2 = yc(x_indx);

y_data_2(x_bad_indx) = nan;

if (ic == 1)

hp_time_data(1)=plot(t, y, ['k-']);

hold all;

end

hp_time_data(1+ic)=plot(x_data, y_data_2, [c_color{ic},'--'],'linewidth',1);

end

xlabel('time'); ylabel('Response');

legend(hp_time_data, ...

sprintf('Data'), ...

sprintf('Fcst < %3.0f%%',yel_pcnt), ...

sprintf('Fcst < %3.0f%%',red_pcnt), ...

sprintf('Fcst > %3.0f%%',red_pcnt), ...

'location','best');

iplot = iplot+1; subplot(nrows,ncols,iplot);

for ic=1:3

x_indx = time_indx{ic}.indx;

x_bad_indx = find(isnan(x_indx));

x_indx(x_bad_indx)=1;

x_data = t(x_indx);

x_data(x_bad_indx) = nan;

y_data = err_time(x_indx);

y_data(x_bad_indx) = nan;

hp_time_err(ic)=plot(x_data, y_data, c_color{ic},'linewidth',1);

hold all;

end

xlabel('time'); ylabel('Error (Data-Forecast)');

legend(hp_time_err, ...

sprintf('< %3.0f%%range',yel_pcnt), ...

sprintf('< %3.0f%%',red_pcnt), ...

sprintf('> %3.0f%%',red_pcnt), ...

'location','northwest');

iplot = iplot+1; subplot(nrows,ncols,iplot);

for ic=1:3

x_indx = hist_indx{ic}.indx;

x_bad_indx = find(isnan(x_indx));

x_indx(x_bad_indx)=1;

x_data = err_dist(x_indx);

x_data(x_bad_indx) = nan;

y_data = cum_err_count(x_indx)*100;

y_data(x_bad_indx) = nan;

hp_cumm(ic)=plot(x_data, y_data, c_color{ic},'linewidth',1);

hold all;

end

xlabel(sprintf('Data - Fcst'));

ylabel('Cummulative Percent');

legend(hp_cumm, ...

sprintf('< %3.0f%%range',yel_pcnt), ...

sprintf('< %3.0f%%',red_pcnt), ...

sprintf('> %3.0f%%',red_pcnt), ...

'location','northwest');

end

function [t, y, y_est, err_dist, cum_err_count, time_indx, err_time, hist_indx, c_color] = plot_3_color_line(t,y,y_est,yel_pcnt,red_pcnt)

err_time = y-y_est;

[err_count,err_dist]=hist(err_time,100);

err_count = err_count/sum(err_count);

cum_err_count = cumsum(err_count);

rng_err = max(err_time) - min(err_time);

hist_indx{1}.indx = [];

hist_indx{2}.indx = [];

hist_indx{3}.indx = [];

indx_hist_red = abs(err_dist)>red_pcnt/100*rng_err;

i_yellow_hist = abs(err_dist)>yel_pcnt/100*rng_err & ~indx_hist_red;

i_green_hist = ~indx_hist_red & ~i_yellow_hist;

i_color_hist = indx_hist_red*3+i_yellow_hist*2+i_green_hist;

delta_color_hist = diff(i_color_hist);

indx_color_change_hist = find(delta_color_hist~=0);

if (indx_color_change_hist(1) > 1)

indx_color_change_hist = [1 indx_color_change_hist];

end

if (indx_color_change_hist(end) < length(indx_hist_red))

indx_color_change_hist = [indx_color_change_hist length(indx_hist_red)];

end

for ic = 1:(length(indx_color_change_hist)-1)

indx = indx_color_change_hist(ic):indx_color_change_hist(ic+1);

colIndx = i_color_hist(indx_color_change_hist(ic)+1);

if (isempty(hist_indx{colIndx}.indx))

hist_indx{colIndx}.indx = indx;

else

hist_indx{colIndx}.indx = [hist_indx{colIndx}.indx nan indx];

end

end

time_indx{1}.indx = [];

time_indx{2}.indx = [];

time_indx{3}.indx = [];

indx_time_red = abs(err_time)>red_pcnt/100*rng_err;

i_yellow_time = abs(err_time)>yel_pcnt/100*rng_err & ~indx_time_red;

i_green_time = ~indx_time_red & ~i_yellow_time;

i_color_time = indx_time_red*3+i_yellow_time*2+i_green_time;

delta_color_time = diff(i_color_time);

indx_color_change_time = find(delta_color_time~=0);

if (indx_color_change_time(1) > 1)

indx_color_change_time = [1; indx_color_change_time];

end

if (indx_color_change_time(end) < length(indx_time_red))

indx_color_change_time = [indx_color_change_time; length(indx_time_red)];

end

for ic = 1:(length(indx_color_change_time)-1)

indx = indx_color_change_time(ic):indx_color_change_time(ic+1);

colIndx = i_color_time(indx_color_change_time(ic)+1);

if (isempty(time_indx{colIndx}.indx))

time_indx{colIndx}.indx = indx;

else

time_indx{colIndx}.indx = [time_indx{colIndx}.indx nan indx];

end

end

end

Joseph Cheng
on 5 Jan 2016

So.... after digging through your code (next time please include a picture of what you're dealing with and why you don't like it). From your description and what I'm assuming your second figure looks like, I propose that you're using the hist() and the resulting err_dist in your plot_3_color_line() incorrectly. I say this as the [err_count,err_dist] = hist() returns the bins of the histogram and not the individual errors associated to the y data index. such that if i go and insert

figure,bar(err_dist,err_count)

after your hist call you'll see that later when you're plotting

x_indx = time_indx{ic}.indx;

x_data = t(x_indx);

hp_time_err(ic)=plot(x_data, y_data, c_color{ic},'linewidth',1);

that the bands should correspond to the error centered on your line. with green at the center then blue then red at the ends of the line.

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

Start Hunting!