pyFresnel - A library for calculating various optical properties of dielectric
interfaces. There are classes for a simple interface, for an etalon/slab of material
and a transfer matrix module for calculating the transmiision and reflection
from a stack of dielectric layers.

Author - Robert Steed
Date - 10th Dec 2012
Email - rjsteed@talk21.com
License - GPL

Requirements - numpy, matplotlib

######################

There are many such thin films codes in existance but this library can also calculate
emission and reflection for a uniaxial layers under the condition that the layer's
optical axis is perpendicular to the plane of the slab. This is useful for certain
types of semiconductor structures and in my case, the intersubband transitions
of quantum wells.

These modules are for people who are happy to program in python, they rely on python's
flexibility with regard to types and so the inputs are not rigorously checked for
correctness (this is not a good example of rigorous programming). Despite that, 
the code works pretty well and I have striven instead to write code that can be 
easily understood.

Each module contains example code that demonstrates the modules in action. There
are more examples in the examples directory, they use the module init.py to find
the pyFresnel modules in case you have chosen not to install the package into your 
python site-packages directory.



Summary:

fresnel.py 
Interface(n1=1.0,n2=1.0,theta=0.0)

materials.py 
See module for defined classes

optical_plate.py 
Plate(n1,d,w,theta,n0=1.0,n2=1.0)

effective_medium.py 
EffectiveMedium(layers) where layers is a tuple of either tuples like (n,thickness (m))
or tuples like (nzz,nxx,thickness (m)) or Layer objects from transfer_matrix.py.
EffectiveMedium_eps(layers) where layers is a tuple of tuples like (epszz, epsxx, thickness (m))

uniaxial_plate.py
AnisoInterface(n1o=1.0,n1e=1.0,n2o=1.0,n2e=1.0,theta=0.0)
AnisoPlate(n1o,n1e,d,w,theta,n0=1.0,n2=1.0)

uniaxial_plate2.py
AnisoPlate(n_xx,n_zz,d,w,theta,n_b=1.0)
AnisoPlate_eps(eps_xx,eps_zz,d,w,theta,eps_b=1.0)


transfer_matrix.py
Contains 6 classes Layer, LayerUniaxial, Layer_eps, LayerUniaxial_eps, Filter_base and Filter. 
See the file for a description of usage.

layer_types.py
material types (basically materials.py adjusted for transfer_matrix compatability)

incoherent_transfer_matrix.py
Contains IncoherentFilter (based on Filter_base) - to mix coherent and incoherent filters use this as the top class.


Briefly:

fresnel.py 
contains the class Interface for modelling dielectric interfacees. We can 
instantiate this class using Interface(n1=1.0,n2=1.0,theta=0.0) where n1 is the
initial refractive index, n2 is the final refractive index and theta is the 
angle of incidence in radians.

materials.py 
contains classes for different dielectric constants. The main class is Material
but this shouldn't be directly instantiated, this contains the methods to 
calculate the dielectric constant or the refractive index. There is a subtle
issue regarding whether to use natural or real frequencies. Natural frequencies
are 2*pi* real frequency and they crop up all of the time in physics. In some of
the models, one or other may be implicitly assumed but I will try to have left 
some comments when this happens. Look at the file to see the materials defined.

optical_plate.py 
contains the Plate class for modelling the transmission or reflection of a slab
of dielectric material. We can create an object of this class using 
Plate(n1,d,w,theta,n0=1.0,n2=1.0) where n0 is the refractive index before, n1 
is the refractive index of the plate/slab/layer, n2 is the refractive index 
after the plate, d is the thickness of the plate, w is the natural frequency
and theta is the angle in radians.

effective_medium.py 
contains two classes for calculating an effective dielectric for a stack of thin 
layers under the assumption that the layer thicknesses are all much less than 
the wavelength of the light considered. The main class is EffectiveMedium(layers)
where layers is a tuple of tuples like (n,thickness (m)) or tuples like 
(nzz,nxx,thickness (m)) or Layer objects from transfer_matrix.py. The other class 
is EffectiveMedium_eps(layers) where layers is a tuple of tuples like 
(epszz, epsxx, thickness (m)).

uniaxial_plate.py
contains 2 classes, AnisoInterface and AnisoPlate. These allow us to model
an interface or a plate which has an uniaxial medium under the rather limiting
condition that the uniaxial medium has its optical axis perpendicular to the 
interface. We call these classes using
AnisoInterface(n1o=1.0,n1e=1.0,n2o=1.0,n2e=1.0,theta=0.0)
AnisoPlate(n1o,n1e,d,w,theta,n0=1.0,n2=1.0)
where n1o and n2o are the ordinary refractive indices, n1e and n2e are the
extraordinary refractive indices and the other quantities are as before. For
AnisoPlate, the refractive indices are the media before and after the 
layer\slab\plate are assumed to isotropic.

uniaxial_plate2.py
contains a class AnisoPlate that is very similar to the class in uniaxial_plate
but comes from a different derivation. It is called using
AnisoPlate(n_xx,n_zz,d,w,theta,n_b=1.0) or
AnisoPlate_eps(eps_xx,eps_zz,d,w,theta,eps_b=1.0)
eps_zz is the dielectric constant perpendicular to plate's sides, equivalent to
the extraordinary refractive index squared, while eps_xx is the dielectric 
constant for electric fields parallel to the plate's sides which is equivalent 
to the ordinary refractive index squared. This code doesn't allow us to 
separately set the properties of the medium either side of the plate, instead 
we use eps_b to set the dielectric constant of media either side of the plate.

transfer_matrix.py
Contains 3 classes Layer, LayerUniaxial and Filter. See the file for a 
description of usage.


