Está en la página 1de 13

Tema 1: Nociones basicas sobre IDL

Para entrar en IDL (Interactive Data Language) 1 desde la lnea de coman-


dos debe ejecutarse idl o bien idlde (IDL Development Environment). En
estas notas supondremos que entramos tecleando idl pero si prefieres usar
la otra opcion sera todo muy similar. Si todo va bien, al entrar debe aparecer
finalmente la lnea de comandos siguiente:

IDL>

IDL posee ayuda dentro de su propio entorno que se obtiene escribiendo:

IDL>?

No dudes en consultarla cuando sea necesario. Para salir ejecutamos el


comando:

IDL>exit

IDL puede usarse ejecutando programas previamente escritos (lo habi-


tual en cuanto tengamos algo relativamente complicado que programar) o
bien directamente, a traves de la lnea de comandos. En este primer tema
aprenderemos algunas nociones basicas usando la lnea de comandos direc-
tamente.

1. Forma de los comandos


Para mostrar por pantalla el resultado de una operacion podemos escri-
bir:

IDL> print,3.1*5.1234
15.8825

Aqu print es el nombre del comando (llamado en IDL procedure, proce-


dimiento). Cada comando va siempre seguido de una coma (,). Finalmente
3.1*5.1234 (3.1 multiplicado por 5.1234) es el argumento.
Cuando tengamos mas de un argumento los separamos mediante comas:
1
IDL requiere de una licencia comercial. Existe una version libre compatible (aunque
no 100 %) que funciona bajo LINUX: GDL - GNU Data Language. Puedes descargarla de:
http://gnudatalanguage.sourceforge.net/

1
IDL> print,10^4,cos(0.)
10000 1.00000

Los comandos admiten tambien opciones denominadas keywords (pala-


bras claves). La forma general que tienen es:

procedure,argumento_1,...,keyword_1=opcion,...

En los ejemplos anteriores puede especificarse el formato de salida mediante


la opcion format. Si escribimos:

IDL> print,3.1*5.1234,format=(f7.3)
15.883

forzamos a que nos muestre el resultado del producto como un numero real
(f) de 7 caracteres (5 dgitos mas el punto mas el signo menos si lo hubiera
habido) con 3 decimales. Si usamos el formato (f20.16) veremos que nos
aparecen 16 decimales aunque eso no significa que el resultado tenga esa
precision; en ningun caso debemos confundir la presentacion (que es lo que
nos da la opcion format) con la precision del calculo.

Ejercicio 1. Considera la operacion:

IDL> print,5./3.
1.66667

Cuantos decimales significativos tiene el resultado? 2


Otra forma usual de escribir el resultado es con potencias de diez. El
formato es similar al anterior pero con e en lugar de f. Por ejemplo si
escribimos:

IDL> print,3.1*5.1234,format=(e11.4)
1.5883e+01

vemos que el resultado (1.5883 101 ), quince y pico, aparece con 4 decimales.
El numero 11 representa el numero total de caracteres que contiene el resul-
tado, a saber: el signo inicial (en este caso al ser un + deja un blanco), el
dgito antes del punto, el propio punto, los cuatro decimales, la letra e (que
significa diez elevado a), el signo del exponente (en este caso un +) y los
dos dgitos del exponente. Es decir 7 caracteres mas el numero de decimales.
Como regla general podemos usar 8+numero de decimales que queramos (en
doble precision el exponente puede tener tres dgitos).
2
Puedes consultar la respuesta a los ejercicios al final del documento.

2
2. Variables
La forma mas sencilla de crear una variable es asignandole un valor. Por
ejemplo, si escribimos:

IDL> a=3*5

habremos creado la variable A (no se distingue entre mayusculas y minuscu-


las) y asignado el valor 3 5.
Podemos usar cualquier combinacion de letras y numeros para los nom-
bres de las variables (tambien se admite el subndice y el $) pero siempre
deben empezar por una letra. Por ejemplo son validas las variables: mas,
vec, a1, velo2, x 1, x$a. No es valida 3b.
Las variables tienen dos atributos importantes:

1. Tipo de datos. La variable A anterior es de tipo INTEGER (entero).


Tambien pueden ser de tipo real, doble precision, complejo, etc.

