terça-feira, 13 de outubro de 2009

Acentos no NCL

Não há no NCL nenhuma fonte com caracteres acentuados e nem a interpretação automática de strings com tais caracteres. Isso atrapalha os usuários cujas línguas nativas exigem estes caracteres. É possível escrever palavras com acentos no NCL, mas é um pouco chato.

Os caracteres acentuados são gerados por meio de Códigos de Função, que permite controlar vários aspectos de um texto. Veja a descrição completa destes códigos aqui.

Para facilitar a minha vida, criei um arquivo que armazena separadamente os códigos para os caracteres acentuados. Os nomes das variáveis do tipo string, que contêm os códigos, seguem os nomes da tabela de acentos do HTML. Veja abaixo os caracteres acentuados e algumas palavras em português, mostrando como o NCL os plota.


Abaixo está o script que gerou esta saída:


load "$NCARG_ROOT/lib/ncarg/nclscripts/csm/gsn_code.ncl"

begin

; tabela de acentos
Agrave = "A~H-15V6F35~A~FV-6H3~" ; À
agrave = "a~H-13V2F35~A~FV-2H3~" ; à
Aacute = "A~H-15V6F35~B~FV-6H3~" ; Á
aacute = "a~H-13V2F35~B~FV-2H3~" ; á
Acirc = "A~H-15V6F35~C~FV-6H3~" ; Â
acirc = "a~H-13V2F35~C~FV-2H3~" ; â
Atilde = "A~H-15V6F35~D~FV-6H3~" ; Ã
atilde = "a~H-13V2F35~D~FV-2H3~" ; ã
Auml = "A~H-15V6F35~H~FV-6H3~" ; Ä
auml = "a~H-13V2F35~H~FV-2H3~" ; ä

Egrave = "E~H-15V6F35~A~FV-6H3~" ; È

egrave = "e~H-13V2F35~A~FV-2H3~" ; è
Eacute = "E~H-15V6F35~B~FV-6H3~" ; É
eacute = "e~H-13V2F35~B~FV-2H3~" ; é
Ecirc = "E~H-15V6F35~C~FV-6H3~" ; Ê
ecirc = "e~H-13V2F35~C~FV-2H3~" ; ê
Euml = "E~H-15V6F35~H~FV-6H3~" ; Ë
euml = "e~H-13V2F35~H~FV-2H3~" ; ë

Igrave = "I~H-10V6F35~A~FV-6H3~" ; Ì

igrave = "i~H-10V2F35~A~FV-2H3~" ; ì
Iacute = "I~H-08V6F35~B~FV-6H3~" ; Í
iacute = "i~H-08V2F35~B~FV-2~" ; í
Icirc = "I~H-09V6F35~C~FV-6H3~" ; Î
icirc = "i~H-09V2F35~C~FV-2H3~" ; î
Iuml = "I~H-09V6F35~H~FV-6H3~" ; Ï
iuml = "i~H-09V2F35~H~FV-2H3~" ; ï

Ograve = "O~H-15V6F35~A~FV-6H3~" ; Ò

ograve = "o~H-13V2F35~A~FV-2H3~" ; ò
Oacute = "O~H-15V6F35~B~FV-6H3~" ; Ó
oacute = "o~H-13V2F35~B~FV-2H3~" ; ó
Ocirc = "O~H-16V6F35~C~FV-6H3~" ; Ô
ocirc = "o~H-14V2F35~C~FV-2H3~" ; ô
Otilde = "O~H-15V6F35~D~FV-6H3~" ; Õ
otilde = "o~H-13V2F35~D~FV-2H3~" ; õ
Ouml = "O~H-16V6F35~H~FV-6H3~" ; Ä
ouml = "o~H-14V2F35~H~FV-2H3~" ; ä

Ugrave = "U~H-15V6F35~A~FV-6H3~" ; Ù
ugrave = "u~H-13V2F35~A~FV-2H3~" ; ù
Uacute = "U~H-13V6F35~B~FV-6H3~" ; Ú
uacute = "u~H-13V2F35~B~FV-2H3~" ; ú
Ucirc = "U~H-15V6F35~C~FV-6H3~" ; Û
ucirc = "u~H-13V2F35~C~FV-2H3~" ; û
Uuml = "U~H-15V6F35~H~FV-6H3~" ; Ü
uuml = "u~H-13V2F35~H~FV-2H3~" ; ü

