Estou tentando usar o gnuplot 5.0 para plotar uma matriz de dados 2D sem margens, bordas ou eixos ... apenas uma imagem 2D (.png ou .jpg) representando alguns dados. Eu gostaria de ter cada elemento da matriz para corresponder a exatamente um pixel da imagem com nenhuma escala / interpolação etc e não pixels brancos extras nas bordas.
Até agora, quando tento definir as margens como 0 e mesmo usando a pixels
bandeira, ainda resta uma linha de pixels brancos nas bordas direita e superior da imagem.
Como posso obter apenas um arquivo de imagem com representação pixel por pixel de uma matriz de dados e nada a mais?
Script gnuplot:
#!/usr/bin/gnuplot --persist
set terminal png size 400, 200
set size ratio -1
set lmargin at screen 0
set rmargin at screen 1
set tmargin at screen 0
set bmargin at screen 1
unset colorbox
unset tics
unset xtics
unset ytics
unset border
unset key
set output "pic.png"
plot "T.dat" binary array=400x200 format="%f" with image pixels notitle
Dados de exemplo do Fortran 90:
program main
implicit none
integer, parameter :: nx = 400
integer, parameter :: ny = 200
real, dimension (:,:), allocatable :: T
allocate (T(nx,ny))
T(:,:)=0.500
T(2,2)=5.
T(nx-1,ny-1)=5.
T(2,ny-1)=5.
T(nx-1,2)=5.
open(3, file="T.dat", access="stream")
write(3) T(:,:)
close(3)
end program main
x y z
formato de lista?Respostas:
Alguns terminais gnuplot implementam "with image" criando um arquivo png separado contendo a imagem e depois vinculando-a dentro da plotagem resultante. Usar esse arquivo de imagem png separado diretamente evitará problemas de layout da página, margens, etc. Aqui eu uso o terminal da tela. O enredo em si é jogado fora; tudo o que mantemos é o arquivo png criado com o conteúdo desejado.
fonte
set term tikz externalimages
e esse terminal reinicia o contador em cada "período definido". Você não pode usarset output "/dev/null"
com o tikz, mas se isso não funcionar para suprimir a saída para você, talvez você não se importe. Os terminais tkcanvas e svg são outras possibilidades, mas o mecanismo png externo depende da versão do gnuplot e das opções de compilação.Não use o gnuplot.
Em vez disso, escreva um script que leia seus dados e os converta em um dos formatos Portable Anymap . Aqui está um exemplo em Python:
Se você pode modificar o programa que gera o arquivo de dados, pode até pular a etapa acima e gerar os dados diretamente no formato PNM.
De qualquer forma, você pode usar o ImageMagick para converter a imagem em um formato de sua escolha:
fonte
imwrite
função pode ser usada para salvar dados 2D como uma imagem PNG.gnuplot
, utilizarei apenasmatplotlib
(veja minha resposta abaixo). Essa é uma grande contribuição, mas tecnicamente a pergunta / recompensa pede umagnuplot
solução, por mais imprópria que pareça ser para essa tarefa em particular.Essa deve ser uma tarefa fácil, no entanto, aparentemente não é. A seguir pode ser uma solução (complicada) porque todas as outras tentativas falharam. Suspeito que algumas bibliotecas de gráficos tenham um problema que você provavelmente não pode resolver como usuário do gnuplot.
Você mencionou que os dados da matriz ASCII também estão ok. O "truque" aqui é plotar dados
with lines
onde os dados são "interrompidos" por linhas vazias, basicamente desenhando pontos únicos. Verifique isso no caso de você precisar colocar seu arquivo de dados 1: 1 em um bloco de dados .No entanto, se já não é estranho o suficiente, parece funcionar para
png
egif
terminal, mas não parapngcairo
ouwxt
. Eu acho que a solução alternativa é provavelmente lenta e ineficiente, mas pelo menos cria a saída desejada. Não tenho certeza se existe um limite de tamanho. Testado com 100x100 pixels com Win7, gnuplot 5.2.6. Comentários e melhorias são bem-vindos.Código:
Resultado: (100x100 pixels)
(ampliada com fundo preto):
Imagem com 400x200 pixels (leva cerca de 22 segundos no meu laptop de 8 anos).
fonte
x
ey
. Ainda está funcionando seSizeX
eSizeY
não é igual. Vou corrigir o código.Data2
?O que acabei realmente usando para obter o que eu precisava, mesmo que a pergunta / recompensa pedisse uma
gnuplot
solução:matplotlib
tem uma função matplotlib.pyplot.imsave, que faz o que eu estava procurando ... ou seja, plotando 'apenas pixels de dados' e sem extras como bordas, margens, eixos, etc. Originalmente, eu só sabia sobre matplotlib.pyplot.imshow e precisava faça muitos truques para eliminar todos os extras do arquivo de imagem e impedir qualquer interpolação / suavização, etc. (e, portanto, ativadagnuplot
em um determinado ponto). Comimsave
isso é bastante fácil, então volto a usarmatplotlib
uma solução fácil e ainda flexível (em termos de mapa de cores, escala, etc.) para plotagens 'exatas em pixels'. Aqui está um exemplo:fonte
OK, aqui está outra solução possível (eu a separei da minha primeira abordagem complicada). Ele cria a trama imediatamente, em menos de um segundo. Não é necessário renomear nem criar um arquivo inútil.
Eu acho que a chave é usar
term png
eps 0.1
.Não tenho uma prova, mas acho
ps 1
que seria ca. 6 pixels de largura e criaria sobreposição e / ou pixels brancos no canto. Novamente, por qualquer motivo, parece funcionar,term png
mas não comterm pngcairo
.O que eu testei (Win7, gnuplot 5.2.6) é um arquivo binário com o padrão
00 00 FF
repetido todo (não consigo exibir bytes nulos aqui). Como o gnuplot aparentemente lê 4 bytes por item da matriz (format="%d"
), isso leva a um padrão RGB alternado se eu estiver plotandowith lc rgb var
.Da mesma forma (espero), podemos descobrir como ler
format="%f"
e usá-lo junto com uma paleta de cores. Eu acho que é isso que você está procurando, certo? Mais resultados, comentários, melhorias e explicações são bem-vindos.Código:
Resultado:
fonte