2. Tipo de estructura. La variable A anterior es un escalar. Hay tambien


vectores, arrays n x m (matrices), etc.

En cada momento podemos ver el tipo de variable y estructura (en el


caso de los escalares su valor) mediante el comando help. Por ejemplo:

IDL> help,a
A INT = 15

Las variables pueden cambiar sus atributos como consecuencia de una


operacion. Por ejemplo si hacemos:

IDL> a=sqrt(a)
IDL> help,a
A FLOAT = 3.87298

vemos que la variable A pasa a ser un numero de tipo FLOAT (floating point
number o numero con coma flotante) correspondiente a los numeros reales de
menor precision en IDL, concretamente entre 6 y 7 decimales significativos.
Las operaciones anteriores pueden escribirse en una sola lnea usando el
smbolo &:

IDL> a=3*5 & a=sqrt(a) & help,a


A FLOAT = 3.87298

En otros lenguajes de programacion que probablemente conozcas las va-


riables se definen una vez, digamos al principio del programa, y luego siempre
son del mismo tipo (las variables enteras pueden cambiar su valor pero siem-
pre seran enteras, etc.). En IDL no. El hecho de que las variables se definan
de forma dinamica tiene sus ventajas: en el ejemplo anterior se calcula la

3
raz cuadrada de un numero como se hace usualmente y en consecuencia
se transforma en real. Pero es importante no olvidarse de las desventajas,
en concreto podemos terminar pensando que siempre va a funcionar como
intuitivamente esperamos y hay excepciones. En este otro ejemplo:

IDL> a=1 & b=3


IDL> print,a/b
0

1/3=0! La division de dos numeros enteros es la parte entera del cociente.


Era eso lo que queramos? posiblemente no. Si alguno de los numeros de un
cociente es real el resultado es un numero real. As, en el ejemplo anterior,
si no queremos que tome solo la parte entera podemos escribir:

IDL> a=1. & b=3. ;ahora, al a~


nadir el punto, A y B son reales.
IDL> print, a/b
0.33333

Hemos usado el punto y coma (;) para indicar que lo que sigue es un comen-
tario. Puede estar al principio de la lnea o despues de un comando. Al
programar, los comentarios son muy importantes.
Mas problemas con los INTEGER: En IDL por defecto estos son de 2
bytes: los numeros positivos llegan hasta el 32767. Si nos pasamos ocurre
esto:
IDL> ent=32760
IDL> i=ent+10 & print,i
-32766
Con un disparate como este es muy posible que el programa termine por
abortar y podamos darnos cuenta del error. No es tan infrecuente pasarnos
de 32767, por ejemplo si la variable corresponde al numero de datos de un
fichero. As que en muchos casos puede ser una buena idea introducir un
LONG INTEGER:
IDL> ent=32760L ;la L del final distingue este tipo de enteros
IDL> i=ent+10 & print,i ;10L estara bien igualmente
32770
IDL> help,i
I LONG = 32770
Los numeros en doble precision (14 decimales significativos aproximada-
mente) pueden introducirse de una forma similar, en este caso anadiendo la
letra d:
IDL> print,5.d/3.d,format=(f17.14)
1.66666666666667

4
que puede compararse con el resultado del primer ejercicio que se encuentra
al final del documento.
Igual que usamos el comando & para poner dos sentencias en la misma
lnea, podemos usar el signo $ para continuar un comando en la siguiente
lnea:
IDL> b=1+2-2+$
IDL> 4
IDL> print,b
5
Como indicamos en su momento, el comando $ se puede usar tambien como
parte del nombre de una variable (por ejemplo var$1); solo si esta al final
de la lnea y va despues de un operador o similar (consulta la ayuda, ?$,
para mas detalles) indica continuacion de lnea. Si lo pones al principio de
la lnea de comandos veras que te enva al interprete de UNIX/LINUX, sin
cerrar la sesion de IDL. Puedes volver a la sesion de IDL con el comando
exit.