Cedil = "C~H-15F35~K~FH2~" ; Ç
cedil = "c~H-13F35~K~FH2~" ; ç

Ntilde = "N~H-15V6F35~D~FV-6H3~" ; Ñ
ntilde = "n~H-13V2F35~D~FV-2H3~" ; ñ

; ambiente grafico
wks = gsn_open_wks("ps","acentos")

; recursos do texto

txres = True
txres@txFontHeightF = 0.03

; plotando caracteres acentuados
txres@txJust = "CenterCenter"
titulo1 = "Acentua"+cedil+atilde+"o com o NCL"
gsn_text_ndc(wks,titulo1,.5,.95,txres)

txres@txJust = "CenterLeft"
titulo2 = "Caracteres acentuados:"
gsn_text_ndc(wks,titulo2,0.,.85,txres)

texto = Agrave+" "+agrave+" "+Aacute+" "+\
aacute+" "+Acirc+" "+acirc+" "+\
Atilde+" "+atilde+" "+ \
Auml+" "+auml
gsn_text_ndc(wks,texto,.2,.8,txres)

texto = Egrave+" "+egrave+" "+Eacute+" "+\
eacute+" "+Ecirc+" "+ecirc+" "+\
Euml+" "+euml
gsn_text_ndc(wks,texto,.2,.75,txres)

texto = Igrave+" "+igrave+" "+Iacute+" "+\
iacute+" "+Icirc+" "+icirc+" "+\
Iuml+" "+iuml
gsn_text_ndc(wks,texto,.2,.7,txres)

texto = Ograve+" "+ograve+" "+Oacute+" "+\
oacute+" "+Ocirc+" "+ocirc+" "+\
Otilde+" "+otilde+" "+\
Ouml+" "+ouml
gsn_text_ndc(wks,texto,.2,.65,txres)

texto = Ugrave+" "+ugrave+" "+Uacute+" "+\
uacute+" "+Ucirc+" "+ucirc+" "+\
Uuml+" "+uuml
gsn_text_ndc(wks,texto,.2,.6,txres)

texto = Cedil+" "+cedil+" "+Ntilde+" "+ntilde
gsn_text_ndc(wks,texto,.2,.55,txres)

; algumas palavras acentuadas

titulo3 = "Algumas palavras:"
gsn_text_ndc(wks,titulo3,0.,.45,txres)

txres@txFontHeightF = 0.025
texto = "ver"+atilde+"o - inst"+aacute+\
"vel - hist"+oacute+"rico - mat"+eacute+"ria"
gsn_text_ndc(wks,texto,.1,.4,txres)

texto = "precipita"+cedil+atilde+\
"o - INFORMA"+Cedil+Otilde+"ES - tr"+ecirc+"s"
gsn_text_ndc(wks,texto,.1,.35,txres)

texto = "dire"+cedil+otilde+\
"es - El-Ni"+ntilde+"o - LA-NI"+Ntilde+"A"
gsn_text_ndc(wks,texto,.1,.3,txres)

texto = "got"+iacute+"culas - pol"+ecirc+\
"mica - Amaz"+ocirc+"nia"
gsn_text_ndc(wks,texto,.1,.25,txres)

texto = "mec"+acirc+"nica - portugu"+ecirc+\
"s - ci"+ecirc+"ncia atmosf"+eacute+"rica"
gsn_text_ndc(wks,texto,.1,.2,txres)

texto = Aacute+"reas - din"+acirc+"mica - Sa"+\
uacute+"de"
gsn_text_ndc(wks,texto,.1,.15,txres)

frame(wks)

end


Neste exemplo, os caracteres acentuados estão no script que os usam, mas podem ser colocados num arquivo .ncl separado que pode ser carregado com o comando load.

