package dmrgvisu2;
/*
 *  dmrgvisu2, the DMRG-Applet.
 *  Copyright (C) 2010 - 2011 Thomas Koehler, created on 11.10.2011.
 *
 *  This program is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation; either
 *  version 2.1 of the License, or (at your option) any later version.
 * 
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 * 
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this program; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *  If you modify or optimize the code in a useful way please let me know.
 *  pcknow@gmx.de
 *
 */
import info.monitorenter.gui.chart.axis.AxisLinear;
import info.monitorenter.gui.chart.Chart2D;
import info.monitorenter.gui.chart.controls.LayoutFactory;
import info.monitorenter.gui.chart.events.Chart2DActionSaveImageSingleton;
import info.monitorenter.gui.chart.io.ADataCollector;
import info.monitorenter.gui.chart.io.RandomDataCollectorOffset;
import info.monitorenter.gui.chart.rangepolicies.RangePolicyMinimumViewport;
import info.monitorenter.gui.chart.rangepolicies.RangePolicyFixedViewport;
import info.monitorenter.gui.chart.traces.Trace2DSimple;
import info.monitorenter.gui.chart.traces.Trace2DLtd;
import info.monitorenter.gui.chart.traces.Trace2DReplacing;
import info.monitorenter.gui.chart.traces.painters.TracePainterDisc;
import info.monitorenter.gui.chart.traces.painters.TracePainterLine;
import info.monitorenter.gui.chart.traces.painters.TracePainterVerticalBar;
import info.monitorenter.gui.chart.views.ChartPanel;
import info.monitorenter.gui.chart.Chart2D.ToolTipType;
import info.monitorenter.util.Range;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

import java.beans.*; //Property change stuff
import java.awt.*;
import java.awt.event.*;

import java.util.Dictionary;
import java.util.Hashtable;

import java.text.DecimalFormat;

import java.applet.*;
import javax.swing.*;

import javax.swing.BorderFactory;
import javax.swing.border.Border;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JApplet;
import javax.swing.JTextArea;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JDialog;
import javax.swing.JSlider;
import javax.swing.JLabel;
import javax.swing.JComboBox;
import javax.swing.border.TitledBorder;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

public final class visu extends JApplet implements Runnable
{ 
	private static final long serialVersionUID = 1L;
	final class ControlPanel extends JPanel 
	{
		private static final long serialVersionUID = 1L;

		/** Slider für die Größe des Systems */
		private JSlider m_SiteSlider;		
		public JTextArea m_SiteText;		
		
		/** Slider für die Größe von h */
		private JSlider m_hSlider;
		public JTextArea m_hText;

		/** Slider für die maximale Größe von d */
		private JSlider m_dSlider;
		public JTextArea m_dText;
		
		/** Slider für die Anzahl der Sweeps */
		private JSlider m_SweepsSlider;
		public JTextArea m_SweepText;		

		/** Start/Pause-Button */
		public JButton m_startStop;		
		
		/** One-Step-Button */
		public JButton m_step;	
		
		/** Clear-Button */
		private JButton m_clear;
		
		/** Reset-Button */
		private JButton m_reset;
		
		/** Hamilton-Dialog-Button */
		private JButton m_setH;

		/** Hamilton-Dialog-Button */
		private JButton m_exit;
		
		protected ControlPanel() 
		{
			this.setBackground(Color.WHITE);
			
			// Erzeugen der einzelnen Kontrollfelder
			this.createStepButton();
			this.createStartStopButton();
			this.createClearButton();
			this.createResetButton();
			this.createSetHButton();
			this.createExitButton();
			this.createSiteText();
			this.createSiteSlider();
			this.createdText();
			this.createdSlider();			
			this.createSweepText();
			this.createSweepsSlider();
			
			// Layouting: Vertikale Anordnung der Slider
			JComponent SliderBox = new JPanel();								// Box in der alle Slider enthalten sind
			SliderBox.setBackground(Color.WHITE);
			SliderBox.setLayout(new BoxLayout(SliderBox, BoxLayout.X_AXIS));
			this.setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
			SliderBox.add(this.m_SiteSlider);
			SliderBox.add(this.m_dSlider);
			SliderBox.add(this.m_SweepsSlider);
			this.add(SliderBox);
			
			JComponent TextBox = new JPanel();									// Box für die Textausgabe
			TextBox.setBackground(Color.WHITE);
			TextBox.setLayout(new BoxLayout(TextBox, BoxLayout.X_AXIS));
			TextBox.add(Box.createHorizontalGlue());
			TextBox.add(this.m_SiteText);
			TextBox.add(Box.createHorizontalGlue());
			TextBox.add(this.m_dText);
			TextBox.add(Box.createHorizontalGlue());
			TextBox.add(this.m_SweepText);
			this.add(TextBox);
			
			JComponent StartStepBox = new JPanel();							// Box für den Start/Pause- und den Step-Button
			StartStepBox.setBackground(Color.WHITE);
			StartStepBox.setLayout(new BoxLayout(StartStepBox, BoxLayout.X_AXIS));
			StartStepBox.add(Box.createHorizontalGlue());
			StartStepBox.add(this.m_startStop);
			StartStepBox.add(Box.createHorizontalGlue());
			StartStepBox.add(this.m_step);
			StartStepBox.add(Box.createHorizontalGlue());
			StartStepBox.add(this.m_clear);
			this.add(StartStepBox);
			
			JComponent ClearResetBox = new JPanel();
			ClearResetBox.setBackground(Color.WHITE);
			ClearResetBox.setLayout(new BoxLayout(ClearResetBox, BoxLayout.X_AXIS));
			ClearResetBox.add(Box.createHorizontalGlue());
			ClearResetBox.add(this.m_setH);
			ClearResetBox.add(Box.createHorizontalGlue());
			ClearResetBox.add(this.m_reset);
			ClearResetBox.add(Box.createHorizontalGlue());
			ClearResetBox.add(this.m_exit);
			this.add(ClearResetBox);
			
		}