3. Vectores
La forma mas sencilla (pero no la mas frecuente) de crear un vector o
array de una dimension es escribiendo sus elementos entre corchetes: 3
IDL> v=[1,2,4,2]
IDL> help,v
V INT = Array[4]
Aqu INT quiere decir que V es una variable de tipo INTEGER mientras
que Array[4] nos indica que es un array con cuatro componentes.
En IDL muchos operadores y funciones trabajan directamente sobre
arrays. Muchas veces el resultado es el que intuitivamente era de esperar: en
el ejemplo que sigue sumamos a un vector, 2*v, un escalar, 1, entendiendo
que lo que se quiere es sumar el escalar a cada uno de los elementos del
vector.
IDL> w=2*v+1
IDL> print,v,w
1 2 4 2
3 5 9 5
3
En las versiones antiguas de IDL (anteriores a la 5.0) se usaban los parentesis en
lugar de los corchetes para indicar los elementos de un array. Por compatibilidad, en las
nuevas versiones esto sigue funcionando. Sin embargo, dado que los parentesis se usan
para indicar los argumentos de las funciones -sqrt(a), cos(a)- esto puede prestarse a
confusion en particular cuando una funcion y un array poseen el mismo nombre. Por ello
no es recomendable usar parentesis para indicar componentes de arrays aunque sea una
practica muy extendida.

5
La suma, el producto y la division entre dos vectores corresponde res-
pectivamente a la suma, el producto y la division entre componentes:

IDL> z=v+w
IDL> print,z
4 7 13 7
IDL> v1=[1.5,2.1,3.2] & v2=[3.0,4.2,6.5]
IDL> p=v1*v2 & print,p
4.50000 8.82000 20.8000
IDL> d=v1/v2 & print,d
0.500000 0.500000 0.492308

3.1. Subndices
Aunque la velocidad de calculo es muy superior si se trabaja con todos
los elementos de un array a la vez, esto no siempre es posible o deseable.
Consideremos el vector:

IDL> t=[1,2,3,4,5]

Para identificar un elemento usamos la notacion t[i], siendo i el ndice


buscado (que es de tipo INTEGER o en su caso LONG). Como ejemplo si
escribimos:

IDL> print,t[1]
2

vemos que t[1] es el segundo elemento del vector t. El primero es t[0].


Por otra parte, podemos manejar un conjunto seguido de elementos usan-
do los dos puntos. Por ejemplo:

IDL> print,t[0:2]
1 2 3

corresponde a los elementos de t del 0 al 2.


Conviene recordar que las variables pueden cambiar sus atributos, in-
cluidas sus dimensiones, mediante una operacion. Por ejemplo, para anadir
un elemento al final del vector t escribimos:

IDL> t=[t,6] & print,t


1 2 3 4 5 6

y si ahora queremos anadir un 7 como tercer elemento:

IDL> t=[t[0:1],7,t[2:5]] & print,t


1 2 7 3 4 5 6

6
Consideremos por ultimo algunas funciones basicas que nos permiten
crear vectores de forma sencilla (usamos los comandos help y print para
ver lo que hacen estas funciones):

IDL> v1=findgen(4) & print,v1


0.00000 1.00000 2.00000 3.00000
IDL> v2=indgen(4) & print,v2
0 1 2 3
IDL> help,v1,v2
V1 FLOAT = Array[4]
V2 INT = Array[4]
IDL> v3=fltarr(4) & print,v3
0.00000 0.00000 0.00000 0.00000
IDL> v4=dblarr(4) & print,v4
0.0000000 0.0000000 0.0000000 0.0000000
IDL> help,v3,v4
V3 FLOAT = Array[4]
V4 DOUBLE = Array[4]

Cuando necesites una descripcion completa de las funciones que acabamos


de introducir usa la ayuda (por ejemplo ?findgen). Por otra parte recuerda
que la precision de los numeros FLOAT y DOUBLE (unos 7 decimales el
primero y unos 14 el segundo) no se corresponde con los que nos muestra el
compando print por defecto.

Ejercicio 2. Crea un vector de 1000 elementos que cubra uniformemente


el intervalo [0, 2.5]. A continuacion qutale los datos 344 y 567.

4. Arrays de dos dimensiones


Podemos crear un array 3 x 2 (3 filas x 2 columnas) escribiendolo colum-
na a columna, de la siguiente forma:

IDL> ar=[[1,2,3],[4,5,6]]
IDL> help,ar
AR INT = Array[3, 2]