A fonte de caracteres 35 contém os caracteres de acentuação, sendo usada, extensivamente, na criação dos caracteres acentuados. Vou analisar a construção de um dos caracteres, sendo direta a extensão desta explicação aos demais. Vejamos o caractere "á", definido no script acima como

aacute = "a~H-13V2F35~B~FV-2H3~"

A explicação se dará quase caractere por caractere:

a é o próprio caractere a
~ é o código de função de texto, que pode ser modificado no arquivo .hluresfile.
H-13 move a posição do texto atual 13 pontos na horizontal, à esquerda (negativo).
V2 move a posição do texto atual 2 pontos na vertical, para cima.
F35 usa a fonte de caracteres 35.
B usa o caractere da fonte de caracteres 35.
F volta a usar a fonte de caracteres anterior.
V-2 move a posição do texto atual 2 pontos na vertical, para baixo.
H3 move a posição do texto na horizontal, três pontos à direita.

Em suma, os caracteres acentuados são montados manualmente, por meio de movimentos do cursor de impressão de caractere para a direita, esquerda, para cima e para baixo.

Quem usou uma máquina de escrever já percebeu o esquema de acentuação, ou seja, (i) escreve o caractere, (ii) volta o cursor para a posição do caractere escrito, (iii) eleva ou abaixa o cursor, (iv) escreve o sinal de acentuação e (v) faz o caminho de volta para continuar a escrever o texto.

Note que os códigos de função de texto ficam sempre entre ~, o sinal indicador do uso destes códigos.

Como comentei no início deste post, a criação dos caracteres acentuados é chata, mas é simples, como se pode ver acima. Uma vez feita, é só sair usando ;).

Abraços e espero que seja útil.

quinta-feira, 8 de outubro de 2009

Unindo figuras com o ImageMagick

Imaginemos a seguinte situação: inúmeras figuras individuais foram geradas por um script e/ou programa, mas somente depois do demorado processamento chegamos à conclusão que o ideal era agrupar as figuras de um modo melhor. O que fazer? Processamos tudo de novo, gerando as figuras da maneira que queremos?

A resposta: sim e não. Sim, se temos tempo disponível para alterar o script e processar os dados novamente para gerar as novas figuras. Não, se o tempo está escasso.

Vamos supor que o tempo está escasso e devemos nos virar com as figuras que temos. O passo óbvio a seguir seria usar um editor de imagens ou editor de texto e agrupar as figuras que queremos. Infelizmente, dá trabalho. Cliques com mouse, seleção das figuras etc. Que tal colocarmos as figuras que queremos agrupar numa linha de comando e, como resultado, tê-las unidas da maneira que queremos.

A solução: o ImageMagick, um pacote de comandos para manipulação de imagens. Entre os vários comandos disponíveis neste pacote, há um chamado montage usado para se criar montagens com figuras.

Vamos aos exemplos práticos. Para isso, vamos supor que as figuras geradas com o NCL no post anterior, ao invés de agrupadas como estão, foram geradas individualmente e vamos agrupar as quatro primeiras daquelas figuras, cujos nomes são: leituraBinarioETA-0.png, leituraBinarioETA-1.png, leituraBinarioETA-2.png e leituraBinarioETA-3.png

Exemplo 1: montagem simples e direta das quatro figuras

montage leituraBinarioETA-0.png leituraBinarioETA-1.png leituraBinarioETA-2.png leituraBinarioETA-3.png montagem1.png

o resultado:


Este é o resultado padrão, sem o uso de opções para o comando montage. Clique na figura e veja o real tamanho desta figura.


Exemplo 2: mesma montagem, mas com o tamanho original das figuras e espaços entre elas

montage -geometry +50+50 leituraBinarioETA-0.png leituraBinarioETA-1.png leituraBinarioETA-2.png leituraBinarioETA-3.png montagem2.png

o resultado:


A opção -geometry +50+50 adiciona espaços na horizontal e na vertical entre as figuras. Clique na figura e veja o tamanho real dela.


Exemplo 3: montando uma coluna com as quatro figuras

montage -tile 1x4 -geometry +0+50 leituraBinarioETA-0.png leituraBinarioETA-1.png leituraBinarioETA-2.png leituraBinarioETA-3.png montagem3.png

