Suponha que eu queira atualizar um gráfico com novos dados. Qual método devo escolher?
XDataSource
como um nome, atualize a variável e chame refreshdata
plot
original e chame o comando de plot
novamente. Set('Xdata',...')
Resposta curta: use sempre Set('Xdata',...')
.
Exemplo de código:
function PlotUpdate() x = 0:.1:8; y = sin(x); h = plot(x,y); y = sin(x.^3); set(h,'XData',x,'YData',y); end
Resposta longa:
Existem três medidas relevantes pelas quais se deve escolher o melhor método.
Agora, vamos analisar os methods possíveis.
Método (1) – refreshdata
function PlotUpdate() x = 0:.1:8; y = sin(x); h = plot(x,y); set(h,'YDataSource','y') set(h,'XDataSource','x') y = sin(x.^3); refreshdata(h,'caller'); end
M-lint emite imediatamente um aviso na linha y=sin(x.^3)
The value assigned to variable `y` might be unused
Por que isso acontece? refreshdata
usa eval
e m-lint
não pode saber que você usará y
. Alguém que lê seu código também pode remover essa linha completamente. Isso aconteceu porque você quebrou o princípio de encapsulamento. refreshdata
acessa variables da área de trabalho do chamador. Outra maneira de dar uma olhada nisso, suponha que você passe a alça da plotagem para outra function. O leitor não tem idéia do porquê você escreveu y = sin(x.^3);
e como isso será relacionado à atualização do enredo?
Agora vamos discutir velocidade / tempo de execução. Ao dar uma olhada no código-fonte refreshdata
, você notará dois loops for-loops, que passam por todas as variables de handles de charts em seu espaço. Aqui está o primeiro:
% gather up all the objects to refresh objs = {}; for k = 1:length(h) obj = h(k); objfields = fields(obj); for k2 = 1:length(objfields) % search for properties ending in DataSource if strncmpi(fliplr(objfields{k2}),'ecruoSataD',10) objs = {objs{:},obj, objfields{k2}}; end end end
Imagine que você não tem um enredo, mas 100 enredo e você deseja atualizar apenas o primeiro. Isso será muito lento, porque para cada um dos lotes você tenta encontrar o que precisa! (Eu estou saindo como um exercício para o leitor descobrir o que é ecruoSataD
e como ele é usado.)
Mesmo se você der o enredo relevante como um argumento, você ainda terá o segundo loop, que executa o eval
várias vezes. Não é exatamente eficiente. Eu mostrarei uma comparação de tempo no final.
Conclusão: Difícil de entender, difícil de refatorar, tempo de execução lento
Método (2) – Excluir e refazer o traçado
function PlotUpdate() x = 0:.1:8; y = sin(x); h = plot(x,y); set(h,'YDataSource','y') set(h,'XDataSource','x') y = sin(x.^3); delete(h); h = plot(x,y); end
Este método é bastante claro para o leitor. Você excluiu o enredo e desenhou um novo. No entanto, como veremos na comparação de tempo no final, esse é o método mais lento.
Conclusão: Fácil de entender, fácil de refatorar, tempo de execução muito lento
Método (3) – set (‘XData’, …, ‘YData’)
O código é muito claro. Você deseja modificar duas propriedades do seu gráfico, XData
e YData
. E isso é exatamente o que você faz. Além disso, o código é executado muito rápido, como você pode ver na comparação abaixo.
function PlotUpdate() x = 0:.1:8; y = sin(x); h = plot(x,y); y = sin(x.^3); set(h,'XData',x,'YData',y); end
Desde o novo motor gráfico hg2 (R2014b e acima), você também pode usar a syntax da propriedade para especificar dados se preferir essa notação:
function PlotUpdate() x = 0:.1:8; y = sin(x); h = plot(x,y); y = sin(x.^3); h.XData = x; h.YData = y; end
Conclusão: Fácil de entender, fácil de refatorar, tempo de execução rápido
Aqui está o código de comparação de tempo
function PlotUpdateTimeCompare() x = 0:.1:8; y = sin(x); h = plot(x,y); set(h,'YDataSource','y') set(h,'XDataSource','x') y = sin(x.^3); tic for i=1:100 refreshdata(h,'caller'); end toc tic for i=1:100 delete(h); h = plot(x,y); end toc tic for i=1:100 set(h,'XData',x,'YData',y); end toc end
E os resultados:
O tempo decorrido é de 0,075515 segundos.
O tempo decorrido é de 0,179954 segundos.
O tempo decorrido é de 0,002820 segundos.
Você pode chamar a function drawnow
e fazer algo assim:
h = plot(nan); for i = 1:n y = ... set(h,'YData',y); drawnow %update the graph end
Suponha que eu queira atualizar um gráfico com novos dados. Qual método devo escolher?
Se você tiver mais de um object de linha nos eixos especificados, então Método:
- Defina a propriedade XDataSource como um nome, atualize a variável e chame
refreshdata
irá gerar um erro no MATLAB R2012b. Um exemplo apropriado é fornecido na resposta de Andrey.
Um bug foi enviado para o Mathworks.