Vemos que efectivamente se trata de una matriz 3 x 2. Para listarla por pan-
talla ponemos la transpuesta porque IDL escribe lo que convencionalmente
se llaman filas y columnas al reves:

IDL> print,transpose(ar)
1 4
2 5
3 6

7
Veamos como operar con arrrays. Para ello creamos dos matrices cua-
dradas a modo de ejemplo. La primera de la siguiente forma:

IDL> a=findgen(9)
IDL> a1=reform(a,3,3)
IDL> help,a,a1
A FLOAT = Array[9]
A1 FLOAT = Array[3, 3]

La funcion reform(a,m,n) nos transforma el vector A en un array de m filas


x n columnas. Para la segunda matriz tomamos la transpuesta:

IDL> a2=transpose(a1)

Probamos a sumar, multiplicar y dividir los dos arrays (los resultados del
print estan quitados pues son demasiado largos):

IDL> print,a1
IDL> print,a2
IDL> b1=a1+a2 & print,b1
IDL> b1=a1*a2 & print,b2
IDL> b3=a1/(a2+1.) & print,b3

Vemos que se suma, multiplica y divide elemento a elemento. Estas son ope-
raciones que nos interesara hacer frecuentemente. Cuidado con no confundir
la multiplicacion elemento a elemento con la multiplicacion de matrices; para
obtener esta ultima debemos poner:

IDL> b4=a1#a2

Usa el comando print, transpose(b4) para comprobar que obtienes lo


esperado.

4.1. Subndices
Supongamos que tenemos una matriz AR cuyos elementos se van cono-
ciendo secuencialmente. Por ejemplo supongamos que por el momento solo
sabemos que ar[1,2]=3.5. Entonces para poder asignar un valor a uno solo
de los elementos del array es necesario tener definida la matriz previamente.
Una forma sencilla de conseguirlo es haciendo inicialmente cero todos sus
elementos. As escribiramos (recuerda la funcion fltarr):

IDL> ar=fltarr(2,4)
IDL> ar[1,2]=3.5 ;empezando por cero: fila 1, columna 2
IDL> print,transpose(ar)
0.00000 0.00000 0.00000 0.00000
0.00000 0.00000 3.50000 0.00000

8
Nuevamente listamos la transpuesta para que se visualice con la apariencia
estandar.
Es importante recalcar que solo cuando asignamos el resultado de una
operacion a uno o a un conjunto de elementos de un array (es decir cuando
en el miembro izquierdo de una igualdad ponemos la variable con corchetes)
es necesario tenerlo definida previamente. Por el contrario, las matrices b1,
b2, b3 y b4 anteriores las introdujimos directamente pues trabajabamos con
todos sus elementos a la vez.
Una de las cosas que cuesta mas acostumbrarse en IDL (y en otros len-
guajes de caractersticas similares) es a operar con trozos de un array. A
modo de ejemplo supongamos que tenemos una serie de datos que repre-
sentan distintas magnitudes (temperatura, presion, densidad). Como por
el momento no sabemos como leer ficheros de datos, vamos a crear unos
numeros aleatorios que hagan las veces de datos:

IDL>data=randomu(seed,300)

La funcion randomu devuelve numeros aleatorios uniformemente distribui-


dos en el intervalo (0,1). Para conseguir el resultado deseado la variable que
hemos llamado seed puede ser en realidad cualquier variable no definida
previamente. Consulta la ayuda para completar la informacion. Suponga-
mos que estos numeros representan los datos indicados anteriormente. Por
tanto tenemos datos de temperatura, presion y densidad agrupados en 100
instantes de tiempo distintos. En concreto supondremos que la temperatu-
ra, presion y densidad en el instante inicial corresponde a los tres primeros
datos del vector:4

IDL> print,data[0:2]
0.957516 0.740806 0.483755

Los siguientes 3 datos, data[3:5], son la temperatura, presion y densidad


en el instante siguiente:

IDL> print,data[3:5]
0.304793 0.939899 0.735009