o resultado:


Aqui, a opção -tile 1x4 diz ao comando montage para criar uma "figura coluna" com as quatro figuras passadas ao comando.


Exemplo 4: montando uma linha com as quatro figuras

montage -tile 4x1 -geometry +50+0 leituraBinarioETA-0.png leituraBinarioETA-1.png leituraBinarioETA-2.png leituraBinarioETA-3.png montagem4.png

o resultado:



Agora, a mesma opção -tile é usada para criar uma "figura linha" com as quatro figuras.


Exemplo 5: igual ao Exemplo 2, mas com a inclusão de texto para cada uma das figuras

montage -geometry +50+50 -label 'a' leituraBinarioETA-0.png -label 'b' leituraBinarioETA-1.png -label 'c' leituraBinarioETA-2.png -label 'd' le ituraBinarioETA-3.png montagem5.png

o resultado:


Neste exemplo, a inclusão de texto logo abaixo das figuras, passadas ao comando pela opção -label.


Mais exemplos e opções para o comando montage pode ser encontrado aqui. Com estes exemplos vimos como é fácil unir figuras de várias formas com o comando montage. Há opções para colocar bordas, usar informações dos próprios arquivos para o texto que acompanha as figuras e muito mais.

Espero que seja útil.

Abraços.

PS. (09/10/2009): quando escrevi este post eu não sabia como controlar o tamanho do texto dos 'labels' atribuídos às figuras. Veja que no Exemplo 5, os 'labels' são extremamente pequenos. Isto é feito com a opção -pointsize tam, sendo tam um número indicando o tamanho do texto. Para o Exemplo 5, um tamanho igual a 50 produz um bom resultado.

segunda-feira, 5 de outubro de 2009

Leitura de arquivos binários com o NCL

O NCL permite a leitura e escrita de arquivos binários, além de outros tipos de arquivos. Há funções para ler arquivos binários gerados tanto por C quanto por Fortran. Como não uso o C, vou mostrar um exemplo com uma das funções para binários gerados por Fortran.

A função usada neste exemplo chama-se "fbindirread", que lê arquivos binários de acesso direto. O script que apresento neste post lê um arquivo binário gerado pelo pós processamento do modelo regional ETA. Baixe o arquivo binário (download) para testar o script NCL apresentado mais abaixo.

O arquivo de controle (CTL) para visualização no GrADS é mostrado abaixo:

DSET ^Indices2006032700+2006032718.bin
UNDEF -9999.
TITLE Indices de Tempestades Severas
XDEF 140 LINEAR -56.0 0.1000
YDEF 85 LINEAR -26.5 0.1000
ZDEF 1 LEVELS 1000
TDEF 1 LINEAR 00Z27Mar2006 1hr
VARS 17
ncl 0 99 Nivel de Cond. Levantamento (m)
nce 0 99 Nivel de Conv. Espontanea (m)
ne 0 99 Nivel de Equilibrio (m)
thetab 0 99 Max dif. Temp. Bulbo umido (K)
li 0 99 Lifted Index (degree)
cape 0 99 CAPE (J/kg)
mcape 0 99 CAPE (J/kg)
cin 0 99 CINE (J/kg)
shr37 0 99 Total 6h Precip. (m)
ustrm 0 99 Desl. Esp. da Tempestade (m/s)
vstrm 0 99 Desl. Esp. da Tempestade (m/s)
heli 0 99 Helicidaade Rel. a Tempestade (m^2/s^2)
nrv 0 99 Numero de Richardson Volumetrico ()
dnrv 0 99 Den. de Num.de R. Volumetrico (m^2/s^2)
dnrv2km 0 99 Den. de Num.de R. V. Cam. 2km (m^2/s^2)
ieh 0 99 Indice de Energia-Helicidade ()
sup 0 99 Parametro de Super Celula ()
ENDVARS

E agora, o script NCL que le o arquivo binário e plota suas variáveis:

load "$NCARG_ROOT/lib/ncarg/nclscripts/csm/gsn_code.ncl"
load "$NCARG_ROOT/lib/ncarg/nclscripts/csm/gsn_csm.ncl"
load "$NCARG_ROOT/lib/ncarg/nclscripts/csm/contributed.ncl"


