我想想象一个函数的峰值,我希望它的标记显示在上面与它们相关联的行。
我制作了一个最小的例子,我已经有了峰值,问题是如何正确地显示标记:
OFFSET
我想要的结果可以通过仔细调整参数plot(x(peaks), y(peaks)+OFFSET, 'v', 'MarkerSize', 24);
来实现:
OFFSET=2.56
如下图所示,对于这个确切示例,
btn_login.rac_signalForControlEvents(.TouchUpInside)
.toSignalProducer().map { [unowned self] _ in
return self.viewModel.s_formErrorMessage.value
}.filter { !$0.isEmpty }
.startWithNext { [unowned self] text in
self.showAlert("", message: text)
}
适用于导出的png,但是使用交互式绘图和导出矢量图形,它再次出错。
有人可以推荐一种方法来获得此结果,而无需手动进行试用/错误吗?
目前我正在使用带有gnuplot的Octave导出到latex + tikz,如果解决方案可以在那里工作那将会很好。
在我的实际(更复杂)用例中,我将多个线条相互绘制到同一个图形中,并且y限制发生变化,因此不能简单地计算偏移量,因为标记尺寸不会随着是限制。
编辑:此外我使用的是semilogx图,因此在x / y轴刻度图中绘制线条看起来会变形。
答案 0 :(得分:2)
一种方法是使用annotations,但是有一些缺点(请参见下文)。
注释使您可以将各种图形对象放置到图形中。关于它们的一件非常令人讨厌的事情是它们在所谓的归一化坐标下工作, 它跨越整个图形窗口(而不仅仅是绘图区域),并且从[0,0]变为[1,1],迫使您首先转换为这些坐标。我编写了一个简单的函数来做到这一点,只要您的绘图比例是线性的(如果需要对数,就必须修改此函数):
## Convert from data coordinates to normalized figure coordinates.
function [xf yf] = figcoords(xa, ya)
axp = get(gca, "position");
lf = axp(1);
bf = axp(2);
rf = lf + axp(3);
tf = bf + axp(4);
xl = xlim();
yl = ylim();
la = xl(1);
ra = xl(2);
ba = yl(1);
ta = yl(2);
xf = lf + (xa-la).*(rf-lf)./(ra-la);
yf = bf + (ya-ba).*(tf-bf)./(ta-ba);
endfunction
通过这种方式,您可以使用annotation
函数对图进行注释:
y = [0.1 0.3 10.0 1.0 0.5 0.1 24.0 0.6 0.1 0.2];
x = (1:length(y));
peaks = [3 7];
## Plot the data as you would normally
plot(x,y);
## Plot peak markers (no `hold on` needed)
[xp yp] = figcoords(peaks, y(peaks)); # Transform to figure coordinates
for coords = [xp; yp]
xpi = coords(1);
ypi = coords(2);
annotation("arrow", [xpi xpi], [ypi+eps ypi]);
endfor
在这里,我们实际上绘制了从顶部指向山峰的小箭头。
由于它们的高度很小,我们只看到箭头。
annotation
函数的参数是x和y坐标
箭头的端点。请注意,我们添加了一小部分(eps
)
到起点的y值以使箭头指向下方。
如果需要,可以调整标记的外观,使它们更具视觉吸引力:
y = [0.1 0.3 10.0 1.0 0.5 0.1 24.0 0.6 0.1 0.2];
x = (1:length(y));
peaks = [3 7];
coloridx = get(gca, "ColorOrderIndex")
peakcolor = get(gca, "ColorOrder")(coloridx,:); # Save current plot colour
plot(x,y);
## Plot peak markers
[xp yp] = figcoords(peaks, y(peaks));
for coords = [xp; yp]
xpi = coords(1);
ypi = coords(2);
annotation("arrow", [xpi xpi], [ypi+eps ypi], "headstyle", "plain",...
"color", peakcolor);
endfor
Plot with annotated peaks in the same color
尽管不管标记的大小或地块如何,这种方法都能很好地工作,但存在一些缺点:
plot
功能。例如,在我的计算机上,用
七个带注释的峰,大约需要一秒钟才能出现标记。
绘制具有数千个峰值的信号几乎是不可能的。答案 1 :(得分:1)
绘制小三角形怎么样?
y = [0.1 0.3 10.0 1.0 0.5 0.1 24.0 0.6 0.1 0.2];
x = (1:length(y));
peaks = [3 7];
plot(x,y);
hold on; line([peaks(1) peaks(1)+0.2], [y(x==peaks(1)) y(x==peaks(1))+1], 'color','b')
hold on; line([peaks(1) peaks(1)-0.2], [y(x==peaks(1)) y(x==peaks(1))+1], 'color','b')
hold on; line([peaks(1)+0.2 peaks(1)-0.2], [y(x==peaks(1))+1 y(x==peaks(1))+1], 'color','b')
hold on; line([peaks(2) peaks(2)+0.2], [y(x==peaks(2)) y(x==peaks(2))+1], 'color','b')
hold on; line([peaks(2) peaks(2)-0.2], [y(x==peaks(2)) y(x==peaks(2))+1], 'color','b')
hold on; line([peaks(2)+0.2 peaks(2)-0.2], [y(x==peaks(2))+1 y(x==peaks(2))+1], 'color','b')
如果峰的y值存在于矢量上的其他位置,则可能存在问题。如果是这样,您可以为first
功能指定find
或其他匹配规范。
答案 2 :(得分:1)
关于Matlab部分,您可以自己绘制峰值标记。沿着这些方向的某个地方(扩展你的例子):
y = [0.1 0.3 10.0 1.0 0.5 0.1 24.0 0.6 0.1 0.2]
x = (1:length(y))
figure, plot(x,y);
leglengthx=0.2;
leglengthy=0.5;
hold on;
peaks = [3 7];
peaks_max=[10 24];
for ii=1:2
line([peaks(ii) peaks(ii)+leglengthx],[peaks_max(ii) peaks_max(ii)+leglengthy]);
line([peaks(ii) peaks(ii)-leglengthx],[peaks_max(ii) peaks_max(ii)+leglengthy]);
line([peaks(ii)-leglengthx peaks(ii)+leglengthx],[peaks_max(ii)+leglengthy peaks_max(ii)+leglengthy]);
end
plot(x(peaks), y(peaks), 'v', 'MarkerSize', 24);
我添加了峰值的最大值,这不应该是自动提取的问题,而是两个控制标记三角形大小的变量。然后它只为每个峰值绘制三条线。
我不知道这会如何转化为Octave。