y as sucesivamente.
Nuestro objetivo final, a modo de ejemplo, es pasar la temperatura de
grados centgrados a Kelvin. En general, si vamos a operar por separado con
cada una de las magnitudes, puede ser una buena idea crearnos una matriz
que nos separe por filas o por columnas cada una de las variables. Para ello
escribimos:
4
Dado que se trata de numeros aleatorios, los valores concretos que tome el vector data
en cada sesion de IDL pueden ser distintos y no tienen porque coincidir con los mostrados
aqu.

9
IDL> tpd=reform(data,3,100)
IDL> help, tpd
TPD FLOAT = Array[3, 100]

Vemos que la funcion reform nos transforma el vector data en un array de 3


filas y 100 columnas de forma que en la primera fila tenemos la temperatura,
en la segunda la presion y en la tercera la densidad. Seguro? o tendramos
que haber tomado 3 columnas y 100 filas? Vamos a comprobar que lo hemos
hecho bien usando el comando print adecuadamente. En concreto la tempe-
ratura (primera fila, es decir, fila 0) en los dos primeros instantes (columnas
0 y 1) correspondera a:

IDL> print,tpd[0,0:1]
0.957516
0.304793

Vemos que efectivamente coinciden con los datos mostrados anteriormente.


Por otra parte, la temperatura, presion y densidad en el instante inicial
corresponderan a la primera columna de la matriz tpd. Entonces le decimos:
filas 0 a 2, columna 0:

IDL> print,tpd[0:2,0]
0.957516 0.740806 0.483755

que efectivamente coincide con lo mostrado al principio. Para indicar todas


tambien podemos usar el smbolo *. La sentencia anterior: todas las filas,
la primera columna es equivalente a:

IDL> print,tpd[*,0]

Supongamos que tenemos la temperatura en grados centgrados y la quere-


mos pasar a Kelvin. Con la separacion en filas de los datos que hemos hecho
es muy facil:

IDL> tpd[0,*]=tpd[0,*]+273.15

es decir sumamos 273.15 a los elementos de la primera fila (la cero) y todas
las columnas (*).

4.2. Subarrays
Supongamos ahora que tenemos el array tpd pero que nos interesa usar
(por ejemplo para guardar) solo la presion y la densidad entre los instante
50 y 60. Entonces creamos un subarray con las filas 1,2 (presion y densidad
respectivamente) y las columnas desde la 49 a la 59, de la siguiente forma:

IDL> sub_tpd=tpd[1:2 , 49:59]

10
Si, por el contrario, queremos almacenar la presion desde el instante 50 hasta
el final podemos hacer lo siguiente:

IDL> p=tpd[1,49:99]

o bien:

IDL> p=tpd[1,49:*]

donde el * en este contexto significa hasta el final. Esto es util si el numero


de datos puede variar lo que ocurrira frecuentemente.

5. Graficas
Veremos en este apartado lo mas elemental. A lo largo del curso iremos
aprendiendo algunas cosas mas sobre graficas. Busquemos algo que dibujar.
Por ejemplo la suma de dos sinusoides:
Creamos un vector con 100 datos uniformemente espaciados en el inter-
valo [0, 6]:

IDL> x=findgen(100)*6.*!pi/99.

Fjate como hemos introducido el numero en precision simple, en doble


precision es !dpi. Creamos un vector con la senal (f1 y f2 son las frecuencias;
a1 y a2 las amplitudes; las fases las ponemos igual a 0):

IDL> f1=0.15 & f2=0.2


IDL> a1=4. & a2=2.
IDL> y=a1*sin(2.*!pi*f1*x)+a2*sin(2.*!pi*f2*x)

Dibujamos y(x):

IDL> plot,x,y,xtitle=tiempo (s),ytitle=velocidad (m/s)

Aqu hemos usado el procedimiento plot con los argumentos x, y junto con
dos opciones para dibujar los carteles en cada eje. Consulta la ayuda (?plot)
cuando sea necesario para ver el resto de opciones. El nombre de las opciones
pueden abreviarse mientras no exista ambiguedad, por ejemplo tambien es
valido:

IDL> plot,x,y,xtit=tiempo (s),ytit=velocidad (m/s)

pero no:

IDL> plot,x,y,xt=tiempo (s),yt=velocidad (m/s)

Si queremos dibujar otra funcion sobre esta grafica lo podemos hacer de


