Documentos de Académico
Documentos de Profesional
Documentos de Cultura
Pimcd2013 PDF
Pimcd2013 PDF
Pimcd2013 PDF
Publicacin 1.0
1. Introduccin 3
1.1. Precedentes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
1.2. Por qu Python? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
1.3. Python vs. Matlab . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
1.4. Python en el mbito cientfico . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
2. Puesta en Marcha 9
2.1. Windows . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
2.2. Linux . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
2.3. Consolas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
2.4. IDEs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
2.5. Pythonpath . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
2.6. Ayudas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
2.7. Autoejecucin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
2.8. Cabecera . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
2.9. Generacin de ayudas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
2.10. Carga de Mdulos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
2.11. Definicin de funciones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
2.12. Cdigo ejecutable: main . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
2.13. Sistema de verificacin del cdigo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
3. Lenguajes de Programacin 29
3.1. Caractersticas de programacin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
4. Mdulos Cientficos 37
4.1. Numpy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
4.2. Scipy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
4.3. Matplotlib . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
6. Polarizacin 81
6.1. Introduccin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82
6.2. Programa interactivo para el anlisis de la polarizacin . . . . . . . . . . . . . . . . . . . . . . . 82
6.3. Definiciones de polarizadores . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82
6.4. Definiciones de estados de luz polarizada . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84
6.5. Clculo de la intensidad de un vector de polarizacin . . . . . . . . . . . . . . . . . . . . . . . . 86
6.6. Polarizacin bsica . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86
6.7. Ley de Malus . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86
6.8. Efecto Zenon . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88
I
7. Interaccin radiacin-materia 91
7.1. Introduccin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91
7.2. Dipolo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93
7.3. Resonancia . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96
7.4. Densidad espectral . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98
7.5. Seccin eficaz . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99
II
14.10. Propiedades de la transformada de Fourier . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 223
III
IV
PIMCD2013-python, Publicacin 1.0
ndice general 1
PIMCD2013-python, Publicacin 1.0
2 ndice general
CAPTULO 1
Introduccin
1.1 Precedentes
El manejo de aplicaciones informticas, actualmente generalizado, no conlleva realmente el dominio de las nuevas
tecnologas informticas. La programacin y simulacin se ha convertido en una tarea necesaria en la sociedad
y en el mbito cientfico-tcnico, y por supuesto en el mbito acadmico. Sin embargo, la gran mayora de los
alumnos que llegan a los primeros cursos universitarios no tienen ninguna experiencia en programacin. Incluso en
cursos superiores, un porcentaje demasiado alto no han ido ms all de los ejercicios propuestos en las asignaturas
obligatoras de clculo numrico.
Dentro de la asignatura ptica del grado en Fsica de la Universidad Complutense de Madrid, Luis Miguel
Snchez Brea y Jos Mara Herrera Fernndez (profesor de la asignatura y alumno-tutor respectivamente) in-
corporaron en el curso 2011 - 2012 una serie de seminarios de Computacin cientfica de fenmenos pticos
basados en el lenguaje de programacin Python. Los seminarios se enfocaron como apoyo al aprendizaje de p-
tica utilizando la programacin como medio de resolucin de ejercicios en ptica y fueron la semilla para este
proyecto docente donde pretendemos presentar ejemplos sencillos y de fcil comprensin del uso de Python como
herramienta en diferentes mbitos.
Python es un lenguaje de programacin moderno, de alto nivel, ideal para pequeas aplicaciones as como para
proyectos de gran envergadura. El cdigo de Python es similar al pseudocdigo utilizado para esquematizar la
programacin. Permite realizar todo lo necesario para una programacin completa: diseo orientado a objetos,
unidades de testeo, generacin de documentacin en el cdigo, sencilla interaccin con el sistema operativo, etc.
Es compatible con la programacin basada en objetos, as como la estructurada y por eventos. Tiene un excelente
conjunto de libreras para extender su funcionalidad, incluyendo libreras cientficas que permiten realizar nume-
rosas tareas de tratamiento de datos, visualizacin, clculo numrico y simblico y otras aplicaciones especficas.
Adems, existe una comunidad muy grande de usuarios que, debido a la filosofa open source, son mucho ms
proclives a compartir su cdigo.
A la hora de empezar a trabajar en computacin lo primero que nos sorprende es la gran cantidad de lenguajes
de programacin, por lo que se debe realizar una seleccin cuidadosa. Una lista de los lenguajes de programacin
3
PIMCD2013-python, Publicacin 1.0
Figura 1.1: Figura 1. Lenguajes de programacin ms utilizados en el mundo. Python se mantiene es-
table como tercer lenguaje de programacin despus de la familia de C y de Java. Adems com-
parndo con un lenguaje de mbito cientfico como MATLAB, su posicin es notablemente superior
(4,3 % de uso frente a 0,6 %). Fuente: TIOBE Programming Community Index for November 2013,
http://www.tiobe.com/index.php/content/paperinfo/tpci/index.html .
Por un lado existen lenguajes de uso muy extendido. Actualmente Java es el lenguaje ms utilizado, pues se
utiliza para aplicaciones corporativas. El segundo lenguaje es C en sus diferentes versiones, un estndar en la
programacin durante muchsimos aos. La mayor parte de las ms famosas aplicaciones de escritorio estn
escritas en C++. Estos dos lenguajes dominan el negocio de la programacin. PHP domina en la red. Mientras Java
lo utilizan las grandes organizaciones, PHP lo utilizan empresas ms pequeas e individuos para crear aplicaciones
web dinmicas. Por otro lado, hay numeros paquetes numricos como Matlab, Mathematica y Maple que se
utilizan en centros de investigacin.
La gran mayora de los alumnos que llegan a los primeros cursos de Fsica no han programado nada o casi nada.
Es por ello que hemos elegido un lenguaje de programacin lo ms sencillo y completo posible. Python nos
ofrece una gran sencillez de programacin, una gran cantidad de libreras en las que basar nuestros programas y
4 Captulo 1. Introduccin
PIMCD2013-python, Publicacin 1.0
una importante comunidad de usuarios y desarrolladores que lo soportan. Tambin tiene la ventaja de ser open
source, por lo no nos vamos a tener que asumir ningn coste debido a derechos de autor. Otra ventaja es ser un
sistema multiplataforma, as que podremos programar en cualquier sistema operativo como Windows, Linux o
Mac Os.
Veamos resumidas algunas de las ventajas del lenguaje de programacin Python.
Python es un lenguaje de programacin de alto nivel que permite una rpida implementacin de aplicaciones
con muy poco cdigo. Es ideal para prototipado rpido, pero tambien permite el desarrollo de grandes
aplicaciones.
El cdigo de Python es legible, muy similar al pseudocdigo utilizado para esquematizar la programacin.
Python es un lenguaje interpretado por una mquina virtual, no compilado, por lo que es multiplataforma.
Python permite realizar todo lo necesario para una programacin de cdigo moderna: diseo orientado a
objetos, unidades de testeo, generacin de documentacin en el cdigo, sencilla interaccin con el sistema
operativo, etc.
Tiene estructuras de datos de alto nivel, como las listas, tuplas y diccionarios
Permite la programacin basada en objetos, aunque tambien soporta la programacin funcional y la progra-
macin estructurada.
Es un lenguaje dinmico, pudiendose aadir nuevas funciones y clases a un objeto existente, incluso en
tiempo de ejecucin.
Existen libreras cientficas escritas en Phython maduras y con gran capacidad.
Permite extender trivialmente su aplicabilidad con mdulos escritos en C, C++ y Fortran, de los que existen
numerosas libreras cientficas. Al ser los procedimientos ms rpidos y eficientes para desarrollo de algo-
ritmos matemticos (aunque a veces mucho ms complicados para otras tareas), se pueden programar las
partes ms sensibles en C y realizar el resto de la aplicacin en Python
Tiene un enorme conjunto de libreras para extender su funcionalidad: para acceseo a base de datos, para
almacenamiento de datos, para procesamiento de imgenes, de sonido, para programacin con GUIs (Inter-
faces grficas de usuario, ventanas), y otras muchisimas ms.
Permite el acceso a toda la funcionalidad del sistema operativo (sobre todo en Linux).
Python se puede utilizar como software glue para combinar distintas aplicaciones en una sola (sobre todo
el Linux).
El uso de la indentacin en lugar de los parntesis permite una mayor legibilidad del cdigo.
El cdigo Python se escriben en archivos .py. Estos archivos se pueden agrupar en mdulos, y se pueden
importar los elementos de los mdulos a otros archivos.
Para sistemas Unix, se puede utilizar cdigo para hacer el archivo autoejecutable indicando al sistema que
programa que el es un ejecutable (no hace falta que sea un archivo .exe). utilizar (#!)
El cdigo es extraordinariamente sencillo de comprender.
Existen mdulos de gran calidad y repositorios de cdigo donde se puede encontrar numerosas aplicaciones.
En linux, gran parte de los mdulos estn en los repositorios estndar, por lo que su instalacin es tn sencilla
como pulsar un botn.
Existe una comunidad muy grande de usuarios y debido a la filosofa open, los desarrolladores son mucho
ms proclives a compartir su cdigo con otros. Adems no suelen existir problemas de uso del cdigo de
otros, siempre que cumplas los requisitos de la licencia GLS.
Al ser Python un lenguaje de propsito general, el cdigo que se genera se puede aprovechar de las ventajas
de otros mdulos (como comprimir archivos, enviar datos, automatizar procesos, enlazar nuestros datos con
bases de datos, con servidores web....
Python se puede ejecutar en bastantes IDEs (editores), desde algunos muy sencillos, como IDLE, hasta otros
tan completos como Spyder, Eclipse o NetBeans.
Existen diversas tcnica para creas sistemas de ventanas (Tkinter, wx, QT, etc.) de una forma sorprendente-
mente sencilla en comparacin con otros sistemas operativos. Si se nos da bien el curso, intentaremos ver
QT4, a travs de la herramienta de creacin de ventanas QT Designer 4.
MATLAB (abreviatura de MATrix LABoratory, laboratorio de matrices) es un software matemtico que ofrece
un entorno de desarrollo integrado (IDE) con un lenguaje de programacin propio (lenguaje M). Est disponible
para las plataformas Unix, Windows y Apple Mac OS X. Entre sus prestaciones bsicas se hallan: la manipulacin
de matrices, la representacin de datos y funciones, la implementacin de algoritmos, la creacin de interfaces de
usuario (GUI) y la comunicacin con programas en otros lenguajes y con otros dispositivos hardware. El paquete
MATLAB dispone de dos herramientas adicionales que expanden sus prestaciones, a saber, Simulink (plataforma
de simulacin multidominio) y GUIDE (editor de interfaces de usuario - GUI). Adems, se pueden ampliar las
capacidades de MATLAB con las cajas de herramientas (toolboxes); y las de Simulink con los paquetes de bloques
(blocksets). Matlab tiene ventajas muy interesantes para la programacin cientfica.
Las sesiones interactivas permiten jugar con los datos de una forma muy sencilla.
La sintaxis est muy bien desarrollada para trabajar con vectores y matrices.
La capacidad de visualizacin de datos y modificacin de figuras es excepcionalemente buena.
Existen libreras (normalmente propietarias) de gran calidad y existe una comunidad muy grande de usua-
rios.
No obstante, la mayor parte de estas ventajas tambin las tiene Phython. Adems, tiene una serie de desventajas
que lo desaconsejan como primer lenguaje de programacin.
En primer lugar no es un lenguaje de programacin verdadero ya que est muy dedicado al clculo numri-
co, aunque su funcionalidad se ha extendido con numerosas toolboxes (control de bases de datos, interaccin
con el sistema operativo, etc...).
Adicionalmente, es un lenguaje propietario que requiere de licencias excesivamente caras para estudiantes.
No se puede ejecutar cdigo de forma independiente (standalone). NOTA: Recientemente se ha proporcio-
nado una herramienta adicional llamada MATLAB Builder bajo la seccin de herramientas Application
Deployment para utilizar funciones MATLAB como archivos de biblioteca que pueden ser usados con
ambientes de construccin de aplicacin .NET o Java.
Es horrible hacer un cdigo largo, pues cada funcin debe estar en un nico archivo. Esto significan miles
de archivos y hace ms complicado que varios programadores trabajen en el mismo cdigo.
Tambin Python tiene algunas desventajas respecto a Matlab:
No es tan sencillo manipular las figuras en tiempo real.
Al existir una cantidad ingente de programadores que aportan su cdigo de forma libre, a veces es dificil
determinar cuales son los mdulos mejores para una cierta aplicacin. Hay ms posiblidades donde elegir.
Python es un lenguaje de programacin de propsito general que, en un principio, no se pens para aplicacio-
nes cientficas. Con los aos, siguiendo la filosofa GNU, se han desarrollado multitud de mdulos cientficos,
que permiten realizar numerosas tareas de tratamiento de datos, visualizacin, clculo simblico y aplicaciones
cientficas especficas. Nosotros utilizaremos fundamentalmente los siguientes mdulos cientficos:
Numpy: Generacin de tipos de datos cientficos. http://www.numpy.org/
Scipy: Funciones cientficas de uso general. http://www.scipy.org/
Matplotlib: Grficas en 2D y 3D. http://matplotlib.org/
Mayavi: visualizacin de datos tridimensionales. http://code.enthought.com/projects/mayavi/
6 Captulo 1. Introduccin
PIMCD2013-python, Publicacin 1.0
8 Captulo 1. Introduccin
CAPTULO 2
Puesta en Marcha
Como en casi todos los programas, dependiendo del sistema operativo del que disponga nuestro ordenador la
instalacin de software variar ligeramente y Python no es una excepcin. A fin de que el sistema operativo no
suponga un bache en nuestro camino hacia el aprendizaje de Python, en esta seccin veremos la instalacin paso a
paso en los dos sistemas operativos ms extendidos en la actualidad. Para otros sistemas operativos recomendamos
al lector que en caso de duda acuda a la gran bibliografa existente en la red.
2.1 Windows
A la hora de instalar Python en el sistema operativo de Microsoft tenemos dos opciones segn el uso que vayamos
a hacer del lenguaje de programacin. Por una parte, como ya hemos mencionado en la introduccin, Python es un
leguanje de programacin de uso general por lo que, si ste es el caso, recomendamos la instalacin del paquete
bsico e incorporar los mdulos que necesitemos. En el sitio oficial de Phython en la seccin de descargas podemos
encontrar diferentes versiones. En la actualidad conviven las versiones 3.3.* y 2.7.* donde * es la ltima versin
estable. Las instalaciones de este libro fueron realizadas con la versin 2.7.2 aunque no vara sustancialmente
para versiones posteriores. Por otra parte, como la programacin que vamos a realizar est orientada al mbito
cientfico-acadmico e ingenieril, la opcin que ms se ajusta a nuestros intereses es el paquete Python(x,y).
Python(x,y) es un software de desarrollo gratuito que incorpora los principales mdulos necesarios para clculo
numrico junto con algn otro complemento que analizaremos posteriormente. La instalacin es similar a otros
programas de Windows. Lo primero que debemos de hacer es descargarmos la ltima versin del programa desde
la seccin de descargas de la web oficial, http://code.google.com/p/pythonxy/wiki/Downloads?tm=2.
9
PIMCD2013-python, Publicacin 1.0
En la Figura 2 podemos ver que en el mismo enlace disponemos de las notas de instalacin que recomendamos
repasar antes de iniciar el proceso. Son unos 420 MB (ya que tiene bastantes aplicaciones). Una vez instalado
observaremos como nuestros archivos con extensin .py se asocian con python por lo que si pinchamos dos veces
sobre ellos se ejecutarn.
Figura 2.1: Figura 2. Descarga de Python(x,y) desde la seccin correspondiente en la web oficial. En las misma
pgina podemos encontrar las notas de instalacin que debemos de tener en cuenta.
2.2 Linux
Python viene incorporado en la mayora de las distribuciones existentes. Si en una terminal ejecutamos el comando
python - V
comprobaremos que versin de Python tenemos instalada. En caso de no ser as podemos instalarlo ejecutando
apt-get install python
Otra opcin es, por ejemplo, desde el centro de software en Ubuntu. Basta con buscar python en el lugar co-
rrespondiente y nos indicar si lo tenemos instalado y si queremos instalarlo o desistalarlo. Para instalar nuevos
mdulos se puede seguir el mismo procedimiento ya sea desde la terminal o desde el centro de software.
A la hora de iniciarse en la programacin es muy importante conocer la sintasis del lenguaje que se va a utilizar
para desarrollar codigo de una manera correcta. De igual importancia es conocer las herramientas de las que
disponemos para ejecutar y depurar el cdigo desarrollado.
2.3 Consolas
Desde el mismo momento en el que Python se instala en el sistema podemos empezar a programar abriendo una
consola interactiva en una terminal. La consola interactiva ms sencilla se ejecuta directamente en un terminal
(Linux) escribiendo
python
Inmediantamente podremos ir introduciendo lineas de comandos y ejecutar de una en una. En Windows la forma
es equivalente.
Existen concolas interactivas ms completas que nos van indicando ayudas inmediatas a medida que vamos escri-
biendo cdigo. Se introduce la instruccion y se ejecuta de una en una. Esta forma de programacin es adecuada
cuando somos principiantes y estamos desarrollando programas cortos donde nos interesa ver inmediatamente si
el resultado es correcto o no.
2.4 IDEs
Las consolas no es el mejor procedimiento para desarrollar programas extensos. El cdigo escrito en la consola
no es fcil de seguir y de volver a utilizar. Una programacin eficaz se realiza mediante un Entorno de Desarro-
llo Integrado (IDE, Integrated Developed Environment). Con este acrnimo ingls se describe a toda aplicacin
de sofware que proporciona una facilidad comprensiva a la hora de la creacin de programas informticos sea
en el lenguaje que sea. Normalmente un IDE consta de un editor de cdigo fuente, un compliador y/o un intr-
prete, herramientas de creacin y un depurador. Tambin suelen tener consolas interactivas. En esta seccin nos
centraremos en tres IDEs en particular: IDLE, Spyder y Eclipse.
IDLE: es el IDE de Python basado en el entorno de ventantas thinter y desarrollado 100 % tambin en
Python. Es el ms simple de los tres que veremos pero para principiantes quizs sea el ms adecuado. Posee
modo depuracin aunque para programadores experimentados se queda bastante corto. La instalacin en
Windows se realiza con la instalacin del propio lenguaje mientras que en el resto de SO la instalacin se
realiza de la forma usual. Para ms informacin podemos consultar la documentacin oficial en el siguiente
enlace: http://docs.python.org/2/library/idle.html. En la Figura 3 se muestra un ejemplo de creacin de un
array en la consola de IDLE.
Spyder: Spyder es un IDE especfico para Python orientado a cientficos y desarrollo ingenieril con una
interfaz muy similar a Matlab, por lo que es la opcin ms adecuada cuando se quiere migrar de Matlab
a Python. Si hemos instalado Python(x,y), al iniciar el programa se nos abre una ventana con diversas
caractersitcas. Dentro de la pestaa Shortcuts nos encontramos el apartado Spyder. Bastar con pinchar
en el smbolo del programa (Figura 4) e inmediatamente se nos abrira el programa. Como siempre, si nos
encontramos en linux abrimos una terminal y ejecutamos la orden
sudo apt-get install spyder
Tanto en linux como en Windows si no los tenemos debemos instalar la ultima versin de Java Development Kit
(JDK) y el Java Runtime Environment (JRE). Para configurar PyDev en Eclipse debemos de seguir los siguientes
pasos:
2.4. IDEs 11
PIMCD2013-python, Publicacin 1.0
Figura 2.3: Figura 4. Spyder en Python(X,Y). Para iniciar el programa pinchamos en el smbolo resaltado en la
imagen.
2.4. IDEs 13
PIMCD2013-python, Publicacin 1.0
1. Abrimos Eclipse y nos vamos a Help -> Install New Software. En la pantalla emergente aadimos
http://pydev.org/updates en el campo work with.
2. Pulsamos en Add, esperamos a que actualize el campo de abajo para poder seleccionar PyDev, luego pulsa-
mos en Next, y seguimos el asistente para completar la instalacin.
3. Reiniciamos Eclipse.
4. Ahora deberemos especificar dnde se encuentra el interprete de python en las preferencias Eclipse, para
ello nos vamos a Eclipse -> preferences -> PyDev -> Interpreter > Python. Pulsamos en auto Config,
marcamos todo (sino lo est) y aceptamos.
En este caso tambin tenemos a nuestra disposicin un manual oficial muy completo en
http://pydev.org/manual_101_root.html. Si hemos realizado todos los pasos correctamente podremos ejecu-
tar programas realizados en python sin ningn problema. En la Figura [figEclipse] podemos ver un ejemplo de la
disposicin de las secciones en Eclipse. Estas seccciones son totalmente configurables por lo que dependiendo de
vuestras preferencias la imagen puede o no coincidir con vuestra disposicin.
2.5 Pythonpath
Dependiendo el IDE elegido se nos habr creado una carpeta como directorio de trabajo. Sin embargo en ocasiones
puede interesarnos trabajar con archivos fuera de este directorio. Para ello debemos de aadir la nueva ruta de
nuestros archivos. Esta operacin se realiza en Pythonpath.
Spyder:
Tools > PYTHONPATH manager.
Se busca el directorio donde tenemos los programas.
Eclipse:
2.6 Ayudas
Las comandos de los lenguajes de programacin son prcticamente infinitos y, slo mediante prctica, consegui-
remos aprendernos algunos de ellos. Sin embargo, en la mayora de los casos debereos acudir a la documentacin
oficial para resolver nuestras dudas. Normalmente cada lenguaje de programacin tiene algn comando especfico
para acceder a la informacin que nos interese. Adems muchos de los IDE facilitan el acceso a esta informacin
mediante algn acceso directo o alguna ventana permanente. En general los pasos a seguir cuando no sabemos
qu comando utilizar o la sintaxis de su utilizacin son los siguientes.
Google. El buscador de informacin en internet por excelencia. En algunas ocasiones no sabremos muy
bien por donde empezar o nos sabremos el comando equivalente en otro lenguaje de programacin. Si el
lector ha tenido esa duda seguramente otra persona la haya tenido antes por lo que podremos encontrar la
respuesta sin demasiado esfuerzo.
Mediante el uso de comandos especificos. Como hemos mencionado, cada lenguaje de programacin tiene
una serie de comandos para accecer a la informacin de los comandos acerca de los cuales tengamos dudas.
Por ejemplo si en una consola tecleamos
import numpy as np
help(np.linspace)
2.6. Ayudas 15
PIMCD2013-python, Publicacin 1.0
Parameters
----------
start : scalar
The starting value of the sequence.
stop : scalar
The end value of the sequence, unless endpoint is set to False.
In that case, the sequence consists of all but the last of num + 1
evenly spaced samples, so that stop is excluded. Note that the step
size changes when endpoint is False.
num : int, optional
Number of samples to generate. Default is 50.
endpoint : bool, optional
If True, stop is the last sample. Otherwise, it is not included.
Default is True.
retstep : bool, optional
If True, return (samples, step), where step is the spacing
between samples.
Returns
-------
samples : ndarray
There are num equally spaced samples in the closed interval
[start, stop] or the half-open interval [start, stop)
(depending on whether endpoint is True or False).
step : float (only if retstep is True)
2.6. Ayudas 17
PIMCD2013-python, Publicacin 1.0
Figura 2.9: Figura 10. Carga de los directorios en el Pythonpath, para eclipse.
2.6. Ayudas 19
PIMCD2013-python, Publicacin 1.0
See Also
--------
arange : Similiar to linspace, but uses a step size (instead of the
number of samples).
logspace : Samples uniformly distributed in log space.
Examples
--------
>>> np.linspace(2.0, 3.0, num=5)
array([ 2. , 2.25, 2.5 , 2.75, 3. ])
>>> np.linspace(2.0, 3.0, num=5, endpoint=False)
array([ 2. , 2.2, 2.4, 2.6, 2.8])
>>> np.linspace(2.0, 3.0, num=5, retstep=True)
(array([ 2. , 2.25, 2.5 , 2.75, 3. ]), 0.25)
Graphical illustration:
En el caso concreto del IDE Spyder tenemos el Object inspector. Si escribimos en la caja object la palabra
que deseamos probablemente aparezca la ayuda de forma automtica. Por ejemplo, si quiero ordenar una
lista y no se cmo, podemos escribir sort y aparecer la forma de utilizacin. Adems tanto en spyder
como en Eclipse, al escribir el comando nos aparece la ayuda de forma automtica como podemos ver en la
Figura 11
Por tradicin se suele decir que un lenguaje de programacin es ms o menos complicado cuanto ms nos cuesta
implementar el Hola Mundo, es decir, imprimir en pantalla estas dos palabras. Python teniendo en cuenta este
criterio es de los lenguajes ms fciles ya que con una sola lnea de cdigo podemos obtener el resultado deseado
>>> print("Hola Mundo")
Hola Mundo
int main() {
return 0;
2.6. Ayudas 21
PIMCD2013-python, Publicacin 1.0
vemos que el cdigo es notablemente ms largo. Por curiosidad y a modo de avance para el tema siguiente podemos
ver como se representa una grfica simple como la del seno en Python,
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Representamos
plt.plot(x,y)
# Mostramos en pantalla
plt.show()
1.0
0.5
0.0
0.5
1.00 2 4 6 8 10
En la seccin anterior hemos podido comprobar lo sencillo y legible que es un programa Python. No obstante,
con el fin de que el cdigo sea lo ms comprensible posible para cualquiera que se disponga a utilizarlo o modi-
ficarlo se suelen aadir por convenio una serie de apartados y lneas de cdico complementarias que facilitan su
comprensin. As, como normal general todos nuestros programas de Python deben tener los siguientes apartados
2.7 Autoejecucin
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from __future__ import division
La primera lnea de cdigo sirve para decir al sistema operativo que este archivo se puede ejecutar, es decir,
si se hace click sobre el archivo, se llama al programa python y se ejecuta. Es el equivalente a los archivos
ejecutables .exe en Windows, aunque aqu el programa no est compilado, sino que se interpreta (esto ltimo
es ms lento).
La segunda lnea de cdigo sirve para poder utilizar la codificacion utf-8. De esta forma podemos poner
acentos, , etc.
La tercera lnea de cdigo carga un mdulo adicional que permite que la divisin entre nmeros enteros
pueda dar nmeros fraccionarios. Al ser Python un lenguaje de propsito general la divisin entre enteros da
lugar a enteros, lo cual suele ser problematico en clculos cientficos. NOTA: Tambin se puede solucionar
escribiendo, en lugar de 3/4, 3./4, pero de esta forma el riesgo de cometer errores por esta causa es menor.
2.8 Cabecera
# Nombre: ejemplo_estructura_programa.py
# Propsito: Ejemplo de archivo con la estructura de un programa
#
# Origen: Propio
# Autor: Jos Mara Herrera-Fernandez y Luis Miguel Sanchez Brea
#
# Creacin: 12 de Septiembre de 2013
# Historia:
#
# Dependencias: scipy, matplotlib
# Licencia: GPL
Esta seccin es estrictamente voluntaria, sin embargo es muy til cuando varios usuarios programan en el mismo
archivo.
Nombre > El nombre del archivo que vamos a crear cuando guardemos por primera vez. En nuestro caso
ejemplo_estructura_programa.py.
Propsito > La finalizad que se persigue al crear el programa, * Crear grfica del seno*, * Calcular los
coeficientes de un polinomio*, etc.
Origen > Si el origen del programa no es propio conviene saber su procedencia por si se debe consultar de
nuevo la fuente original en un futuro.
Autor(es) > Los nombres de los creadores del programa.
Creacin > Fecha de creacin del programa.
Historia > En caso de modificacines posteriores es en esta secin donde se indica la modificacin, la fecha
de la realizacin y el autor de la misma.
Dependencias > Mdulos necesarios para la ejecucin del programa. Por ejemplo scipy, matplotlib..
Licencia > Apartado correspondiente a los derechos de autor.
Como se observa, para incluir un comentario se utiliza el caracter #
2.7. Autoejecucin 23
PIMCD2013-python, Publicacin 1.0
En el apartado de Ayudas (2.2.4) aprendimos a utilizar el comando help para obtener informacin sobre el uso de
un determinado comando. El resultado es una informacin muy valiosa que nosotros debemos de aadir tambin
a nuestras funciones, programas etc. Es lo que se denomina Docstring. Las ayudas se deben de incluir inmediata-
mente despes de la cabecera en el caso de ser una descripcin general e inmediantamente despus de cualquier
funcin, clase, etc. La metodologa es simple, todo aquella informacin que creamos necesaria para el Docstring
debe de ir encerrada entre seis pares de comillas dobles (tres al inicio y tres al final). Adems para funciones
deberemos de incluir los siguientes apartados:
(Entradas) > (salidas). Se enumeran el tipo de entrados que necesita como entradas la funcin y el tipo de
salidas que nos devolver, int, bool, float, etc
Descripcin. Ecplicacin de la funcin.
Explicacin de cada entrada.
Explicacin de cada salida.
Test. Ejemplo sencillo con el resultado que pueda servir como comprobador del buen uso de la funcin
creada.
Ejemplo de ayuda para un archivo general,
"""
Descripcin: Archivo plantilla para generar programas en Python.
"""
Aunque todava no hemos visto las funciones podemos ver un ejemplo de ayuda en una funcin que nos devuelve
el seno del nmero que entremos,
def f1(x = 3.3):
"""
* (float) --> (float)
* Descripcin: Funcin que devuelve el seno de un entero dado.
* Entradas:
- x = entero.
* Salidas:
- y = seno(entero)
* Test:
>>> print("f1(0.7)")
0.64421768723769102
"""
y = sp.sin(x)
return y
En Python no es necesario declarar las variables, lo cual supone una gran simplificacin respecto a programas
como C. Sin embargo para llamar a funciones y clases que no estn en el archivo que se est ejecutando, es
necesario decirle dnde estn. Se pueden declarar un mdulo, o llamar a sus funciones de diversas formas. En los
siguientes ejemplos cargamos algunas o todas las funciones del mdulo cientfico scipy.
import scipy
import scipy as sp
from scipy import *
from scipy import sin
from scipy.fftpack import fft
import matplotlib.pyplot as plt
Veamos como llamaramos a la funcion sin dependiendo la forma en la que hayamos cargado scipy
import scipy > y = scipy.sin(x), Importamos scipy y llamamos a las funciones que tiene.
import scipy as sp > y = sp.sin(x), Renombramos scipy con un alias ms corto.
from scipy import * > y = sin(x), importamos todas las funciones que contiene scipy
from scipy import sin, cos > y = sin(x), importamos nicamente sin y cos
from scipy.fftpack import fft > Si los mdulos son muy largos, se pueden hacer en varios archivos. Entonces
las funciones o clases estn anidadas.
Esto es de gran utilidad por varios motivos:
Permite no estar pendiente del nombre de las funciones, clases, etc. Si el nombre se repite en dos mdulos,
no hay problema, pues sabemos a qu mdulo pertenece
Permite escribir cdigo de forma modular. Para utilizar en mdulo desarrollado por otro programado, por
ejemplo optica.py, lo nico que hay que hacer es llamarlo antes, import optica
Seguidamente a las declaraciones de los mdulos se pueden escribir las funciones y clases que vayamos a utilizar.
Esto no significa que el programa vaya a realizar ninguna accin. En el siguiente tema se ver cmo hay que
desarrollar el cdigo para crear estas funciones y clases.
Una ventaja de Python es que en un mismo programa (o mdulo, segn definamos) podemos escribir muchas
funciones y clases a la vez, por lo que se simplifica la revisin de cdigo y su mantenimiento. Asimismo, incluir
varias funciones en un mismo archivo permite poder pasar nuestro cdigo a otros programadores de una forma
sencilla.
def f1(x = 3.3):
"""
* (float) --> (float)
* Descripcin: Funcin que devuelve el seno de un entero dado.
* Entradas:
- x = entero.
* Salidas:
- y = seno(entero)
* Test:
>>> print("f1(0.7)")
0.64421768723769102
"""
y = sp.sin(x)
return y
def f2(x=3):
"""
* (float) --> (float)
* Descripcin: Funcin que devuelve el seno de un entero dado.
* Entradas:
- x = entero.
* Salidas:
- y = cos(entero)
* Test:
>> print("f2(0.7)")
0.7648421872844885
"""
y = sp.cos(x)
return y
Python no utiliza parntesis o llaves para decir qu cdigo pertenece a una funcin. Es de esencial importancia
en Python seguir un sistema de indentacin. Es decir, el cdigo que est dentro de una funcin tiene que estr
indentado dentro de la funcin como en el ejemplo anterior para que pertenezca a la funcin. Para salirnos de la
funcin, simplemente des-indentamos el cdigo.
A una funcin de Python se la puede llamar de dos formas: a travs de otra funcin python o directamente. El
comportamiento de la funcin puede ser distinto por lo que se debe de tener cuidado. Si, por ejemplo, tenemos el
siguiente codigo al final del archivo:
if __name__ == __main__:
# Creamos el array x
x = sp.linspace(0,10,100)
Llegados a este punto podemos ver nuestra programa completo que no servir de plantilla para el resto de progra-
mas que creemos,
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from __future__ import division
#----------------------------------------------------------------------
# Nombre: ejemplo_estructura_programa.py
# Propsito: Ejemplo de archivo con la estructura de un programa
#
# Origen: Propio
# Autor: Jos Mara Herrera-Fernandez y Luis Miguel Sanchez Brea
#
# Creacin: 12 de Septiembre de 2013
# Historia:
#
# Dependencias: scipy, matplotlib
# Licencia: GPL
#----------------------------------------------------------------------
"""
Descripcin: Archivo plantilla para generar programas en Python.
"""
import scipy
import scipy as sp
from scipy import *
from scipy import sin
from scipy.fftpack import fft
import matplotlib.pyplot as plt
def f2(x=3):
"""
* (float) --> (float)
* Descripcin: Funcin que devuelve el seno de un entero dado.
* Entradas:
- x = entero.
* Salidas:
- y = cos(entero)
* Test:
>> print("f2(0.7)")
0.7648421872844885
"""
y = sp.cos(x)
return y
if __name__ == __main__:
# Creamos el array x
x = sp.linspace(0,10,100)
Ejecutando,
1.0
0.5
0.0
0.5
1.00 2 4 6 8 10
En el apartado de generacin de ayudas vimos que era conveniente aadir un apartado de verificacin de la la fun-
cin que llamamos Test. Sin embargo, en ocasiones las funciones son demasiado grades para aadir este apartado.
En estas ocasiones la solucin es simple, nos creamos otra funcin que invoque a la primera proporcionando datos
conocidos. De esta forma continuaremos probando el buen funcionamiento de nuestra funcin sin el inconveniente
del espacio.
Lenguajes de Programacin
Existen numerosos manuales de programacin, adems de magnificos y extensos manuales oficiales. Sirva de
ejemplo, http://pyspanishdoc.sourceforge.net/tut/tut.html, una amplia gua en espaol que a pesar de ser escrita en
2005 nos proporcionar toda la informacn que necesitamos. Nosotros en esta seccin nos limitaremos a aportar
un resumen tomado de la wikipedia para que el lector pueda seguir el resto del libro de forma cmoda aunque
recomendamos visitar tanto la fuente original de la informacin, http://es.wikipedia.org/wiki/Python, como la gua
que acabamos de mencionar.
Python fue diseado para ser ledo con facilidad. Una de sus caractersticas es el uso de palabras donde otros
lenguajes utilizaran smbolos. Por ejemplo, los operadores lgicos !, || y && en Python se escriben not, or y and,
29
PIMCD2013-python, Publicacin 1.0
respectivamente.
El contenido de los bloques de cdigo (bucles, funciones, clases, etc.) es delimitado mediante espacios o tabula-
dores, conocidos como indentacin, antes de cada lnea de rdenes pertenecientes al bloque. Python se diferencia
as de otros lenguajes de programacin que mantienen como costumbre declarar los bloques mediante un conjunto
de caracteres, normalmente entre llaves {}. Se pueden utilizar tanto espacios como tabuladores para identar el
cdigo, pero se recomienda no mezclarlos.
Debido al significado sintctico de la indentacin, una instruccin debe estar contenida en lnea. No obstante, si
por legibilidad se quiere dividir la instruccin en varias lneas, aadiendo una barra invertida al final de una lnea,
se indica que la instruccin contina en la siguiente.
lista = [valor 1,valor 2,valor 3]
cadena = Esto es una cadena bastante larga
que es equivalente a
lista = [valor 1,valor 2 \
,valor 3]
cadena = Esto es una cadena \
bastante larga
3.1.2 Comentarios
Los comentarios se pueden poner de dos formas. La primera y ms apropiada para comentarios largos es utilizando
la notacin comentario , tres apostrofes de apertura y tres de cierre.
El intrprete no tiene en cuenta los comentarios, lo cual es til si deseamos poner informacin adicional en nuestro
cdigo como, por ejemplo, una explicacin sobre el comportamiento de una seccin del programa.
3.1.3 Variables
Las variables se definen de forma dinmica, lo que significa que no se tiene que especificar cul es su tipo de
antemano y puede tomar distintos valores en otro momento, incluso de un tipo diferente al que tena previamente.
Se usa el smbolo = para asignar valores.
x = 1
x = "Esta variable es una cadena" # Esto es posible porque los tipos son asignados dinmicamente.
Para declarar una lista se usan los corchetes [ ], en cambio, para declarar una tupla se usan los parntesis (
). En ambas los elementos se separan por comas, y en el caso de las tuplas es necesario que tengan como
mnimo una coma.
Tanto las listas como las tuplas pueden contener elementos de diferentes tipos. No obstante las listas suelen
usarse para elementos del mismo tipo en cantidad variable mientras que las tuplas se reservan para elementos
distintos en cantidad fija.
Para acceder a los elementos de una lista o tupla se utiliza un ndice entero (empezando por 0, no por 1).
Se pueden utilizar ndices negativos para acceder elementos a partir del final, por ejemplo para acceder al
ltimo ndice deberamos de usar -1.
Las listas se caracterizan por ser mutables, es decir, se puede cambiar su contenido en tiempo de ejecucin,
mientras que las tuplas son inmutables ya que no es posible modificar el contenido una vez creada.
Listas
>>> lista = ["abc", 42, 3.1415] # Definicin de una lista con elementos de distinto tipo.
>>> lista[0] # Acceder a un elemento por su ndice, en este caso al primero.
abc
>>> lista[-1] # Acceder a un elemento usando un ndice negativo, en este caso el ltimo.
3.1415
>>> lista.append(True) # Aadir un elemento al final de la lista.
>>> lista
[abc, 42, 3.1415, True]
>>> del lista[3] # Borra un elemento de la lista usando un ndice (en este caso: True).
>>> lista
[abc, 42, 3.1415]
>>> lista[0] = "xyz" # Re-asignar el valor del primer elemento de la lista.
>>> lista
[xyz, 42, 3.1415]
>>> lista[0:2] # Mostrar los elementos de la lista del ndice "0" al "2" (sin incluir este ltimo)
[xyz, 42]
>>> lista_anidada = [lista, [True, 42L]] # Es posible anidar listas
>>> lista_anidada
Tuplas
>>> tupla = ("abc", 42, 3.1415) # Definicin de una tupla con elementos de distinto tipo.
>>> tupla[0] # Acceder a un elemento por su ndice en este caso al primero.
abc
>>> del tupla[0] # No es posible borrar (ni aadir) un elemento en una tupla, lo que provocar una
( Excepcin )
# Tampoco es posible re-asignar el valor de un elemento en una tupla, lo que tambin provocar una
>>> tupla[0] = "xyz"
( Excepcin )
>>> tupla[0:2] # Mostrar los elementos de la tupla del ndice "0" al "2" (sin incluir este ltimo)
(abc, 42)
>>> tupla_anidada = (tupla, (True, 3.1415)) # Tambin es posible anidar tuplas.
>>> 1, 2, 3, "abc" # Esto tambin es una tupla, aunque es recomendable ponerla entre parntesis (
(1, 2, 3, abc)
>>> (1) # Aunque entre parntesis, esto no es una tupla, ya que no posee al menos una coma, por lo
1
>>> (1,) # En cambio, en este otro caso, s es una tupla.
(1,)
>>> (1, 2) # Con ms de un elemento no es necesaria la coma final.
(1, 2)
>>> (1, 2,) # Aunque agregarla no modifica el resultado.
(1, 2)
3.1.6 Diccionarios
Para declarar un diccionario se usan las llaves { }. Contienen elementos separados por comas, donde cada
elemento est formado por un par clave : valor (el smbolo : separa la clave de su valor correspondiente).
Los diccionarios son mutables, es decir, se puede cambiar el contenido de un valor en tiempo de ejecucin.
En cambio, las claves de un diccionario deben ser inmutables. Esto quiere decir, por ejemplo, que no podre-
mos usar ni listas ni diccionarios como claves.
El valor asociado a una clave puede ser de cualquier tipo de dato, incluso un diccionario.
>>> diccionario = {"cadena": "abc", "numero": 42, "lista": [True, 42L]} # Diccionario que tiene di
>>> diccionario["cadena"] # Usando una clave, se accede a su valor.
abc
>>> diccionario["lista"][0] # Acceder a un elemento de una lista dentro de un valor (del valor de
True
>>> diccionario["cadena"] = "xyz" # Re-asignar el valor de una clave.
>>> diccionario["cadena"]
xyz
>>> diccionario["decimal"] = 3.1415927 # Insertar un nuevo elemento clave:valor.
>>> diccionario["decimal"]
3.1415927
>>> diccionario_mixto = {"tupla": (True, 3.1415), "diccionario": diccionario} # Tambin es posible
>>> diccionario_mixto["diccionario"]["lista"][1] # Acceder a un elemento dentro de una lista, que
42L
>>> diccionario = {("abc",): 42} # S es posible que una clave sea una tupla, pues es inmutable.
>>> diccionario = {["abc"]: 42} # No es posible que una clave sea una lista, pues es mutable, lo
( Excepcin )
3.1.7 Conjuntos
Los conjuntos se construyen mediante set(items) donde items es cualquier objeto iterable, como listas o
tuplas. Los conjuntos no mantienen el orden ni contienen elementos duplicados.
Se suelen utilizar para eliminar duplicados de una secuencia, o para operaciones matemticas como inter-
seccin, unin, diferencia y diferencia simtrica.
>>> conjunto_inmutable = frozenset(["a", "b", "a"]) # Se utiliza una lista como objeto iterable.
>>> conjunto_inmutable
frozenset([a, b])
>>> conjunto1 = set(["a", "b", "a"]) # Primer conjunto mutable.
>>> conjunto1
set([a, b])
>>> conjunto2 = set(["a", "b", "c", "d"]) # Segundo conjunto mutable.
>>> conjunto2
set([a, c, b, d]) # Recuerda, no mantienen el orden, como los diccionarios.
>>> conjunto1 & conjunto2 # Interseccin
set([a, b])
>>> conjunto1 | conjunto2 # Unin.
set([a, c, b, d])
>>> conjunto1 - conjunto2 # Diferencia (1).
set([])
>>> conjunto2 - conjunto1 # Diferencia (2).
set([c, d])
>>> conjunto1 ^ conjunto2 # Diferencia simtrica.
set([c, d])
Una lista por comprensin (en ingls: list comprehension) es una expresin compacta para definir listas. Al igual
que lambda, aparece en lenguajes funcionales. Ejemplos:
>>> range(5) # La funcin "range" devuelve una lista, empezando en 0 y terminando con el nmero in
[0, 1, 2, 3, 4]
>>> [i*i for i in range(5)] # Por cada elemento del rango, lo multiplica por s mismo y lo agrega
[0, 1, 4, 9, 16]
>>> lista = [(i, i + 2) for i in range(5)].
>>> lista
[(0, 2), (1, 3), (2, 4), (3, 5), (4, 6)]
3.1.9 Funciones
Las funciones se definen con la palabra clave def, seguida del nombre de la funcin y sus argumentos entre
parntesis para finalizar con :, es decir,
>>> def mi_funcion(arg1, arg2,..., argN):
Otra forma de escribir funciones, aunque menos utilizada, es con la palabra clave lambda. lambda es un
cosntructor que sirver para ejecutar funciones annimas, es decir funciones sin ningn nombre pero que
crean una referencia a un objeto funcin. La sintaxis de lambda en python es
lambda <aParameterList> : <a Python expression using the parameters>
El valor devuelto en las funciones con def ser el dado con la instruccin return. lambda no necesita de re-
turn para retornar un valor, ya que est implcito, puesto que la funcin entera debe ser una nica expresin.
def
lambda
>>> suma = lambda x, y = 2: x + y
>>> suma(4) # La variable "y" no se modifica, siendo su valor: 2
6
>>> suma(4, 10) # La variable "y" s se modifica, siendo su nuevo valor: 10
14
3.1.10 Clases
Las clases se definen con la palabra clave class, seguida del nombre de la clase y, si hereda de otra clase, el
nombre de esta.
En Python 2.x es recomendable que una clase herede de object, en Python 3.x esto ya no har falta.
En una clase un mtodo equivale a una funcin, y una propiedad equivale a una variable.
__init__ es un mtodo especial que se ejecuta al instanciar la clase, se usa generalmente para inicializar
propiedades y ejecutar mtodos necesarios. Al igual que todos los mtodos en Python, debe tener al menos
un parmetro, generalmente se utiliza self. El resto de parmetros sern los que se indiquen al instanciar la
clase.
Las propiedades que se desee que sean accesibles desde fuera de la clase se deben declarar usando self.
delante del nombre.
En python no existe el concepto de encapsulacin, por lo que el programador debe ser responsable de asignar
los valores a las propiedades
>>> class Persona(object):
... def __init__(self, nombre, edad):
... self.nombre = nombre # Una Propiedad cualquiera.
... self.edad = edad # Otra propiedad cualquiera.
... def mostrar_edad(self): # Es necesario que, al menos, tenga un parmetro, generalmente: "s
... print self.edad # mostrando una propiedad.
... def modificar_edad(self, edad): # Modificando Edad.
... if edad < 0 or edad > 150: # Se comprueba que la edad no sea menor de 0 (algo imposibl
... return False
... else: # Si est en el rango 0-150, entonces se modifica la variable.
... self.edad = edad # Se modifica la edad.
...
>>> p = Persona("Alicia", 20) # Instanciamos la clase, como se puede ver, no se especifica el valo
>>> p.nombre # La variable "nombre" del objeto s es accesible desde fuera.
Alicia
>>> p.nombre = "Andrea" # Y por tanto, se puede cambiar su contenido.
>>> p.nombre
Andrea
>>> p.mostrar_edad() # Podemos llamar a un mtodo de la clase.
20
>>> p.modificar_edad(21) # Y podemos cambiar la edad usando el mtodo especfico que hemos hecho p
>>> p.mostrar_edad()
21
3.1.11 Condicionales
Una sentencia condicional if ejecuta su bloque de cdigo interno slo si se cumple cierta condicin. Se define
usando la palabra clave if seguida de la condicin, y el bloque de cdigo. Condiciones adicionales, si las hay, se
introducen usando elif seguida de la condicin y su bloque de cdigo. Todas las condiciones se evalan secuen-
cialmente hasta encontrar la primera que sea verdadera, y su bloque de cdigo asociado es el nico que se ejecuta.
Opcionalmente, puede haber un bloque final (la palabra clave else seguida de un bloque de cdigo) que se ejecuta
slo cuando todas las condiciones resultan falsas.
>>> verdadero = True
>>> if verdadero: # No es necesario poner "verdadero == True".
... print "Verdadero"
... else:
... print "Falso"
...
Verdadero
>>> lenguaje = "Python"
>>> if lenguaje == "C": # lenguaje no es "C", por lo que este bloque se obviar y evaluar la sigu
... print "Lenguaje de programacin: C"
... elif lenguaje == "Python": # Se pueden aadir tantos bloques "elif" como se quiera.
... print "Lenguaje de programacin: Python"
... else: # En caso de que ninguna de las anteriores condiciones fuera cierta, se ejecutara este
... print "Lenguaje de programacin: indefinido"
...
Lenguaje de programacin: Python
>>> if verdadero and lenguaje == "Python": # Uso de "and" para comprobar que ambas condiciones son
... print "Verdadero y Lenguaje de programacin: Python"
...
Verdadero y Lenguaje de programacin: Python
El bucle for es similar a foreach en otros lenguajes. Recorre un objeto iterable, como una lista, una tupla o un
generador, y por cada elemento del iterable ejecuta el bloque de cdigo interno. Se define con la palabra clave for
seguida de un nombre de variable, seguido de in, seguido del iterable, y finalmente el bloque de cdigo interno.
En cada iteracin, el elemento siguiente del iterable se asigna al nombre de variable especificado:
>>> lista = ["a", "b", "c"]
>>> for i in lista: # Iteramos sobre una lista, que es iterable.
... print i
...
a
b
c
>>> cadena = "abcdef"
>>> for i in cadena: # Iteramos sobre una cadena, que tambin es iterable.
... print i, # Aadiendo una coma al final hacemos que no introduzca un salto de lnea, sino u
...
a b c d e f
El bucle while evala una condicin y, si es verdadera, ejecuta el bloque de cdigo interno. Contina evaluando y
ejecutando mientras la condicin sea verdadera. Se define con la palabra clave while seguida de la condicin, y a
continuacin el bloque de cdigo interno:
>>> numero = 0
>>> while numero < 10:
... numero += 1
... print numero,
...
1 2 3 4 5 6 7 8 9
3.1.14 Mdulos
Existen muchas propiedades que se pueden agregar al lenguaje importando mdulos, que son minicdigos (la
mayora escritos tambin en Python) que proveen de ciertas funciones y clases para realizar determinadas tareas.
Un ejemplo es el mdulo Tkinter, que permite crear interfaces grficas basadas en la biblioteca Tk. Otro ejemplo es
el mdulo os, que provee acceso a muchas funciones del sistema operativo. Los mdulos se agregan a los cdigos
escribiendo import seguida del nombre del mdulo que queramos usar.
>>> import os # Mdulo que provee funciones del sistema operativo
>>> os.name # Devuelve el nombre del sistema operativo
posix
>>> os.mkdir("/tmp/ejemplo") # Crea un directorio en la ruta especificada
>>> import time # Mdulo para trabajar con fechas y horas
>>> time.strftime("%Y-%m-%d %H:%M:%S") # Dndole un cierto formato, devuelve la fecha y/o hora ac
2010-08-10 18:01:17
En Python todo es un objeto (incluso las clases). Las clases, al ser objetos, son instancias de una metaclase. Python
adems soporta herencia mltiple y polimorfismo.
>>> cadena = "abc" # Una cadena es un objeto de "str"
>>> cadena.upper() # Al ser un objeto, posee sus propios mtodos
ABC
>>> lista = [True, 3.1415] # Una lista es un objeto de "list"
>>> lista.append(42L) # Una lista tambin (al igual que todo) es un objeto, y tambin posee sus pr
>>> lista
[True, 3.1415, 42L]
Mdulos Cientficos
Con los mdulos generales, Phyton es dificilmente aplicable al entorno cientfico. Afortunadamente la comunidad
de desarrolladores pronto puso solucin a este inconveniente mediante la creacin de potentes mdulos de clculo
numrico. Hoy da existen mdulos especficos de casi todas las reas cientifico-ingenieriles. En este tema presen-
taremos brevemente algunos de los mdulos ms utilizados y explicaremos diversos ejemplos que nos ayudaran a
aprender su utilizacin de forma rpida e intuitiva.
.
4.1 Numpy
Uno de los mdulos ms importantes de Python es Numpy. El origen de Numpy se debe principalmente al dise-
ador de software Jim Hugunin quien dise el mdulo Numeric para dotar a Python de capacidades de clculo
similares a las de otros softwares como MATLAB. Posteriormente, mejor Numeric incorporando nuevas funcio-
nalidades naciendo lo que hoy conocemos como Numpy.
Numpy es el encargado de aadir toda la capacidad matemtica y vectorial a Python haciendo posible operar
con cualquier dato numrico o array (posteriormente veremos qu es un array). Incorpora operaciones tan bsicas
como la suma o la multiplicacin u otras mucho ms complejas como la transformada de Fourier o el lgebra lineal.
Adems incorpora herramientas que nos permiten incorporar cdigo fuente de otros lenguajes de programacin
como C/C++ o Fortran lo que incrementa notablemente su compatibilidad e implementacin.
Para poder utilizar este mdulo sino hemos instalado python(x,y) lo primero que debemos de hacer es descargarnos
la ltima versin desde el sitio oficial http://www.scipy.org/Download. En caso de que nuestro sistema operativo
sea Linux probablemente venga instalado dentro de Python. De no ser as debemos instalarlo por el mtodo
habitual. Para ms informacin y otros sistemas operativos consultar las notas oficiales de instalacin. Para cargar
el mdulo en Python y poder llamarlo de formar ms cmoda es de uso extendido la utilizacin del alias np,
import numpy as np
En el mbito cientfico es frecuente almacenar y trasladar paquetes de datos en archivos escritos en, por ejemplo,
cdigo ASCII. Python incorpora varias funciones que nos permiten la lectura y escritura en estos archivos facili-
37
PIMCD2013-python, Publicacin 1.0
tando su manejo. Un ejemplo de ello es el comando loadtxt que nos permite cargar los datos contenidos en un
archivo de texto o dat.
Ejemplo 4.1
>>> import numpy as np # Importamos numpy como el alias np
# Cargamos los datos de archivo.txt en datos. En este caso el delimitador es la coma.
>>> datos = numpy.loadtxt(C:\ruta\a\tu\archivo.txt, delimiter = ,)
Ejemplo 4.2
>>> import numpy as np # Importamos numpy como el alias np.
>>> archivoDatos = np.loadtxt(codigo\archivoDatos.dat)
>>> print (archivoDatos) # Presentamos en pantalla los datos cargados.
Ejemplo 4.3
>>> from StringIO import StringIO # StringIO se comporta como un archivo objeto.
>>> c = StringIO("0 1\n2 3")
>>> np.loadtxt(c)
array([[ 0., 1.],
[ 2., 3.]])
4.1.2 Arrays
Con toda probabilidad, el lector que haya realizado un acercamiento a cualquier lenguaje de programacin habr
odo hablar de arrays. Un array es el termino que traslada el concepto matemtico de vector o matriz a la progra-
macin aadindole la nocin de almacenamiento en memoria. Los arrays disponen en su interior de una serie de
elementos dispuestos en filas y/o columnas dependiendo de la dimensin.
El desarrollo y la principal finalidad del mdulo Numpy es la creacin y modificacin de arrays multidimensio-
nales. Para este fin utilizaremos las clase ndarray del ingles N-dimensional array o usando su alias simplemente
array (no confundir con la clase array.array que ofrece menos funcionalidad). En Python cada clase puede tener
atributos que se pueden llamar con el mtodo visto anteriormente o simplemente escribiendo a continuacin de
la clase un punto y el atributo. En la mayora de los IDEs al cargar la clase y escribir el punto aparecen todos los
atributos disponibles en orden alfabtico por lo que en caso de dudar siempre podemos utilizar este mtodo para
escribir el comando. En el caso de ndarray los principales atributos son los siguientes:
ndarray.ndim > Proporciona el nmero de dimensiones de nuestro array. El array identidad es un array
cuadrado con una diagonal principal unitaria.
ndarray.shape > Devuelve la dimensin del array, es decir, una tupla de enteros indicando el tamao del
array en cada dimensin. Para una matriz de n filas y m columnas obtendremos (n,m).
ndarray.size > Es el nmero total de elementos del array.
ndarray.dtype > Es un objeto que describe el tipo de elementos del array.
ndarray.itemsize > devuelve el tamao del array en bytes.
ndarray.data > El buffer contiene los elementos actuales del array.
Veamos un ejemplo de su uso con un array sencillo de diez elementos,
Ejemplo 4.4
>>> import numpy as np # Importamos numpy como el alias np
>>> miArray = np.arange(10) # Creamos un array de 0 a 9 separados de uno en uno
>>> miArray # Presentamos en pantalla el array creado
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
>>> type(miArray) #Comprobamos que es un ndarray
<type numpy.ndarray>
>>> miArray.ndim # Consultamos el nmero de dimensiones
1
>>> miArray.shape # Consultamos la dimensin
(10,)
>>> miArray.size # Consultamos la dimensin
10
>>> miArray.dtype # Consultamos el tipo de elementos del array
dtype(int64)
>>> miArray.itemsize # tamao en bytes
8
>>> miArray.data # Consultamos el buffer de memoria.
<read-write buffer for 0x2fb57a0, size 80, offset 0 at 0x2f664b0>
Como hemos mencionando anteriormente, los arrays son unos de los elementos ms utilizados por los progra-
madores bajo cualquier lenguaje. Este gran uso hace que dispongamos de una gran variedad de comandos para
la creacin de arrays: arrays unidimensionales, multidimensionales, nulos, unitarios, secuenciales, de nmeros
aleatorios, etc. Dependiendo de las necesidades de nuestro problema escogeremos la opcin ms adecuada.
identity(n,dtype). Devuelve la matriz identidad, es decir, uma matriz cuadrada nula excepto en su diagonal
principal que es unitaria. n es el nmero de filas (y columnas) que tendr la matriz y dtype es el tipo de dato.
Este argumento es opcional. Si no se establece, se toma por defecto como flotante.
ones(shape,dtype). Crea un array de unos compuesto de shape elementos.
zeros(shape, dtype). Crea un array de ceros compuesto de shape elementos.
empty(shape, dtype). Crea un array de ceros compuesto de shape elementos sin entradas.
eye(N, M, k, dtype). Crea un array bidimensional con unos en la diagonal k y ceros en el resto. Es similar
a identity. Todos los argumentos son opcionales. N es el nmero de filas, M el de columnas y k es el ndice
de la diagonal. Cuando k=0 nos referimos a la diagonal principal y por tanto eye es similar a identity.
arange([start,]stop[,step,],dtype=None). Crea un array con valores distanciados step entre el valor inicial
star y el valor final stop. Si no se establece step python establecer uno por defecto.
linspace(start,stop,num,endpoint=True,retstep=False). Crea un array con valor inicial start, valor final
stop y num elementos.
meshgrid(x,y). Genera una matriz de coordenadas a partir de dos los arrays x, y.
En el siguiente ejemplo podemos ver su utilizacin,
Ejemplo 4.5
>>> from numpy import * # Importamos todo el mdulo numpy.
>>> zeros( (3,4) ) # Creamos un array nulo de 3 filas y 4 columnas.
array([[0., 0., 0., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 0.]])
>>> ones(9) # Creamos un array unitario de 1 fila y 9 columnas,
array([ 1., 1., 1., 1., 1., 1., 1., 1., 1.])
>>> empty( (2,3) ) # Creamos un array sin entradas de 2x3.
array([[ 3.73603959e-262, 6.02658058e-154, 6.55490914e-260],
[ 5.30498948e-313, 3.14673309e-307, 1.00000000e+000]])
>>> arange( 10, 30, 5 ) # Creamos un array con inicio en 10 final en 30 y paso de 5.
array([10, 15, 20, 25])
>>> linspace( 0, 2, 9 ) # Array de 9 elementos de 0 a 2
array([ 0. , 0.25, 0.5 , 0.75, 1. , 1.25, 1.5 , 1.75, 2. ])
>>> x = linspace( 0, 2*pi, 100 ) # Para grficas conviene tener muchos puntos, en este caso 100
>>> X, Y = np.meshgrid([1,2,3], [4,5,6,7]) # Generamos una matriz de coordenadas.
>>> X
array([[1, 2, 3],
[1, 2, 3],
[1, 2, 3],
[1, 2, 3]])
>>> Y
array([[4, 4, 4],
[5, 5, 5],
4.1. Numpy 39
PIMCD2013-python, Publicacin 1.0
[6, 6, 6],
[7, 7, 7]])
4.1.3 Matrices
Un subtipo especial de array bidimensional de NumPy es la matriz. Una matriz es como una array, excepto que la
multiplicacin de matrices (y exponenciacin) reemplaza la multiplicacin elemento a elemento. Las matrices se
crean mediante la funcin matrix.
Ejemplo 4.6
>>> from numpy import matrix # Importamos matrix del mdulo numpy.
>>> a = matrix([[1,3,-5],[3,4,2],[-5,2,0]])
matrix([[ 1, 3, -5],
[ 3, 4, 2],
[-5, 2, 0]])
>>> b = matrix([[1],[5],[3]])
>>> b
matrix([[1],
[5],
[3]])
>>> a*b
matrix([[ 1],
[29],
[ 5]])
Definidas las matrices, podemos hacer uso de todas las funciones relacionadas con el lgebra lineal como la
transposicin, la diagonalizacin etc.
Ejemplo 4.7
>>> b.T # Calculamos la transpuesta de *b*.
matrix([[1, 5, 3]])
>>> b.H # Calculamos la hermtica (transpuesta y conjugada) de *b*.
matrix([[1, 5, 3]])
>>> c = a.I # Calculamos la inversa de *b*.
>>> c
matrix([[ 0.02439024, 0.06097561, -0.15853659],
[ 0.06097561, 0.15243902, 0.10365854],
[-0.15853659, 0.10365854, 0.0304878 ]])
>>> a*c # Multiplicamos las matrices *a* y *c*.
matrix([[ 1.00000000e+00, -5.55111512e-17, -6.93889390e-18],
[ 0.00000000e+00, 1.00000000e+00, 4.16333634e-17],
[ 0.00000000e+00, 0.00000000e+00, 1.00000000e+00]])
Con el paquete linalg podemos calcular el determinante (det), resolver ecuaciones lineales (solve) y calcular auto-
valores y autovectores.
Ejemplo 4.8
>>> linalg.det(a) # Clculo del determinante.
-164.0
>>> d = linalg.solve(a,b) # Resolucin de ecuaciones lineales.
>>> d
matrix([[-0.14634146],
[ 1.13414634],
[ 0.45121951]])
>>> a*d
matrix([[ 1.],
[ 5.],
[ 3.]])
>>> e = linalg.eig(a) # Clculo de autovalores y autovectores.
>>> e[0]
La funcin eig devuelve una tupla donde el primer elemento es un array de autovalores y el segundo es una matriz
que contiene a los autovectores.
El mdulo numpy contiene todas las operaciones usuales entre arrays como las matemticas (suma, resta, multi-
plicacin, etc), las lgicas (and, or, xor, etc), binarias, ... Lo ms fcil y sencillo es en caso de duda consultar la
documentacin oficial. De particular inters en ptica es la transformada de Fourier,
Ejemplo 4.9
>>> import numpy as np # Importamos numpy como el alias np.
>>> x=np.linspace(0,1,16)
>>> y=np.sin(x)
>>> print np.fft.fft(y)
array([ 6.82834723+0.j , -0.72886897+1.98380961j,
-0.46469805+0.9337634j , -0.42166285+0.57663662j,
-0.40711196+0.38478538j, -0.40066563+0.25695308j,
-0.39747563+0.15924205j, -0.39594637+0.07645992j,
-0.39548834+0.j , -0.39594637-0.07645992j,
-0.39747563-0.15924205j, -0.40066563-0.25695308j,
-0.40711196-0.38478538j, -0.42166285-0.57663662j,
-0.46469805-0.9337634j , -0.72886897-1.98380961j])
obsrvese como se ha formado en nmero complejo 2j. En python los nmeros complejos se forman (parte real
signo jparte imaginaria), es decir, separando parte real e imaginaria y sin ningn signo multiplicativo entre el
coeficiente y el numero imaginario j.
Ejemplo 4.10
>>> numero_complejo = (1 + 1j) # Defino el nmero complejo.
>>> print(numero_complejo) # Lo presento en pantalla.
(1+1j)
>>> type(numero_complejo) # Compruebo el tipo.
complex
4.2 Scipy
4.2. Scipy 41
PIMCD2013-python, Publicacin 1.0
Scipy es una librera de herramientas numricas para Python que se distribuye libremente. El mdulo scipy con-
fiere al lenguaje general Python capacidades de clculo numrico de gran capacidad. Scipy adems de poseer en
su ncleo a Numpy, posee mdulos para optimizacin de funciones, integracin, funciones especiales, resolucin
de ecuaciones diferenciales ordinarias y otros muchos aspectos.
Tanto Scipy como Numpy tienen versiones de su documentacin en pdf y html en http://docs.scipy.org/. Tambin
se puede obtener ayuda de las funciones y de los mdulos mediante
>>> sp.info(funcion)
Parameters
----------
func : callable func(x,*args)
The objective function to be minimized.
x0 : ndarray
Initial guess.
args : tuple
Extra arguments passed to func, i.e. f(x,*args).
callback : callable
Called after each iteration, as callback(xk), where xk is the
current parameter vector.
Returns
-------
xopt : ndarray
Parameter that minimizes function.
fopt : float
Value of function at minimum: fopt = func(xopt).
iter : int
Number of iterations performed.
funcalls : int
Number of function calls made.
warnflag : int
1 : Maximum number of function evaluations made.
2 : Maximum number of iterations reached.
allvecs : list
Solution at each iteration.
Other parameters
----------------
xtol : float
Relative error in xopt acceptable for convergence.
ftol : number
Relative error in func(xopt) acceptable for convergence.
maxiter : int
Maximum number of iterations to perform.
maxfun : number
Maximum number of function evaluations to make.
full_output : bool
Set to True if fopt and warnflag outputs are desired.
disp : bool
Set to True to print convergence messages.
retall : bool
4.2. Scipy 43
PIMCD2013-python, Publicacin 1.0
Notes
-----
Uses a Nelder-Mead simplex algorithm to find the minimum of function of
one or more variables.
Otra forma de buscar informacin es con el comando source, que lista el cdigo de esa funcin,
>>> sp.source(sp.linspace)
En scipy las funciones universales (suma, resta, division, etc.) se han alterado para no producir errores de coma
flotante cuando se encuentran errores; por ejemplo se devuelve NaN e Inf en los arrays en lugar de errores. Para
ayudar a la deteccin de estos eventos, hay disponibles varias funciones como sp.isnan, sp.isinfinite, sp.isinf.
Adems se han modificado algunas funciones (log, sqrt, funciones trigonometricas inversas) para devolver valores
complejos en lugar de NaN (por ejemplo sp.sqrt(-1) devuelve 1j).
Dada la gran cantidad de mdulos contenidos en Scipy, en esta seccin nos limitaremos en dar ejemplos de algunos
de ellos recordando que el camino ideal para el aprendizaje es la lectura de los manuales oficiales.
Desde la educacin secundara uno de los problemas matemticos ms comunes es el de encontrar el mnimo de
una funcin. Si la funcin es simple no necesitamos python para encontrar las posibles soluciones, sin embargo,
si la funcin es compleja o simplemente queremos automatizar el calculo la respuesta es fmin el cual se encuentra
en scipy.optimize. En nuestro caso vamos a tratar de encontrar algn mnimo de intensidad de la diffraccin que
resulta a la salida de una rendija. Esta intensidad viene dada por la funcin sinc, (ecuacin (4.1)).
( ())
= 0 (4.1)
()/
donde a es el ancho de la rendija, x es el ngulo y es la longitud de onda. Como nos proponemos mantener
nuestro programa, lo primero que vamos a hacer es escribir la autoejecucin, la cabecera y la descripcin de
nuestro programa tal y como aprendimos en el tema anterior.
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from __future__ import division
#----------------------------------------------------------------------
# Nombre: ejemplo_scipy_uso_fmin.py
# Propsito: Aprender el uso de fmin para minimizar funciones
#
# Origen: Propio
# Autor: Jos Mara Herrera-Fernandez
#
# Creacin: 17 de Septiembre de 2013
# Historia:
#
# Dependencias: scipy, matplotlib
# Licencia: GPL
#----------------------------------------------------------------------
"""
Descripcin: Ejemplo de cmo usar la funcin fmin perteneciente a scipy.optimize para
encontrar el mnimo de una funcin.
"""
Definimos el sistema fsico de unidades y la funcin sinc(x) en python. Para ello recurrimos al comando def para
indicar que vamos a definir una funcin, el nombre que le vamos a dar a nuestra funcin que en este caso es sinc
y por ltimo los argumentos de nuestra funcin. Para nuestro ejemplo con un nico argumento nos valdr, (x),
# Definimos el sistema fsico de unidades
um = 1 # micras
mm = 100 * um # milmetros
la funcin fmin necesita de valores iniciales a modo de semilla para comenzar las iteraciones. En nuestro caso
hemos elegido como valor 0.001,
# fmin necesita una semilla as que se la proporcionamos.
semilla = 0.001
y por ltimo presentamos en pantalla el resultado mediante un print. Como podemos observar, tomamos direc-
tamente el valor calculado para el print. Esto lo conseguimos gracias al simbolo %. La utilizacin es sencilla, en
el lugar donde queramos que aparezca el valor de nuestra variable escribimos el smbolo % seguido del nmero
de digitos que queramos que tenga la parte real y por ltipo el tipo de numero que queremos mostrar. En nuestro
caso %1.2f significa un digito real, dos decimales y el tipo float. Adems fuera de las comillas del print debemos
de poner otro % y entre parntesis la variable a la que llamamos (en nuestro caso x_minimo_intensidad y sinc
(x_minimo_intensidad) ).
# Presenta en pantalla el mnimo y el valor de la funcin en ese punto.
print (El valor de x en el que se encuentra el mnimo es %1.2f que se corresponde con y = %1.2f
% (x_minimo_intensidad , sinc (x_minimo_intensidad )))
Ejecutando,
Optimization terminated successfully.
Current function value: 0.000000
Iterations: 14
Function evaluations: 28
El valor de x en el que se encuentra el mnimo es 0.02 que se corrsponde con y = 0.00
4.2. Scipy 45
PIMCD2013-python, Publicacin 1.0
La funcin sinc(x) tiene bastantes mnimos absolutos. En la imagen podemos ver sealados el encontrado y el
simtrico en rojo y la semilla en verde,
0.8
0.6
Intensidad
0.4
0.2
Otro camino para encontrar mnimos es mediante el uso de fminbound como vemos en este ejemplo. Sea la funcin
( )
= + (4.2)
donde a, b, c, d son coeficientes y x es la variable. Para definirla en python vamos a crear una funcin cuyos
argumentos sean estos parmetros.
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from __future__ import division
#----------------------------------------------------------------------
# Nombre: ejemplo_scipy_minimizacion.py
# Proposito: Aprender como encontrar minimos locales con python.
#
# Origen: Propio a partir de la documentacion oficial.
# Autor: Jose Maria Herrera-Fernandez, Luis Miguel Sanchez-Brea
#
# Creacion: 18 de Septiembre de 2013
# Historia:
#
# Dependencias: scipy
# Licencia: GPL
#----------------------------------------------------------------------
"""
Descripcion: Encuentra minimos locales de una funcion escalar en el intervalo (x1,x2 usando el met
"""
"""
y = -sp.cos(a*sp.pi*x/b) + c*x**d
return y
4.2. Scipy 47
PIMCD2013-python, Publicacin 1.0
1.0
0.5
y
0.0
0.5
Para este ejemplo imaginaremos que una heladera cuyas previsiones de venta en las cinco primeras horas viene
dada por la funcin,
2
( )
= 22 + (4.3)
siendo a, b, c y d coeficientes desconocidos que el propietario quiere saber para mejorar las ventas. Lo primero
que vamos a hacer es crear nuestro archivo .py segn la plantilla junto con la importacin de los mdulos que
vamos a utilizar.
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from __future__ import division
#----------------------------------------------------------------------
# Nombre: ejemplo_scipy_ajusteFunciones.py
# Propsito: Aprender el uso de curve_fit para ajustar funciones.
#
# Origen: Propio a partir del ejemplo de la documentacin oficial.
"""
Descripcin: Ejemplo de cmo usar la funcin curve_fit perteneciente a scipy.optimize para
ajustar una funcin a una curva.
"""
return a*sp.exp(-b*x**2/(2*d**2)) + c * x
Al no tener datos experimentales reales, vamos a crearnos unos a partir de nuestra funcin. Es lo que en clculo
cientfico se denomina aadir ruido. Para ell nos definimos una nueva funcin que a partir de unos coeficientes
inventados crea un array y al que aadimos un array de numeros aleatorios de la misma dimension que x mediante
sp.random.normal que ponderamos con el factor k.
# Aadimos ruido a la funcin
x = sp.linspace(0, 5,30)
y = mi_funcion(x, 2.5, 1.3, 0.5,1)
def ruido(x,y,k):
"""
* (array, array, float) --> (array)
* Descripcin: definicin de una funcin general que mete ruido a la funcin creada.
De esta forma simulamos puntos experimentales.
* Entradas:
- x, y = arrays dimensionales.
* Salidas:
- yn = array dimensional con los datos experimentales simulados
* Test:
>>> x = sp.linspace(-5, 5,30)
>>> y = mi_funcion(x, 2.5, 1.3, 0.5,1)
>>> yn = ruido(x,y,k)
[ -1.6507892 -4.94424381 5.15178988 2.2186972 -5.84069527
4.33003238 -1.7888872 -0.30041015 -7.1204506 -2.283254
6.81036412 5.39317282 -8.57465789 -1.53478417 10.00896415
4.2. Scipy 49
PIMCD2013-python, Publicacin 1.0
yn = y + k * sp.random.normal(size = len(x))
return yn
Ajustamos nuestros datos experimentales recien creados a la funcin inicial mediante curve_fit. Los resultados los
vamos a almacener en coeficientes_optimizados y covarianza_estimada que es la covarianza de los coeficientes
optimizados,
# Ajustamos los datos experimentales a nuestra funcin y los almacenamos
coeficientes_optimizados, covarianza_estimada = curve_fit(mi_funcion, x, yn)
obteniendo,
Coeficientes optimizados: [ 2.57706857 64.3221008 0.50208527 6.86175853]
Covarianza estimada: [[ 4.92845597e-03 5.04794116e+06 -6.29090049e-05 2.69252336e+05]
[ 5.04794117e+06 2.20479587e+16 -3.76113582e+05 1.17601699e+15]
[ -6.29090094e-05 -3.76113634e+05 6.21152142e-05 -2.00615411e+04]
[ 2.69252337e+05 1.17601699e+15 -2.00615406e+04 6.27276188e+13]]
Nota: En el archivo se aade tambin el cdigo para la representacin sin embargo se explicar cuando hablemos
del mdulo Matplotlib.
Scipy dispone de un paquete muy interesante llamando special donde se encuentran funciones como airy o bessel,
http://docs.scipy.org/doc/scipy/reference/tutorial/special.html. Como ejemplo de este paquete nosotros vamos a
calcular la funcin de Bessel de orden cero. La ecuacin diferencial de Bessel viene definida por,
2 ( 2
2 + + 2 = 0
)
+ (4.4)
2
si ,
2 ( 2
2 + + 2 = 0
)
+ (4.5)
2
cuya solucin es,
( )+2
(1) 2
() = (4.6)
! ( + )!
=0
para n = 0 y n = 1 obtenemos las funciones de Bessel de orden 0 y 1. Estas funciones son de gran inportancia ya
que las funciones del resto de ordenes se pueden escribir en funcin de estas dos.
( )2 ( )4 ( )6
2 2 2 (4.7)
0 () = 1 2 + 2 2 +
(1!) (2!) (3!)
[ ( )2 ( )4 ( )6 ]
1 () = 1 2 2 + 2 2 2 2 + (4.8)
2 (1!2!) (2!3!) (3!4!)
en python,
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from __future__ import division
#----------------------------------------------------------------------
# Nombre: ejemplo_scipy_bessel.py
# Propsito: Aprender el uso el paquete special de scipy.
#
# Origen: Propio.
# Autor: Jos Mara Herrera-Fernandez, Luis Miguel Snchez-Brea
#
# Creacin: 18 de Septiembre de 2013
# Historia:
#
# Dependencias: scipy, matplotlib
# Licencia: GPL
#----------------------------------------------------------------------
"""
Descripcin: Clculo de los coeficientes de orden cero y uno de la funcin de Bessel
contenida en el paquete special.
"""
from scipy import special # Importamos scipy.special
import scipy as sp # Importamos scipy como el alias sp
import matplotlib.pyplot as plt # Importamos matplotlib.pyplot como el alias plt.
4.2. Scipy 51
PIMCD2013-python, Publicacin 1.0
Orden cero
1.0 Orden uno
0.5
J(x)
0.0
0.5
0 10 20 30 40 50
x
Nota: En el archivo se aade tambin el cdigo para la representacin sin embargo se explicar cuando hablemos
del mdulo Matplotlib.
Gracias a integrate de Scipy tambin podemos realizar integrales en Python. La primera integral que vamos a
realizar es
= () (4.9)
en el intervalo de 0 a
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from __future__ import division
#----------------------------------------------------------------------
# Nombre: ejemplo_scipy_integrales.py
# Propsito: Aprender como integrar con python.
#
# Origen: Propio .
# Autor: Jos Mara Herrera-Fernandez, Luis Miguel Snchez-Brea
#
# Creacin: 18 de Septiembre de 2013
# Historia:
#
# Dependencias: scipy
# Licencia: GPL
#----------------------------------------------------------------------
"""
Descripcin: Ejemplo de cmo usar la funcin integrate para realizar integrales
numricas en python.
"""
# Los devuelvo
return integrate.quad(exponencial_decreciente ,limite_inferior,limite_superior)
donde podemos ver que hemos creado un if para mostrar o no los resultados en pantalla. Ejecutando,
>>> integral_1(limite_inferior = 0, limite_superior = sp.inf, mostrar_resultados = True)
La integral entre 0.00 y inf es
(1.0000000000000002, 5.842606742906004e-11)
De la misma forma podemos adems tener en cuenta coeficientes de la funcin que pueden variar,
def integral_2(limite_inferior, limite_superior,a,b, mostrar_resultados):
"""
(float,float,float, float, bool) -->(float, float)
* Descripcin: Calculo de la integral de limite_inferior a limite_superior de
la funcin y = ax^(b)
* Entradas:
- limite_inferior = inicio del intervalo de integracin.
- limite_superior = fin del intervalo de integracin.
- a,b = coeficientes de la funcin
* Salidas:
- y = integral
- err = error cometido.
* Test:
>>> y = integral_2(limite_inferior = 0, limite_superior = 1,a = 4, b = 5, mostrar_resultados =
La integral vale 0.67, y el error cometido 0.00
"""
4.2. Scipy 53
PIMCD2013-python, Publicacin 1.0
# Calculo la integral
y, err = integrate.quad(funcion, limite_inferior, limite_superior, args=(a,b,))
# Los devuelvo
return y, err
donde tambin hemos aadido el if con una pequea modificacin. Python nos permite ahorrarnos == True.
Ejecutando,
>>> y = integral_2(limite_inferior = 0, limite_superior = 1,a = 2, b = 3, mostrar_resultados = Tru
La integral vale 0.50, y el error cometido 0.00
Otra opcin interesante de python es poder interpolar a partir de nuestros datos experimentales. Como ejemplo
interpolaremos en una dimensin mediante interpolate.interp1d,
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from __future__ import division
#----------------------------------------------------------------------
# Nombre: ejemplo_scipy_interpolar.py
# Propsito: Aprender como interpolar con python.
#
# Origen: Propio a partir de la documentacin oficial.
# Autor: Jos Mara Herrera-Fernandez, Luis Miguel Snchez-Brea
#
# Creacin: 18 de Septiembre de 2013
# Historia:
#
# Dependencias: scipy
# Licencia: GPL
#----------------------------------------------------------------------
"""
Descripcin: Ejemplo de cmo hacer una interpolacin en python.
"""
import scipy as sp # Importamos scipy como el alias sp
from scipy import interpolate # Importamos interpolate de scipy
import matplotlib.pyplot as plt # Importamos matplotlib.pyplot como el alias plt
# Interpolamos
interpolacion = interpolate.interp1d(x, y)
# Evaluamos x2 en la interpolacin
y2 = interpolacion(x2)
# Creamos la figura
plt.figure
# Aadimos la leyenda
plt.legend((Datos conocidos, Datos experimentales))
# Mostramos en pantalla
plt.show()
1.0
Datos conocidos
0.9 Datos experimentales
0.8
0.7
Eje y
0.6
0.5
0.4
Scipy posibilita la opcin de clacular las raices de un polinomio de una forma rpida y sencilla,
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from __future__ import division
#----------------------------------------------------------------------
# Nombre: ejemplo_scipy_raicesPolinomio.py
# Propsito: Aprender como calcular las raices de un polinomio con python.
#
# Origen: Propio a partir de la documentacin oficial.
# Autor: Jos Mara Herrera-Fernandez, Luis Miguel Snchez-Brea
4.2. Scipy 55
PIMCD2013-python, Publicacin 1.0
#
# Creacin: 20 de Septiembre de 2013
# Historia:
#
# Dependencias: scipy, matplotlib
# Licencia: GPL
#----------------------------------------------------------------------
"""
Descripcin: Ejemplo de cmo calcular las raices de un polinomio mediante scipy.
"""
# Creamos un polinomio
polinomio = [1.3,4,.6,-1] # polinomio = 1.3 x^3 + 4 x^2 + 0.6 x - 1
obteniendo,
Las raices son -2.82, -0.67, 0.41.
10
y
15
20
25 4 3 2 1 0 1
x
4.3 Matplotlib
Matplotlib es el mdulo de dibujo de grficas 2D y 3D que vamos a utilizar aunque no es el nico exis-
tente. Matplotlib tiene multitud de libreras de las cuales nosotros, por semejanza a Matlab, utilizaremos
pyplot. Recomendamos al lector visitar http://matplotlib.sourceforge.net/, donde puede encontrar multitud de
programas y ejemplos de como hacer dibujos con Matplotlib. La documentacin oficial se encuentra en
http://matplotlib.sourceforge.net/contents.html no obstante, a lo largo de esta seccin veremos algunas de las fun-
ciones ms interesantes.
Para poder utilizar el mdulo Matplotlib en nuestros programas primero debemos importarlo. Por comodidad los
mdulos de nombre ms extenso suelen renombrarse para optimizar su importacin. En nuestro caso vamos a
importarlo como plt incluyendo en el inicio de nuestro programa la siguiente lnea de cdigo:
import matplotlib.pyplot as plt
En la Figura 3 podemos ver que si escribimos esta lnea de comando en una consola, con solo poner plt se
nos muestra en pantalla la ayuda para este mdulo. Si adems tras plt aadimos un punto, se nos muestra un
4.3. Matplotlib 57
PIMCD2013-python, Publicacin 1.0
Figura 4.2: Figura 2. Ejemplo de grfica realizada con la librera pyplot de Matplotlib (DOE de fase).
desplegable con todas las funciones en este mdulo. Si pinchamos en una de ellas, al igual que antes, se nos abre
una ventana de ayuda que nos indica el uso del comando.
como ya explicamos en temas anteriores tambin podemos importar matplotlib mediante la sentencia
from matplotlib import pyplot
El mdulo Matplotlib (al igual que la mayora de los mdulos) es enorme y explicar todas y cada una de las
funciones nos llevara demasiado tiempo as que analizaremos las ms interesnates para un usuario principiante.
figure(num, figsize, dpi, facecolor, edgecolor, frameon) > Crea una nueva figura. Se puede utilizar sin argu-
mentos. Devuelve un identificador a la figura.
num = numeracin de la figura, si num = None, las figuras se numeran automticamente.
figsize = w, h tuplas en pulgadas. Tamao de la figura
dpi = Resolucin de la imagen en puntos por pulgada.
facecolor = Color del rectngulo de la figura.
edgecolor = Color del permetro de la figura.
frameon = Si es falso, elimina el marco de la figura.
>>> figure(num = None, figsize = (8, 6), dpi = 80, facecolor = w, edgecolor = k)
subplot(numRows, numCols, plotNum) > Permite incluir varias grficas en una nica figura.
numRows = Nmero de filas
Figura 4.3: Figura 3. Importacin del mdulo matplotlib como plt en una consola interactiva de Eclipse.
4.3. Matplotlib 59
PIMCD2013-python, Publicacin 1.0
plot(x, y, linestyle, linewidth, marker) > Permite incluir varias grficas en una nica figura.
x = Abcisas.
y = Ordenadas. Tanto x como y pueden ser abcisas tuplas, listas o arrays. La nica condicin es que el
tamao de ambas debe ser el mismo ya que en caso contrario python nos devolver un fallo de tipo dimesin.
Tambin se puede hacer una grfica sin especificar la coordenada x.
linestyle = color y tipo de dibujar la grfica. Por ejemplo k- -
linewidth = ancho de lnea.
marker = Marcador.
por ejemplo,
>>> plt.plot(x, y, k--, linewidth = 2)
Dibuja la curva y(x) en trazo discontinuo de color negro con ancho de lnea de tamao 2. La funcin plot devuelve
una lista. El nmero de elementos depende del nmero de plots realizados. El tipo retornado para cada elemento
de la lista es matplotlib.lines.Lines2D. Analizando cada elemento se puede extraer informacin que caracteriza al
grfico (formato de marcador, colores usados,...).
>>> from matplotlib import pyplot
>>> x = range(10)
>>> y = x
>>> a = pyplot.plot(x,y)
>>> len(a)
1
>>> a[0].get_color()
b
>>> a[0].get_ls()
-
>>> a[0].get_marker()
None
w Blanco
Tambin se puede escribir el color de las siguientes formas: nombres (green); cadenas hexadecimales
(#008000); tuplas con convencin RGB (0,1,0); intensidades de escala de grises (0.8).
Marcadores
Los tipos principales son:
[ + | * | , | . | 1 | 2 | 3 | 4 | < | > | D | H | ^ | _ | d | h | o | p | s | v | x ].
Fillstyle Relleno de smbolo elegido para representar cada dato.
[full | left | right | bottom | top]
show() Presenta las figuras en pantalla mediante una ventana en la que podemos interactuar. Este comando se
debe aadir siempre que necesitemos obervar nuestra grfica ya que sino python realizar el clculo pero no
presentar la imagen. Lo usual es ponerlo al final del programa posibilitando aas la llamada a todas las figuras
que se encuentren en el mismo.
>>> plt.show()
legend(labels, loc) Coloca una leyenda. Cuando se presentan varas curvas simultneamente este comando identi-
fica cada una. Puede utilizarse sin argumentos si en cada funcin plot (o equivalente) se ha incluido el argumento
label, que es un texto para identificar la curva.
>>> plt.legend( (Etiqueta1, Etiqueta2, Etiqueta3), loc = upper left)
axis() Establece u obtiene las propiedades de los ejes. Podemos establecer el rango de coordenadas en x e y que
queremos mostrar en el grfico. Del mismo modo, podemos seleccionar la relacin de aspecto entre las coordena-
das x e y.
axis(), devuelve los lmites de los ejes ([xmin, xmax, ymin, ymax])
axis(v), establece los valores lmites de los ejes a v = [xmin, xmax, ymin, ymax]
axis(off), elimina lneas de ejes y etiquetas
axis(equal), cambia los lmites de x e y para que los incrementos de x e y tengan la misma longitud (un
crculo parece un crculo)
axis(scaled), cambia las dimensiones del plot para conseguir la misma longitud de intervalo en x e y.
axis(tight), cambia los ejes para que se muestren todos los datos.
axhline(y, xmin, xmax) Con esos valores de los parmetros predeterminados establecidos, la lnea se ajusta al
rango representado por los correspondientes ejes.
y, array con los datos
4.3. Matplotlib 61
PIMCD2013-python, Publicacin 1.0
hold() Si el parmetro es True, podemos poner ms curvas en la misma grfica. Si el parmetro es False, entonces
al escribir una nueva curva, las anteriores se borran.
grid() Establece la malla a True (visible) o False (oculta).
>>> plt.grid(True)
>>> plt,grid(color = r, linestyle = , linewidth = 2)
se muestra como ()
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Representamos
plt.plot(x,y)
# Mostramos en pantalla
plt.show()
1.0
0.5
0.0
0.5
1.00 2 4 6 8 10
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from __future__ import division
#----------------------------------------------------------------------
# Nombre: ejemplo_matplotlib_grafica_completa.py
# Propsito: Aprender a realizar una grfica lo ms completa posible
#
# Origen: Propio.
# Autor: Luis Miguel Snchez-Brea,Jos Mara Herrera-Fernandez
#
# Creacin: 18 de Septiembre de 2013
# Historia:
#
# Dependencias: numpy, matplotlib
# Licencia: GPL
#----------------------------------------------------------------------
"""
Descripcin: Doble grfica senoidal donde se muestran la mayora de los complementos
que se pueden aadir a una grfica
"""
4.3. Matplotlib 63
PIMCD2013-python, Publicacin 1.0
periodo = 0.5
# Creamos la figura
plt.figure()
# Aadimos la leyenda
plt.legend(loc = 2)
# Aadimos texto
plt.text(x = 1, y = 0.0, s = uT = 0.05, fontsize = 24)
# Aadimos la rejilla
plt.grid(True)
plt.grid(color = 0.5, linestyle = --, linewidth = 1)
# Aadimos el ttulo
plt.title((a),fontsize = 28, color = 0.75, verticalalignment = baseline, horizontalalignment
# Guardamos
plt.savefig(plotCompleta.png)
# Mostramos en pantalla
plt.show()
(a)
y1
y2
0.5
T = 0.05
y(m)
0.0
0.5
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from __future__ import division
#----------------------------------------------------------------------
# Nombre: ejemplo_matplotlib_subplot.py
# Propsito: Aprender a mostrar varas grficas separadas en una figura
#
# Origen: Propio.
# Autor: Luis Miguel Snchez-Brea,Jos Mara Herrera-Fernandez
#
# Creacin: 18 de Septiembre de 2013
# Historia:
#
# Dependencias: numpy, matplotlib
# Licencia: GPL
#----------------------------------------------------------------------
"""
Descripcin: En este ejemplo se muestra como realizar la presentancin de varas
grficas individuales en una misma figura mediante "subplot"
"""
4.3. Matplotlib 65
PIMCD2013-python, Publicacin 1.0
periodo = 2
# Creamos la figura
plt.figure()
# Primera grfica
plt.subplot(2,2,1)
plt.plot(x, y,r)
# Segunda grfica
plt.subplot(2,2,2)
plt.plot(x, y,g)
# Tercera grfica
plt.subplot(2,2,3)
plt.plot(x, y,b)
# Cuarta grfica
plt.subplot(2,2,4)
plt.plot(x, y,k)
# Mostramos en pantalla
plt.show()
1.0 1.0
0.5 0.5
0.0 0.0
0.5 0.5
1.00 2 4 6 8 10 1.00 2 4 6 8 10
1.0 1.0
0.5 0.5
0.0 0.0
0.5 0.5
1.00 2 4 6 8 10 1.00 2 4 6 8 10
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from __future__ import division
#----------------------------------------------------------------------
# Nombre: ejemplo_matplotlib_imshow.py
# Propsito: Aprender a realizar una grfica en 2D
#
# Origen: Propio.
# Autor: Luis Miguel Snchez-Brea,Jos Mara Herrera-Fernandez
#
# Creacin: 18 de Septiembre de 2013
# Historia:
#
# Dependencias: numpy, matplotlib
# Licencia: GPL
#----------------------------------------------------------------------
"""
Descripcin: En este ejemplo se muestra como realizar una grfica en dos dimensiones
mediante imshow
"""
# Representamos
plt.imshow(fxy);
# Mostramos en pantalla
plt.show()
4.3. Matplotlib 67
PIMCD2013-python, Publicacin 1.0
0 1.0
0.8
200 0.6
0.4
400 0.2
0.0
600 0.2
0.4
800 0.6
0.8
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from __future__ import division
#----------------------------------------------------------------------
# Nombre: ejemplo_matplotlib_grafica_superficie3d.py
# Propsito: Aprender como leer una image y representar una grafica en 3D.
#
# Origen: Propio .
# Autor: Jos Mara Herrera-Fernandez
#
# Creacin: 18 de Septiembre de 2013
# Historia:
#
# Dependencias: scipy, mpl_toolkits, matplotlib, numpy
# Licencia: GPL
#----------------------------------------------------------------------
"""
Descripcin: Ejemplo de cmo usar la funcin integrate para realizar integrales
numricas en python.
"""
# Aado etiquetas
plt.title(Imagen que usaremos de superficie)
plt.xlabel(u# de pxeles)
plt.ylabel(u# de pxeles)
# Aadimos etiquetas
plt.title(uImagen sobre una grafica 3D)
plt.xlabel(Eje x)
plt.ylabel(Eje y)
# Mostramos en pantalla
plt.show()
4.3. Matplotlib 69
PIMCD2013-python, Publicacin 1.0
0
Imagen que usaremos de superficie
20
40
# de pxeles
60
80
100
1.0
0.5
0.0
0.5
6
4 1.0
2 6
Eje 0 4
x 2
2 0 y
4 4
2 Eje
6 6
5.1 Introduccin
E = E1 + E2
tambin es una solucin. Sin embargo, el campo no es un parmetro observable, sino que lo es el promedio
temporal del vector de Poynting, que se define como
1
S E B,
0
con tiene unidades de [S] = /2 . Al particularizar al caso de ondas armnicas planas tenemos
1 0 2
S = |E| u ,
2 0
: : (, )
71
PIMCD2013-python, Publicacin 1.0
5.2 Programacin
Debido a la sencillez conceptual de las interferencias, las utilizaremos para analizar los distintos tipos de pro-
gramacin que se puede realizar con Python, como es la programacin con scripts (todo el cdigo en un mismo
archivo lineal), la programacin funcional (se escriben funciones que simplifican lo clculos) y la programacin
con clases (donde funciones y datos estn ntimamente relacionados). Finalmente veremos un procedimiento sen-
cillo para desarrollar vdeos, simulando un interfermetro de Michelson.
tamano=100*um
x=sp.linspace(-tamano,tamano, 256)
y=sp.linspace(-tamano,tamano, 256)
X,Y=sp.meshgrid(x,y)
#!/usr/local/bin/python
# -*- coding: utf-8 -*-
#------------------------------------
# Autor: Luis Miguel Sanchez Brea
# Fecha 2013/10/24 (version 1.0)
# Licencia: GPL
# Objetivo: onda plana
#-------------------------------------
import scipy as sp
import matplotlib.pyplot as plt
import sys
sys.path.append(../)
IDfig = plt.figure()
IDax = IDfig.add_subplot(111)
extension = [x.min(), x.max(), y.min(), y.max()]
angulo = sp.angle(u) #/ sp.pi
angulo[angulo == 1] = -1
IDimagen = plt.imshow(angulo, interpolation = bilinear, aspect = auto,origin = lower
plt.xlabel("$x (\mu m)$", fontsize = 20)
plt.ylabel("$y (\mu m)$", fontsize = 20)
titulo="$A =$ %4.2f $\phi =$ %4.2f $^{0}, \Theta =$ %4.2f $^0$" %(A, phi*180/sp.pi, teta
plt.suptitle(titulo, fontsize = 20)
plt.axis(scaled)
plt.axis(extension)
plt.colorbar()
IDimagen.set_cmap("RdBu")
plt.clim(vmin = -sp.pi, vmax = sp.pi)
1.6
50
0.8
y(m)
0 0.0
0.8
50
1.6
100 2.4
100 50 0 50 100
x(m)
5.2. Programacin 73
PIMCD2013-python, Publicacin 1.0
1.6
50
0.8
y(m)
0 0.0
0.8
50
1.6
100 2.4
100 50 0 50 100
x(m)
#!/usr/local/bin/python
# -*- coding: utf-8 -*-
#------------------------------------
# Autor: Luis Miguel Sanchez Brea
# Fecha 2013/10/24 (version 1.0)
# Licencia: GPL
# Objetivo: onda esferica
#-------------------------------------
import scipy as sp
import matplotlib.pyplot as plt
um=1
#Onda esferica
u = A * sp.exp(-1.j * sp.sign(z0) * k * Rz) / Rz
IDfig = plt.figure()
IDax = IDfig.add_subplot(111)
extension = [x.min(), x.max(), y.min(), y.max()]
angulo = sp.angle(u)
angulo[angulo == 1] = -1
IDimagen = plt.imshow(angulo, interpolation = bilinear, aspect = auto,origin = lower
plt.xlabel("$x (\mu m)$", fontsize = 20)
plt.ylabel("$y (\mu m)$", fontsize = 20)
titulo="fase A = %4.2f z0 = %4.2f mm" %(A, z0/1000*um)
plt.suptitle(titulo, fontsize = 20)
plt.axis(scaled)
plt.axis(extension)
plt.colorbar()
IDimagen.set_cmap("RdBu")
plt.clim(vmin = -sp.pi, vmax = sp.pi)
plt.show()
1.6
50
0.8
y(m)
0 0.0
0.8
50
1.6
100 2.4
100 50 0 50 100
x(m)
5.2. Programacin 75
PIMCD2013-python, Publicacin 1.0
1.6
50
0.8
y(m)
0 0.0
0.8
50
1.6
100 2.4
100 50 0 50 100
x(m)
fase A = 1.00 z0 = 5.00 mm
100 2.4
1.6
50
0.8
y(m)
0 0.0
0.8
50
1.6
100 2.4
100 50 0 50 100
x(m)
#!/usr/local/bin/python
# -*- coding: utf-8 -*-
#------------------------------------
# Autor: Luis Miguel Sanchez Brea
# Fecha 2013/10/24 (version 1.0)
# Licencia: GPL
# Objetivo: Emision de una onda esferica
#-------------------------------------
wavelength=0.6328*um
k = 2 * sp.pi / wavelength
c= 299792.458 *m/s
w=c*k
#area de visualizacion
tamano=1.25*um
x=sp.linspace(-tamano, tamano, 250)
z=sp.linspace(-tamano, tamano, 250)
X,Z=sp.meshgrid(x, z)
#calculo de la intensidad
R = sp.sqrt(X** 2 + Z ** 2)
E_theta=sp.cos(k*R)/R
intensidad = abs(E_theta) ** 2
intensidad=sp.log(intensidad+1)
#fase=sp.angle(E_theta)
#tiempo
t=sp.linspace(0,50000*fs,1001)
#bucle
i=0
def updatefig(*args):
global t, i
E_theta=sp.cos((k*R-w*t[i]))/R
intensidad = abs(E_theta) ** 2
intensidad=sp.log(intensidad+1)
#fase=sp.angle(E_theta)
im.set_array(intensidad)
titulo="t = %4.0f fs" %(t[i]/fs)
plt.title(titulo)
manager.canvas.draw()
i += 1
if i==len(t):
return False
return True
5.2. Programacin 77
PIMCD2013-python, Publicacin 1.0
gobject.idle_add(updatefig)
plt.show()
50
100
150
200
#!/usr/local/bin/python
# -*- coding: utf-8 -*-
#------------------------------------
# Autor: Luis Miguel Sanchez Brea
# Fecha 2013/10/24 (version 1.0)
# Licencia: GPL
# Objetivo: haz gaussiano
#-------------------------------------
import scipy as sp
import matplotlib.pyplot as plt
import sys
sys.path.append(../)
#Definicion de la amplitud
u = A * sp.exp(-X ** 2 / (2 * wx ** 2) - Y** 2 / (2 * wy ** 2))
intensidad=abs(u)**2
IDfig = plt.figure()
IDax = IDfig.add_subplot(111)
extension = [x.min(), x.max(), y.min(), y.max()]
IDimagen = plt.imshow(intensidad ,origin = lower, extent = extension)
plt.xlabel("$x (\mu m)$", fontsize = 20)
plt.ylabel("$y (\mu m)$", fontsize = 20)
plt.axis(scaled)
plt.axis(extension)
plt.colorbar()
IDimagen.set_cmap("gist_heat")
1.0
400 0.9
0.8
200 0.7
0.6
y(m)
0 0.5
0.4
200 0.3
0.2
400 0.1
5.2. Programacin 79
PIMCD2013-python, Publicacin 1.0
1.0
400 0.9
0.8
200 0.7
0.6
y(m)
0 0.5
0.4
200 0.3
0.2
400 0.1
Veamos ahora el proceso de interferencia de 2 haces de Gauss. Estos hace se pueden definir como
2 2
( ) ( )
0
(, , ) = 0 exp 2 exp + ()
() () 2()
donde
0
02 =
( )2
() = 0 1+
0
[ ]
() = 1 + ( )2
0
Este tipo de haces se puede programar fcilmente. Asumamos que estamos en el foco del haz z=0 y los haces estn
rotados. Entonces tambin se van a producir interferencias entre los haces.
Polarizacin
81
PIMCD2013-python, Publicacin 1.0
6.1 Introduccin
Desde un punto de vista clsico, la luz es una onda electromagntica constituida por dos campos, elctrico y
magntico oscilando normales a la direccin de propagacin y normalmente entre s. Bajo esta definicin se llama
polarizacin de la luz a la trayectoria del vector campo elctrico. Si la trayectoria de la luz es catica se dice que
la luz est despolarizada, as mismo si la trayectoria est bien definida hablamos de estados de polarizacin o
tambin llamados estados puros.
La polarizacin de la luz est intrnsecamente ligada al concepto de onda plana (ver seccin, Fuentes de luz-Onda
plana).
Andras Szilagyi ha realizado un mdulo interactivo muy interesante para el anlisis de la polarizacion:
emanim12.py. Se puede encontrar en http://www.enzim.hu/~szia/emanim for more information.
En la siguiente Figura se muestra un ejemplo de utilizacin de este mdulo. Tiene un men y botones para selec-
cionar el tipo de anlisis de polarizacin y parmetros utilizados
La luz polarizada puede cambiar de estado al atravesar distintos elementos pticos. La caracterizacin y modelado
de estos medios resulta crtica en ptica. El clculo de Jones permite no solo definir estados de polarizacin sino
82 Captulo 6. Polarizacin
PIMCD2013-python, Publicacin 1.0
adems, representar los elementos pticos mediante matrices, tales que el vector de Jones a la salida del sistema
sea la accin de la matriz del medio sobre un vector de Jones.
Rotador
Un rotador es un sistema capaz de rotar el vector de Jones pero no modificar su estado. Por ello estn representados
por matrices de rotacin. Para su implementacin basta con definir la matriz
( )
cos sin
,
sin cos
Polarizador lineal
Los polarizadores lineales son elementos pticos tales que independientemente del estado de polarizacin a la
entrada transforman dicho estado en luz linealmente polarizada con acimut . Donde representa el ngulo del
eje del polarizador. La matriz de Jones de un polarizador lineal viene representada por
cos2
( )
sin cos
,
sin cos sin2
Polarizador Retardador
Un retardador lineal es un elemento ptico compuesto por un material birrefringente capaz de introducir un re-
tardo entre las componentes paralela y perpendicular de la luz incidente. Est constituido por dos ejes o tambin
llamadas lneas neutras con ndices de refraccin asociados ordinario y extraordinario, la orientacin de los ejes y
el espesor determinan la accin de la lmina sobre la luz incidente. El retardo se introduce fruto de la diferencia
de camino ptico asociada a cada eje. La matriz de Jones asociada a un retardador viene dada por
Lmina Lambda/4
Las lminas retardadoras hacen uso de la birrefringencia de la luz. Una lmina de cuarto de onda introduce un
retardo de /2 entre las componentes del vector de Jones de la luz incidente sobre la lmina. La matriz de Jones
del retardador de cuarto de onda es
( )
1 + cos 2 sin 2
,
sin 2 1 cos 2
Lmina Lambda/2
Las lminas de media onda, alteran el sentido de giro del vector luz, derechas a izquierda o viceversa. Por tanto
los estados linealmente polarizados son invariantes bajo estos elementos pticos, mientras que si se incide sobre
una lmina de media onda con luz circular a derechas, a la salida mantiene la circularidad pero el sentido de giro
ser levgiro. Idem para estados elpticamente polarizados. La matriz de Jones del retardador de media onda es
( )
cos 2 sin 2
,
sin 2 cos 2
Considrese una onda plana monocromtica de frecuencia , vector de onda , y amplitud 0 representada como
= 0 + ,
= 0 + .
Es posible definir esta seal nicamente con la parte espacial. As denotando el desfase como = se
escribe
( )
0
= .
0
Este vector recibe el nombre de vector de Jones. Obsrvese como este vector representa la proyeccin trayectoria
del campo elctrico sobre un plano perpendicular a la direccin de propagacin. As se puede probar como el
conjunto de trayectorias posibles de acuerdo a estos vectores estn definidas por la ecuacin
2 2 cos
2 + 2 2 = sin2 .
0 0 0 0
84 Captulo 6. Polarizacin
PIMCD2013-python, Publicacin 1.0
Esta ecuacin representa una elipse, la llamada elipse de polarizacin y de ella derivan el conjunto de estados
puros. De este modo, si = con , entero, o si 0 = 0 o 0 = 0, la elipse de polarizacin degenera en una
recta, y se dice que el estado de la luz es linealmente polarizado, as mismo, si 0 = 0 y = /2, la elipse
degenera en una circunferencia, y por tanto la luz es circularmente polarizada. En cualquier otro caso distinto de
estos dos la luz se dice que posee polarizacin elptica.
Luz Lineal
Un vector de Jones unitario de luz linealmente polarizada es siempre de la forma
( )
cos
= .
sin
Donde representa el azimut del estado de luz, es decir, la inclinacin del vector campo elctrico. luzLineal
implementa este vector.
def luzLineal(alfa = 0):
"""Luz linealmente polarizada
- alfa, angulo en el cual esta polarizada
"""
#Definicion del vector de Jones
return sp.matrix([[ cos(alfa)], [sin(alfa)]])
Luz Circular
Bajo la condicin = /2 con 0 = 0 se obtienen los vectores de Jones
El doble signo denota el sentido de giro del vector campo elctrico, si es positivo, entonces la luz ser circularmente
polarizada a derechas o dextrgira. En caso contrario se dice que es circularmente polarizada a izquierdas o
levgira. La eleccin entre circular a derechas o izquierdas se especifica mediante una d o una i en el argumento
de la funcin luzCircular
def luzCircular(tipo = d):
"""Luz circularmente polarizada
- tipo, d: derecha i: izquierda
"""
#Definicion del vector de Jones a dextrogiro o levogiro
if tipo == d:
return sp.matrix([[1], [1j]]) / sp.sqrt(2)
elif tipo == i:
return sp.matrix([[1], [-1j]]) / sp.sqrt(2)
Luz Elptica
Si el vector de Jones no es ninguno de los dos casos anteriores, lineal o circular, entonces es necesariamente
elpticamente polarizado. Su definicin como funcin de Python debe emplear la forma ms general del vector de
Jones,
( )
.
La intensidad de la luz no es ms que el mdulo del vector de Jones. La funcin intensidad cumple este cometido
def intensidad(vectorPolarizacion):
#Calculo de la intensidad
return float(abs(vectorPolarizacion[0]) ** 2 + abs(vectorPolarizacion[1]) ** 2)
La polarizacin de la luz se puede ver afectada al atravesar esta distintos elementos pticos. El formalismo de Jones
constituye una representacin tanto de los elementos pticos, mediante matrices 2x2, como de estados puros de
polarizacin, mediante vectores. De este modo, el estado de polarizacin a la salida de un elemento ptico queda
determinado por la accin de la matriz de Jones del elemento sobre el vector de Jones que representa el estado de
polarizacin incidente.
As supnganse los siguientes ejemplos
Polarizador lineal
Un haz de luz linealmente polarizado segn el eje x incide sobre un polarizador cuyo eje est alineado con el eje
y. Obviamente no hay transmisin de luz, por ello el vector de Jones a la salida del polarizador debe ser el vector
nulo, y en consecuencia la intensidad de la luz es cero. En efecto
( ) ( ) ( )
0 0 1 0
=
0 1 0 0
( ) ( ) ( )
1 0 1 1
=
0 1
( ) ( ) ( )
1 1 1
=
1 0
La ley de Malus establece que la intensidad de la luz a la salida de un sistema de dos polarizadores es directamente
proporcional a cos2 siendo el ngulo comprendido entre los ejes de los polarizadores. La demostracin es
sencilla, basta considerar un estado de luz lineal incidiendo sobre un polarizador, y calcular el vector de Jones a
86 Captulo 6. Polarizacin
PIMCD2013-python, Publicacin 1.0
la salida, el mdulo cuadrado de este vector de Jones posee una dependencia directamente proporcional a cos2 .
Este hecho se muestra en el siguiente cdigo.
"""Ley de Malus"""
#Importamos modulos scipy, sys y polarizacion
import scipy as sp
import sys
sys.path.append(../)
from polarizacion import *
#haz incidente
haz=luzLineal(alfa=0*grados)
P1 = polarizadorLineal(theta = 0*grados)
#Representacion de la intensidad
plt.figure()
plt.plot(angulos/grados,I,k,lw=2)
plt.xlabel(r$\theta$ (grados),fontsize=24)
plt.ylabel(Intensidad transmitida,fontsize=24)
plt.xlim([0,angulos[-1]/grados])
plt.show()
1.0
Intensidad transmitida
0.8
0.6
0.4
0.2
El efecto Zenn es el paso de luz a travs de un sistema de polarizadores. Si bien se extingue la luz bajo cuando
dos polarizadores posicionan sus ejes perpendicularmente, bajo otros ngulos la luz atraviesa el sistema. As, si se
disponen N polarizadores con ngulo entre sus ejes 360/ aumentar la transmitancia al aumentar el nmero de
polarizadores.
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#----------------------------------------------------------------------
# Autor: Luis Miguel Sanchez Brea
# Fecha 2013/10/24 (version 1.0)
# Licencia: GPL
#----------------------------------------------------------------------
"""
Efecto Zenon, n polarizadores rotados igual entre si.
"""
import scipy as sp
import sys
sys.path.append(../)
from polarizacion import *
#Representacion de la intensidad
plt.figure()
plt.plot(numPolarizadores, intensidad, ko)
plt.xlabel(# polarizadores, fontsize = 20)
plt.ylabel($I_{transmitida}$, fontsize = 24)
plt.title(efecto zenon, fontsize = 24)
if __name__ == __main__:
efectoZenon(numMaxPolarizadores = 75)
plt.show()
88 Captulo 6. Polarizacin
PIMCD2013-python, Publicacin 1.0
0.4
Itransmitida
0.3
0.2
0.1
0.00 10 20 30 40 50 60 70 80
# polarizadores
90 Captulo 6. Polarizacin
CAPTULO 7
Interaccin radiacin-materia
7.1 Introduccin
#!/usr/local/bin/python
# -*- coding: utf-8 -*-
#------------------------------------
# Autor: Luis Miguel Sanchez Brea
# Fecha 2013/10/24 (version 1.0)
# Licencia: GPL
# Objetivo: Ejemplos de difraccion en campo lejano
#-------------------------------------
import scipy as sp
import matplotlib.pyplot as plt
m = 1 #metros
kg = 1 #kilogramo
sg = 1 #segundos
V = 1 #voltio
91
PIMCD2013-python, Publicacin 1.0
C = 1 #culombios
Hz = 1 / sg #hertzio
nm = 1e-9 * m
- Precondicion: g<<w0
- Entradas:
* w0: frecuencia de resonancia
* gamma: amortiguamiento
- Salidas:
* r: distancia compleja
"""
#distancia electron-nucleo
r = (qe / me) * E0 / (w ** 2 - w0 ** 2 - 1.j * gamma * w)
#diversos dibujos
#distancia
plt.figure(figsize = (11, 9), facecolor = w, edgecolor = k)
plt.subplot(221)
plt.plot(w, abs(r) / nm, k, linewidth = 2)
plt.xlabel($\omega \; (Hz)$, fontsize = 18)
plt.ylabel($r\;(nm)$, fontsize = 18)
#desfase
plt.subplot(222)
plt.plot(w, sp.angle(r) * 180 / sp.pi, k, linewidth = 2)
plt.xlabel($\omega \; (Hz)$, fontsize = 18)
plt.ylabel($\phi \;(grados)$, fontsize = 18)
#parte real
plt.subplot(223)
plt.plot(w, sp.real(r), k, linewidth = 2)
plt.xlabel($\omega \; (Hz)$, fontsize = 18)
plt.ylabel($Re(r)$, fontsize = 18)
#parte imaginaria
plt.subplot(224)
plt.plot(w, sp.imag(r), k, linewidth = 2)
plt.xlabel($\omega \; (Hz)$, fontsize = 18)
plt.ylabel($Im(r)$, fontsize = 18)
plt.show()
1.8 0
1.6 20
1.4 40
1.2 60
(grados)
r (nm)
1.0 80
0.8 100
0.6 120
0.4 140
0.2 160
0.00.0 0.5 1.0 1.5 2.0 1800.0 0.5 1.0 1.5 2.0
(Hz) 1e9+9.99999e14 (Hz) 1e9+9.99999e14
1.0 1e 9 0.0 1e 9
0.2
0.5 0.4
0.6
0.8
Im(r)
Re(r)
0.0
1.0
1.2
0.5 1.4
1.6
1.00.0 0.5 1.0 1.5 2.0 1.80.0 0.5 1.0 1.5 2.0
(Hz) 1e9+9.99999e14 (Hz) 1e9+9.99999e14
7.2 Dipolo
Una carga elctrica oscilante genera un campo electromagntico. En el caso de un movimiento sinusoidal de
frecuencia w, el campo generado resulta
3 2 2
= cos ( )()
4 ()3 ()2
3 1 1 ()
= sin ( )
4 ()3 ()2
= 0
Esto es lo que se ha programado en las siguientes figuras, para el caso de un plano y para un instante de tiempo
t=0.
7.2. Dipolo 93
PIMCD2013-python, Publicacin 1.0
#!/usr/local/bin/python
# -*- coding: utf-8 -*-
#------------------------------------
# Autor: Luis Miguel Sanchez Brea
# Fecha 2013/10/24 (version 1.0)
# Licencia: GPL
# Objetivo: Emision del dipolo
#-------------------------------------
import scipy as sp
import matplotlib
import matplotlib.pyplot as plt
import matplotlib.cm as cm
wavelength=0.6328*um
k = 2 * sp.pi / wavelength
c= 299792.458 *m/s
w=c*k
q=1; r0=1; epsilon0=1; #normalizacion
#area de visualizacion
tamano=2.5*um
x=sp.linspace(-tamano/2, tamano/2, 250)
z=sp.linspace(-tamano/2, tamano/2, 250)
X,Z=sp.meshgrid(x, z)
#calculo de la intensidad
R = sp.sqrt(X** 2 + Z ** 2)
sinTheta=X/R
E_theta=q*r0*k**2/(4*sp.pi*R*epsilon0)*sinTheta*sp.cos((k*R))
intensidad = abs(E_theta) ** 2
intensidad=sp.log(intensidad+1)
50
100
150
200
contourf contour
4 4
2 2
0 0
2 2
4 4
4 2 0 2 4 4 2 0 2 4
0.0 1.5 3.0 4.5 6.0 7.5 9.0 10.512.0 1.5 3.0 4.5 6.0 7.5 9.0 10.5
Como la fluctuacin es temporal, en los siguientes archivos se muestra este movimiento. Uno de ellos genera una
7.2. Dipolo 95
PIMCD2013-python, Publicacin 1.0
50
100
150
200
7.3 Resonancia
El efecto que tiene la luz sobre el movimiento de los electrones depende fuertemente de la frecuencia de la
onda electromagntica incidente en comparacin con la frecuencia de resonancia del electrn en el tomo. En la
siguiente figura se muestra cul es el desplazamiento mximo producido en el tomo en funcion de los parmetros
del tomo y de la frecuencia de la luz incidente.
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# -*- coding: cp1252 -*- " Codigo para poder usar tildes"
#------------------------------------
# Autor: Luis Miguel Sanchez Brea
# Fecha 2013/10/24 (version 1.0)
# Licencia: GPL
#-------------------------------------
import scipy as sp
import matplotlib.pyplot as plt
m = 1 #metros;
kg = 1 #kilogramo
sg = 1 #segundos
V = 1 #voltio
C = 1 #culombios
Hz = 1 / sg #hertzio
nm = 1e-9 * m
qe = -1.602176565 * 10 ** -19 * C #carga del electron
me = 9.10938291 * 10 ** -31 * kg #masa del electron
1.8 r 0 desfase
1.6 20
1.4 40
1.2 60
(grados)
r (nm)
1.0 80
0.8 100
0.6 120
0.4 140
0.2 160
0.00.0 0.5 1.0 1.5 2.0 1800.0 0.5 1.0 1.5 2.0
(Hz) 1e9+9.99999e14 (Hz) 1e9+9.99999e14
7.3. Resonancia 97
PIMCD2013-python, Publicacin 1.0
la densidad de energa espectral, i.e, la cantidad de energa electromagntica por unidad espectral que llega por
unidad de superficie
2 /4
() = | |2 = ( ) ,
2 /4 + ( )2
donde es el campo a la salida del elemento difra, es la frecuencia de resonancia y es la frecuencia del haz
incidente
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# -*- coding: cp1252 -*- " Codigo para poder usar tildes"
#------------------------------------
# Autor: Luis Miguel Sanchez Brea
# Fecha 2013/10/24 (version 1.0)
# Licencia: GPL
#-------------------------------------
import scipy as sp
import matplotlib.pyplot as plt
m = 1 #metros;
kg = 1 #kilogramo
sg = 1 #segundos
V = 1 #voltio
C = 1 #culombios
Hz = 1 / sg #hertzio
nm = 1e-9 * m
qe = -1.602176565 * 10 ** -19 * C #carga del electron
me = 9.10938291 * 10 ** -31 * kg #masa del electron
epsilon0=8.8541878176e-12
c=3e8*m/sg
#distancia electron-nucleo
J=epsilon0*c*abs(E0)**2/(gamma**2/4+(w-w0)**2)
#distancia
plt.figure(facecolor = w, edgecolor = k)
plt.plot(w, J, k, linewidth = 2)
plt.xlabel($\omega \; (Hz)$, fontsize = 18)
plt.ylabel($J(\omega)$, fontsize = 18)
1.2 1e 12
1.0
0.8
J ( )
0.6
0.4
0.2
Esta seccin eficaz de extincin la denotamos y su relacin con la potencia extrada es la siguiente
2 2
= =
|| ( 2 2 )2 + 2 2
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# -*- coding: cp1252 -*- " Codigo para poder usar tildes"
#------------------------------------
# Autor: Luis Miguel Sanchez Brea
# Fecha 2013/10/24 (version 1.0)
# Licencia: GPL
#-------------------------------------
import scipy as sp
import matplotlib.pyplot as plt
m = 1; kg = 1; s = 1; V = 1; C = 1; Hz = 1 / s
nm = 1e-9 * m
qe = -1.602176565e-19 * C #carga del electron
me = 9.10938291e-31 * kg #masa del electron
epsilon0=8.8541878176e-12
c= 299792458*m/s
sigma=sigma_T*w**4/((w**2-w0**2)**2+w**2*gamma**2)
#distancia
plt.figure(facecolor = w, edgecolor = k)
plt.plot(w, sigma, k, linewidth = 2)
plt.xlabel($\omega \; (Hz)$, fontsize = 18)
plt.ylabel($\sigma(\omega)$, fontsize = 18)
plt.title("Seccion eficaz de scattering", fontsize=24)
texto="radio = %4.4g m" %(sp.sqrt(sigma_T/sp.pi))
plt.text(w.min(),sigma.max()/2,texto,fontsize=16)
plt.tight_layout()
plt.show()
0.6
()
0.4
0.2
8.1 Introduccin
Los ejemplos que aqu se desarrollan son autocontenidos, es decir, no necesitan de libreras especificas excepto
las estndar. El objetivo de este tema es, por una parte, conocer la relacin entre el modelo microscpico clsico
de interaccin radiacin-materia con el ndice de refraccin. Asimismo, se pretende analizar diversas expresiones
analticas para el ndice de refraccin, conociendo las propiedades del ndice de refraccin tales como la absorcin
y la dispersin.
Se compara las definiciones macroscpica y microscpica de la polarizacin. La primera se calcula a travs las
ecuaciones macroscpicas de Maxwell.
P = 0 E ,
La segunda se calcula a partir de las trayectorias de los tomos analizadas en el tomo de Lorentz. Mediante esta
comparacin se obtiene una ecuacin para la constante dielctrica en funcin de los parmetros microscpicos:
1
P= E, .
=1
103
PIMCD2013-python, Publicacin 1.0
Como tambin es conocido, se puede obtener el ndice de refraccin a partir de la constante dielctrica
= .
0
En el caso de que no haya cargas libres, es decir, que el medio sea dielctrico, el ndice de refraccin se puede
simplificar a
2
= 0 1 + ,
0 02 2
donde la sumatoria representa los distintos tipos de resonancias que existen en el material.
Sacando las partes real e imaginaria se puede obtener el ndice de refraccin y de absorcin.
2
2 (0, 2 )
= 1 + 2 2 )2 + 2 ,
20 (0
2
= 2 2 )2 + 2 2 .
20 (0
En el siguiente ejemplo se muestra el ndice de refraccin para dos ejemplos. En el primero se muestra el ndice
de refraccin debido solamente a una resonancia.
En el segundo ejemplo se muestra el ndice de refraccin cuando el medio tiene 3 resonancias. Se observa un
carcter acumulativo. Para bajas frecuencias, el ndice de refraccin no es la unidad, sino mayor, mientras que
para altas frecuencias, por encima de la resonancia, la luz no observa la materia y el ndice de refraccin es la
unidad.
#!/usr/local/bin/python
# -*- coding: utf-8 -*-
#------------------------------------
# Autor: Luis Miguel Sanchez Brea
# Fecha 2013/10/24 (version 1.0)
# Licencia: GPL
# Objetivo: Ejemplos de difraccion en campo lejano
#-------------------------------------
import scipy as sp
import matplotlib.pyplot as plt
m = 1; kg = 1; sg = 1; V = 1; C = 1;
Hz = 1 / sg; nm = 1e-9 * m
q=1.6021765e-19*C
m=9.109382911e-31*kg
epsilon0=8.8541878176e-12
n_puntos = 1000
anchura = 20
w = sp.linspace(min(w0) - anchura * max(gamma), max(w0) + anchura * max(gamma), n_puntos)
#distancia electron-nucleo
n2=1
nc=sp.sqrt(n2)
n=sp.real(nc)
kappa=sp.imag(nc)
plt.figure()
#parte real
plt.subplot(211)
plt.plot(w, n, k, linewidth = 2)
plt.xlabel($\omega \; (Hz)$, fontsize = 18)
plt.xlim(max(0,w[0]),w[-1])
plt.ylabel($n$, fontsize = 18)
plt.grid(True)
#parte imaginaria
plt.subplot(212)
plt.plot(w, kappa, k, linewidth = 2)
plt.xlabel($\omega \; (Hz)$, fontsize = 18)
plt.xlim(max(0,w[0]),w[-1])
plt.ylabel($\kappa$, fontsize = 18)
plt.grid(True)
plt.tight_layout()
#ejemplo de 1 resonancia
indice_refraccion(Nv=1e18, f=(1,), w0 = (1e13 * Hz,), gamma = (1e8 * Hz,))
#muchas resonancias
f=(0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1)
w0= sp.array([1.0,1.2,1.4,1.6,1.8,2.0,2.2,2.4,2.6,2.8])*4e14*Hz
gamma= sp.array([1.0,1.1,1.2,1.3,1.4,1.5,1.6,1.7,1.8,1.9,2.0])*1e13*Hz
indice_refraccion(Nv=1e26, f=f, w0 = w0, gamma = gamma)
plt.show()
1.8
1.6
1.4
1.2
n
1.0
0.8
0.6
0.40.0 0.5 1.0 1.5 2.0 2.5 3.0 3.5 4.0
(Hz) 1e9+9.998e12
1.2
1.0
0.8
0.6
0.4
0.2
0.00.0 0.5 1.0 1.5 2.0 2.5 3.0 3.5 4.0
(Hz) 1e9+9.998e12
3.5
3.0
2.5
2.0
n
1.5
1.0
0.5
0.0 2.0 2.5 3.0 3.5 4.0
(Hz) 1e14
3.5
3.0
2.5
2.0
1.5
1.0
0.5
0.0 2.0 2.5 3.0 3.5 4.0
(Hz) 1e14
3.0
2.5
2.0
1.5
n
1.0
0.5
0.00.0 0.2 0.4 0.6 0.8 1.0 1.2 1.4
(Hz) 1e15
2.0
1.5
1.0
0.5
0.00.0 0.2 0.4 0.6 0.8 1.0 1.2 1.4
(Hz) 1e15
La ecuacin anteriormente descrita es interesante, pero a la hora de trabajar con ella es mejor realizar algn tipo
de aproximacin. En primer lugar porque en ptica se suele trabajar con longitudes de onda y no con frecuencias.
La segunda es para hacer casar las ecuaciones de la dispersin de materiales, conocidas previamente y utilizadas
en la ptica geomtrica.
Una de ellas es la ec. de Sellmeier.
2 2
2 () 1 = + + + ...
2 21 2 22
Se pueden encontrar los parmetros en muchas pginas web. Por ejemplo, hemos utilizado los siguientes materia-
les bastante comunes
Fused_Silica_B=(6.96166300E-01, 4.07942600E-01, 8.97479400E-01)
Fused_Silica_C=(4.67914826E-03, 1.35120631E-02, 9.79340025E01)
Veamos algunas de las grficas y el cdigo para programarlos. Este parmetro se denomina dispersin cromtica.
#!/usr/local/bin/python
# -*- coding: utf-8 -*-
#------------------------------------
# Autor: Luis Miguel Sanchez Brea
# Fecha 2013/10/24 (version 1.0)
# Licencia: GPL
# Objetivo: Ejemplos de difraccion en campo lejano
#-------------------------------------
import scipy as sp
import matplotlib.pyplot as plt
wavelength=sp.linspace(0.4, 1 ,1000)
i=2
n2=sp.zeros_like(wavelength)+1
for bi,ci in zip(B,C):
n2=n2+bi*wavelength**2/(wavelength**2-ci)
n=sp.sqrt(n2)
return n
n=indice_refraccion(wavelength, BK7_B,BK7_C)
dibujar_n(wavelength,n,Sellmeier: BK7)
n=indice_refraccion(wavelength, Fused_Silica_B,Fused_Silica_C)
dibujar_n(wavelength,n,Sellmeier: Fused_Silica)
n=indice_refraccion(wavelength, Zafiro_B,Zafiro_C)
dibujar_n(wavelength,n,Sellmeier: Zafiro)
"""
#tambien se puede obtener el valor para 1 dato solo, sin dibujar
wavelength=0.5
n05=indice_refraccion(wavelength, BK7_B,BK7_C)
print "el indice de refraccion BK7 para %4.4f um es %4.6f" %(wavelength,n05)
"""
plt.show()
1.530
1.525
1.520
n
1.515
1.510
1.470
1.465
n
1.460
1.455
1.770
1.765
n
1.760
1.755
1.750
material.
Otra de las expresiones tpicas para ajustar el indice de refraccin con la longitud de onda es la ecuacin de
Cauchy,
() = + + 4 + ..
2
#!/usr/local/bin/python
# -*- coding: utf-8 -*-
#------------------------------------
# Autor: Luis Miguel Sanchez Brea
# Fecha 2013/10/24 (version 1.0)
# Licencia: GPL
# Objetivo: Ejemplos de difraccion en campo lejano
#-------------------------------------
import scipy as sp
import matplotlib.pyplot as plt
m = 1; kg = 1; sg = 1; V = 1; C = 1;
Hz = 1 / sg; nm = 1e-9 * m; um=1e-6
q=1.6021765e-19*C
m=9.109382911e-31*kg
epsilon0=8.8541878176e-12
wavelength=sp.linspace(400*nm, 1000*nm,1000)
Fused_silica=(1.4580,0.00354*um**2)
Borosilicate_BK7=(1.5046,0.00420*um**2)
Hard_crown_K5=(1.5220,0.00459*um**2)
Barium_crown_BaK4 =(1.5690,0.00531*um**2)
Barium_BaF10=(1.6700,0.00743*um**2)
Dense_flint_SF10=(1.7280,0.01342*um**2)
#ejemplo de 1 resonancia
n=indice_refraccion(wavelength, Fused_silica)
dibujar_n(wavelength,n, titulo=Cauchy: Fused_silica)
n=indice_refraccion(wavelength, Borosilicate_BK7)
dibujar_n(wavelength,n, titulo=Cauchy: Borosilicate_BK7)
"""
wavelength=0.5
n05=indice_refraccion(wavelength,Borosilicate_BK7)
print "el indice de refraccion BK7 para %4.4f um es %4.6f" %(wavelength,n05)
"""
plt.show()
1.480
1.475
n
1.470
1.465
1.530
1.525
1.520
n
1.515
1.510
En los medios conductores tenemos cargas ligadas (electrones internos) y cargas libres. Sin embargo, stos ltimos
son los que ms afectan al ndice de refraccin. Por ello, suponemos que slo hay cargas libres. La ecuacin de
ndice de refraccin se simplifica a
2 1
2 = 1 .
0 ( + )
2
2 () 1 .
2
donde
2
=
0
import scipy as sp
import matplotlib.pyplot as plt
m = 1; kg = 1; sg = 1; V = 1; C = 1;
Hz = 1 / sg; nm = 1e-9 * m; um=1e-6
q=1.6021765e-19*C; m=9.109382911e-31*kg
epsilon0=8.8541878176e-12; c=299792458*m/sg
plt.plot(w, n, k, linewidth = 2)
plt.xlabel($\omega \; (Hz)$, fontsize = 18)
plt.xlim(w[0],w[-1])
plt.ylabel($n$, fontsize = 18)
plt.grid(True)
if wp>0:
plt.subplot(211)
plt.axvline(x=wp, ymin=0, ymax=1, lw=2, color=k, linestyle=--)
plt.subplot(212)
plt.axvline(x=wp, ymin=0, ymax=1, lw=2, color=k, linestyle=--)
plt.tight_layout()
def ejemplo(Nv,gamma):
wp=sp.sqrt(Nv*q**2/(m*epsilon0))
""" print "la frecuencia de resonancia es %4.6g" %(wp)
print "la longitud de onda de resonancia es %4.6g" %(2*sp.pi*c/wp)"""
w=sp.linspace(wp/4,wp*4,1000)
nc=indice_refraccion(w, Nv,gamma)
dibujar_n(w,nc,wp)
ejemplo(Nv=1e25, gamma=1e12)
ejemplo(Nv=1e25, gamma=1e14)
plt.show()
1.0
0.8
0.6
n
0.4
0.2
0.0 1 2 3 4 5 6 7
(Hz) 1e14
4.0
3.5
3.0
2.5
2.0
1.5
1.0
0.5
0.0 1 2 3 4 5 6 7
(Hz) 1e14
1.6
1.4
1.2
1.0
n
0.8
0.6
0.4 1 2 3 4 5 6 7
(Hz) 1e14
2.0
1.5
1.0
0.5
0.0 1 2 3 4 5 6 7
(Hz) 1e14
Ecuaciones de Fresnel
117
PIMCD2013-python, Publicacin 1.0
Descarga de archivos:
fresnel.py. Archivo con las funciones principales fresnel.py
fresnel_aire_vidrio.py. Archivo con el ejemplo del del calculo de la amplitud, fase e intensidad
de las componentes paralela y perpendicular en una intercara aire-vidrio fresnel_aire_vidrio.py
fresnel_vidrio_aire.py. Archivo con el ejemplo del del calculo de la amplitud, fase e intensidad
de las componentes paralela y perpendicular en una intercara aire-vidrio fresnel_vidrio_aire.py
fresnel_aire_metal.py. Archivo con el ejemplo del del calculo de la amplitud, fase e intensidad de
las componentes paralela y perpendicular en una intercara aire-vidrio fresnel_aire_metal.py
9.1 Introduccin
Las ecuaciones de Fresnel permiten calcular los campos transmitido y reflejado cuando una onda armnica plana
incide sobre una interfaz entre dos medios con ndice de refraccin distinto. Tienen una dependencia del estado
de polarizacin del haz incidente (paralelo al plano de incidencia, perpendicular al plano de incidencia o una
combinacin), de los ndices de refraccin del medio de entrada y de salida (1 , 2 ) y del ngulo de incidencia .
El ngulo del haz transmitido se obtiene a travs de la ley de Snell: 1 ( ) = 2 ( ).
Dichos campos reflejados y transmitido son lineales con el campo incidente y los coeficientes de proporcionalidad
son los coeficientes de fresnel. Para el caso de los campos reflejados
= * ,
= * ,
= * .
Un anlisis riguroso de cmo calcular dichos coeficientes de Fresnel a partir de las ecuaciones de Maxwell se
pueden encontrar en el libro de Cabrera 1 (captulos 9 y 10). Para el caso de que los dos medios sean dielctricos
estas ecuaciones resultan ser
2 ( ) 1 ( )
= ,
2 ( ) + 1 ( )
1 ( ) 2 ( )
= ,
1 ( ) + 2 ( )
2 1 ( )
= ,
2 ( ) + 1 ( )
2 1 ( )
= .
1 ( ) + 2 ( )
Para el caso de que uno de los medios tenga ndice de refraccin comlejo, es decir sea un medio absorbente,
entonces las ecuaciones son algo ms complicadas. Se pueden encontrar en el libro de Cabrera 1 , captulo 9.
1 J.M. Cabrera, F.J. Lpez, F. Agull Lpez ; ptica Electromagntica: Fundamentos; Addison-Wesley (2001) ISBN 9788478290215
En el archivo fresnel.py se han implementado las funciones que permiten el clculo de los coeficientes y las
reflectancias. Dichas funciones tienen la entrada de los ndices de refraccin n1, n2 y de un array de nmeros
que representan el ngulo de incidencia. La salida de estas funciones son: r_perp, r_par, t_perp, t_par cuando se
calculan coeficientes y R_perp, R_par, T_perp, T_par cuando se calculan reflectancias o transmitancias. Estos
parmetros los aceptan las funciones para dibujar.
La variable theta_i puede ser un nmero o un array generado con numpy. De esta forma se simplifican las repre-
sentaciones y se acelera enormemente el tiempo de clculo. Por consiguiente, las funciones de clculo devuelven
un array para los coeficientes , , y cuyo tamao es igual al .
#Coeficientes de Fresnell
r_par=(n2*cos_i-n1*cos_t)/(n2*cos_i+n1*cos_t)
r_perp=(n1*cos_i-n2*cos_t)/(n1*cos_i+n2*cos_t)
t_par=(2*n1*cos_i)/(n2*cos_i+n1*cos_t)
t_perp=(2*n1*cos_i)/(n1*cos_i+n2*cos_t)
Definidos los coeficientes de Fresnel se puede calcular la transmitancia y la reflectancia entendiendo estas magni-
tudes como la relacin entre la intensidad reflejada o transmitida y la intensidad del haz incidente(ms detalles en
1
). As estos parmetros pueden ser derivados de los coeficientes de Fresnell como se muestra en el cdigo a partir
de la funcin reflectancia_transmitancia_dielectricos.
def reflectancia_transmitancia_dielectricos(n1, theta_i, n2):
""""Cabrera. pag 266"""
#Se calculan lo coeficientes de Fresnel
r_perp, r_par, t_perp, t_par= coeficientesFresnel_dielectricos(n1, theta_i, n2)
Los medios absorbentes se caracterizan por tener un ndice de refraccin complejo. Nuevamente las relaciones de
Fresnel permiten determinar los coeficientes de transmisin y reflexin.
def coeficientesFresnel_complejo(n1, theta_i, n2c):
"""
Calcula las componentes rs y rp mediante las eq. de Fresnel
n^=n-ik
ejemplo:
theta_i=sp.linspace(0*grados,90*grados,10),
#Reflectancia
R_perp=abs(r_perp)**2
R_par=abs(r_par)**2
#Precalculo
kiz=cos(theta_i)
ki2 = n1**2
ktcz=sp.sqrt(n2c**2-n1**2*sin(theta_i)**2)
ktc2=n2c**2
n2R=sp.real(n2c)
kappa2=sp.imag(n2c)
B=n2R**2-kappa2**2-n1**2*sin(theta_i)**2
ktz=sp.sqrt(0.5*(B+sp.sqrt(B**2+4*n2R**2*kappa2**2)))
#Transmitancias
T_perp=ktz*abs(t_perp)**2/kiz
T_par=ki2*sp.real(ktcz/ktc2)*abs(t_par)**2/kiz
Hasta el moemnto se han implementado fisntintas funciones que permiten determinar los coeficientes de Fres-
nel en funcin del ngulo del haz incidente y de los ndices de refraccin del medio y del material. En es-
te epgrafe, se pretende definir una funcin de debujo capaz de dibujar los coeficientes de Fresnel en fun-
cin de . Los datos que dibuja son los resultantes de coeficientesFresnel_dielectricos() o de
coeficientesFresnel_complejo().
def dibujarCoeficientes(n1, theta_i, n2, r_perp, r_par, t_perp, t_par, nombreArchivo = ):
"""
Dibuja las ecuaciones de fresnel en funcion del angulo de entrada
"""
#Generacion della figura
plt.figure(figsize=(12,6))
#Amplitud
plt.subplot(1,2, 1)
plt.plot(theta_i / grados, abs(r_perp)*sp.sign(r_perp) , k--, lw = 2,\
label = u"$r_{\perp}$")
plt.plot(theta_i / grados, abs(r_par)*sp.sign(r_par) , k, lw = 2,\
label = u"$r_{\parallel}$")
plt.plot(theta_i / grados, abs(t_perp)*sp.sign(t_perp) , r--, lw = 2,\
label = r"$t_{\perp}$")
plt.plot(theta_i / grados, abs(t_par)*sp.sign(t_par) , r, lw = 2,\
label = r"$t_{\parallel}$")
#Leyenda de los ejes
plt.xlabel(r"$\phi (grados)$", fontsize = 22)
plt.ylabel(r"$Amplitud$", fontsize = 22)
plt.ylim(-1., 2.01)
plt.legend(loc=2,prop={size:18})
#Fase
plt.subplot(1,2, 2)
plt.plot(theta_i / grados, sp.unwrap(sp.angle(r_perp),2*sp.pi), k--, lw = 2,\
label = r"$r_{\perp}$")
plt.plot(theta_i / grados, sp.unwrap(sp.angle(r_par),2*sp.pi), k, lw = 2,\
label = r"$r_{\parallel}$")
plt.plot(theta_i / grados, sp.unwrap(sp.angle(t_perp),2*sp.pi), r--, lw = 2,\
label = r"$t_{\perp}$")
plt.plot(theta_i / grados, sp.unwrap(sp.angle(t_par),2*sp.pi), r, lw = 2,\
label = r"$t_{\parallel}$")
#Leyenda de los ejes
plt.xlabel(r"$\phi (grados)$", fontsize = 22)
if not nombreArchivo == :
plt.savefig(nombreArchivo, dpi = 100, bbox_inches = tight, pad_inches = 0.1)
if not nombreArchivo == :
plt.savefig(nombreArchivo, dpi = 100, bbox_inches = tight, pad_inches = 0.1)
9.3 Ejemplos
def coeficientes():
"interfaz aire-vidrio"
#Coeficientes de Fresnel para un caso particular
r_perp, r_par, t_perp, t_par = coeficientesFresnel_dielectricos(n1 = 1.5,\
theta_i = 45 * grados, n2 = 1.0)
#Muestra de resultados
print "coeficientes de reflexion paralelo: r_par= (%2.4f,%2.4f)" % (r_par.real,\
r_par.imag)
print "coeficientes de reflexion perpendicular: r_perp= (%2.4f,%2.4f)" % (r_perp.real,\
r_perp.imag)
print "coeficientes de transmision paralelo: t_par= (%2.4f,%2.4f)" % (t_par.real,\
t_par.imag)
print "coeficientes de transmision perpendicular: t_perp= (%2.4f,%2.4f)" % (t_perp.real,\
t_perp.imag)
if __name__ == __main__:
coeficientes()
Se supone la propagacin de un haz en aire, que incide a 45 grados sobre un vidrio dielctrico con ndice 1.5. As,
el resultado es:
>> coeficientes de reflexion paralelo: r_par= (0.2800,-0.9600)
>> coeficientes de reflexion perpendicular: r_perp= (0.8000,-0.6000)
>> coeficientes de transmision paralelo: t_par= (1.9200,-1.4400)
>> coeficientes de transmision perpendicular: t_perp= (1.8000,-0.6000)
En este ejemplo se considera la incidencia de un haz de luz en el aire sobre una superficie de vidrio con ndice
1.5. Se representan la amplitud transmitida y reflejada, as como la fase reflejada en funcin del ngulo de inci-
dencia. Como se puede ver en las curvas de amplitud, la transmitancia paralela y perpendicular son relativamente
similares. Si se representan las transmitancias y reflectancias, se observa que cuando la reflectancia es mnima la
transmitancia es mxima. Relacin lgica puesto que R+T=1. No obstante es de especial inters este extremal,
llamandose ngulo de Brewster a aquel para el que la reflectancia es mnima. As se observa que la fase cambia
radicalmente en dicho punto, y la luz reflejada resulta perfectamente polarizada.
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#----------------------------------------------------------------------
# Autor: Luis Miguel Sanchez Brea
# Fecha 2013/10/24 (version 1.0)
# Licencia: GPL
#----------------------------------------------------------------------
"""
ejemplos para las ecuaciones de Fresnel
"""
#Carga de paquetes
import sys
sys.path.append(../)
from fresnel import * #@UnusedWildImport
def fresnel_aire_vidrio():
"interfaz aire-vidrio"
n1 = 1.
n2 = 1.5
theta_i = sp.linspace(0 * grados, 90 * grados, 500)
#Transmitancia y reflectancia
R_perp, R_par, T_perp, T_par= reflectancia_transmitancia_dielectricos(n1, theta_i, n2)
dibujarTransmitancias(n1, theta_i, n2, R_perp, R_par, T_perp, T_par)
if __name__ == __main__:
fresnel_aire_vidrio()
plt.show()
2.0 3.5
r r
1.5 r 3.0 r
t t
2.5
1.0 t t
Amplitud
2.0
fase
0.5
1.5
0.0
1.0
0.5 0.5
1.00 10 20 30 40 50 60 70 80 90 0.00 10 20 30 40 50 60 70 80 90
(grados) (grados)
1.0
0.8
0.6
I
0.4
R
R
0.2
T
T
0.0
0 10 20 30 40 50 60 70 80 90
(grados)
Este ejemplo es el contrario al anterior, se supone un haz de luz propagandose en vidrio, y se analiza el comporta-
miento del haz a la salida del material. Nuevamente se observa la reflexin de Brewster en un ngulo cercano a los
40 grados, y como cerca de este la transmitancia cambia abruptamente hasta el punto que nicamente se produce
reflexin del haz.
def fresnel_vidrio_aire():
"interfaz vidrio-aire"
n1 = 1.5
n2 = 1.
theta_i = sp.linspace(0 * grados, 90 * grados, 500)
2.0 4
r r
3
1.5 r r
t 2 t
1.0 t t
1
Amplitud
fase
0.5 0
1
0.0
2
0.5
3
1.00 10 20 30 40 50 60 70 80 90 40 10 20 30 40 50 60 70 80 90
(grados) (grados)
1.0
0.8
0.6
I
0.4
R
R
0.2
T
T
0.0
0 10 20 30 40 50 60 70 80 90
(grados)
9.3.4 Interfaz aire-metal
Los metales se caracterizan por tener un ndice de refraccin complejo siendo negativa la parte imaginaria del
mismo. As se supone la incidence de un haz sobre una intercara aire-metal, con ndice de refraccin = 0,769
6,08. Es destacable como la variacin en la fase de la componente paralela, es prcticamente invariante bajo
cambios en el ngulo de incidencia.
def fresnel_aire_metal():
"interfaz aire-metal"
n1 = 1.
#el metal se introduce con numero complejo cuya parte imaginaria es negativa
n2c = 0.769 - 6.08j
theta_i = sp.linspace(0 * grados, 90 * grados, 500)
2.0 4
r r
3
1.5 r r
t 2 t
1.0 t t
1
Amplitud
fase
0.5 0
1
0.0
2
0.5
3
1.00 10 20 30 40 50 60 70 80 90 40 10 20 30 40 50 60 70 80 90
(grados) (grados)
1.0
0.8
0.6
I
0.4
R
R
0.2
T
T
0.0
0 10 20 30 40 50 60 70 80 90
(grados)
9.4 Ejercicios
9.5 Referencias
Pulsos de luz
129
PIMCD2013-python, Publicacin 1.0
10.1 Introduccin
Un pulso temporal plano se puede tratar como una suma infinita de ondas armnicas planas, pues forman una
base. Para calcular los componentes de cada una de las ondas armnicas de frecuencia que componen el pulso
se tiene que realizar una transformacin de Fourier temporal,
E (, ) = E0, ( ) ,
donde E0, es la amplitud compleja de cada una de las ondas planas. Para calcular esta amplitud se tiene que
recurir a la transformacin de Fourier inversa
1
E0, = E ( = 0, ) ,
2
Existen dos casos particularmente tiles como son el pulso gaussiano y el pulso de exponencial, que discutiremos
brevemente a continuacin.
( 0 )2
[ ]
E0, = E0 .
2 2
#Modulos empleados
import scipy as sp
import matplotlib.pyplot as plt
#Unidades
sg = 1
Hz = 1 / sg #hertzio
t= sp.linspace(-3/gamma,3/gamma,n_puntos)
1.0 1.0
0.8
0.5
perfil Gaussiano
0.6
E(t)
0.0
0.4
0.5
0.2
Otro pulso que se utiliza frecuentemente es el pulso exponencial, pues es el modelo clsico de cmo los tomos
emiten luz. Una vez excitados pierden energa hasta que vuelven al estado estacionario. El modelo de Lorentz
asume que el desplazamiento resulta
r() = r /2 .
E( = 0, ) = 0 u /2 0 .
Al realizar la transformada de Fourier resulta que la distribucin de frecuencias es compleja (se producen desfases).
ux
E =
/2 ( )
En este caso, la densidad de energa espectral, esto es, la cantidad de energa electromagntica por unidad espectral
que llega por unidad de superficie
2 /4 1
() = | |2 = ( ) , = ( ) ,
2 /4 + ( )2 1 + 4( )2 / 2
En el siguiente cdigo se muestra cmo generar una grfica con el espectro gaussiano y el pulso generado.
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#------------------------------------
# Autor: Luis Miguel Sanchez Brea
# Fecha 2013/10/24 (version 1.0)
# Licencia: GPL
#-------------------------------------
"""pulso de gauss"""
#Definicion de frecuencia
sg= 1
Hz = 1 / sg #hertzio
#campo
campo=sp.exp(-gamma*t)*sp.cos(w0*t)
#Figuras
plt.figure(figsize=(10,5))
plt.subplot(1,2,1)
plt.plot(t, campo, k, linewidth = 2)
plt.xlabel($t \; (s)$, fontsize = 18)
plt.ylabel($E(t)$, fontsize = 18)
1.0 1.0
0.8
0.5
perfil Lorenziano
0.6
E(t)
0.0
0.4
0.5
0.2
1.00.0 0.5 1.0 1.5 2.0 2.5 3.0 3.5 0.02.0 2.5 3.0 3.5 4.0
t (s) 1e 14 (Hz) 1e15
Desde el punto de vista terico tambin es importante un pulso cuadrado, que se obtiene como una funcin coseno
dentro del intervalo y 0 fuera.
r() = r /2 .
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#------------------------------------
# Autor: Luis Miguel Sanchez Brea
# Fecha 2013/10/24 (version 1.0)
# Licencia: GPL
#-------------------------------------
"""pulso de gauss"""
#Modulos empleados
import scipy as sp
import matplotlib.pyplot as plt
#Unidades
sg = 1
Hz = 1 / sg #hertzio
t= sp.linspace(-3/gamma,3/gamma,n_puntos)
1.0 1.0
0.8
0.5
0.6
perfil sinc
0.4
E(t)
0.0
0.2
0.0
0.5
0.2
Interferencias
137
PIMCD2013-python, Publicacin 1.0
11.1 Introduccin
El efecto de las interferencias surge directamente de que las ecuaciones de Maxwell son lineales en los campos
elctricos y magnticos. Supongamos que E1 y E2 son soluciones. Entonces
E = E1 + E2
tambin es una solucin. Sin embargo, el campo no es un parmetro observable, sino que lo es el promedio
temporal del vector de Poynting, que se define como
1
S E B,
0
con tiene unidades de [S] = /2 . Al particularizar al caso de ondas armnicas planas tenemos
1 0 2
S = |E| u ,
2 0
Si no existiera el tercer trmino, entonces ocurre que = 1 + 2 , que es lo que normalmente vemos en la
naturaleza.
Para que se cumplan las interferencias, pues necesitamos que la luz est polarizada, sea bastante monocromtica
y sea coherente. En particular, se deben verificar:
nicamente interfieren ondas con la misma frecuencia, 1 = 2
Las ondas que interfieren deben tener estados de polarizacin no ortogonales. E01 E02 = 0
Coherencia: Las fases en el trmino interferencial deben tener poca dependencia de (, )
En este captulo asumiremos las mejores condiciones para producir las interferencias. Las 2 ondas tienen la misma
polarizacin, son puramente monocromticas y coherentes. De esta forma, desaparece el carcter vectorial de las
interferencias.
11.2 Programacin
Debido a la sencillez conceptual de las interferencias, las utilizaremos para analizar los distintos tipos de pro-
gramacin que se puede realizar con Python, como es la programacin con scripts (todo el cdigo en un mismo
archivo lineal), la programacin funcional (se escriben funciones que simplifican lo clculos) y la programacin
con clases (donde funciones y datos estn ntimamente relacionados). Finalmente veremos un procedimiento sen-
cillo para desarrollar vdeos, simulando un interfermetro de Michelson.
(r, ) = (k r)
para poder representar esta ecuacin en muchas posiciones x,y entonces X e Y son matrices generadas como
tamano=100*um
x=sp.linspace(-tamano,tamano, 256)
y=sp.linspace(-tamano,tamano, 256)
X,Y=sp.meshgrid(x,y)
El mtodo lineal es quizs el ms sencillo para iniciarse, pues la programacin est en el mismo archivo y el
cdigo se ejecuta de arriba hacia abajo en el programa. Un ejemplo de esta programacin est en la funcin
interferencias_ondasPlanas1.py. El archivo consiste en la definicin de dos ondas de la misma longitud de onda y
la posterior superposicin de las mismas, para finalmente obtener la intensidad. As se obtiene el patrn de franjas
de la figura.
#!/usr/local/bin/python
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#------------------------------------
# Autor: Luis Miguel Sanchez Brea
# Fecha 2013/10/24 (version 1.0)
# Licencia: GPL
#-------------------------------------
"""
Interferencia entre ondas planas.
Programacion lineal.
"""
#variables globales
um=1
grados=sp.pi/180
#Tamano
tamano=100*um
x=sp.linspace(-tamano,tamano, 256)
y=sp.linspace(-tamano,tamano, 256)
X,Y=sp.meshgrid(x,y)
A2=1
theta2=90*grados
phi2=1*grados
#proceso interferencial
u=u1+u2
#calculo de la intensidad
I=abs(u)**2
#grafica de la intensidad
plt.figure() #creacion de la figura
#escalado de la grafica
plt.axis(scaled)
#etiquetas
plt.xlabel("$x (\mu m)$", fontsize = 22)
plt.ylabel("$y (\mu m)$", fontsize = 22)
plt.title("$Intensidad(x,y)$", fontsize = 22)
#color
h1.set_cmap("gist_heat")
#muestra la grafica
plt.show()
100
Intensidad(x,y) 4.0
3.6
3.2
50
2.8
2.4
y(m)
0 2.0
1.6
1.2
50
0.8
0.4
100100 50 0 50 100 0.0
x(m)
11.3.2 Mtodo funcional
Si nos damos cuenta en el cdigo anterior, la onda plana se generar dos veces, una para 1 , y otra para 2 . Esto
se puede evitar definiendo una funcin que denominamos onda_plana() a la cual llamamos dos veces. Los
parmetros de entrada de la funcin son aquellos que alguna vez podemos variar. Tambin podemos generar una
funcin que realiza la grfica. De esta forma la podemos llamar tambin varias veces.
#!/usr/local/bin/python
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#------------------------------------
# Autor: Luis Miguel Sanchez Brea
# Fecha 2013/10/24 (version 1.0)
# Licencia: GPL
#-------------------------------------
"""
Interferencia entre ondas planas.
Programacion con funciones.
"""
#variables globales
um=1
grados=sp.pi/180
#parametros opticos
wavelength=0.6328*um
k=2*sp.pi/wavelength
#Tamano
tamano=100*um
x=sp.linspace(-tamano,tamano, 256)
y=sp.linspace(-tamano,tamano, 256)
X,Y=sp.meshgrid(x,y)
#definicion de la grafica
def dibujar_grafica(I):
#grafica de la intensidad
plt.figure() #creacion de la figura
#datos para ajustar el dibujo a la escala
extension = [x.min(), x.max(), y.min(), y.max()]
#dibujar intensidad + acondicionamiento de la grafica
h1 = plt.imshow(I, interpolation = bilinear, aspect = auto,
origin = lower, extent = extension)
#escalado de la grafica
plt.axis(scaled)
#etiquetas
plt.xlabel("$x (\mu m)$", fontsize = 22)
plt.ylabel("$y (\mu m)$", fontsize = 22)
plt.title("$Intensidad(x,y)$", fontsize = 22)
#color
h1.set_cmap("gist_heat") #RdBu
#dibujar barra de colores
plt.colorbar()
100
Intensidad(x,y) 4.0
3.6
3.2
50
2.8
2.4
y(m)
0 2.0
1.6
1.2
50
0.8
0.4
100100 50 0 50 100 0.0
x(m)
100
Intensidad(x,y) 4.0
3.6
3.2
50
2.8
2.4
y(m)
0 2.0
1.6
1.2
50
0.8
0.4
100100 50 0 50 100 0.0
x(m)
Como se ve, el cdigo incluido en las funciones se puede reutilizar. No obstante, las variables que utiliza la funcion
onda_plana() tienen dos orgenes. Uno como variables globales definidas anteriormente (como puede ser k,
X, Y y otras variables que se introducen a travs de la defincin de la funcin A, , .
En las clases, las funciones y los datos estn todos bajo un mismo marco, por lo que no existe el peligro de
modificar las variables globales de forma inadvertida. Normalmente la clase se define en una funcin (compleja)
y las aplicaciones de la clase llaman a esta funcin. Esta forma permite generar las figuras mostradas debajo del
cdigo
#!/usr/local/bin/python
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#------------------------------------
# Autor: Luis Miguel Sanchez Brea
# Fecha 2013/10/24 (version 1.0)
# Licencia: GPL
#-------------------------------------
"""
Metodo que utiliza las clases
"""
u1 = fuenteXY()
u2 = fuenteXY()
plt.show()
4.0
200 3.6
3.2
100 2.8
2.4
y(m)
0 2.0
1.6
100 1.2
0.8
200 0.4
100 100
y(m)
y(m)
0 0
100 100
200 200
200 100 0 100 200 200 100 0 100 200
x(m) x(m)
0.2 0.4 0.6 0.8 1.0 1.2 1.4 1.6 1.8 2.0 0.0 0.4 0.8 1.2 1.6 2.0 2.4 2.8
Dentro de la clase fuentesXY (no es necesario comprender todas las funciones todava), las funciones que
hemos utilizado son:
__init__()
onda_plana()
def __init__(self, x = x0, y = y0, wavelength = lambda0):
"""Se inicia un nuevo experimento"""
#arrays de entrada
self.x = x
self.y = y
#Longitud de onda
self.wavelength = wavelength
#Generacion de un mallado
self.X, self.Y = sp.meshgrid(x, y)
#Predefinicion del campo
self.u = sp.zeros(sp.shape(self.X), dtype = complex)
Veamos ahora el proceso de interferencia de 2 haces de Gauss. Estos hace se pueden definir como
2 2
( ) ( )
0
(, , ) = 0 exp 2 exp + ()
() () 2()
donde
0
02 =
( )2
() = 0 1+
0
[ ]
2
() = 1 + ( )
0
Este tipo de haces se puede programar fcilmente. Asumamos que estamos en el foco del haz z=0 y los haces estn
rotados. Entonces tambin se van a producir interferencias entre los haces.
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#------------------------------------
# Autor: Luis Miguel Sanchez Brea
# Fecha 2013/10/24 (version 1.0)
# Licencia: GPL
#-------------------------------------
"""
ejemplos de interferencias
"""
#variables globales
um=1
grados=sp.pi/180
wavelength=0.6328*um
tamano=100*um
x=sp.linspace(-tamano,tamano, 256)
y=sp.linspace(-tamano,tamano, 256)
X,Y=sp.meshgrid(x,y)
if __name__ == __main__:
interferenciasGauss(theta=20*grados, titulo=r$\theta=20^{0}$)
interferenciasGauss(theta=40*grados, titulo=r$\theta=40^{0}$)
plt.show()
0
=200
3.6
50 3.2
2.8
100 2.4
2.0
150 1.6
1.2
200 0.8
0.4
250 0.0
0 50 100 150 200 250
0
=400
3.6
50 3.2
2.8
100 2.4
2.0
150 1.6
1.2
200 0.8
0.4
250 0.0
0 50 100 150 200 250
Aqu est todo programado en funciones, tanto la amplitud del haz de Gauss en z=0, como el procedimiento de
dibujar y la funcin de ejecucin __main__. De esta forma se puede reutilizar el cdigo de una forma muy
eficiente, adems de entenderse mejor el cdigo. Los parmetros entre las funciones se pasan a travs de las
variables de entrada.
Finalmente, vemos cmo se puede representar esto a partir de la clase FuenteXY. La forma de programar las
interferencias es mucho ms sencilla y clara, casi pseudocdigo
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#------------------------------------
# Autor: Luis Miguel Sanchez Brea
# Fecha 2013/10/24 (version 1.0)
# Licencia: GPL
#-------------------------------------
"""
ejemplos de interferencias
"""
#Carga de paquetes y librerias
import scipy as sp
import matplotlib.pyplot as plt
import sys
sys.path.append(../)
from fuentesXY import fuenteXY, grados, um
#definicion de parametros
x=sp.linspace(-100*um,100*um,256)
y=sp.linspace(-100*um,100*um,256)
wavelength=0.6328*um
#onda 1
u1 = fuenteXY(x,y,wavelength)
u1.haz_gauss(A=1, r0=(0*um,0*um), w=(50*um, 50*um), theta=20.*grados, phi=2*grados)
#onda 2
u2 = fuenteXY(x,y,wavelength)
u2.haz_gauss(A=1, r0=(0*um,0*um), w=(50*um, 50*um), theta=-20.*grados, phi=2*grados)
#Superposicion
u12 = u1 + u2
#Representacion
u12.dibujar(tipo=intensidad)
plt.show()
100
3.6
3.2
50
2.8
2.4
y(m)
0 2.0
1.6
1.2
50
0.8
0.4
100100 50 0 50 100 0.0
x(m)
Como ejemplo de programacin con clases veremos las interferencias entre ondas esfricas. Estas son de gran
importancia terica pues nos permiten analizar los interfermetros de Young y de Michelson. La diferencia fun-
damental estriba en la posicin de las fuentes. Mientras que en el interfermetro de Young las dos fuentes estn
desplazadas en el eje x, en el interferometro de Michelson estn desplzadas en el eje z.
Como veremos, la programacin con clases nos permite centrarnos en el problema, ya que la programacin es de
alto nivel (el profesor ya desarrolla las funciones de generacin de las fuentes).
Como hemos dicho las dos fuentes estn desplazadas en el eje x. Esto genera una distribucin de intensidad en
forma de elipses que, si nos centramos en el eje, son muy prximas a franjas verticales, como puede ver en la
siguiente funcin.
#!/usr/local/bin/python
# -*- coding: utf-8 -*-
#------------------------------------
# Autor: Luis Miguel Sanchez Brea
# Fecha 2013/10/24 (version 1.0)
# Licencia: GPL
# Objetivo: Interferencias entre 2 ondas esfericas desplazadas en el eje x
#-------------------------------------
import sys
sys.path.append(../)
from fuentesXY import fuenteXY, grados, um
plt.show()
200 3.6
3.2
100 2.8
2.4
y(m)
0 2.0
1.6
100 1.2
0.8
200 0.4
Ahora las fuentes estn desplazadas en el eje z. Esto genera una distribucin de intensidad en forma de anillos,
como se puede ver en la siguiente funcin.
#!/usr/local/bin/python
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#------------------------------------
# Autor: Luis Miguel Sanchez Brea
# Fecha 2013/10/24 (version 1.0)
# Licencia: GPL
#-------------------------------------
"""
Interferencias
"""
#Carga de paquetes y librerias
import scipy as sp
import matplotlib.pyplot as plt
import sys
sys.path.append(../)
from fuentesXY import fuenteXY, grados, um
plt.show()
0.0000027
200
0.0000024
0.0000021
100
0.0000018
0.0000015
y(m)
0
0.0000012
100 0.0000009
0.0000006
200 0.0000003
Cuando tenemos un desplazamiento combinado x-z entre las dos fuentes, entonces la situacin no es tan sencilla,
apareciendo unas elipses que nos son familiares si hemos ajustado un interfermetro de Michelson.
#!/usr/local/bin/python
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#------------------------------------
#Representacion
u12.dibujar(tipo=intensidad)
plt.show()
0.0000036
200 0.0000032
0.0000028
100
0.0000024
0.0000020
y(m)
0
0.0000016
0.0000012
100
0.0000008
200 0.0000004
Para finalizar mostramos un cdigo que ejecuta un vdeo de qu ocurre en un interfermetro de Michelson cuando
uno de los espejos se desplaza.
#!/usr/local/bin/python
# -*- coding: utf-8 -*-
#------------------------------------
# Autor: Luis Miguel Sanchez Brea
# Fecha 2013/10/24 (version 1.0)
# Licencia: GPL
# Objetivo: grafica animada simulando un interferometro de Michelson
#-------------------------------------
import time
import gobject
import gtk #@UnusedImport
import scipy as sp
import matplotlib
matplotlib.use(GTKAgg)
import matplotlib.pyplot as plt
import matplotlib.cm as cm
um=1;
mm=1000*um;
fig = plt.figure(1)
a = plt.subplot(111)
wavelength=0.6328*um
k=2*sp.pi/wavelength
X,Y=sp.meshgrid(x,y)
I=1+sp.cos(2*k*d*cos_theta)
im = a.imshow( I, cmap=cm.gist_heat)
manager = plt.get_current_fig_manager()
cnt = 0
tstart = time.time()
def updatefig(*args):
#parametros globales definidos fuera de la funcion
global x, y, cnt, start, k, cos_theta, d
d-=.025*um
I=1+sp.cos(2*k*d*cos_theta)
im.set_array(I)
manager.canvas.draw()
cnt += 1
if cnt==250:
FPS=cnt/(time.time() - tstart)
cnt = 0
gobject.idle_add(updatefig)
plt.show()
tmp=raw_input("pulse enter para cerrar:")
Mdulos de ptica
Una vez que conocemos los mdulos cientficos, en el Departamento de ptica de la UCM hemos desarrollado
mdulos especficos para aplicaciones pticas. .
12.1.1 Introduccin
La mayor parte de las veces observamos un campo ptico en un plano XY, como es en el caso de la deteccin
sobre una pantalla o sobre una cmara CCD o CMOS.
Aqu es donde vamos a definir los campos elctricos de observacin. En este mdulo realizaremos un tratamiento
escalar, que permitir realizar operaciones sobre el campo elctrico. Asimismo, ser utilizado por otros mdulos
como mascarasXY.py y fuentesXY.py, puesto que las mscaras y las fuentes se pueden tratar de idntica forma.
En este captulo se pretende estudiar el funcionamiento del mdulo, no desarrollar ejemplos y aplicaciones pticas.
Se inicializa con la funcin __init__ que dice las operaciones cuando se carga.
157
PIMCD2013-python, Publicacin 1.0
El campo self.u es nulo hasta que no se utilice una funcin que lo rellena.
Los dos campos que se suman o multiplican tienen que tener la misma dimensin. Un pequeo ejemplo de uso.
Utilizamos la clase fuenteXY, pero es lo mismo, pues una hereda las funciones de la otra.
u1 = fuenteXY()
u2 = fuenteXY()
def binarizar(self, tipo = "amplitud", corte = None, nivel0 = None, nivel1 = None, campoNuevo = Fa
def perfil(self, punto1=, punto2=, npixels=1000, tipo=intensidad, order=2):
Rayleigh-Sommerfeld:
def RS(self, z = 10 * mm, newField = True, xout = None, yout = None):
def progresion(self, zs=sp.linspace(1*mm,2*mm,500), tipo=intensidad, generarTemporales=True):
def testCamposXY():
"""poner un comentario # en aquellas funciones que no se quieren ejecutar"""
#test_FFT_ondaPlana()
#test_FFT_Gauss()
#test_FFTrectangulo()
#test_RS()
test_RS_tamano_distinto()
#test_RS_inversa()
#test_variosPasos()
Las ejemplos se basan en la funcin self.dibujar() que dibuja los datos que hay en los campos. Hay diversos tipos
de dibujos intensidad, amplitud, fase, campo, campoReal.
def dibujar(self, tipo = intensidad, logaritmico = False, normalizar = False,\
titulo = " ", nombreArchivo = , dibujar = True, valorCorte = 1):
""" * tipo: intensidad, amplitud, fase, campo, campoReal
* logartimico: True o False
* normalizar: maximo, area, intensidad """
Asimismo es muy sencillo realizar dibujos logaritmicos, simplemente incluyendo True o False en la variable.
Si la variable nombreArchivo no es nula, se guarda un dibujo.
Si la variable normalizar es True el valor mximo del dibujo es la unidad.
Si se incluye un valorCorte, entonces se satura el dibujo al valor determinado.
Otra funcin que tambin es interesante es la de dibujar_perfil, que permite sacar una grfica 1D del camp entre 2
puntos.
def dibujar_perfil(self, punto1=, punto2=, npixels=1000, tipo=intensidad, normalizar=, ord
12.2.1 Introduccin
Para poder realizar tratamientos numricos con haces de luz, lo primero que tenemos que hacer es definirlos. La
clase fuentesXY hereda las propiedades de la clase campoXY. Aade fuentes que se observan en el plano XY.
Para ello hemos desarrollado una clase que contiene distintos tipos de fuentes tales como ondas planas, ondas
esfricas, haces de Gauss, haces de Laguerre, vrtices y Zernikes. Veremos aqu las definiciones y los ejemplos
de utilizacin.
La clase fuentesXY est constituida por un conjunto de funciones. Estas funciones describen distintos tipos de
onda o fuentes de luz en forma de: onda plana, esfrica, haz gaussiano, haz de Laguerre, o aberraciones de Zernike.
En el archivo fuentesXY_ejemplos, se muestra la obtencin de las figuras de cada apartado.
La clase FuentesXY hereda funciones de la clase camposXY, que ms general. No es necesario conocer el funcio-
namiento de esta clase camposXY. Cuando haga falta se har referencia a ella como, por ejemplo, al realizar las
grficas.
A modo de ejemplo veamos como se define y utiliza una fuente:
#definicion de parametros iniciales
tamano = 250 * um
npixels = 256
x0=sp.linspace(-tamano / 2, tamano / 2, npixels)
y0=sp.linspace(-tamano / 2, tamano / 2, npixels)
#Generacion de la clase
campo = fuenteXY(x = x0 , y = y0 , wavelength = 0.6328 * um)
#carga de la onda plana
campo.onda_plana(phi = 2 * grados, theta = 5 * grados)
#dibujar y guardar (si se escribe nombreArchivo)
campo.dibujar(tipo = fase)
Se define una onda plana como aquella que su frente de onda es plano y normal a la velocidad de fase. Son
uno de los tipos de ondas ms habituales en fsica. Y estn definidas en regiones suficientemente alejadas de
fuentes de carga. Su representacin matemtica se realiza mediante funciones armnicas, as sea una onda plana
propagndose en el eje z con amplitud A, frecuencia constante, , y con vector de onda = 2 (sin() sin
+
cos() sin ), la orientacin de los frentes de onda queda definida por dicho vector. De este modo, una onda
plana se expresa como
= .
En rigor, estamos obviando la parte temporal, puesto que a nuestros fines carece de importancia.
En representacin compleja una onda plana se expresa como
(r, ) = (k r)
para poder representar esta ecuacin en muchas posiciones x,y entonces X e Y son matrices generadas como
tamano=100*um
x=sp.linspace(-tamano,tamano, 256)
y=sp.linspace(-tamano,tamano, 256)
X,Y=sp.meshgrid(x,y)
#----------------------------------------------------------------------
# Name: fuentesXY.py
#Author: Luis Miguel Sanchez Brea
# Licence: GPL
#----------------------------------------------------------------------
"""
Clases campoXY y Fuentes2D con las fuentes utilizadas para propagacion
"""
import scipy as sp
import matplotlib.pyplot as plt
import sys
sys.path.append(../)
def test_onda_plana():
"""Generacion de una onda plana"""
test_onda_plana()
plt.show()
100 2.4
1.6
50
0.8
y(m)
0 0.0
0.8
50
1.6
100 2.4
100 50 0 50 100
x(m)
12.2.4 Onda esfrica
De manera anloga a la definicin de onda plana, una onda esfrica es aquella cuyos frentes de onda son superficies
esfricas. Las ecuaciones de Maxwell postulan la existencia de ondas electromagnticas mediante la ecuacin de
ondas. La resolucin en esfricas de esta ecuacin da lugar a ondas esfricas como soluciones a las ecuaciones de
Maxwell. As se puede probar como la magnitud del campo elctrico viene definida mediante
= .
Las ondas esfricas han sido implementadas dentro de la clase fuenteXY mediante la funcin onda_esferica,
como se muestra en el cdigo a debajo. La onda encuentra su fuente de emisin centrada en el punto de coorde-
nadas x0, y0. Debido a que los frentes de onda son crculos concntricos, se ha definido una mscara circular
con el fin de no cortar ningn frente de onda, representando as nicamente los frentes de onda en el interior de
la mscara circular. Esto se logra con el ltimo if del cdigo. Finalmente se muestran las representaciones de la
amplitud y la fase.
En la figura se muestra la mscara de amplitud a la izquierda y a la derecha la fase en el plano XY. Es destacable
el decaimiento de la misma de con la distancia.
amplitud fase
300 300
200 200
100 100
y(m)
y(m)
0 0
100 100
200 200
300 300
300 200 100 0 100 200 300 300 200 100 0 100 200 300
x(m) x(m)
amplitud fase
300 300
200 200
100 100
y(m)
y(m)
0 0
100 100
200 200
300 300
300 200 100 0 100 200 300 300 200 100 0 100 200 300
x(m) x(m)
Un haz gaussiano es aquel en el que cualquier plano normal a la direccin de propagacin a distribucin de
intensidades del campo elctrico se ajusta a una gaussiana. As sea una gaussiana de varianza w, centrada en el
punto (x0,y0). As se define amplitud como
(0 )2 (0 )2
( 2
2
2
2
)
=
Mientras que la fase vale
Esta ltima ecuacin desglosada en fase y amplitud es la que se implementa en la funcin haz_gauss
A continuacin se muestra una representacin del perfil de intensidades para un haz gaussiano.
1.0
400 0.9
0.8
200 0.7
0.6
y(m)
0 0.5
0.4
200 0.3
0.2
400 0.1
Las estructuras tipo vrtice son aquellas en las que la fase se comporta linealmente con la variable angular (en
coordenadas cilndricas), esto es (, , ) = , siendo m el orden del vrtice.
Ahora veremos cmo se puede llamar a esta funcin
y(m)
0 0
100 100
200 200
300 300
300 200 100 0 100 200 300 300 200 100 0 100 200 300
x(m) x(m)
0.00 0.15 0.30 0.45 0.60 0.75 0.90 2.4 1.6 0.8 0.0 0.8 1.6 2.4
Ahora N vrtices
Vortices
(1) (2) (3) (4) (5)
Similarmente a los haces gaussianos se definen los modos de Laguerre como aquellos haces en los que el perfil de
intensidades sigue una distribucin de modo de Laguerre, es decir una distribucin
2
2()
2
() 2
2 +(2++1)() (1) ( ()2 )
/2 22
(, , ) = ( )
()2
La funcin haz_laguerre realiza exactamente este cometido, pero desglosa el producto en pequeos trminos
t1,t2,t3,t4.
As se pueden extraer la amplitud y la fase del haz y ser representadas anlogamente a los casos anteriores.
y(m)
0 0
100 100
200 200
300 300
300 200 100 0 100 200 300 300 200 100 0 100 200 300
x(m) x(m)
0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 2.4 1.6 0.8 0.0 0.8 1.6 2.4
Finalmente mostrados distintos modos de Laguerre para diferentes pares (l,p). Al aumentar l aumenta el nmero
de anillos, as como la intensidad local se reduce si se incrementa p.
(0,0) (1,0)
amplitud (2,0) (3,0)
(0,0) (1,0)
fase (2,0) (3,0)
Los frentes de onda de un haz de luz pueden presentar perturbaciones, debidas a la propia propagacin en el medio
o introducidas por elementos pticos estas perturbaciones reciben el nombre de aberraciones del haz. La forma
ms comn de clasificar las aberraciones es en las llamadas aberraciones de Zernike, las cuales hacen uso de la
base de polinomio que les da nombre, polinomios de Zernike. Estos polinomios estn definidos sobre el crculo
unidad, en trminos de dos variables radial, y acimutal, junto con dos parmetros, (m,n) que representan el
orden del Zernike. As se define si n es par
(, ) = () cos( )
(, ) = () sin( )
Donde
()/2
(1) ( )!
() = 2
! (( + )/2 )! (( )/2 )!
=0
Esto ha sido implementado en la clase fuentesXY mediante la funcin fZernike, con argumentos, n, m y radio
La gran utilidad de los polinomios de Zernike es que permiten expresar cualquier aberracin del frente de ondas
como una suma de trminos . As, si son los coeficientes del polinomio de Zernike, cualquier aberracin
en la fase podr escribirse como
=
Por tanto, haciendo uso de los polinomios definidos con fZernike se determina la aberracin del frente de ondas
calculando la variacin en la fase.
1000
amplitud 1000
fase
500 500
y(m)
y(m)
0 0
500 500
Existen distintos pares (, ) de especial importancia en ptica cuyo trmino de Zernike asociado recibe nombre
propio. Estos son:
(0, 0) Pistn.
(1, 1) Tilt.
(2, 2) Astigmatismo.
(2, 0) Desenfoque.
(4, 0) Aberracin Esfrica.
A continuacin se muestra una representacin en fase y amplitud de las aberraciones ms importantes
(1,-1) (1,1)
circulo() Simula una mscara circular con transmitancia en el interior del crculo.
anillo() Define una mscara anular con transmitancia nicamente en la corona del anillo, no per-
mitiendo el paso de luz ni en el centro ni en el exterior del anillo.
cruz() Simulacin de una mscara con forma de cruz con transmitancia unidad en el interior de la
misma.
dosNiveles() Discretiza una imagen en dos niveles de intensidad definidos.
imagen() Permite modificar algunas propiedades de imgenes tales como normalizar su intensidad,
seleccionar un calar de color, invertir la imagen, entre otros.
escalaGrises() Construye una escala de grises.
lente() Determina la amplitud y la fase de la luz al atravesar una lente.
axicon() Modela una lente tipo axicon.
redForked() Modela una red tipo Forked.
rugosidad() Simula una superficie rugosa.
Las mscaras estn guardados en una clase, muy sencilla, que sirve de repositorio de funciones, cada una de ellas,
rellena la variable self.u que es la matriz donde se almacena la mscara en forma de coeficientes de transmisin
t(x,y).
Adicionalmente a las mscaras, se incluyen 4 operaciones sobre las mscaras (__add__, __sub__, __mul__, __ro-
tar__). Las tres primeras son operaciones son predefinidas de la clase y actuan sobre los simbolos +,-,*.
Las mscaras que se han definido dentro de la clase mascarasXY se muestran a continuacin y representan distintos
tipos de mscaras bidimensionales que habitualmente se emplean en ptica, tales como rendijas, dobles rendijas,
mscaras cuadradas, circulares, anillo, en cruz, entre otras.
La mayora de las mscaras definidas tienen la forma:
def nombre(self, r0, parametros, angulo):
En este caso r0 representa la posicin (x,y) de la mscara, parametros son los parmetros propios de la mscara,
como el tamao, y angulo es la rotacin.
Para facilitar la creacin de nuevas mscaras, se han incluido las operaciones sobre las mscaras __add__,
__sub__, __mul__, __rotar__, ya definidas, las cuales respectivamente, suman, restan multiplican y rotan. Para
la definicin de estas funciones se requiere de la clase macarasXY y camposXY.
Hay otra operacin __rotar__ (no se implementa a travs de un operador) y que se utiliza en las definiciones de
las mscaras para rotarlas.
Sumar Mscaras
En este primer ejemplo veremos la suma de dos mascaras una cuadrada y otra circular. El cdigo para definir
este tipo de mscaras se explica ms abajo. La estructura de la implementacin en python consiste en declarar
las dos mscaras, t1, t2 y posteriormente sumarlas t2=t2+t1. Finalmente se dibujan a fin de obtener una
representacin.
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#------------------------------------
# Autor: Luis Miguel Sanchez Brea
import sys
sys.path.append(../)
from mascarasXY import *
def sumar_mascaras():
ndatos = 128
tamano = 250 * um
x = sp.linspace(-tamano / 2, tamano / 2, ndatos)
y = sp.linspace(-tamano / 2, tamano / 2, ndatos)
wavelength = 0.6328 * um
#Mascara 1
t1 = mascaraXY(x, y, wavelength)
t1.cuadrado(r0 = (-50 * um, 0 * um), size = (50 * um, 50 * um), angulo = 0 * grados)
#Mascara 2
t2 = mascaraXY(x, y, wavelength)
t2.circulo(r0 = (50 * um, 0 * um), radius = (25 * um, 25 * um), angulo = 0 * grados)
#suma
t3 = t2 + t1
#funcion para dibujar varias mascaras a la vez
dibujar_varios_campos(campos=(t1,t2,t3),titulos=(mascara 1,mascara 2, suma))
sumar_mascaras()
plt.show()
En este primer ejemplo incluimos todo el cdigo del archivo. A partir de ahora solo incluiremos la funcin. Es
decir, quitaremos el cabecero, las importaciones necesarias, que en estos ejemplos son
import sys
sys.path.append(../)
from mascarasXY import *
Hay que tener cuidado qu ocurre cuando las dos mscaras solapan: el coeficiente de transmisin no puede ser
superior a 1 (no son medios activos). Si nos fijamos en mascaraXY.__add__ esto est considerado.
Restar Mscaras
Con dos mscaras tambin se puede quitar la parte comn entre ellas. El procedimiento a seguir en python es
anlogo al caso de la suma. Nuevamente las mscaras cuadrada y circular se definirn ms abajo en esta seccin.
Rotar mscaras
En este ejemplo se genera un rectngulo (ya veremos como) y se cambia su orientacin representando as mscaras
rectangulares a 0, 45 y 90 grados. Nuevamente las mscaras cuadrada y circular se definirn ms abajo en esta
seccin.
60
0 grados 60
45 grados 60
90 grados
40 40 40
20 20 20
0 0 0
20 20 20
40 40 40
60 60 60
60 40 20 0 20 40 60 60 40 20 0 20 40 60 60 40 20 0 20 40 60
El uso de la clase mscara se puede ver en el mdulo correspondiente. Aqu pasamos a ver diversas mscaras que
luego se pueden utilizar en difraccin y en otros ejemplos de ptica.
12.3.3 Rendija
Una rendija consiste en una regin del plano de la mscara comprendida entre dos rectas paralelas, tal que en
dicha regin se permite el paso de la luz, fuera de esta zona, la luz no atraviesa la mscara. As dentro de la clase
mascarasXY se ha definido la funcin rendija. En ella se dan de argumentos el centro de la misma x0, la
anchura de la rendija um y el ngulo de inclinacin en grados. El cdigo define dos rectas verticales xmin y max,
cuyo espacio abarcado determina el paso de luz, la rendija. Estas dos rectas son verticales, por ello se aplica la
rotacin para describir la inclinacin de la rendija. Finalmente el if, determina la regin del plano que puede ser
atravesada por la luz.
A modo de ejemplo se muestra la representacin de una rendija con una anchura 100 um.
1.0
100 0.9
0.8
50 0.7
0.6
y(m)
0 0.5
0.4
50 0.3
0.2
100 0.1
Anlogamente con el caso de una rendija, se puede definir una doble rendija como una composicin o suma de dos
rendijas simples. El estudio de dobles rendijas es de vital importancia en ptica constituyendo una de las bases
de la difraccin y a interferometra. Obsrvese como el cdigo Python de la funcin doblerendija consiste en una
suma de dos rendijas simples separadas una distancia definida por el argumento separacin.
As se obtiene un ejemplo de representacin de la doble rendija:
1.0
10 0.9
0.8
5 0.7
0.6
y(m)
0 0.5
0.4
5 0.3
0.2
10 0.1
10 5 0 5 10 0.0
x(m)
12.3.5 Cuadrados y rectngulos
Otro tipo de mscara de amplio uso en ptica son las mscaras cuadradas o rectangulares. Estas mscaras con-
sisten en una regin del espacio comprendida entre cuatro rectas paralelas dos a dos, tales que los ngulos que
forman son todos rectos, de modo que la transmitancia en cualquier punto interior a dicha regin es la unidad. La
implementacin del cdigo de python supone la definicin del centro del cuadrado/rectngulo, as como el tamao
de sus lados. Finalmente se define una rotacin y los puntos de transmitancia unidad.
Su representacin queda as
cuadrado rectangulo
100 100
50 50
0 0
50 50
100 100
100 50 0 50 100 100 50 0 50 100
0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0 0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0
De manera anloga a la mscara cuadrada, se define una mscara circular como aquella que permite el paso de luz
para aquellos rayos que incidan en el interior del crculo o elipse. Para ello se define el origen del crculo con r0
y los semiejes de la elipse radiox y radioy, en caso de ser iguales, se obtiene un crculo. La lnea de cdigo
ipasa = (Xrot - x0) * * 2 / radiusx * * 2 + (Yrot - y0) * * 2 / radiusy * * 2 < 1
circulo elipse
100 100
50 50
0 0
50 50
100 100
100 50 0 50 100 100 50 0 50 100
0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0 0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0
12.3.7 Anillo
Una estructura tipo anillo consiste en dos regiones circulares o elpticas concntricas, tales que el paso de luz
sucede nicamente en la regin comprendida entre ambas. Para su implementacin se definen dos vectores con
dos compontes cada uno, llamados radio1 y radio2 tales que sus componentes representan los semiejes de
las elipses interior y exterior. Nuevamente el ngulo theta describe la inclinacin del anillo. Por tanto se definen
dos crculos o elipses concntricos tales que se permite el paso de luz en su interior, estos estn binarizados, es
una mscara o matriz con 1 en aquellos puntos interior y cero en los exteriores. Para construir la estructura tipo
anillo, se restan ambos crculos (mscaras), de este modo que la corona es la nica regin con unos en su interior.
Como resultado se tiene
50 50
0 0
50 50
100 100
100 50 0 50 100 100 50 0 50 100
0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0 0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0
Tambin se pueden hacer figuras ms interesantes si no se mantiene que el tamao del anillo 2 sea mayor que el
anillo uno, como en el segundo ejemplo, donde
t1.anillo(r0 = (0 * um, 0 * um), radius1 = (50 * um, 100 * um), radius2 = (100 * um, 50 * um), ang
12.3.8 Cruz
Las mscaras tipo cruz se pueden interpretar como la superposicin de dos mscaras tipo cuadrado rotadas entre
s 90 permitiento el paso de luz nicamente en la regin interior a la cruz. Por tanto para la implementacin de
este tipo de mscara, bastar con definir las dos mscaras cuadradas, mediante su origen (comn) r0 y los lados
de cada cuadrado. De este modo se definen t1 y t2 como dos mscaras cuadradas rotadas entre s 90. La suma de
las matrices de cada mscara, da lugar a la mscara de cruz, no obstante hay puntos en la matriz suma t1+t2 con
transmitancia mayor que la unidad por ello en la ltima lnea de cdigo se redefinen todos los puntos con valor
mayor a uno, reescalndolos a la unidad.
As queda representada como
1.0
100 0.9
0.8
50 0.7
0.6
y(m)
0 0.5
0.4
50 0.3
0.2
100 0.1
Esta funcin discretiza una imagen en dos niveles de intensidad definidos por los argumentos nivel1 y nivel2. Esta
discretizacin se hace acorde a un nivel de corte o de referencia, xcorte, de modo que todos aquellos puntos de
la imagen con intensidad menor xcorte adquieren el valor nivel1, as mismo, los niveles mayores a xcorte
son asignados con intensidad nivel2. La estructura del programa realiza este proceso en dos lneas, la primera
crea una matriz de nivel1 con el mismo tamao que la imagen, X. La segunda lnea asigna la intensidad nivel2
a aquellas columnas de la matriz con nivel de intensidad mayor que el nivel de corte, xcorte.
As resulta
0.250
100 0.225
0.200
50 0.175
0.150
y(m)
0 0.125
0.100
50 0.075
0.050
100 0.025
Si no sabemos crear una mscara, o resulta demasiado complicada la podemos dibujar en otro programa, como
Gimp, Inkscape. Entonces la podemos cargar como mscara a travs de la funcin imagen. Para ello necesi-
tamos la librera Image especfica de python para trabajar con imgenes. Posteriormente se carga la imagen
especificada con el argumento nombre, para ello se hace uso de dos funciones especficas cargarImagen y
visualizarimagen, las cuales cargar una imagen desde un archivo con localizacin especfica, y la visuali-
zan respectivamente. No entramos a explicar el funcionamiento de estas dos funciones, estando definidas en una
clase externa imagenesLM, y sin poseer mayor dificultad. Image.open(nombre) abre la imagen pero no la
muestran en pantalla, sino que la almacena como variable im, recurdese que la imagen ya est siendo visualizada,
puesto que se emple visualizarImagen, en la lnea anterior. im.transpose(1), transpone la imagen,
intercambiando filas por columnas. Mediante im.split() se descompone la imagen en colores extrayendo un
array con las componentes RGB de la imagen. Debido a que no interesa el color sino la intensidad, se selecciona la
componente de color canal especificada en el argumento de nuestra funcin imagen con colores[canal].
El resto del programa son if y suponen una serie de condiciones. El primero, cambia el tamao de la imagen
manteniendo la relacin de aspecto permitiendo adems una rotacin de la imagen. Para ello se extraen las di-
mensiones de la imagen y se definen dos arrays para finalmente generar un mallado y aplicar una rotacin. El
siguiente if plantea una inversin de intensidad, ello lo logra restando la intensidad mxima de la imagen menos
la intensidad de la imagen en cada punto y generando as una imagen invertida en intensidades. Finalmente, el
ltimo if, normaliza las intensidades a la unidad.
Veamos un ejemplo de sencillo de cmo cargar una imagen.
1.0
100 0.9
0.8
50 0.7
0.6
y(m)
0 0.5
0.4
50 0.3
0.2
100 0.1
La funcin escalaGrises construye un vector con el nmero de niveles de gris establecidos en el argumento
NumNiveles, con intensidades mxima nivelMax y mnima nivelMin. Para ello se define un vector t de
ceros a fn de generar la estructura de nuestro vector salida, sobre este vector sobrescribiremos los datos finales.
Posteriormente, se define un array, niveles con intensidades entre nivelMin y nivelMax del tamao del vector
x definido en la clase mascarasXY. As mismo, otro vector xpos de nmeros enteros con valores entre 0 y el
entero ms prximo a la longitud de x, con numNiveles + 1 componentes. El objetivo de este vector ser de-
terminar las filas de t a las que se asocia cada nivel de gris. Esto ltimo se logra mediante el bucle for, asociando
a las componentes de t comprendidas entre los valores de dos compontes consecutivas de xpos el valor de gris
especificado.
De este modo se obtiene la figura
1.0
100 0.9
0.8
50 0.7
0.6
y(m)
0 0.5
0.4
50 0.3
0.2
100 0.1
Mediante la funcin lente calculamos la fase y la amplitud de la luz al atravesar una lente con astigmatismo. As
sean f1 y f2 las focales, de modo que la fase, de la luz viene determinada por
As mismo, la transmitancia se supone determinada por la superficie de la lente, la cual modelamos mediante
una mscara circular. Por tanto se define el centro de la lente, con r0 y la focal f1, f2, para definir la mscara
circular/elptica con orientacin determinada por el ngulo especificado en el argumento de la funcin conforme
se describi en la seccin de la mscara crculo. De este modo, queda definida la amplitud mediante la mscara.
Finalmente, para la fase basta implementar la ecuacin anterior.
En los siguientes ejemplos se muestra una representacin de la amplitud y la fase queda
amplitud fase
400 400
200 200
y(m)
y(m)
0 0
200 200
400 400
amplitud fase
400 400
200 200
y(m)
y(m)
0 0
200 200
400 400
12.3.13 Axicn
Un axicn es un tipo particular de lente con superficie cnica. Su funcin principal es la de transformar haces co-
limados en anillos. La funcin axicon con argumentos, radio y altura del cono, as como ndice de refraccin
del vidrio, calcula la intensidad y la fase de la luz al atravesar dicho elemento ptico. As una vez definidos el
origen r0, el vector de onda k y la distancia, r, de la generatriz al eje del cono, se implementa la superficie del
elemento ptico como h en trminos de r. Definida la superficie del axicon, queda imponer una serie de restric-
ciones tales como que la altura, h no puede ser nunca negativa, esto es, el axicon, no se extiende en el espacio
objeto. As mismo, se determina la regin de transmitancia de la luz como aquella en la que incide la luz sobre el
axicon, es decir, nicamente son vlidos los puntos de la base del axicon, r<radius. Finalmente se determina
la fase con la relacin
..:math:: e^{ik(n-1)h}
En el ejemplo se muestra la amplitud y la fase a la salida de un axicon
amplitud fase
100 100
50 50
y(m)
y(m)
0 0
50 50
100 100
100 50 0 50 100 100 50 0 50 100
x(m) x(m)
0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0 2.4 1.6 0.8 0.0 0.8 1.6 2.4
Se muestra cmo desarrollar la espiral de Arqumedes. Resulta un poco complicado entender como se desarrolla
(yo tampoco lo entiendo),
0 0
50 50
0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0 0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0
Esta funcin hace uso de las clases fuentesXY as como de mscaras. Por defecto la
EspiralLaguerreGauss obtiene la espiral en amplitud, salvo que se especifique lo contrario. Se im-
porta la clase fuentesXY, y se genera un haz tipo Laguerre conforme se vio en la seccin de fuentes. A
continuacin definimos el radio del haz que se va a representar siendo este la mitad del cuadrado de represen-
tacin. Resta implementar la espiral, para ello se llama a la clase mascarasXY, y se implemente la funcin
crculo ya definida anteriormente. Posteriormente se extrae la fase con angle y se normalizan las intensidades,
finalmente se realiza un binarizacin. Alternativamente se puede especificar la fase en el argumento de la funcin,
el ltimo if es el encargado de esta tarea.
1.0
100 0.9
0.8
50 0.7
0.6
y(m)
0 0.5
0.4
50 0.3
0.2
100 0.1
amplitud fase
100 100
50 50
y(m)
y(m)
0 0
50 50
100 100
100 50 0 50 100 100 50 0 50 100
x(m) x(m)
0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0 0.0 0.4 0.8 1.2 1.6 2.0 2.4 2.8
Una red tipo Forked es un tipo de mscara binaria de tipo franjas en la que existe una macla, punto en el cual un
conjunto de franjas convergen. Este tipo de red se puede definir mediante el siguiente cdigo.
El resultado es
1.0
100 0.9
0.8
50 0.7
0.6
y(m)
0 0.5
0.4
50 0.3
0.2
100 0.1
La superficies rugosas son de gran importancia prctica en ptica pues muchas de las superficies tienen un cierto
grado de rugosidad. La rugosidad es un proceso aleatorio que se caracteriza a travs de ciertos parmetros como
la altura media y la longitud de correlacin, que puede ser distinta en las direcciones x e y, por los procesos de
fabricacin de las superficies. En el siguiente cdigo se muestra un ejemplo de cmo generar una superficie rugosa
con unos parmetros dados.
La fase y amplitud quedan representadas como sigue
100 2.4
1.6
50
0.8
y(m)
0 0.0
0.8
50
1.6
100 2.4
100 50 0 50 100
x(m)
topografia
1.6
100
1.2
50 0.8
0.4
y(m)
0
0.0
50 0.4
0.8
100
1.2
100 50 0 50 100
x(m)
ejemplos de visualizacin 3D
191
PIMCD2013-python, Publicacin 1.0
13.1 Introduccin
13.2 Programacin
Para el desarrollo de los ejemplos de esta seccin hemos programado numricamente el clculo de esta integral a
partir de 'fast-Fourier-transform based direct integration (FFT-DI) method' segn el artculo de Shen
y Wang 1 . Este algoritmo lo hemos implementado en la clase camposXY (que es heredada por mascarasXY y
fuentesXY) con el nombre de RS (a partir de Rayleigh-Sommerfed, que es una versin ligeramente mejorada de
la integral de Fresnel).
Por consiguiente, si tenemos un campo, mscara o fuente, tendr un mtodo RS que podemos aplicar. Si tenemos
un campo de tamao NxM, el resultado de la propagacin ser tambin NxM, aunque existe un parmetro de
amplificacin que nos permite calcular tamaos del plano de observacin mayores (jN)x(jM).
La ventaja que tiene es que nos devuelve un parametro de calidad que nos informa si la aproximacin se ha
realizado debidamente. Si el parmetro de calidad (almacenado en self.calidad) tiene un valor superior a 1, la
propagacin se ha realizado convenientemente.
def RS(self, z = 10 * mm, newField = True, tipo=z, xout = None, yout = None):
"""Metodo de Fast-Fourier-Transform para la integracion numerica
de la Formula de la difraccion de Rayleigh-Sommerfeld.
Extraido de Applied Optics vol 45 num 6 (1102-1110) - 2006
- z es la distancia (si es <0 se realiza la propagacion inversa
- newfield, si es False el calculo se queda en la instancia, si es True se genera
- xout, yout se utilizan para decir las coordenadas de salida (para la amplificaci
el tamao del pixel debe ser igual, aunque la mscara puede tener distinto tamao
"""
if xout == None:
xout = self.x
if yout == None:
yout = self.y
nx = len(xout); ny = len(yout)
1 Fabin Shen and Anbo Wang "Fast-Fourier-transform based numerical integration method for the RayleighSommerfeld diffraction
#parametro de calidad
dr_real = sp.sqrt(dx ** 2 + dy ** 2)
rmax = sp.sqrt((xout ** 2).max() + (yout ** 2).max())
dr_ideal = sp.sqrt(self.wavelength ** 2 + rmax ** 2 + 2 * self.wavelength * sp.sqr
self.calidad = dr_ideal / dr_real
#siempre que se hace un clculo se informa por consola de la calidad de este.
if(self.calidad > 1):
print Buena aproximacion: factor , self.calidad
else:
print Necesita un muestreo mayor: factor, self.calidad
#matriz computada
W = 1
U = sp.zeros((2 * ny - 1, 2 * nx - 1), dtype = complex)
U[0:ny, 0:nx] = W*self.u #el transpose lo he cambiado porque daba problemas para
xext = x1 - xin[::-1] #da la vuelta
xext = xext[0:-1]
xext = sp.concatenate((xext, self.x - xin1))
yext = y1 - yin[::-1]
yext = yext[0:-1]
yext = sp.concatenate((yext, self.y - yin1))
Xext, Yext = sp.meshgrid(xext, yext)
#los calculos se pueden dejar en la instancia o crear un nuevo campo (ms usual).
if newField == True:
campoSalida = campoXY(self.x, self.y, self.wavelength)
campoSalida.u = Usalida / z
campoSalida.calidad=self.calidad
return campoSalida
else:
self.u = Usalida / z
Todos los clculos realizados en esta seccin sern nmericos, lo cual nos da una gran ventaja computacional:
solamente tenemos que describir la fuente y la mscara, y tendremos el campo difractado a una distancia z.
Como primer ejemplo realizaremos la propagacin en campo cercano de una abertura bidimensional cuadrada.
Utilizaremos este ejemplo para explicar el proceso.
Se definen los parmetros dimensionales de las mscaras y los parmetros pticos (longitud de onda).
Se crea una fuente de iluminacin a travs de la clase fuenteXY().
Se crea una mscara con las dimensiones apropiadas.
Se realiza la Aproximacin de elemento delgado: u2 = u1 * t1
se realiza la propagacin: u3 = u2.RS(z = z_difraccion, newField = True)
Se dibuja el resultado.
import sys
sys.path.append(../)
sys.path.append(../general/)
def difraccion_cuadrado():
#tamano de area de visualizacion
tamano = 100 * um
ndatos = 256
x0 = sp.linspace(-tamano / 2, tamano / 2, ndatos)
y0 = sp.linspace(-tamano / 2, tamano / 2, ndatos)
#longitud de onda
lambda0 = 0.6238 * um
#fuente de iluminacion
u1 = fuenteXY(x = x0, y = y0, wavelength = lambda0);
u1.onda_plana(A = 1, theta = 0 * grados, phi = 0 * grados)
#mascara
radio = 20 * um
t1 = mascaraXY(x = x0, y = y0, wavelength = lambda0)
t1.cuadrado(r0 = (0 * um, 0 * um), size = (60 * um, 60 * um), angulo = 0 * grados)
u2 = u1 * t1
#plano de observacion
z_difraccion = 500*um
dibujar_varios_campos(campos=(u2,u3),titulos=(cuadrado, texto))
difraccion_cuadrado()
plt.show()
cuadrado z=500 m
40 40
20 20
0 0
20 20
40 40
40 20 0 20 40 40 20 0 20 40
0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0 0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0
u2 = u1 * t1
return u2
plt.figure(figsize=(12,6))
num_figuras = len(distancias)
filas = [1, 1, 1, 2, 2, 2, 3, 3, 3, 2, 4, 4, 4, 4, 5, 4]
columnas = [1, 2, 3, 2, 3, 3, 3, 3, 3, 5, 3, 3, 4, 4, 3, 4]
extension=[u2.x[0],u2.x[-1],u2.y[0],u2.y[-1]]
plt.subplot(filas[num_figuras], columnas[num_figuras], 1)
El campo total se genera llamando a las dos funciones secuencialmente, transmitiendo el valor u2 de una a la otra
funcin:
u2=mascara_cuadrado()
difraccion_varias_posiciones(u2, distancias = sp.linspace(25 * um, 2* mm, 5))
plt.show()
Eventualmente, si la distancia de propagacin fuera mucho mayor que la distancia de Fresnel, >> 2 /, el
campo difractado sera la transformada de Fourier del objeto (pues estamos iluminando con onda plana), en este
caso una funcin sinc.
Una mscara de gran importancia en la ptica es la abertura circular. Segn hemos definido la clase mascarasXY,
para determinar el campo generado por la mscara circular, los ejemplos anteriores son completamente vlidos, y
solamente es necesaio intercambiar la funcin de creacin de la mscara
t1.circulo(r0 = (0 * um, 0 * um), radius = (radio, radio))
circulo z=1282 m
40 40
20 20
0 0
20 20
40 40
40 20 0 20 40 40 20 0 20 40
0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0 0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0
1.5
Intensidad
1.0
0.5
40 20 0 20 40
h (perfil)
Para este ejemplo se ha elegido que la distancia sea exactamente la mitad de la distancia de Fresnel
t1.circulo(r0 = (0 * um, 0 * um), radius = (radio, radio))
#distancia de fresnel
z_fresnel = radio ** 2 / lambda0
#plano de observacion
z_difraccion = .5 * z_fresnel
import sys
sys.path.append(../)
sys.path.append(../general/)
plt.figure(figsize=(12,8))
num_figuras = len(distancias)
filas = [1, 1, 1, 2, 2, 2, 3, 3, 3, 2, 4, 4, 4, 4, 5, 4]
columnas = [1, 2, 3, 2, 3, 3, 3, 3, 3, 5, 3, 3, 4, 4, 3, 4]
extension=[u2.x[0],u2.x[-1],u2.y[0],u2.y[-1]]
plt.subplot(filas[num_figuras], columnas[num_figuras], 1)
h1 = plt.imshow(abs(u2.u) ** 2, interpolation = bilinear,
origin = lower, extent = extension)
h1.set_cmap("gist_heat")
plt.title(ucircle)
def mascara_circulo():
tamano = 100 * um
ndatos = 256
num_figuras = 3
z_fresnel = (tamano) ** 2 / lambda0
distancias_difraccion = sp.linspace(25 * um, .25 * z_fresnel, num_figuras)
u2 = u1 * t1
return u2
u2=mascara_circulo()
difraccion_varias_posiciones(u2, distancias = sp.linspace(25 * um, 1* mm, 3))
plt.show()
En este epgrafe se considera como elemento difractor un borde. As se considera como mscara una mscara
binaria, y se calcula la propagacina una distancia de 25 um de la mscara. El proceder es anlogo a una mscara
cuadrada.
#!/usr/local/bin/python
# -*- coding: utf-8 -*-
#------------------------------------
# Autor: Luis Miguel Sanchez Brea
# Fecha 2013/10/24 (version 1.0)
# Licencia: GPL
# Objetivo: Ejemplos de difraccion en campo lejano
#-------------------------------------
import sys
sys.path.append(../)
def difraccion_borde():
#tamano de area de visualizacion
tamano = 100 * um
ndatos = 256
x0 = sp.linspace(-tamano / 2, tamano / 2, ndatos)
y0 = sp.linspace(-tamano / 2, tamano / 2, ndatos)
#longitud de onda
lambda0 = 0.6238 * um
#fuente de iluminacion
u1 = fuenteXY(x = x0, y = y0, wavelength = lambda0);
u1.onda_plana(A = 1, theta = 0 * grados, phi = 0 * grados)
#mascara
#plano de observacion
z_difraccion = 25*um
difraccion_borde()
plt.show()
circulo z=25 m
40 40
20 20
0 0
20 20
40 40
40 20 0 20 40 40 20 0 20 40
0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0 0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0
1.4
1.2
1.0
Intensidad
0.8
0.6
0.4
0.2
15 10 5 0 5 10
h (perfil)
Debido a la difraccin, la luz al propagarse se introduce en la sombra, como se observa en el perfil.
Veamos que ocurre a varias distancias. A medida que nos separamos del borde, ms luz entra en la zona de sombra
y mas perceptibles son los efectos difractivos
#!/usr/local/bin/python
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#------------------------------------
# Autor: Luis Miguel Sanchez Brea
# Fecha 2013/10/24 (version 1.0)
# Licencia: GPL
#-------------------------------------
import sys
sys.path.append(../)
sys.path.append(../general/)
plt.figure(figsize=(12,6))
num_figuras = len(distancias)
filas = [1, 1, 1, 2, 2, 2, 3, 3, 3, 2, 4, 4, 4, 4, 5, 4]
columnas = [1, 2, 3, 2, 3, 3, 3, 3, 3, 5, 3, 3, 4, 4, 3, 4]
plt.subplot(filas[num_figuras], columnas[num_figuras], 1)
h1 = plt.imshow(abs(u2.u) ** 2)
h1.set_cmap("gist_heat")
plt.title(umascara)
def mascara_borde():
tamano = 100 * um
ndatos = 256
x0 = sp.linspace(-tamano / 2, tamano / 2, ndatos)
y0 = sp.linspace(-tamano / 2, tamano / 2, ndatos)
lambda0 = 0.6238 * um
num_figuras = 8
z_fresnel = (tamano) ** 2 / lambda0
distancias_difraccion = sp.linspace(25 * um, .25 * z_fresnel, num_figuras)
u2 = u1 * t1
return u2
u2=mascara_borde()
difraccion_varias_posiciones(u2, distancias = sp.linspace(10 * um, 100* um, 2))
plt.tight_layout()
plt.show()
En este caso el elemento difractor es una doble rendija. Se calcula la propagacin a varias disntancias talesque la
distribucin de intensidad no est en la posicin de la zona clara, sino en la zona opaca, en contradiccin con la
teora geomtrica (cosas que tienen los efectos difractivos), es decir entre las dos rendijas.
#!/usr/local/bin/python
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#------------------------------------
# Autor: Luis Miguel Sanchez Brea
# Fecha 2013/10/24 (version 1.0)
# Licencia: GPL
import sys
sys.path.append(../)
sys.path.append(../general/)
def difraccionDobleRendija():
tamano = 250 * um
numdatos = 128
x0 = sp.linspace(-tamano / 2 , tamano / 2, numdatos)
y0 = sp.linspace(-tamano / 2 , tamano / 2, numdatos)
lambda0 = 0.6238 * um
z = 4 * mm
u2 = u1 * t
u3 = u2.RS(z=z, newField = True)
difraccionDobleRendija()
plt.show()
50 50
0 0
50 50
100 100
100 50 0 50 100 100 50 0 50 100
0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0 0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0
Ntese como aunque la ptica geomtrica predice la no existencia de luz en dicha regin, experimentalmente (en
este caso simulacin) se observa un patrn de intensidad en dicha regin. Este muestra como la difraccin es la
capacidad de la luz para sortear bordes y agujeros.
Otro ejemplo es la difraccin por una lente, de la cual mostramos la intensidad y la fase. Debido a que la lente
se ha suspuesto rotacionalmente simtrica, el patrn de difraccin es perfectamente simtrico. As se muestra un
perfil de intensidad.
#!/usr/local/bin/python
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#------------------------------------
# Autor: Luis Miguel Sanchez Brea
# Fecha 2013/10/24 (version 1.0)
# Licencia: GPL
#-------------------------------------
import sys
sys.path.append(../)
sys.path.append(../general/)
def difraccion_lente():
tamano = 200 * um
numdatos = 256
x0 = sp.linspace(-tamano / 2 , tamano / 2, numdatos)
y0 = sp.linspace(-tamano / 2 , tamano / 2, numdatos)
lambda0 = 0.6238 * um
t = t1 * t2
t.dibujar(tipo = campo)
u3 = u1 * t
u3 = u3.RS(z = 2 * mm, newField = True)
u3.dibujar(tipo = intensidad)
difraccion_lente()
plt.show()
100
amplitud 100
fase
50 50
y(m)
y(m)
0 0
50 50
100 400
350
50 300
250
y(m)
0 200
150
50 100
50
100100 50 0 50 100 0
x(m)
400
300
Intensidad
200
100
0 30 20 10 0 10 20
h (perfil)
13.9 Difraccin por una lente binaria
En este ltimo ejemplo se supone una lente de Fresnel. Este tipo de lentes es puramente difractiva. As se obtiene
#!/usr/local/bin/python
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#------------------------------------
# Autor: Luis Miguel Sanchez Brea
# Fecha 2013/10/24 (version 1.0)
# Licencia: GPL
#-------------------------------------
import sys
sys.path.append(../)
from camposXY import * #@UnusedWildImport
from fuentesXY import fuenteXY
from mascarasXY import mascaraXY
def difraccion_lente_binaria():
tamano = 200 * um
numdatos = 256
x0 = sp.linspace(-tamano / 2 , tamano / 2, numdatos)
y0 = sp.linspace(-tamano / 2 , tamano / 2, numdatos)
lambda0 = 0.6238 * um
t = t1 * t2
t.dibujar(tipo = campo)
u3 = u1 * t
u3 = u3.RS(z = 2 * mm, newField = True)
u3.dibujar(tipo = intensidad)
u3.dibujar_perfil(punto1=(-30*um, 0),punto2=(30*um,0), tipo=intensidad)
difraccion_lente_binaria()
plt.show()
100
amplitud 100
fase
50 50
y(m)
y(m)
0 0
50 50
100
160
140
50
120
100
y(m)
0 80
60
50 40
20
100100 50 0 50 100 0
x(m)
150
Intensidad
100
50
0 30 20 10 0 10 20
h (perfil)
209
PIMCD2013-python, Publicacin 1.0
14.1 Introduccin
2
donde a es el tamao mximo del elemento difractor. Bajo esta aproximacin, el campo difractado se puede
calcular como una integral
2 + 2
(+ 2 )
E(, , ) = E0 (, ) (+) .
E (, ) = (, )E (, ).
La gran ventaja de esta ecuacin es que se puede escribir como una transformada de Fourier, que es una operacin
bastante conocida en matemticas
2 + 2
(+ 2 )
E(, , ) = [E0 (, )] .
Como el primer trmino delante de la transformada de Fourier es casi constante para un plano z determinado, se
suele eliminar.
Vamos a calcular mediante implementacin de cdigo de Python el campo difractado a partir de una mscara
cuadrada. Se observa el perfil con la tpica figura de 2 ()
#!/usr/local/bin/python
# -*- coding: utf-8 -*-
#------------------------------------
# Autor: Luis Miguel Sanchez Brea
# Fecha 2013/10/24 (version 1.0)
# Licencia: GPL
# Objetivo: Ejemplos de difraccion en campo lejano
#-------------------------------------
def difraccion_cuadrado():
#Se carga la clase fuentes
u1 = fuenteXY(x = x0, y = y0, wavelength = lambda0)
#Condicion de onda plana
u1.onda_plana(A = 1, theta = sp.pi / 2, phi = 0 * grados)
#Trabajaremos con la clase mascaras
t1 = mascaraXY(x = x0, y = y0, wavelength = lambda0)
#Mascara cuadrada
t1.cuadrado(r0 = (0 * um, 0 * um), size = (15 * um, 15 * um), angulo = 0 * grados)
#Campo por mascara
u2 = u1 * t1
#Transformada de Fourier
u3 = u2.fft(quitar0 = False)
#Representacion
dibujar_varios_campos(campos=(t1,u3), titulos=(mascara,campo lejano), logaritmico=True
plt.axis([u3.x.min()/3, u3.x.max()/3, u3.y.min()/3, u3.y.max()/3])
punto1=(u3.x.min(),0)
punto2=(u3.x.max(), 0)
u3.dibujar_perfil(punto1,punto2, normalizar=maximo)
difraccion_cuadrado()
plt.show()
1000
100
0 0
100
1000
200
2000
200 100 0 100 200 2000 1000 0 1000 2000
1.0
0.8
Intensidad
0.6
0.4
0.2
En este ejemplo calcular el campo difractado Por una rendija. Es muy parecido al cuadrado, pero en una de las
direcciones colapsa a una lnea, pues la transformada de Fourier de un campo plano (en la direccin y) es una delta
de Dirac.
def difraccion_rendija():
#Clase fuentes
u1 = fuenteXY(x = x0, y = y0, wavelength = lambda0)
#Iluminacion de onda plana
u1.onda_plana(A = 1, theta = sp.pi / 2, phi = 0 * grados)
#Clase mascaras
t1 = mascaraXY(x = x0, y = y0, wavelength = lambda0)
#Rendija
t1.rendija(x0 = 0, size = 5 * um, angulo = 0 * grados)
#Campo transmitido
u2 = u1 * t1
#Campo difractado
u3 = u2.fft(quitar0 = False)
#Representacion
dibujar_varios_campos(campos=(u2, u3),titulos=(mascara, fft),
titulo=tamano, logaritmico = True, normalizar = maximo )
plt.set_cmap("gray")
#perfiles
punto1=(u3.x.min()/2,0)
punto2=(u3.x.max()/2,0)
Tras ejecutar el cdigo se obtiene la mscara y el patrn de intensidades, as mismo se muestra un perfil de
intensidad.
50 5000
0 0
50 5000
100 10000
100 50 0 50 100 10000 5000 0 5000 10000
0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0 0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0
1.0
0.8
Intensidad
0.6
0.4
0.2
Se calcula el campo difractado por una mscara circular. El resultado muestra el perfil con la tpica figura de
02 ().
def difraccion_circulo():
#Clase fuentes
u1 = fuenteXY(x = x0, y = y0, wavelength = lambda0)
#Iluminacion onda plana
u1.onda_plana(A = 1, theta = sp.pi / 2, phi = 0 * grados)
#Clase mascaras
t1 = mascaraXY(x = x0, y = y0, wavelength = lambda0)
#Mascara
t1.circulo(r0 = (0 * um, 0 * um), radius = (15 * um, 15 * um), angulo = 0 * grados)
#Campo transmitido
u2 = u1 * t1
#Campo difractado
u3 = u2.fft(quitar0 = False)
#Representacion
punto1=(u3.x.min()/5,0)
punto2=(u3.x.max()/5,0)
dibujar_varios_campos(campos=(t1,u3), titulos=(mascara,campo lejano), logaritmico=True
plt.axis([u3.x.min()/3, u3.x.max()/3, u3.y.min()/3, u3.y.max()/3])
u3.dibujar_perfil(punto1,punto2, normalizar=maximo)
Tras ejecutar el cdigo se obtiene la mscara y el patrn de intensidades, as mismo se muestra un perfil de
intensidad.
mascara 2000
campo lejano
200
100 1000
0 0
100 1000
200
2000
200 100 0 100 200 2000 1000 0 1000 2000
0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0 0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0
0.8
Intensidad
0.6
0.4
0.2
Se muestra tambin la figura de difraccin de una nica rendija y se observa que es la envolvente de la doble
rendija: doble rendija = difraccin de una rendija + interferencia entre dos rendijas.
def difraccion_doble_rendija():
#Clase fuentes
u1 = fuenteXY(x = x0, y = y0, wavelength = lambda0)
#Iluminacion onda plana
u1.onda_plana(A = 1, theta = sp.pi / 2, phi = 0 * grados)
#Doble rendija
t1 = mascaraXY(x = x0, y = y0, wavelength = lambda0)
t1.dobleRendija(x0 = 0, size = 5 * um, separacion = 20 * um, angulo = 0 * grados)
#Campo transmitido y difractado 1
u2 = u1 * t1
u3 = u2.fft(quitar0 = False)
punto2=(u5.x.max(),0)
h, z_perfil, punto1, punto2=u5.perfil(punto1,punto2)
u3.dibujar_perfil(punto1,punto2, normalizar = maximo)
plt.plot(h,z_perfil/z_perfil.max(),r,lw=2)
plt.legend((doble rendija, una rendija))
plt.xlim(h.min()/3,h.max()/3)
Tras ejecutar el cdigo se obtiene la mscara y el patrn de intensidades, as mismo se muestra un perfil de
intensidad. Ntese como la envolvente del patrn de intensidades en la pantalla es la intensidad de una nica
rendija.
100100 15000
50 0 50 100 1500010000 5000 0 5000 1000015000
0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0 0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0
doble rendija
una rendija
0.8
Intensidad
0.6
0.4
0.2
Las estructuras ms complejas tienen una distribucin en el plano de Fourier tambin ms complejo. En este
ejemplo la mscara ha sido una estrella, esta se ha cargado a partir de una imagen binarizada, por tanto no ha sido
programada o tomada de la clase mscaraXY.
def difraccion_estrella():
u1 = fuenteXY(x = x0, y = y0, wavelength = lambda0)
u1.onda_plana(A = 1, theta = sp.pi / 2, phi = 0 * grados)
t1 = mascaraXY(x = x0, y = y0, wavelength = lambda0)
t1.imagen(nombre=estrella_pequena.png)
u2 = u1 * t1
u3 = u2.fft(quitar0 = False)
dibujar_varios_campos(campos=(u2,u3), titulos=(mascara,fft), \
logaritmico=True, normalizar=maximo)
mascara 3000
fft
200
2000
100
1000
0 0
1000
100
2000
200
3000
200 100 0 100 200 3000 2000 1000 0 1000 2000 3000
0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0 0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0
Las estructuras ms complejas tienen una distribucin en el plano de Fourier tambin ms complejo, este es el
caso de una fotografa real, en la cual debido a los mltiples detalles, la transformada de Fourier se muestra como
un patrn del que podra decirse que carece de orden, sin embargo conserva la informacin de la imagen original.
def difraccion_lena():
u1 = fuenteXY(x = x0, y = y0, wavelength = lambda0)
u1.onda_plana(A = 1, theta = sp.pi / 2, phi = 0 * grados)
t1 = mascaraXY(x = x0, y = y0, wavelength = lambda0)
t1.imagen(nombre=lena.png)
u2 = u1 * t1
u3 = u2.fft(quitar0 = False)
dibujar_varios_campos(campos=(u2,u3), titulos=(mascara,fft), \
logaritmico=True, normalizar=maximo)
mascara 3000
fft
200
2000
100
1000
0 0
1000
100
2000
200
3000
200 100 0 100 200 3000 2000 1000 0 1000 2000 3000
0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0 0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0
La red sinusoidal tiene solamente tres frecuencias espaciales, que son las que se observan en la figura de difraccin.
def difraccion_red_seno():
#tamano de area de visualizacion
tamano = 1000 * um
ndatos = 512
x0 = sp.linspace(-tamano / 2, tamano / 2, ndatos)
y0 = sp.linspace(-tamano / 2, tamano / 2, ndatos)
#longitud de onda
lambda0 = 0.6238 * um
#fuente de iluminacion
u1 = fuenteXY(x = x0, y = y0, wavelength = lambda0);
u1.onda_plana(A = 1, theta = 0 * grados, phi = 0 * grados)
#mascara
t1 = mascaraXY(x = x0, y = y0, wavelength = lambda0)
t1.red_seno(periodo=40*um)
u2 = u1 * t1
u3 = u2.fft(quitar0 = False)
u2.dibujar()
punto1=(u3.x.min(),0)
punto2=(u3.x.max(),0)
1.0
400 0.9
0.8
200 0.7
0.6
y(m)
0 0.5
0.4
200 0.3
0.2
400 0.1
0.8
0.6
Intensidad
0.4
0.2
0.0
La red de Ronchi tiene ms frecuencias espaciales, todas equidistanciadas, que son las que se observan en la figura
2
de difraccin. La altura de cada pico es el cuadrado del valor del coeficiente de Fourier , = | | .
def difraccion_red_ronchi():
#tamano de area de visualizacio
tamano = 1000 * um
ndatos = 512
x0 = sp.linspace(-tamano / 2, tamano / 2, ndatos)
y0 = sp.linspace(-tamano / 2, tamano / 2, ndatos)
#longitud de onda
lambda0 = 0.6238 * um
#fuente de iluminacion
u1 = fuenteXY(x = x0, y = y0, wavelength = lambda0);
u1.onda_plana(A = 1, theta = 0 * grados, phi = 0 * grados)
#mascara
t1 = mascaraXY(x = x0, y = y0, wavelength = lambda0)
t1.red_ronchi( periodo = 40 * um, x0 = 0 * um, fillFactor = 0.5, angulo = 0 * grados)
u2 = u1 * t1
u3 = u2.fft(quitar0 = False)
u2.dibujar()
punto1=(u3.x.min(),0)
punto2=(u3.x.max(),0)
1.0
400 0.9
0.8
200 0.7
0.6
y(m)
0 0.5
0.4
200 0.3
0.2
400 0.1
0.8
0.6
Intensidad
0.4
0.2
0.0
En esta seccin se analizan las propiedades matemticas de la transformada de Fourier, a traves de la observacin
de la misma en el plano de Fourier.
En este epgrafe mostramos como desplazar un elemento difractivo, la distribucin de intensidad es la misma (no
la fase). Esto matemticamente se corresponde con la propiedad:
[ ( )]() = [ ()]()
As queda patente al ejecutar el siguiente cdigo, el cual considera la difraccin por una mscara cuadrada. Las
figuras muestras la mscara y su desplazamiento as como la obsercacin en el plano de Fourier de sendas msca-
ras.
def difraccion_desplazamiento():
u1 = fuenteXY(x = x0, y = y0, wavelength = lambda0)
u1.onda_plana(A = 1, theta = sp.pi / 2, phi = 0 * grados)
t1 = mascaraXY(x = x0, y = y0, wavelength = lambda0)
t1.cuadrado(r0 = (0 * um, 0 * um), size = (15 * um, 15 * um), angulo = 0 * grados)
u2 = u1 * t1
u3 = u2.fft(quitar0 = False)
u4 = u1 * t2
u5 = u4.fft(quitar0=False)
100 100
0 0
100 100
200 200
200 100 0 100 200 200 100 0 100 200
0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0 0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0
6000
x=0 um desplazamiento
6000
x=100*um
4000 4000
2000 2000
0 0
2000 2000
4000 4000
6000 6000
6000 4000 2000 0 2000 4000 6000 6000 4000 2000 0 2000 4000 6000
0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0 0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0
En este epgrafe se considera el mismo elemento difractivo del ejemplo anterior pero aplicndole una rotacin, as
resulta una rotacin de la transformada de Fourier.
def difraccion_rotacion():
u1 = fuenteXY(x = x0, y = y0, wavelength = lambda0)
u1.onda_plana(A = 1, theta = sp.pi / 2, phi = 0 * grados)
t1 = mascaraXY(x = x0, y = y0, wavelength = lambda0)
t1.cuadrado(r0 = (0 * um, 0 * um), size = (15 * um, 15 * um), angulo = 0 * grados)
u2 = u1 * t1
u3 = u2.fft(quitar0 = False)
u4 = u1 * t2
u5 = u4.fft(quitar0=False)
100 100
0 0
100 100
200 200
200 100 0 100 200 200 100 0 100 200
0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0 0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0
0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0 0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0
Si el ngulo del incidencia es variado, la posicin en el plano de Fourier del orden cero de difraccin se ve
desplazada.
#!/usr/local/bin/python
# -*- coding: utf-8 -*-
#------------------------------------
# Autor: Luis Miguel Sanchez Brea
# Fecha 2013/10/24 (version 1.0)
# Licencia: GPL
# Objetivo: Ejemplos de difraccion en campo lejano
#-------------------------------------
sys.path.append(../)
def difraccion_haz_inclinado(haz_incidente):
u1=haz_incidente
t1 = mascaraXY(x = x0, y = y0, wavelength = lambda0)
t1.cuadrado(r0 = (0 * um, 0 * um), size = (15 * um, 15 * um), angulo = 0 * grados)
u2 = u1 * t1
u3 = u2.fft(quitar0 = False)
return u2, u3
plt.show()
0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0 0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0
Se compara la difraccin por un mscara cuadrada bajo dos fuentes de iluminacin, un haz de entrada en primer
lugar considerado una onda plana y en segudno, una onda gaussiana con un tamao comparable al elemento
difractor. El resultado, muestra como en el caso del haz gausiano, la mayor parte de la energa del haz difractado
se concentra en los rdenes ms bajo de difraccin. Mientras que en el caso de una onda plana, la energa est ms
repartida entre los distintos rdenes.
#!/usr/local/bin/python
# -*- coding: utf-8 -*-
#----------------------------------------------------------------------
#!/usr/local/bin/python
# -*- coding: utf-8 -*-
#------------------------------------
# Autor: Luis Miguel Sanchez Breaje
# Fecha 2013/10/24 (version 1.0)
# Licencia: GPL
# Objetivo: Ejemplos de difraccion en campo lejano
#-------------------------------------
def difraccion_rectangulo_onda_plana(haz_incidente):
u1=haz_incidente
u2 = u1 * t1
u2.dibujar(tipo = intensidad, logaritmico = False, normalizar = maximo)
plt.axis([-15*um,15*um,-15*um,15*um])
u3 = u2.fft(quitar0 = False)
return u2, u3
plt.show()
15 1.0
0.9
10
0.8
0.7
5
0.6
y(m)
0 0.5
0.4
5
0.3
0.2
10
0.1
1515 10 5 0 5 10 15 0.0
x(m)
15 1.0
0.9
10
0.8
0.7
5
0.6
y(m)
0 0.5
0.4
5
0.3
0.2
10
0.1
1515 10 5 0 5 10 15 0.0
x(m)
plana fft gauss
6000 6000
4000 4000
2000 2000
0 0
2000 2000
4000 4000
6000 6000
6000 4000 2000 0 2000 4000 6000 6000 4000 2000 0 2000 4000 6000
0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0 0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0
Considrense dos mscaras con la misma topologa pero de distinto tamao. La observacin del haz difractado en
el plano de Fourier cambia de escala, esto es mantiene la misma topologa pero no su tamao.
#!/usr/local/bin/python
# -*- coding: utf-8 -*-
#------------------------------------
def difraccion_tamano(anchura):
u1 = fuenteXY(x = x0, y = y0, wavelength = lambda0)
u1.onda_plana(A = 1, theta = sp.pi / 2, phi = 0 * grados)
t1 = mascaraXY(x = x0, y = y0, wavelength = lambda0)
t1.cuadrado(r0 = (0 * um, 0 * um), size = (anchura,anchura), angulo = 0 * grados)
u2 = u1 * t1
u3 = u2.fft(quitar0 = False)
return t1, u3
fft_pequeno, t1=difraccion_tamano(5*um)
fft_grande, t2 =difraccion_tamano(15*um)
plt.show()
5 m desplazamiento 15 m
6000 6000
4000 4000
2000 2000
0 0
2000 2000
4000 4000
6000 6000
6000 4000 2000 0 2000 4000 6000 6000 4000 2000 0 2000 4000 6000
0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0 0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0
5 m tamano 15 m
200 200
100 100
0 0
100 100
200 200
200 100 0 100 200 200 100 0 100 200
0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0 0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0
Si se considera una misma mscara pero distintas longitudes de onda de luz incidente en el plano de Fourier se
observa que la distribucin de intensidad es la misma, pero no su tamao. Este hecho queda patente en las figuras
ejemplo fruto de ejecutar el cdigo de abajo. Si tuvieran distinta escala se veran diferente.
#!/usr/local/bin/python
# -*- coding: utf-8 -*-
#------------------------------------
# Autor: Luis Miguel Sanchez Breaje
# Fecha 2013/10/24 (version 1.0)
# Licencia: GPL
# Objetivo: Ejemplos de difraccion en campo lejano
#-------------------------------------
import sys
sys.path.append(../)
def difraccion_cuadrado(longitud_onda):
u1 = fuenteXY(x = x0, y = y0, wavelength = longitud_onda)
u1.onda_plana(A = 1, theta = sp.pi / 2, phi = 0 * grados)
t1 = mascaraXY(x = x0, y = y0, wavelength = longitud_onda)
t1.cuadrado(r0 = (0 * um, 0 * um), size = (15 * um, 15 * um), angulo = 0 * grados)
u2 = u1 * t1
u3 = u2.fft(quitar0 = False)
return u3
s1=difraccion_cuadrado(0.405*um)
s2=difraccion_cuadrado(0.6328*um)
dibujar_varios_campos(campos=(s1,s2), titulos=(r$0.405\,\mu m$, r$0.6238\,\mu m$), \
logaritmico=True, normalizar=maximo)
plt.show()
4000
0.405 m 0.6238 m
6000
3000
4000
2000
1000 2000
0 0
1000 2000
2000
4000
3000
4000 6000
4000300020001000 0 1000200030004000 6000 4000 2000 0 2000 4000 6000
0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0 0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0
Redes de Difraccin
233
PIMCD2013-python, Publicacin 1.0
15.1 Introduccin
Podemos definir una red de difraccin como un elemento ptico que modula de forma peridica alguna propiedad
de la luz. Normalmente existen redes de amplitud y de fase, aunque se puede modular de forma peridica cualquier
otra propiedad de la luz, tal como la polarizacin o la coherencia. Como la modulacin se produce de forma
peridica, el anlisis de cmo se comporta la red se puede realizar mediante un anlisis de Fourier, de forma que
la transmitancia se puede describir matemticamente mediante
( )
2
() = exp .
=
Una red sinusoidal es un conjunto de franjas equiespaciadas cuya intensidad puede ser ajustada a una funcin
sinusoidal. La orientacin de las franjas puede ser arbitraria. En la funcin que nos atae su ngulo de inclinacin
aparece en el argumento como angulo. As se llama a la funcin __rotar__ dentro de la clase a fin de rotar
las franjas. Finalmente se implementa la intensidad de las franjas, entre una intensidad mnima amp_min y una
mxima amp_max. La modulacin de la intensidad ha sido definida como
[ ( )]
2( + )
() = + 1 + cos
2
#Definicion de la sinusoidal
self.u = amp_min + (amp_max - amp_min) * (1 + sp.cos(2 * sp.pi * (Xrot + desfase)
import sys
sys.path.append(../)
from mascarasXY import * #@UnusedWildImport
def ejemplo_redSeno():
x = sp.linspace(-250 * um, 250 * um, 512)
y = sp.linspace(-250 * um, 250 * um, 512)
wavelength = 0.6238 * um
periodo = 75 * um
t = mascaraXY(x, y, wavelength)
t.red_seno(periodo= periodo, amp_min=0, amp_max=1,\
desfase=periodo / 2, angulo=0 * grados)
t.dibujar(tipo=intensidad, titulo=red seno)
if __name__ == __main__:
ejemplo_redSeno()
plt.show()
red seno
1.0
200 0.9
0.8
100 0.7
0.6
y(m)
0 0.5
0.4
100 0.3
0.2
200 0.1
1 = 1/2, 0 = 1, 1 = 1/2.
Una red de Ronchi es un conjunto de franjas equiespaciadas tales que los mximos y los mnimos de intensidad
poseen la misma anchura. Para la implementacin de una red de Ronchi se har uso de la clase mascaraXY
as como de la funcin rendija ya vista anteriormente en la seccin mscaras. As en primer lugar tras llamar a la
clase y generar nuestro vector salida, t con ceros a fin de optimizar nuestra funcin se calcula el nmero de franjas,
numperiodos a partir de redondear al entero ms prximo el cociente
donde p es el periodo, x nuestro vector de entrada y xmax y xmin, los mximos y mnimos de x. Finalmente
sumamos 5 con la intencin de tener un nmero de periodos suficientes y no quedarnos cortos debido al redondeo.
Con el fin de definir la anchura de la rendija se multiplica el factor de relleno por el periodo. Para definir las franjas
se llama para cada lnea a la funcin rendija, as es preciso definir un punto de inicio para la implementacin de
las franjas, xinicial siendo este el valor mnimo del vector de entrada menos el valor el puto central, x0.
Finalmente, mediante un bucle for se definen las franjas con inclinacin angulo. Esto se hace superponiendo
nuestro vector de ceros, t, cuyos valores son los mnimos con los mximos que dan lugar del uso de la funcin
rendija.
#Numero de periodos
numperiodos = int(round((self.x.max() - self.x.min()) / periodo + 5))
#Anchura de la rendija
anchuraRendija = fillFactor * periodo;
#Generacion de la red
for i in range(-3, numperiodos + 1):
t2.rendija(xinicial + i * periodo, anchuraRendija, angulo)
t = t + t2
self.u = t.u
La representacin de las franjas es (solo mostramos la funcin, pues el resto es igual al ejemplo anterior)
def ejemplo_redRonchi():
x = sp.linspace(-250 * um, 250 * um, 512)
y = sp.linspace(-250 * um, 250 * um, 512)
wavelength = 0.6238 * um
periodo = 40 * um
t = mascaraXY(x, y, wavelength)
t.red_ronchi(periodo=periodo, x0=20 * um, fillFactor=0.5, angulo=0 * grados)
t.dibujar(tipo=intensidad, titulo=red Ronchi)
red Ronchi
1.0
200 0.9
0.8
100 0.7
0.6
y(m)
0 0.5
0.4
100 0.3
0.2
200 0.1
Una red binaria est constituida por un conjunto de franjas equiespaciadas entre s una distancia determinada, en
este caso, a travs de los parmetros de entrada podemos controlar la amplitud mnima (amin), mxima (max), el
desfase (desfase) y el factor de forma (fillFactor), adems del ngulo de rotacin (angulo)
def red_binaria(self, periodo = 40 * um, amin = 0, amax = 1, desfase = 0 * sp.pi / 2, x0 = 0, fill
#Numero de periodos
numperiodos = int(round((self.x.max() - self.x.min()) / periodo + 5))
#Anchura de la rendija
anchuraRendija = fillFactor * periodo;
#Se define un origen
xinicial = self.x.min() - x0
#Generacion de la red
for i in range(-3, numperiodos):
t2.rendija(xinicial + i * periodo + anchuraRendija, anchuraRendija, angulo
t.u = t.u + amax * t2.u * sp.exp(1.j * desfase)
t2.rendija(xinicial + i * periodo, periodo - anchuraRendija, angulo)
t.u = t.u + amin * t2.u
self.u = t.u
La representacin queda:
def ejemplo_redBinaria():
x = sp.linspace(-250 * um, 250 * um, 512)
y = sp.linspace(-250 * um, 250 * um, 512)
wavelength = 0.6238 * um
t = mascaraXY(x, y, wavelength)
t.red_binaria( periodo = 40 * um, amin=.5, amax=1, desfase=1 * sp.pi / 2,\
x0=0, fillFactor=0.5)
t.dibujar(tipo=campo, titulo=red Binaria)
100 100
y(m)
y(m)
0 0
100 100
200 200
200 100 0 100 200 200 100 0 100 200
x(m) x(m)
0.500.550.600.650.700.750.800.850.900.951.00 0.0 0.2 0.4 0.6 0.8 1.0 1.2 1.4
Los coeficientes de Fourier de una red binaria (que incluye a la red de Ronchi como caso especial son
0 = 1 + 1
( )
= 1 ()
( )
2 4
donde el desfase resulta ser = ( 1) para el caso de transmisin y = ( 1) para el caso de
reflexin.
Normalmente en una red de difraccin convencional la luz difractada se concentra en su mayor parte en el orden
cero. Una red Blazed es un tipo particular de red de difraccin que permite homogeneizar la luz difractada en los
distintos rdenes Esto se logra mediante una red con forma de dientes de sierra. Las redes de difraccin trabajan
bajo determinadas condiciones de iluminacin como es la longitud de onda del haz y el ngulo de incidente, que
en general se supone normal a la red. As para implementar una red Blazed se comienza definiendo el vector de
onda. La definicin de los dientes de sierra de la red se hace mediante el periodo de la red y la altura del diente, el
cociente de estas dos cantidades representa la pendiente de cada diente. La altura en cada punto de la red ser por
tanto, la pendiente de los dientes por la posicin x. La fase viene dado por el camino ptico como se muestra en k
* (indice - 1) * h la cual debe estar normalizada entre 0 y 2, esto se logra con remainder. Dado que
es relativa se fija un origen de referencia, el cual est especificado por el mnimo. Finalmente se devuelve la fase
def red_blazed(self, periodo = 40 * um, altura = 2 * um, indice = 1.5, angulo = 0 * grados
#Vector de onda
k = 2 * sp.pi / self.wavelength
#Inclinacion de las franjas
Xrot, Yrot = self.__rotar__(angulo)
#Calculo de la pendiente
pendiente = altura / periodo
#Calculo de la altura
h = Xrot * pendiente
red blazed
200 2.4
1.6
100
0.8
y(m)
0 0.0
0.8
100
1.6
200 2.4
Una red bidimensional es aquella constituida por un conjunto de franjas verticales y horizontales, tales que per-
mite la transmisin de luz nicamente en dichas franjas. La implementacin es sencilla basta con definir los dos
conjuntos de franjas horizontal y vertical y superponerlas. La superposicin es equivalente a multiplicar las franjas
puesto que cada una es un matriz de ceros (no hay transmisin) y unos (transmisin permitida.
def red2D(self, periodo = 40.*um, amin = 0, amax = 1., desfase = 0.*sp.pi / 2, x0 = 0, fil
#Se inicializa
t1 = mascaraXY(self.x, self.y, self.wavelength);
t2 = mascaraXY(self.x, self.y, self.wavelength);
#Red horizontal
t1.red_binaria(periodo, amin, amax, desfase, x0, fillFactor, angulo)
#Red vertical
t2.red_binaria(periodo, amin, amax, desfase, x0, fillFactor, angulo + 90.*grados)
#Red binaria
self.u = t1.u * t2.u
red 2D
1.0
200 0.9
0.8
100 0.7
0.6
y(m)
0 0.5
0.4
100 0.3
0.2
200 0.1
Como su propio nombre indica una red tipo ajedrez genera un damero con regiones de transmitancia unidad y
nula. Debido a como se ha definido la funcin, se pueden implementar distintos tipos de dameros con regiones de
transmitancia mayores y menores como se muestra en el ejemplo. La implementacin del a funcin es completa-
mente anloga a la de la red bidimensional cambiando nicamente la ltima lnea del cdigo, en la cual en vez de
realizar el producto de las dos matrices, se realiza una funcin xor entre ellas. Esta funcin toda dos argumentos
binarios, y su resultado nicamente nulo cuando los dos argumentos adquieren simultneamente el mismo valor
(0,0), o (1,1), de lo contrario el resultado es la unidad.
def red2D_ajedrez(self, periodo = 40 * um, amin = 0, amax = 1, desfase = 0 * sp.pi / 2,\
x0 = 0, fillFactor = 0.75, angulo = 0 * grados):
#Mismo proceder que en 2D
t1 = mascaraXY(self.x, self.y, self.wavelength);
t2 = mascaraXY(self.x, self.y, self.wavelength);
t1.red_binaria(periodo, amin, amax, desfase, x0, fillFactor, angulo)
t2.red_binaria(periodo, amin, amax, desfase, x0, fillFactor, angulo + 90.*grados)
#Actuacion de la XOR
self.u = sp.logical_xor(t1.u, t2.u)
As resulta la representacin
def ejemplo_redAjedrez1():
x = sp.linspace(-250 * um, 250 * um, 1024)
y = sp.linspace(-250 * um, 250 * um, 1024)
wavelength = 0.6238 * um
periodo = 50 * um
t = mascaraXY(x, y, wavelength)
t.red2D_ajedrez(periodo=periodo, amin=0, amax=1., desfase=0 * sp.pi / 2, x0=0,\
red 1 red 2
200 200
100 100
0 0
100 100
200 200
200 100 0 100 200 200 100 0 100 200
0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0 0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0
Las redes de difraccin tambin pueden tener simetra radial. Son parecidos a los axicones, pero con transmitancia
1 o 0.
def red_radial(self, r0 = (0 * um, 0 * um), periodo = 20 * um, desfase=0*um, radius=400*um
#si solamente hay un numero, es que las posiciones y radios son los mismos para am
if len(r0) == 1:
r0 = (r0[0], r0[0])
#Vector de onda
k = 2 * sp.pi / self.wavelength
x0, y0 = r0
#Distancia de la generatriz al eje del cono
r = sp.sqrt((self.X - x0) ** 2 + (self.Y - y0) ** 2)
#hago un seno y luego binarizo
t = 0.5*(1+sp.sin(2*sp.pi*(r+desfase)/periodo))
if binaria==True:
i0 = t <= 0.5; t[i0] = 0
i1 = t > 0.5; t[i1] = 1
#Region de transmitancia
u = sp.zeros(sp.shape(self.X))
ipasa = r < radius
u[ipasa] = 1
self.u = u * t
As resulta la representacin
def ejemplo_red_radial():
ndatos = 512
tamano = 250 * um
x = sp.linspace(-tamano / 2, tamano / 2, ndatos)
t1 = mascaraXY(x, y, wavelength)
t1.red_radial(r0 = (0 * um, 0 * um), periodo=20*um, desfase=10*um, radius = 100 * um)
t1.dibujar(tipo = intensidad)
1.0
100 0.9
0.8
50 0.7
0.6
y(m)
0 0.5
0.4
50 0.3
0.2
100 0.1
Las redes de difraccin tambin pueden tener simetra angular. El periodo va en grados.
def red_angular(self, r0 = (0 * um, 0 * um), periodo = 20*grados, desfase=0*grados, radius
#si solamente hay un numero, es que las posiciones y radios son los mismos para am
if len(r0) == 1:
r0 = (r0[0], r0[0])
#Vector de onda
k = 2 * sp.pi / self.wavelength
x0, y0 = r0
#Distancia de la generatriz al eje del cono
r = sp.sqrt((self.X - x0) ** 2 + (self.Y - y0) ** 2)
theta=sp.arctan((self.Y - y0)/(self.X - x0))
#Region de transmitancia
t = (1+sp.sin(2*sp.pi*(theta-desfase)/periodo))/2
if binaria==True:
i0 = t <= 0.5; t[i0] = 0
i1 = t > 0.5; t[i1] = 1
u = sp.zeros(sp.shape(self.X))
ipasa = r < radius
u[ipasa] = 1
self.u = u * t
As resulta la representacin
1.0
100 0.9
0.8
50 0.7
0.6
y(m)
0 0.5
0.4
50 0.3
0.2
100 0.1
Este tipo de redes puede tener incidencia para eliminar armnicos en la direccin x
def red_borde_sinusoidal(self, r0 = (0 * um, 0 * um), periodo = 20*grados, lp=10*um, ap=2*
#si solamente hay un numero, es que las posiciones y radios son los mismos para am
#lp es la longitud del periodo del borde, ap es la amplitud del periodo del borde
if len(r0) == 1:
r0 = (r0[0], r0[0])
#Vector de onda
k = 2 * sp.pi / self.wavelength
x0, y0 = r0
#Distancia de la generatriz al eje del cono
r = sp.sqrt((self.X - x0) ** 2 + (self.Y - y0) ** 2)
theta=sp.arctan((self.Y - y0)/(self.X - x0))
#Region de transmitancia
Desfase=desfase+ap*sp.sin(2*sp.pi*self.Y/lp)
t = (1+sp.sin(2*sp.pi*(self.X-Desfase)/periodo))/2
if binaria==True:
i0 = t <= 0.5; t[i0] = 0
i1 = t > 0.5; t[i1] = 1
u = sp.zeros(sp.shape(self.X))
ipasa = r < radius
u[ipasa] = 1
self.u = u * t
1.0
100 0.9
0.8
50 0.7
0.6
y(m)
0 0.5
0.4
50 0.3
0.2
100 0.1
#rotacion de la lente
Xrot, Yrot = self.__rotar__(angulo)
u = sp.zeros(sp.shape(self.X))
ipasa = r < radius
u[ipasa] = 1
self.u = u * t
t1 = mascaraXY(x, y, wavelength)
t1.red_hiperbolica( r0 = (0 * um, 0 * um), periodo = 10*um, desfase=45*grados, radius=200*
t1.dibujar(tipo=intensidad)
100 1.0
0.9
0.8
50
0.7
0.6
y(m)
0 0.5
0.4
0.3
50
0.2
0.1
100100 50 0 50 100 0.0
x(m)
El efecto de las interferencias surge directamente de que las ecuaciones de Maxwell son lineales en los campos
elctricos y magnticos. Supongamos que E1 y E2 son soluciones. Entonces
2
donde a es el tamao mximo del elemento difractor. Bajo esta aproximacin, el campo difractado se puede
calcular como una integral
2 + 2
(+ 2 )
E(, , ) = E0 (, ) (+) .
E (, ) = (, )E (, ).
La gran ventaja de esta ecuacin es que se puede escribir como una transformada de Fourier, que es una operacin
bastante conocida en matemticas
2 + 2
(+ 2 )
E(, , ) = [E0 (, )] .
Como el primer trmino delante de la transformada de Fourier es casi constante para un plano z determinado, se
suele eliminar.
La red sinusoidal tiene solamente tres frecuencias espaciales, que son las que se observan en la figura de difraccin.
def difraccion_red_seno():
#tamano de area de visualizacion
tamano = 1000 * um
ndatos = 512
x0 = sp.linspace(-tamano / 2, tamano / 2, ndatos)
y0 = sp.linspace(-tamano / 2, tamano / 2, ndatos)
#longitud de onda
lambda0 = 0.6238 * um
#fuente de iluminacion
u1 = fuenteXY(x = x0, y = y0, wavelength = lambda0);
u1.onda_plana(A = 1, theta = 0 * grados, phi = 0 * grados)
#mascara
t1 = mascaraXY(x = x0, y = y0, wavelength = lambda0)
t1.red_seno(periodo=40*um)
u2 = u1 * t1
u3 = u2.fft(quitar0 = False)
u2.dibujar()
punto1=(u3.x.min(),0)
punto2=(u3.x.max(),0)
1.0
400 0.9
0.8
200 0.7
0.6
y(m)
0 0.5
0.4
200 0.3
0.2
400 0.1
0.8
0.6
Intensidad
0.4
0.2
0.0
La red de Ronchi tiene ms frecuencias espaciales, todas equidistanciadas, que son las que se observan en la figura
2
de difraccin. La altura de cada pico es el cuadrado del valor del coeficiente de Fourier , = | | .
def difraccion_red_ronchi():
#tamano de area de visualizacio
tamano = 1000 * um
ndatos = 512
x0 = sp.linspace(-tamano / 2, tamano / 2, ndatos)
y0 = sp.linspace(-tamano / 2, tamano / 2, ndatos)
#longitud de onda
lambda0 = 0.6238 * um
#fuente de iluminacion
u1 = fuenteXY(x = x0, y = y0, wavelength = lambda0);
u1.onda_plana(A = 1, theta = 0 * grados, phi = 0 * grados)
#mascara
t1 = mascaraXY(x = x0, y = y0, wavelength = lambda0)
t1.red_ronchi( periodo = 40 * um, x0 = 0 * um, fillFactor = 0.5, angulo = 0 * grados)
u2 = u1 * t1
u3 = u2.fft(quitar0 = False)
u2.dibujar()
punto1=(u3.x.min(),0)
punto2=(u3.x.max(),0)
1.0
400 0.9
0.8
200 0.7
0.6
y(m)
0 0.5
0.4
200 0.3
0.2
400 0.1
0.8
0.6
Intensidad
0.4
0.2
0.0
Para conocer la distribucin de intensidad en campo cercano utilizaremos la aproximacin de Fresnel (ver di-
fraccin en campo cercano), considerando la invariancia de la red de difraccin en el eje . Entonces el campo
difractado se puede calcular a partir de
2
E (, ) = E0 () 2 ()
Resolviendo la integral para la estructura peridica de una red de difraccin, el campo resulta
( ) ( )
E (, ) = exp 2 exp 22 2
2
=
150
5.6
100
4.8
50 4.0
x (microns)
0 3.2
2.4
50
1.6
100
0.8
= 22 /.
zT=2*periodo**2/t.wavelength
X,Z=sp.meshgrid(t.x,z)
periodo=50*um
ordenes=sp.array([-3, -1, 0, 1, 3])
coefs=sp.array([.25, 0.5, 1, 0.5, .25])
red=sp.transpose([ordenes, coefs])
u2=sp.zeros(X.shape,complex)
campoxz=sp.real(u2)
return campoxz
Podemos observar el aspecto de las automgenes simplemente calculando la distribucin de intensidad en campo
cercano mediante la aproximacin de Rayleigh-Sommerfeld. Esto lo hemos hecho para 3 distancias significativas
en la red de Ronchi, , /2 y /4:
efecto talbot
zT zT/2 zT/4
100 100 100
50 50 50
0 0 0
50 50 50
100 100 100
100 50 0 50 100 100 50 0 50 100 100 50 0 50 100
Veamos ahora que ocurre cuando sobre la red de difraccin se incide con un haz gaussiano. Al propagarse la luz,
los distintos rdenes de tamao finito, empiezan a no interferir entre s, al no estar espacialmente en la mismas
posiciones. Entonces, deja de producirse el fenmeno interferencial y tenemos los distintos ordenes aislados. Esto
ocurre en campo cercano, y no solamente cuando estamos muy lejos de la red.
Los sistemas de doble red se utilizan frecuentemente en metrologa ptica, como en deflectometra moir para
medir la topografa 3D de objetos o en sistemas Talbot, Lau o autoimgenes generalizadas para medir desplaza-
mientos con gran precisin.
Veremos ahora algunos efectos de doble red. En el desplazamiento Talbot (movimiento de dos redes cuando es
iluminado con onda plana). Se muestra una animacin
200
100
100
200
Otro efecto interesante es el efecto vernier, donde aparecen franjas cuando a) el periodo de las dos redes es distinto
y b) el ngulo entre las dos redes es distinto.
Se muestra estos dos casos mostrando una imagen y una animacin:
Distinto periodo:
efecto vernier
1000
500
y(m)
500
100
200
300
400
500
0 100 200 300 400 500
Distinto ngulo:
efecto vernier
1000
500
y(m)
500
100
200
300
400
500
0 100 200 300 400 500
Estos dos efectos permiten medir (macroscpicamente) el desplazamiento, puesto que las franjas de vernier (las
400
200
200
400
400
200
200
400
259
PIMCD2013-python, Publicacin 1.0
As mismo se define la funcin de procesamiento, la cual calcula el campo producto del objeto con la ilumi-
nacin. Puesto que se trabaja en el plano focal y en este se obtiene la transformada de Fourier del objeto bajo
un haz colimado, se calcula la transformada de Fourier. Finalmente se aplica el filtro realizando el producto de
la transformada de Fourier por la funcin filtro. Finalmente, se deshace la transformada, para obtener el campo
filtrado.
def procesar(self):
#Campo inicial
campoInicial = self.fuente * self.objeto
self.planoFourier = planoFourier
self.campoFiltrado = campoFiltrado
Resta realizar una representacin de los campos a fin de comprar el incidente y el filtrado, esto se lo hace la funcin
dibujar. As se genera un array de imgenes donde se ubicarn el objeto, su fase, la transformada de Fourier,
el filtro de intensidad, el filtro de fase y finalmente el campo filtrado. As se selecciona la componente del array
donde representar la imagen (objeto, fase, transformada de Fourier...). Finalmente se dibuja con plt, el resto de
comandos determinan el ttulo, los ejes, entre otros.
#objeto intensidad
#Seleccion de la region dela figura donde se pretende representar
plt.subplot(2, 3, 1)
#Intensidad
dibujo = abs(self.objeto.u) ** 2
#Representacion
so=self.objeto
h1 = plt.imshow(dibujo, interpolation = bilinear, aspect = auto,
origin = lower, extent = [so.x.min(), so.x.max(), so.y.min(),\
#Titulo
plt.title(objeto intensidad, fontsize = 18)
#Seleccion del mapa de color
h1.set_cmap("gist_heat") #RdBu
#Los ejes no se representan
plt.axis(off)
#objeto fase
plt.subplot(2, 3, 2)
dibujo = sp.angle(self.objeto.u)
#Representacion
h1 = plt.imshow(dibujo, interpolation = bilinear, aspect = auto,
origin = lower, extent = [so.x.min(), so.x.max(), so.y.min(),\
#Titulo
plt.title(objeto fase, fontsize = 18)
#Seleccion del mapa de color
h1.set_cmap("RdBu") #RdBu
#Los ejes no se representan
plt.axis(off)
#filtro intensidad
plt.subplot(2, 3, 4)
#Intensidad
dibujo = abs(self.filtro.u) ** 2
#Representacion
sf=self.filtro
h1 = plt.imshow(dibujo, interpolation = bilinear, aspect = auto,\
origin = lower, \
extent = [sf.x.min(), sf.x.max(), sf.y.min(), sf.y.max()])
#Titulo
plt.title(filtro intensidad, fontsize = 18)
#Seleccion del mapa de color
h1.set_cmap("gist_heat") #RdBu
#Los ejes no se representan
plt.axis(off)
#filtro fase
plt.subplot(2, 3, 5)
dibujo = sp.angle(self.filtro.u)
#Representacion
h1 = plt.imshow(dibujo, interpolation = bilinear, aspect = auto,
origin = lower, extent = [sf.x.min(), sf.x.max(), sf.y.min(),\
#Titulo
plt.title(filtro fase, fontsize = 18)
#Seleccion del mapa de color
h1.set_cmap("RdBu") #RdBu
#Los ejes no se representan
plt.axis(off)
#planoFourier
plt.subplot(2, 3, 3)
dibujo = sp.log(abs(self.planoFourier.u) ** 2 + 1)
#Representacion
pf=self.planoFourier
h1 = plt.imshow(dibujo, interpolation = bilinear, aspect = auto,
origin = lower, extent = [pf.x.min(), pf.x.max(), pf.y.min(),\
#campoFiltrado
plt.subplot(2, 3, 6)
dibujo = sp.fliplr(sp.flipud(abs(self.campoFiltrado.u) ** 2))
#Representacion
cf=self.campoFiltrado
h1 = plt.imshow(dibujo, interpolation = bilinear, aspect = auto,
origin = lower, extent = [cf.x.min(), cf.x.max(), cf.y.min(),\
#Titulo
plt.title(campo Filtrado, fontsize = 18)
#Seleccion del mapa de color
h1.set_cmap("gist_heat") #RdBu
#Los ejes no se representan
plt.axis(off)
if not nombreArchivo == :
plt.savefig(nombreArchivo, dpi = 100, bbox_inches = tight,\
pad_inches = 0.1)
Un filtro pasa es aquel que atena las altas frecuencias y permitiendo nicamente el paso de las bajas frecuencias.
De este modo, un filtro pasa baja conserva los detalles ms generales de la imagen, eliminando los pequeos
detalles. Esto se logra en el plano de Fourier diafragmando los mayores rdenes de difraccin, por ser estos los
correspondientes a altas frecuencias. En las imgenes de plano Fourier y filtro intensidad se puede apreciar este
hecho. La abertura del filtro de intensidad se ubica en el plano de Fourier, atravesando el filtro las bajas frecuencias.
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#------------------------------------
# Autor: Luis Miguel Sanchez Brea
# Fecha 2013/10/24 (version 1.0)
# Licencia: GPL
#-------------------------------------
"""Simulaciones relacionadas con la leccion de filtrado optico"""
#Tamano
tamano = 1000 * um
x0 = sp.linspace(-tamano/2 * um, tamano/2 * um, 512)
y0 = sp.linspace(-tamano/2 * um, tamano/2 * um, 512)
#Definicion de la fuente
fuente1 = fuenteXY(x=x0, y=y0)
fuente1.onda_plana(A=1, theta=0*grados, phi=0*grados)
if __name__ == __main__:
test_filtroPasaBaja()
plt.show()
Una aplicacin interesante del filtro pasa baja es la eliminacin de ruido en una imagen. Para comprobarlo, toma-
mos la foto de lena.png y aadimos un ruido aleatorio.
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#------------------------------------
# Autor: Luis Miguel Sanchez Brea
# Fecha 2013/10/24 (version 1.0)
# Licencia: GPL
#-------------------------------------
"""Simulaciones relacionadas con la leccion de filtrado optico"""
tamano = 1000 * um
x0 = sp.linspace(-tamano/2 * um, tamano/2 * um, 512)
y0 = sp.linspace(-tamano/2 * um, tamano/2 * um, 512)
def test_filtroEliminarRuido():
#Definicion de la fuente
fuente1 = fuenteXY(x=x0, y=y0)
fuente1.onda_plana(A=1, theta=0*grados, phi=0*grados)
#Definicion del objeto
objeto = mascaraXY(x=x0, y=y0)
objeto.imagen(nombre=lena.png, normalizar=True, canal=0, tamanoImagen=False, invertir=Fa
objeto.u=objeto.u+sp.rand(len(x0),len(y0))
#Definicion del filtro
filtro = mascaraXY(x=x0, y=y0)
filtro.circulo(r0=(0*um,0*um), radius=(50*um,50*um), angulo=0*grados)
#Campo filtrado, procesado de la imagen
p1=procesadoOptico(fuente1, objeto, filtro)
p1.dibujar2(idfigs=(1,0,2,3,0,4))
p1.dibujarCampoFiltrado()
test_filtroEliminarRuido()
plt.show()
Este tipo de filtro es el opuesto al filtro pasa baja, conserva las altas frecuencias y atena las bajas. De este modo,
los detalles ms gruesos de la imagen ser pierden, pero los pequeos se mantienen. Por ejemplo un conjunto de
franjas equiespaciadas muy separadas entre s, se atenuaran respecto de otro conjunto de franjas poco espaciadas
entre s. La consecucin de este tipo de filtro se logra tapando los rdenes ms bajos de difraccin en el plano de
Fourier, atravesando nicamente el filtro, los ms altos. Nuevamente, vase la imagen, como el plano de Fourier el
filtro de intensidad tapa dichos rdenes, de modo que el campo filtrado muestra los pequeos detalles de la imagen
(altas frecuencias).
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#------------------------------------
# Autor: Luis Miguel Sanchez Brea
# Fecha 2013/10/24 (version 1.0)
# Licencia: GPL
#-------------------------------------
"""Simulaciones relacionadas con la leccion de filtrado optico"""
import sys
sys.path.append(../)
from procesadoOptico import *
from fuentesXY import fuenteXY
from mascarasXY import mascaraXY
#Tamano
tamano = 1000 * um
x0 = sp.linspace(-tamano/2 * um, tamano/2 * um, 512)
y0 = sp.linspace(-tamano/2 * um, tamano/2 * um, 512)
def test_filtroPasaAlta():
#Definicion de la fuente
fuente1 = fuenteXY(x=x0, y=y0)
fuente1.onda_plana(A=1, theta=0*grados, phi=0*grados)
#Definicion del Objeto
objeto = mascaraXY(x=x0, y=y0)
objeto.imagen(nombre=lena.png, normalizar=True, canal=0, tamanoImagen=False, invertir=Fa
#Definicion del filtro
filtro = mascaraXY(x=x0, y=y0)
filtro.circulo(r0=(0*um,0*um), radius=(50*um,50*um), angulo=0*grados)
filtro.inversaAmplitud()
#Campo filtrado, procesado de la imagen
p1=procesadoOptico(fuente1, objeto, filtro)
p1.dibujar2(idfigs=(1,0,2,3,0,4))
p1.dibujarCampoFiltrado()
test_filtroPasaAlta()
plt.show()
tamano = 1000 * um
x0 = sp.linspace(-tamano/2 * um, tamano/2 * um, 512)
y0 = sp.linspace(-tamano/2 * um, tamano/2 * um, 512)
def test_filtroPasaAlta2():
#Definicion de la fuente
fuente1 = fuenteXY(x=x0, y=y0)
fuente1.onda_plana(A=1, theta=0*grados, phi=0*grados)
#Definicion del bjeto
objeto = mascaraXY(x=x0, y=y0)
objeto.cuadrado(r0=(0,0), size=(250*um,250*um), angulo=45*grados)
#Definicion del filtro
filtro = mascaraXY(x=x0, y=y0)
filtro.circulo(r0=(0*um,0*um), radius=(40*um,40*um), angulo=0*grados)
filtro.inversaAmplitud()
#Campo filtrado, procesamiento de la imagen
p1=procesadoOptico(fuente1, objeto, filtro)
p1.dibujar2(idfigs=(1,0,2,3,0,4))
p1.dibujarCampoFiltrado()
test_filtroPasaAlta2()
plt.show()
Los filtros pasa banda se ubican entre los filtros pasa alta y los filtros pasa baja, permitiendo nicamente el paso de
frecuencias dentro de una banda espectral, filtrando las altas y las bajas frecuencias. Para ello, se bloquean en el
plano de Fourier los bajos y altos rdenes de difraccin, as el filtro de intensidad tendr forma de corona circular,
siendo los puntos interiores a la corona, aquellos que permiten en paso de luz.
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#------------------------------------
# Autor: Luis Miguel Sanchez Brea
# Fecha 2013/10/24 (version 1.0)
# Licencia: GPL
#-------------------------------------
"""Simulaciones relacionadas con la leccion de filtrado optico"""
tamano = 1000 * um
x0 = sp.linspace(-tamano/2 * um, tamano/2 * um, 512)
y0 = sp.linspace(-tamano/2 * um, tamano/2 * um, 512)
test_filtroPasaBanda()
plt.show()
Un filtro de contraste de fase potencia las diferencias de fase entre las distintas regiones del objeto. Para ello se
ilumina el objeto con luz colimada y se introduce una lmina/anillo desfasador posterior al sistema de iluminacin,
el objetivo de este anillo es retardar la fase de la luz.
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#------------------------------------
# Autor: Luis Miguel Sanchez Brea
# Fecha 2013/12/10 (version 1.5) - dibujar 2
# Licencia: GPL
#-------------------------------------
"""Simulaciones relacionadas con la leccion de filtrado optico"""
def filtroContrasteFase():
#Definicion de la fuente
fuente1 = fuenteXY(x=x0, y=y0)
fuente1.onda_plana(A=1, theta=0*grados, phi=0*grados)
#Definicion del objeto
objeto = mascaraXY(x=x0, y=y0)
objeto.imagen(nombre=lena.png, normalizar=True, canal=0, tamanoImagen=False, invertir=Fa
objeto.setFase(q=1, fase_min=0, fase_max=sp.pi)
#Definicion del filtro
filtro = mascaraXY(x=x0, y=y0)
filtro.circulo(r0=(0*um,0*um), radius=(4*um,4*um), angulo=0*grados)
filtro.setFase(q=1, fase_min=0, fase_max=sp.pi)
#Campo filtrado y procesado de la imagen
p1=procesadoOptico(fuente1, objeto, filtro)
p1.dibujar2(idfigs=(0,1,2,0,3,4))
p1.dibujarCampoFiltrado()
filtroContrasteFase()
plt.show()