begin


; ============== LEITURA DOS DADOS BINARIOS ============
arquivo = "Indices2006032700+2006032718.bin"


; dimensoes das variaveis

; informação obtida do CTL
lon = fspan( -56., -56+139*0.1, 140 )
lat = fspan( -26.5, -26.5+84*0.1, 85 )


; lendo todos os 17 campos do arquivo
saidasETA = fbindirread( arquivo, 0, (/17,85,140/), "float" )

; ==== ATRIBUICAO DE COORDENADAS E OUTRAS INFORMACOES =====
; atribuindo coordenadas ao campo lido

saidasETA!0 = "campos"

saidasETA!1 = "lat"

saidasETA&lat = lat
saidasETA&lat@units = "degree_north"
saidasETA!2 = "lon"

saidasETA&lon = lon
saidasETA&lon@units = "degree_east"


; nome dos campos contidos no arquivo binario
nomeCampos = (/"NCL","NCE","NE","Max. Dif. T~B~W~N~","LI","CAPE", \
"MCAPE", "CINE", "Precip. em 6h", "Desloc. U da Tempestade", \
"Desloc. V da Tempestade", "Helic. Rel. Tempestade", \

"Nro. Vol. de Richardson", "Denom. Nro. Vol. Richardson", \
"Denom. Nro. Vol. Richardson (0-2km)", \
"Indice de Energia-Helicidade", "Parametro de Super Celula" /)

; unidade fisica dos campos
unidadeCampos = (/ "[m]","[m]","[m]","[K]","[C]","[J/kg]", \
"[J/kg]","[J/kg]","[m]",
"[m/s]","[m/s]","[m^2/s^2]","", \
"[m^2/s^2]","[m^2/s^2]","","" /)

;============= PARTE GRAFICA ========================
; criando ambiente grafico

wks = gsn_open_wks("ps","leituraBinarioETA")
; escolha do mapa de cores

gsn_define_colormap(wks,"BlWhRe")

; opcoes do grafico
Res = True
Res@gsnMaximize = True
Res@gsnAddCyclic = False

Res@gsnFrame = False
Res@gsnDraw = False

; mapa

Res@pmTickMarkDisplayMode = "Always"
Res@mpDataSetName = "Earth..4"
Res@mpDataBaseVersion = "MediumRes"

Res@mpOutlineOn = True
Res@mpOutlineSpecifiers = (/"Brazil:states"/)
Res@mpMaxLatF = max(lat)
Res@mpMinLatF = min(lat)

Res@mpMaxLonF = max(lon)
Res@mpMinLonF = min(lon)
Res@mpFillOn = False

; contorno
Res@cnFillOn = True
Res@lbLabelBarOn = True

Res@lbLabelAutoStride = True

Res@gsnSpreadColors = True
Res@cnLineThicknessF = 3.

; desenhando graficos
plot = new( 17, graphic )
do i=0,16
Res@gsnLeftString = nomeCampos(i) ; nome do campo
Res@gsnRightString = unidadeCampos(i) ; unidade fisica do campo
plot(i) = gsn_csm_contour_map( wks, saidasETA(campos|i,lat|:,lon|:), Res )

end do


; colocando tudo em duas paginas
gsn_panel( wks, plot(0:8), (/3,3/), False )

gsn_panel( wks, plot(9:16), (/3,3/), False )

; convertendo arquivo PS para arquivos PNG
system("convert -trim -density 300 -rotate -90 -geometry 1000x1000"+\
" leituraBinarioETA.ps leituraBinarioETA.png")


end


Abaixo estão os dados do arquivo binário plotados pelo script acima:

Primeiro conjunto de figuras:


Segundo conjunto de figuras:



Pronto, arquivo binário lido e informações plotadas. Gastando um pouco mais de tempo, pode-se melhorar o script para pegar as informações do CTL (dimensões das variáveis, número de variáveis, nomes e unidades físicas das variáveis etc) automaticamente.

Fica aqui a sugestão!

Até mais.