/*
 * dicharge.java    Plots emission line spectra of elements from tables
 *                  of emission line wavelength and line strength
 * INPUT :  filename of element emission line wavelengths/strengths table
 *          and various other applet parameters (see below)
 * OUTPUT:  Color encoded spectra simulating a gas discharge plasma
 *
 *  by John Talbot Friday June 13, 1997
 */
import java.applet.*;
import java.awt.*;
import java.io.*;
import java.net.*;
public class discharge extends Applet
{

int spectraWidth,spectraHeight;
Color spectra[]=new Color[1280];

public void init()
{
  int count=0;
  double wavelength[]=new double[200];
  double strength[]=new double[200];
  Dimension d=size();        // size of applet window
  spectraWidth=d.width;
  spectraHeight=d.height;
  String element=getParameter("element");
  if(element==null)
    element="neon.txt";

  double startWavelength=ourParameter("startWavelength",4000);
  double endWavelength=ourParameter("endWavelength",7000);
  double lineWidth=ourParameter("lineWidth",1);
  double contrast=ourParameter("contrast",10);
  double continuum=ourParameter("continuum",0.3);

  // Read element emission line file
  try
  {
    URL lines=new URL(getCodeBase()+element);
    if(lines!=null)
    {
      InputStream elementStream=lines.openConnection().getInputStream();
      if(elementStream!=null)
      {
        StreamTokenizer tokens = new StreamTokenizer(elementStream);
        while(tokens.nextToken()!=tokens.TT_EOF)
        {
        wavelength[count]=tokens.nval;
        tokens.nextToken();
        strength[count]=tokens.nval;
        if(count++>199) break;
        }
      }
    }
  }
  catch(IOException e) {}

  // compute spectra intensity array
  double intensity[]=new double[spectraWidth];
  double dwave=(endWavelength-startWavelength)/spectraWidth;
  double lineWidth2=lineWidth*lineWidth;
  double wave,sum,delta;
  double maxs=-1e23;
  for(int i=0;i<spectraWidth;i++)
  {
    wave=i*dwave+startWavelength;
    sum=0;
    for(int j=0;j<count;j++)   // sum gaussian emission line profile for all lines
    {
      delta=wavelength[j]-wave;
      sum=sum+strength[j]*Math.exp(-delta*delta/lineWidth2);
    }
    intensity[i]=sum;
    if(sum>maxs) maxs=sum;
  }

  if(maxs==0) {
     maxs=1;
  }
  double scale=(1-continuum)*contrast/maxs;

  // Interpolate color array to obtain spectra
  int RED  = 1;
  int GREEN= 2;
  int BLUE = 3;

  // chosen points in the color array spectra
  double colors[][] = {{   0.0/255,        0,   0,   8},
                         {48.0/255,        0,   0, 255},
                         {96.0/255,        0, 255, 255},
                        {128.0/255,        0, 255,   0},
                        {160.0/255,      255, 255,   0},
                        {207.0/255,      255,   0,   0},
                        {255.0000001/255,  8,   0,   0} };
  double dw,fraction;
  for(int i=0;i<spectraWidth;i++)
  {
     wave=i*dwave + startWavelength;
     dw=(wave-4000)/(7000-4000);
     if(dw<0)
       dw=0;
     else if(dw>1)
       dw=1;
     int k=0;
     while(dw>colors[++k][0]) {}

     fraction=(dw-colors[k-1][0])/(colors[k][0]-colors[k-1][0]);
     double wavRed  =fraction*(colors[k][RED]  -colors[k-1][RED])  +colors[k-1][RED];
     double wavGreen=fraction*(colors[k][GREEN]-colors[k-1][GREEN])+colors[k-1][GREEN];
     double wavBlue =fraction*(colors[k][BLUE] -colors[k-1][BLUE]) +colors[k-1][BLUE];

     double plot=continuum+scale*intensity[i];
     if(plot>1) plot=1;
     spectra[i]=new Color((int)(plot*wavRed), (int)(plot*wavGreen), (int)(plot*wavBlue));
  }

		//{{INIT_CONTROLS
		setLayout(null);
		addNotify();
		resize(640,64);
		//}}
}

public void paint(Graphics g)
{
  for(int i=0;i<spectraWidth;i++)
  {
     g.setColor(spectra[i]);
     g.drawLine(i,0,i,spectraHeight-1);
  }
}

public double ourParameter(String label, double defaultValue)
{
  String valueString=getParameter(label);
  Double value;
  if(valueString!=null)
    try {
       value = new Double(valueString);
    } catch (NumberFormatException e) {
       value = new Double(defaultValue);
    }
  else
    value=new Double(defaultValue);
  return value.doubleValue();
}

public String[][] getParameterInfo() {
  String[][] info = {
  // Parameter Name     Kind of Value  Description
    {"element",         "String",      "element filename"},
    {"startWavelength", "double",      "starting wavelength in Angstroms (default 4000)"},
    {"endWavelength",   "double",      "ending wavelength in Angstroms (default 7000)"},
    {"lineWidth",       "double",      "emission line spectral width in Angstroms"},
    {"contrast",        "double",      "contrast boost faint line if required (default 1)"},
    {"continuum",       "double",      "blackbody background continuum (default 0 up to 1)"}
  };
  return info;
}    
	//{{DECLARE_CONTROLS
	//}}
}