		private void createdSlider()
		{
			this.m_dSlider = new JSlider(JSlider.VERTICAL, 1, 32, visu.this.d_max);
			this.m_dText.setText(""+visu.this.d_max);
			this.m_dSlider.setBackground(Color.WHITE);
			this.m_dSlider.setMajorTickSpacing(4);
			this.m_dSlider.setMinorTickSpacing(1);
			this.m_dSlider.setSnapToTicks(true);
			this.m_dSlider.setPaintLabels(true);
			this.m_dSlider.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), "d_max", TitledBorder.LEFT, TitledBorder.BELOW_TOP));
			this.m_dSlider.setPaintTicks(true);

			this.m_dSlider.addChangeListener
			(
				new ChangeListener() 
				{
					public void stateChanged(final ChangeEvent e) 
					{
						JSlider source = (JSlider) e.getSource();
						if (!source.getValueIsAdjusting()) 
						{
							int value = source.getValue();
							visu.this.d_max = value;
							visu.this.conPan.m_dText.setText(""+value);
							visu.this.stopData();
							visu.this.clearTrace();
							visu.this.resetDMRG();
							visu.this.conPan.m_startStop.setText("start");
						}
					}
				}
			);

		}

		private void createSweepsSlider() 
		{
			this.m_SweepsSlider = new JSlider(JSlider.VERTICAL, 1, 100, visu.this.Sweeps);
			this.m_SweepText.setText(""+visu.this.Sweeps);
			this.m_SweepsSlider.setBackground(Color.WHITE);
			this.m_SweepsSlider.setMajorTickSpacing(10);
			this.m_SweepsSlider.setMinorTickSpacing(1);
			this.m_SweepsSlider.setSnapToTicks(true);
			this.m_SweepsSlider.setPaintLabels(true);
			this.m_SweepsSlider.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), "Sweeps", TitledBorder.LEFT, TitledBorder.BELOW_TOP));
			this.m_SweepsSlider.setPaintTicks(true);
			this.m_SweepsSlider.addChangeListener
			(
				new ChangeListener() 
				{
					public void stateChanged(final ChangeEvent e) 
					{
						JSlider source = (JSlider) e.getSource();
						if (!source.getValueIsAdjusting()) 
						{
							int value = source.getValue();
							visu.this.Sweeps = value;
							visu.this.conPan.m_SweepText.setText(""+value);
							visu.this.stopData();
							visu.this.clearTrace();
							visu.this.resetDMRG();
							visu.this.conPan.m_startStop.setText("start");
						}
					}
				}
			);
		}
		
		private void createSiteSlider() 
		{
			this.m_SiteSlider = new JSlider(JSlider.VERTICAL, 2, 102, visu.this.Site);
			this.m_SiteText.setText(""+visu.this.Site);
			this.m_SiteSlider.setBackground(Color.WHITE);
			this.m_SiteSlider.setMajorTickSpacing(5);
			this.m_SiteSlider.setMinorTickSpacing(1);
			this.m_SiteSlider.setSnapToTicks(true);
			this.m_SiteSlider.setPaintLabels(true);
			this.m_SiteSlider.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), "Sites", TitledBorder.LEFT, TitledBorder.BELOW_TOP));
			this.m_SiteSlider.setPaintTicks(true);
			this.m_SiteSlider.addChangeListener
			(
				new ChangeListener() 
				{
					public void stateChanged(final ChangeEvent e) 
					{
						JSlider source = (JSlider) e.getSource();
						if (!source.getValueIsAdjusting()) 
						{
							int value = source.getValue();
							visu.this.Site = value;
							visu.this.conPan.m_SiteText.setText(""+value);
							visu.this.stopData();
							visu.this.clearTrace();
							visu.this.resetDMRG();
							visu.this.conPan.m_startStop.setText("start");
						}
					}
				}
			);
		}	

		private void createClearButton() 
		{
			this.m_clear = new JButton("clear");
			this.m_clear.setBackground(Color.WHITE);
			this.m_clear.addActionListener
			(
				new ActionListener() 
				{
					public void actionPerformed(final ActionEvent e) 
					{
						visu.this.clearTrace();
					}
				}
			);
		}

		private void createResetButton() 
		{
			this.m_reset = new JButton("reset");
			this.m_reset.setBackground(Color.WHITE);
			this.m_reset.addActionListener
			(
				new ActionListener() 
				{
					public void actionPerformed(final ActionEvent e) 
					{
						visu.this.stopData();
						visu.this.clearTrace();
						visu.this.resetDMRG();
					}
				}
			);
		}		
		
		private void createStepButton() 
		{
			this.m_step = new JButton("step");
			this.m_step.setBackground(Color.WHITE);
			this.m_step.addActionListener
			(
				new ActionListener() 
				{
					public void actionPerformed(final ActionEvent e) 
					{
						JButton source = (JButton) e.getSource();
						if (!visu.this.getEnergyCollector().isRunning()) 
						{
							visu.this.m_energy_trace.addPoint(visu.this.getEnergyCollector().collectData());
						} 
						source.invalidate();
						source.repaint();
					}
				}
			);
		}
		
		private void createStartStopButton() 
		{
			this.m_startStop = new JButton("start");
			this.m_startStop.setBackground(Color.WHITE);
			this.m_startStop.addActionListener
			(
				new ActionListener() 
				{
					public void actionPerformed(final ActionEvent e) 
					{
						JButton source = (JButton) e.getSource();
						if (visu.this.getEnergyCollector().isRunning()) 
							visu.this.stopData();
						else 
							visu.this.startData();
						source.invalidate();
						source.repaint();
					}
				}
			);
		}
		
		private void createSetHButton() 
		{
			this.m_setH = new JButton("Set H");
			this.m_setH.setBackground(Color.WHITE);
			this.m_setH.addActionListener
			(
				new ActionListener() 
				{
					public void actionPerformed(final ActionEvent e) 
					{
						visu.this.stopData();
						visu.this.clearTrace();
						hamCon SetHDialog = new hamCon(visu.this.J, visu.this.Jy, visu.this.D, visu.this.hx, visu.this.hz, visu.this.selection);
						SetHDialog.setModal(true);
						SetHDialog.setVisible(true);
						if (SetHDialog.OK)
						{
							visu.this.selection = SetHDialog.selection;
							if (SetHDialog.selection == 0)
							{
								visu.this.J = SetHDialog.J1;
								visu.this.Jy = SetHDialog.Jy1;
								visu.this.D = SetHDialog.D1;
								visu.this.hx = SetHDialog.hx1;
								visu.this.hz = SetHDialog.hz1;
							}
							else
							{
								visu.this.J = SetHDialog.J2;
								visu.this.Jy = SetHDialog.Jy2;
								visu.this.D = SetHDialog.D2;
								visu.this.hx = SetHDialog.hx2;
								visu.this.hz = SetHDialog.hz2;
							}
						}	
						visu.this.resetDMRG();
					}
				}
			);
		}	
		
		private void createExitButton() 
		{
			this.m_exit = new JButton("Exit");
			this.m_exit.setBackground(Color.WHITE);
			this.m_exit.addActionListener
			(
				new ActionListener() 
				{
					public void actionPerformed(final ActionEvent e) 
					{
						visu.this.stop();
						System.exit(0);
					}
				}
			);
		}
		
		private void createSiteText() 
		{
			this.m_SiteText = new JTextArea("0");
			this.m_SiteText.setMaximumSize(new Dimension(200, this.m_clear.getMaximumSize().height));
			this.m_SiteText.setEditable(false);
			this.m_SiteText.setBackground(Color.WHITE);
			this.m_SiteText.setBorder(BorderFactory.createEtchedBorder());
		}

		private void createdText() 
		{
			this.m_dText = new JTextArea("0");
			this.m_dText.setMaximumSize(new Dimension(200, this.m_clear.getMaximumSize().height));
			this.m_dText.setEditable(false);
			this.m_dText.setBackground(Color.WHITE);
			this.m_dText.setBorder(BorderFactory.createEtchedBorder());
		}
		
		private void createSweepText() 
		{
			this.m_SweepText = new JTextArea("0");
			this.m_SweepText.setMaximumSize(new Dimension(200, this.m_clear.getMaximumSize().height));
			this.m_SweepText.setEditable(false);
			this.m_SweepText.setBackground(Color.WHITE);
			this.m_SweepText.setBorder(BorderFactory.createEtchedBorder());
		}		
		
	}

	public static void main(String[] args)
	{
		JFrame frame = new JFrame("DmrgShow");
		visu show = new visu();
		show.init();
		show.frame = frame;
		frame.getContentPane().add(show);
		frame.setSize(1024, 600);
		frame.addWindowListener
		(
			new WindowAdapter() 
			{
				@Override
				public void windowClosing(final WindowEvent e) 
				{
					System.exit(0);
				}
			}
		);
		frame.setVisible(true);	
	}
	
	Thread thread;
	
	public static JFrame frame;
	
	/** Energie-Chart */
	protected Chart2D m_energy_chart;
	private transient ADataCollector m_energy_collector;		// Energie-Data-Collector
	private Trace2DSimple m_energy_trace;						// Energie-Trace
	private Trace2DLtd m_energy_pos_trace;						// Energie-Position-Trace
	
	/** DichteMatrix-Chart */
	protected Chart2D m_dm_chart;
	private Trace2DSimple m_dm_trace;							// DichteMatrix-Trace
	
	/** Erwartungswert-Chart */
	protected Chart2D m_erw_chart;
	private Trace2DSimple m_erw_sx_trace;						// Erwartungswert-Trace
	private Trace2DSimple m_erw_sz_trace;						// Erwartungswert-Trace
	private Trace2DLtd m_erw_pos_trace;							// Erwartungswert-Position-Trace
	
	/** Entanglement-Entropy-Chart */
	protected Chart2D m_ee_chart;
	private Trace2DSimple m_ee_trace;							// ?-Trace

	/** Hauptvariablen */
	public int Site;											// Anzahl der Sites
	public int Sweeps;											// Maximale Anzahl der auszuführenden Sweeps
	public double J;											// 
	public double Jy;
	public double D;											// 
	public double hx;											// 
	public double hz;											// 
	public int selection;										//
	
	public Dmrg DmrgRef;										// Referenz auf ein Dmrg-Objekt (dort wird die gesamte Rechnung durchgeführt)
	public int d_max;
	
	/** Panels */
	public ControlPanel conPan;									// Komplettes Control-Panel
	public ChartPanel energychartpanel;							// Panel für die Energieausgabe
	public ChartPanel dmchartpanel;								// Panel für die Dichtematrixausgabe
	public ChartPanel erwchartpanel;							// Panel für die Erwartungswertausgabe
	public ChartPanel eechartpanel;								// Panel für die ?-ausgabe
	
	/** Textausgaben */
	public JTextArea EnergyText;								// Energieausgabe
	public JTextArea SweepText;									// Sweepausgabe
	
	/** Operatoren */
	public Matrix s_plus;
	public Matrix s_minus;
	public Matrix s_x;
	public Op sx;
	public Matrix s_y;
	public Matrix s_z;
	public Op sz;
	public Matrix I;
	public Mpo mpo_sz;
	public Mpo mpo_sx;
	
	/** Hamilton-Matrix */
	public MatrixMatrix H;
	
	public visu() 
	{
		super();
	}
	
	@Override
	public void destroy() 
	{
		super.destroy();
	}	
	
	@Override
	public void start() 
	{
		thread = new Thread(this);
		thread.start();
	}

	@Override
	public void stop() 
	{
		// running = false;
		super.stop();
	}	
	
	public void run() 
	{
	}	
	
	@Override
	public void init() 
	{
		super.init();
		this.setSize(new Dimension(1024, 600));
		int d=2;			// Anfangs-Groesse der Matrizen
		int s=2;			// Anzahl der möglichen Zustände
		
		/** Setzen der wesentlichen Variablen. Werden nur für die Initialisierung gebraucht. */
		String text;
		if((text=getParameter("sites"))==null)	// Wenn der Parameter nicht von der einbindenden Webseite kommt...
			this.Site = 5;		// Laenge der Kette (Anzahl der Sites)
		else
			this.Site = Integer.parseInt(text);
		if((text=getParameter("sweeps"))==null)	// Wenn der Parameter nicht von der einbindenden Webseite kommt...
			this.Sweeps = 50;	// Anzahl der Sweeps
		else
			this.Sweeps = Integer.parseInt(text);
		if((text=getParameter("d_max"))==null)	// Wenn der Parameter nicht von der einbindenden Webseite kommt...
			this.d_max = 8;		// Maximale Groesse der Matrizen
		else
			this.d_max = Integer.parseInt(text);
		
		if((text=getParameter("J"))==null)	// Wenn der Parameter nicht von der einbindenden Webseite kommt...
			this.J = 1.0;
		else
			this.J = Double.parseDouble(text);
		if((text=getParameter("Jy"))==null)	// Wenn der Parameter nicht von der einbindenden Webseite kommt...
			this.Jy = 1.0;
		else
			this.Jy = Double.parseDouble(text);
		if((text=getParameter("D"))==null)	// Wenn der Parameter nicht von der einbindenden Webseite kommt...
			this.D = 1.0;
		else
			this.D = Double.parseDouble(text);
		if((text=getParameter("hx"))==null)	// Wenn der Parameter nicht von der einbindenden Webseite kommt...
			this.hx = 1.0;
		else
			this.hx = Double.parseDouble(text);
		if((text=getParameter("hz"))==null)	// Wenn der Parameter nicht von der einbindenden Webseite kommt...
			this.hz = 1.0;
		else
			this.hz = Double.parseDouble(text);
		if((text=getParameter("selection"))==null)	// Wenn der Parameter nicht von der einbindenden Webseite kommt...
			this.selection = 0;
		else
			this.selection = Integer.parseInt(text);

		// Erzeugen der Operatoren
		this.s_plus = new Matrix(2,2);
		this.s_minus = new Matrix(2,2);
		this.s_z = new Matrix(2,2);
		this.s_y = new Matrix(2,2);
		this.s_x = new Matrix(2,2);
		this.I = new Matrix(2,2);
			
		this.s_plus.SetContent(1,0,1.0);
		this.s_minus.SetContent(0,1,1.0);
		this.s_z.SetContent(0,0,0.5);
		this.s_z.SetContent(1,1,-0.5);
		this.s_x.SetContent(0,1,0.5);
		this.s_x.SetContent(1,0,0.5);
		this.s_y.SetContent(0,1,-0.5);
		this.s_y.SetContent(1,0,0.5);
		this.I.SetContent(0,0,1);
		this.I.SetContent(1,1,1);
	
		
		this.mpo_sx=new Mpo(this.Site, s, 1);
		this.mpo_sz=new Mpo(this.Site, s, 1);
		this.sz = new Op(this.Site);
		this.sx = new Op(this.Site);

		// Erzeugen der Hamilton-Matrix
		this.H = new MatrixMatrix(5,5);
		for (int i=0; i<5; i++)
			for (int j=0; j<5; j++)
				H.SetContent(i,j,new Matrix(2,2));

		this.H.SetContent(0,0,I);
		this.H.SetContent(0,3,s_z);
		this.H.SetContent(0,4,s_x.mult(this.hx).add(s_z.mult(this.hz)));
		this.H.SetContent(3,4,s_z.mult(this.D));
		this.H.SetContent(4,4,I);
		
		if (this.selection == 0)
		{
			this.H.SetContent(0,1,s_plus);
			this.H.SetContent(0,2,s_minus);
			this.H.SetContent(1,4,s_minus.mult(this.J/2.0));
			this.H.SetContent(2,4,s_plus.mult(this.Jy/2.0));
		}
		else
		{
			this.H.SetContent(0,1,s_x);
			this.H.SetContent(0,2,s_y);
			this.H.SetContent(1,4,s_x.mult(this.J));
			this.H.SetContent(2,4,s_y.mult(this.Jy*(-1.0)));
		}	
	
		Mpo OpH = new Mpo(H, this.Site, s, d);
		Mps psi = new Mps(this.Site, d, d_max, s, OpH);
		// Erzeugen der Berechnungsumgebung
		this.DmrgRef = new Dmrg(psi, OpH, this);
		
		// Energy-Chart Setup
		{
			this.setEnergyChart(new Chart2D());
			this.getEnergyChart().setPaintLabels(false);
			this.getEnergyChart().getAxisX().setPaintGrid(true);
			this.getEnergyChart().getAxisY().setPaintGrid(true);		
			this.getEnergyChart().getAxisX().setRangePolicy(new RangePolicyFixedViewport(new Range(0.0, this.Site-1)));
			this.getEnergyChart().getAxisX().setStartMajorTick(false);
			this.getEnergyChart().getAxisX().setMajorTickSpacing(1.0);
			this.getEnergyChart().getAxisX().setMinorTickSpacing(1.0);
			this.getEnergyChart().getAxisX().getAxisTitle().setTitle("Site");
			this.getEnergyChart().getAxisY().getAxisTitle().setTitle("Energy");
			this.getEnergyChart().setPaintLabels(false);
			this.getEnergyChart().setGridColor(Color.LIGHT_GRAY);
			this.getEnergyChart().setToolTipType(Chart2D.ToolTipType.VALUE_SNAP_TO_TRACEPOINTS);
			this.setEnergyTrace(new Trace2DSimple());
			this.setEnergyPosTrace(new Trace2DLtd(2));
			this.getEnergyPosTrace().setStroke(new BasicStroke(2));
			this.getEnergyPosTrace().setName("Current Site");
			this.getEnergyTrace().setTracePainter(new TracePainterDisc());
			this.getEnergyTrace().setName("");
//			this.getEnergyTrace().setPhysicalUnits("Site", "Energy");
			this.getEnergyTrace().setColor(Color.RED);
//			this.getEnergyTrace().
			this.getEnergyChart().addTrace(this.getEnergyTrace());
			this.getEnergyChart().addTrace(this.getEnergyPosTrace());
		}
		// DichteMatrix-Chart Setup
		{
			this.setDmChart(new Chart2D());
			this.getDmChart().getAxisX().setPaintGrid(true);
			this.getDmChart().getAxisY().setPaintGrid(true);
			this.getDmChart().getAxisY().setRangePolicy(new RangePolicyFixedViewport(new Range(0.0, 1.0)));
			this.getDmChart().getAxisX().setRangePolicy(new RangePolicyFixedViewport(new Range(0.0, d_max-1)));
			this.getDmChart().getAxisX().setMajorTickSpacing(1.0);
			this.getDmChart().getAxisX().getAxisTitle().setTitle("Priority");
			this.getDmChart().getAxisY().getAxisTitle().setTitle("s^2");
			this.getDmChart().setGridColor(Color.LIGHT_GRAY);
			this.setDmTrace(new Trace2DSimple());
			this.getDmTrace().setTracePainter(new TracePainterVerticalBar(12, this.getDmChart()));
			this.getDmTrace().setName("");
//			this.getDmTrace().setPhysicalUnits("Priority", "s^2");
			this.getDmTrace().setColor(Color.RED);
			this.getDmChart().addTrace(this.getDmTrace());
		}
		// Erwartungswert-Chart Setup
		{
			this.setErwChart(new Chart2D());
			this.getErwChart().getAxisX().setPaintGrid(true);
			this.getErwChart().getAxisY().setPaintGrid(true);
			this.getErwChart().getAxisX().setRangePolicy(new RangePolicyFixedViewport(new Range(0.0, this.Site-1)));
			this.getErwChart().getAxisX().setMajorTickSpacing(1.0);	
			
			this.getErwChart().getAxisX().getAxisTitle().setTitle("Site");
			this.getErwChart().getAxisY().getAxisTitle().setTitle("Expectation-value");
			
			this.getErwChart().setGridColor(Color.LIGHT_GRAY);
			this.getErwChart().setToolTipType(Chart2D.ToolTipType.VALUE_SNAP_TO_TRACEPOINTS);
			this.setErwSxTrace(new Trace2DReplacing());
			this.getErwSxTrace().setTracePainter(new TracePainterDisc());
			this.getErwSxTrace().setName("Expectation-value of S_x");
			this.getErwSxTrace().setColor(Color.RED);
			this.getErwChart().addTrace(this.getErwSxTrace());
			this.setErwSzTrace(new Trace2DReplacing());
			this.getErwSzTrace().setTracePainter(new TracePainterDisc());
			this.getErwSzTrace().setName("Expectation-value of S_z");
			this.getErwSzTrace().setColor(Color.BLUE);
			this.getErwChart().addTrace(this.getErwSzTrace());
			this.setErwPosTrace(new Trace2DLtd(2));
			this.getErwPosTrace().setStroke(new BasicStroke(2));
			this.getErwPosTrace().setName("Current Site");

			this.getErwChart().addTrace(this.getErwPosTrace());
		}
		// Entropy-Chart Setup
		{
			this.setEeChart(new Chart2D());
			this.getEeChart().getAxisX().setPaintGrid(true);
			this.getEeChart().getAxisY().setPaintGrid(true);		
			this.getEeChart().getAxisX().setRangePolicy(new RangePolicyFixedViewport(new Range(0.5, this.Site-1.5)));
			this.getEeChart().getAxisX().setMajorTickSpacing(1.0);
			this.getEeChart().getAxisX().getAxisTitle().setTitle("Site-change");
			this.getEeChart().getAxisY().getAxisTitle().setTitle("Entropy");
			this.getEeChart().setGridColor(Color.LIGHT_GRAY);
			this.getEeChart().setToolTipType(Chart2D.ToolTipType.VALUE_SNAP_TO_TRACEPOINTS);
			this.setEeTrace(new Trace2DSimple());
			this.getEeTrace().addTracePainter(new TracePainterLine());
			this.getEeTrace().addTracePainter(new TracePainterDisc());
			this.getEeTrace().setName("");
//			this.getEeTrace().setPhysicalUnits("Location", "Entropy");
			this.getEeTrace().setColor(Color.RED);
			this.getEeChart().addTrace(this.getEeTrace());
		}
		
		// Layouting: Horizontale Anordnung der Panels		
		Container content = this.getContentPane();
		content.setLayout(new BoxLayout(content, BoxLayout.X_AXIS));		
		
		JComponent Output = new JPanel();
		Output.setBackground(Color.WHITE);
		Output.setLayout(new BoxLayout(Output, BoxLayout.Y_AXIS));
		
		JComponent Charts = new JPanel();
		JComponent ChartsLeft = new JPanel();
		JComponent ChartsRight = new JPanel();
		JPanel ChartEn = new JPanel();
		JPanel ChartDm = new JPanel();
		JPanel ChartEr = new JPanel();
		JPanel ChartEe = new JPanel();
		// Erzeugung der Panels
		{
			Charts.setBackground(Color.WHITE);
			Charts.setLayout(new BoxLayout(Charts, BoxLayout.X_AXIS));
			
			ChartsLeft.setBackground(Color.WHITE);
			ChartsLeft.setLayout(new BoxLayout(ChartsLeft, BoxLayout.Y_AXIS));
			
			ChartsRight.setBackground(Color.WHITE);
			ChartsRight.setLayout(new BoxLayout(ChartsRight, BoxLayout.Y_AXIS));

			ChartEn.setBackground(Color.WHITE);
			ChartEn.setLayout(new BoxLayout(ChartEn, BoxLayout.Y_AXIS));
			ChartDm.setBackground(Color.WHITE);
			ChartDm.setLayout(new BoxLayout(ChartDm, BoxLayout.Y_AXIS));
			ChartEr.setBackground(Color.WHITE);
			ChartEr.setLayout(new BoxLayout(ChartEr, BoxLayout.Y_AXIS));
			ChartEe.setBackground(Color.WHITE);
			ChartEe.setLayout(new BoxLayout(ChartEe, BoxLayout.Y_AXIS));

			
			energychartpanel = new ChartPanel(this.getEnergyChart());
			JLabel EnText = new JLabel("Energy Chart");//, JLabel.CENTER);
			EnText.setFont(new Font(null, 0, 24));
			ChartEn.add(EnText);
			ChartEn.add(Box.createHorizontalGlue());
			ChartEn.add(energychartpanel);
			ChartsLeft.add(ChartEn);
			ChartsLeft.addPropertyChangeListener(energychartpanel);
			
			erwchartpanel = new ChartPanel(this.getErwChart());
			JLabel ErText = new JLabel("Expectation-value Chart");//, JLabel.CENTER);
			ErText.setFont(new Font(null, 0, 24));
			ChartEr.add(ErText);
			ChartEr.add(Box.createHorizontalGlue());
			ChartEr.add(erwchartpanel);
			ChartsRight.add(ChartEr);
			ChartsRight.addPropertyChangeListener(erwchartpanel);

			
			dmchartpanel = new ChartPanel(this.getDmChart());
			JLabel DmText = new JLabel("Density-Matrix Chart");//, JLabel.CENTER);
			DmText.setFont(new Font(null, 0, 24));
			ChartDm.add(DmText);
			ChartDm.add(Box.createHorizontalGlue());
			ChartDm.add(dmchartpanel);
			ChartsLeft.add(ChartDm);
			ChartsLeft.addPropertyChangeListener(dmchartpanel);
			
			eechartpanel = new ChartPanel(this.getEeChart());
			JLabel EeText = new JLabel("Entanglement Entropy Chart");//, JLabel.CENTER);
			EeText.setFont(new Font(null, 0, 24));
			ChartEe.add(EeText);
			ChartEe.add(Box.createHorizontalGlue());
			ChartEe.add(eechartpanel);
			ChartsRight.add(ChartEe);
			ChartsRight.addPropertyChangeListener(eechartpanel);
		}
		Charts.add(ChartsLeft);
		Charts.add(ChartsRight);
		Output.add(Charts);
		
		// Control-Panel
		this.conPan = new ControlPanel();
		
		JComponent TextOutput = new JPanel();
		TextOutput.setBackground(Color.WHITE);
		TextOutput.setLayout(new BoxLayout(TextOutput, BoxLayout.X_AXIS));
		
		TextOutput.add(Box.createVerticalGlue());
		this.DmrgRef.EnergyText = new JTextArea("Minimal energy: infinit");
		this.DmrgRef.EnergyText.setMaximumSize(new Dimension(4000, this.conPan.m_startStop.getMaximumSize().height));
		this.DmrgRef.EnergyText.setEditable(false);
		this.DmrgRef.EnergyText.setBackground(Color.WHITE);
		this.DmrgRef.EnergyText.setBorder(BorderFactory.createEtchedBorder());	
		TextOutput.add(this.DmrgRef.EnergyText);
		this.DmrgRef.SweepText = new JTextArea("Current sweep: 0");
		this.DmrgRef.SweepText.setMaximumSize(new Dimension(4000, this.conPan.m_startStop.getMaximumSize().height));
		this.DmrgRef.SweepText.setEditable(false);
		this.DmrgRef.SweepText.setBackground(Color.WHITE);
		this.DmrgRef.SweepText.setBorder(BorderFactory.createEtchedBorder());	
		TextOutput.add(this.DmrgRef.SweepText);
		TextOutput.add(Box.createVerticalGlue());	
		this.DmrgRef.SiteText = new JTextArea("Current site: 0");
		this.DmrgRef.SiteText.setMaximumSize(new Dimension(4000, this.conPan.m_startStop.getMaximumSize().height));
		this.DmrgRef.SiteText.setEditable(false);
		this.DmrgRef.SiteText.setBackground(Color.WHITE);
		this.DmrgRef.SiteText.setBorder(BorderFactory.createEtchedBorder());	
		TextOutput.add(this.DmrgRef.SiteText);		
		Output.add(TextOutput);
		
		content.add(Output);
		
		content.add(this.conPan);
		
		DmrgCollector EnergyCollector = new DmrgCollector(this.getEnergyTrace(), 1);
		EnergyCollector.SetVisu(this);
		this.setEnergyCollector(EnergyCollector);
//		this.DmrgRef.SetEnergyTrace(this.getEnergyTrace());
		this.stopData();
		this.resetDMRG();
		this.clearTrace();
	}
	
	public void resetDMRG()
	{
		int d=2;			// Anfangs-Groesse der Matrizen
		int s=2;			// Anzahl der möglichen Zustände
		
		this.H.SetContent(0,0,I);
		if (this.selection == 0)
		{
			this.H.SetContent(0,1,s_plus);
			this.H.SetContent(0,2,s_minus);
			this.H.SetContent(1,4,s_minus.mult(this.J/2.0));
			this.H.SetContent(2,4,s_plus.mult(this.Jy/2.0));
		}
		else
		{
			this.H.SetContent(0,1,s_x);
			this.H.SetContent(0,2,s_y);
			this.H.SetContent(1,4,s_x.mult(this.J));
			this.H.SetContent(2,4,s_y.mult(this.Jy*(-1.0)));
		}		
		this.H.SetContent(0,3,s_z);
		this.H.SetContent(0,4,s_x.mult(this.hx).add(s_z.mult(this.hz)));
		this.H.SetContent(3,4,s_z.mult(this.D));
		this.H.SetContent(4,4,I);
		
		this.mpo_sx=new Mpo(this.Site, s, 1);
		this.mpo_sz=new Mpo(this.Site, s, 1);
		this.sz = new Op(this.Site);
		this.sx = new Op(this.Site);
		
		Mpo OpH = new Mpo(H, this.Site, s, d);
		Mps psi = new Mps(this.Site, d, d_max, s, OpH);

		// Erzeugen der Berechnungsumgebung
		Dmrg OldDMRG = this.DmrgRef;
		this.DmrgRef = new Dmrg(psi, OpH, this);
		
		this.DmrgRef.EnergyText = OldDMRG.EnergyText;
		this.DmrgRef.EnergyText.setText("Minimal energy: infinit");
		this.DmrgRef.SweepText = OldDMRG.SweepText;
		this.DmrgRef.SweepText.setText("Current sweep: 0");
		this.DmrgRef.SiteText = OldDMRG.SiteText;
		this.DmrgRef.SiteText.setText("Current site: 0");
		
		this.getEnergyChart().getAxisX().setRangePolicy(new RangePolicyFixedViewport(new Range(0.0, this.Site-1)));
		this.getErwChart().getAxisX().setRangePolicy(new RangePolicyFixedViewport(new Range(0.0, this.Site-1)));
		this.getDmChart().getAxisX().setRangePolicy(new RangePolicyFixedViewport(new Range(0.0, this.d_max-1)));
		this.getEeChart().getAxisX().setRangePolicy(new RangePolicyFixedViewport(new Range(0.5, this.Site-1.5)));
	}
	
	public synchronized void clearTrace() 
	{
		this.getEnergyTrace().removeAllPoints();
		this.getDmTrace().removeAllPoints();
		this.getErwSxTrace().removeAllPoints();
		this.getErwSzTrace().removeAllPoints();
		this.getEeTrace().removeAllPoints();
	}
	public synchronized void startData() 
	{
		if (!this.getEnergyCollector().isRunning())
		{
			this.getEnergyCollector().start();
			this.conPan.m_startStop.setText("stop");
			this.conPan.m_step.setEnabled(false);
		}
	}
	public synchronized void stopData() 
	{
		if (this.getEnergyCollector().isRunning())
		{
			this.getEnergyCollector().stop();
			this.conPan.m_startStop.setText("start");
			this.conPan.m_step.setEnabled(true);
		}
	}

	public void setEnergyChart(final Chart2D chart2D) 
	{
		if (this.m_energy_chart == null) 
			this.m_energy_chart = chart2D;
	}
	public void setDmChart(final Chart2D chart2D) 
	{
		if (this.m_dm_chart == null) 
			this.m_dm_chart = chart2D;
	}
	public void setErwChart(final Chart2D chart2D) 
	{
		if (this.m_erw_chart == null) 
			this.m_erw_chart = chart2D;
	}
	public void setEeChart(final Chart2D chart2D) 
	{
		if (this.m_ee_chart == null) 
			this.m_ee_chart = chart2D;
	}
	
	public Chart2D getEnergyChart() 
	{
		return this.m_energy_chart;
	}
	public Chart2D getDmChart() 
	{
		return this.m_dm_chart;
	}
	public Chart2D getErwChart() 
	{
		return this.m_erw_chart;
	}
	public Chart2D getEeChart() 
	{
		return this.m_ee_chart;
	}
	
	private void setEnergyCollector(final DmrgCollector collector) 
	{
		this.m_energy_collector = collector;
	}

	public ADataCollector getEnergyCollector() 
	{
		return this.m_energy_collector;
	}

	public void setEnergyTrace(final Trace2DSimple trace) 
	{
		if (this.m_energy_trace == null) 
			this.m_energy_trace = trace;
	}
	public void setEnergyPosTrace(final Trace2DLtd trace) 
	{
		if (this.m_energy_pos_trace == null) 
			this.m_energy_pos_trace = trace;
	}
	public void setDmTrace(final Trace2DSimple trace) 
	{
		if (this.m_dm_trace == null) 
			this.m_dm_trace = trace;
	}
	public void setErwSxTrace(final Trace2DSimple trace) 
	{
		if (this.m_erw_sx_trace == null) 
			this.m_erw_sx_trace = trace;
	}
	public void setErwSzTrace(final Trace2DSimple trace) 
	{
		if (this.m_erw_sz_trace == null) 
			this.m_erw_sz_trace = trace;
	}
	public void setErwPosTrace(final Trace2DLtd trace) 
	{
		if (this.m_erw_pos_trace == null) 
			this.m_erw_pos_trace = trace;
	}
	public void setEeTrace(final Trace2DSimple trace) 
	{
		if (this.m_ee_trace == null) 
			this.m_ee_trace = trace;
	}
	
	
	public Trace2DSimple getEnergyTrace() 
	{
		return this.m_energy_trace;
	}
	public Trace2DLtd getEnergyPosTrace() 
	{
		return this.m_energy_pos_trace;
	}
	public Trace2DSimple getDmTrace() 
	{
		return this.m_dm_trace;
	}
	public Trace2DSimple getErwSxTrace() 
	{
		return this.m_erw_sx_trace;
	}
	public Trace2DSimple getErwSzTrace() 
	{
		return this.m_erw_sz_trace;
	}
	public Trace2DLtd getErwPosTrace() 
	{
		return this.m_erw_pos_trace;
	}
	public Trace2DSimple getEeTrace() 
	{
		return this.m_ee_trace;
	}
}