la siguiente forma:

11
IDL> w=abs(y)
IDL> oplot,x,w,linestyle=2
El procedimiento oplot (overplot) permite pintar encima de lo que hay.
Consulta la ayuda para ver las posibilidades segun te vaya haciendo falta.
En el ejemplo anterior el procedimiento plot nos abrio automaticamente
una ventana grafica. En realidad esto ocurrio porque no tenamos ninguna
abierta en ese momento. Si ahora queremos un dibujo en otra ventana de-
bemos especificarlo. Para abrir ventanas podemos usar el comando:
IDL> window,1
donde en lugar de 1 podemos poner cualquier numero entero entre 0 y 31. 5
En la cabecera de la ventana puedes ver el numero de cada una (el dibujo
anterior esta en la 0, no?). Dibujemos algo en la pantalla nueva, por ejemplo:
IDL> z=x*y
IDL> plot,x,z,tit=NUEVO
La ventana grafica no siempre sale en la posicion y con el tamano que
queremos. A parte de usando el cursor de la forma estandar, para cambiar
los valores por defecto podemos usar las siguientes opciones:
IDL> window, 1, xsize=200, ysize=300 ;tama~
no en pixeles
IDL> window, 2, xpos=75, ypos=150 ;posicion origen
A la hora de crear documentos es muy frecuente incluir figuras que mues-
tren los resultados de un calculo. En general la mejor forma de introducirlos
en los procesadores de texto es guardando previamente las figuras en un
fichero postScript o similar. Supongamos que queremos guardar la grafica
que generamos en la ventana 0 como un fichero postScript encapsulado en
un fichero de nombre (por ejemplo) figura.prueba.eps. Lo podemos hacer
de la siguiente forma:
IDL> set_plot,ps
IDL> device,filename=figura.prueba.eps,/encapsulated
IDL> plot,x,y,xtit=tiempo (s),ytit=velocidad (m/s)
IDL> oplot,x,w,linestyle=2
IDL> device,/close
IDL> set_plot,x
El primer comando pasa de modo ventana a fichero postScript, luego abrimos
el fichero con el nombre que queramos, dibujamos con los mismos comandos
que antes: plot, oplot, etc., cerramos el fichero y por ultimo volvemos al
modo pantalla para los siguientes dibujos (suponiendo que eso sea lo que
nos interese). La Figura 1 muestra el resultado.
5
No existe un lmite para el numero de ventanas. Para abrir la que tenga el ndice menor
por encima de 31 todava sin usar en la sesion debe escribirse la sentencia window,/free.

12
Figura 1: Este es el resultado de anadir el fichero figura.prueba.eps que
acabamos de generar al procesador de texto (LATEX 2 concretamente). Pa-
ra decir verdad la opcion /encapsulated que pusimos antes nos permite
cambiar el tamano de la grafica a posteriori con el procesador de texto. En-
tonces si, como suele ocurrir frecuentemente, nos interesa reducir el tamano
de la grafica en el texto, conviene aumentar previamente con IDL el tamano
de las letras y numeros de los ejes para que se vean bien, esto se hace con
la opcion charsize que nos multiplica el tamano de los caracteres por un
factor, concretamente la figura tiene: plot,...,chars=1.5

6. Respuesta a los ejercicios


Ejercicio 1: Por defecto el comando print nos ensena un numero determinado
de decimales pero la precision puede ser mayor. Para ver mas decimales ponemos:

IDL> print,5./3.,format=(f15.12)
1.666666626930

y sabiendo que el resultado debe ser uno con seis periodo resultan como mucho
7 decimales significativos.

Ejercicio 2: Al tener decimales, el vector debe ser real. Como el comando


findgen empieza en 0, el ultimo numero sera el 999. Entonces para que sea 2.5
lo reescalamos adecuadamente. Luego para quitar los puntos tenemos en cuenta
que el elemento 344 es a[343] y el 567 es a[566]. As:

IDL> a=findgen(1000)*2.5/999.
IDL> print, a[0],a[999]
0.00000 2.50000
IDL> b=[a[0:342],a[344:565],a[567:999]]
IDL> help,a,b
A FLOAT = Array[1000]
B FLOAT = Array[998]

13

También podría gustarte