/**
 * Copyright (c) Artenum SARL 2004-2005
 * @author Julien Forest / Sebastien Jourdain
 *
 * All rights reserved. This software can
 * not be used or copy or diffused without
 * an explicit license of Artenum SARL, Paris-France
 */
package com.artenum.cassandra.plugin.probingline;

import java.awt.Frame;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;

import javax.swing.JDialog;
import javax.swing.JFileChooser;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPopupMenu;

import vtk.vtkActor;
import vtk.vtkDataSet;
import vtk.vtkDataSetMapper;
import vtk.vtkLineSource;
import vtk.vtkLineWidget;
import vtk.vtkLookupTable;
import vtk.vtkProbeFilter;
import vtk.vtkScalarBarActor;
import vtk.vtkTransformPolyDataFilter;

import com.artenum.cassandra.pipeline.Filter;
import com.artenum.cassandra.pipeline.FilterImpl;
import com.artenum.cassandra.pipeline.PipeLineManager;
import com.artenum.cassandra.pipeline.RemoveListener;
import com.artenum.cassandra.pipeline.CassandraObject;
import com.artenum.cassandra.pipeline.graph.VtkObjectCellAdapter;
import com.artenum.cassandra.plugin.CassandraPlugInProperty;
import com.artenum.cassandra.plugin.CassandraPlugin;
import com.artenum.cassandra.plugin.PlugInControlUI;
import com.artenum.cassandra.plugin.PluginManager;
import com.artenum.cassandra.plugin.SimplePlugInProperty;

/**
 * <pre>
 * &lt;b&gt;Project ref           :&lt;/b&gt; CASSANDRA project
 * &lt;b&gt;Copyright and license :&lt;/b&gt; See relevant sections
 * &lt;b&gt;Status                :&lt;/b&gt; under development
 * &lt;b&gt;Creation              :&lt;/b&gt; 04/03/2005
 * &lt;b&gt;Modification          :&lt;/b&gt;
 * &lt;b&gt;Description  :&lt;/b&gt;
 *             This class defines the VTK processing pipeline itself
 *             and the initialisation of the contextual GUI of the plugin.
 * 
 * </pre>
 * <table cellpadding="3" cellspacing="0" border="1" width="100%">
 * <tr BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
 * <td><b>Version number</b></td>
 * <td><b>Author (name, e-mail)</b></td>
 * <td><b>Corrections/Modifications</b></td>
 * </tr>
 * <tr>
 * <td>0.1</td>
 * <td>Julien Forest, j.forest@artenum.com</td>
 * <td>Creation</td>
 * </tr>
 * </table>
 * 
 * @author Julien Forest, ARTENUM SARL
 * @version 1.2
 */
public class ProbingLinePlugin implements CassandraPlugin, RemoveListener {
    private String name;
    private PipeLineManager pipelineManager;
    private PluginManager pluginManager;
    private JPopupMenu contextualMenu;
    private ProbingLineControlUI controlUI;
    private int nbUpdate = 0;

    // Data
    private double[] startPt;
    private double[] endPt;
    private int resol = 128;
    private ArrayList x;
    private ArrayList y;
    private Plot2D plot;
    private JDialog plotDialog; // we use a JDialog to keep the window on the
    // front

    // Vtk data
    private vtkLineSource line;
    private vtkDataSetMapper lineMapper;
    private vtkActor lineActor;
    //private vtkTransformPolyDataFilter tf;
    private vtkProbeFilter probe;
    private vtkDataSet lastDataSet;
    private vtkLookupTable outputLookupTable;
    private vtkScalarBarActor outputScalarBar;
    
    // Cassandra objects
    private CassandraObject outputCassDataset;
    private CassandraObject cassFilter;
    private CassandraObject outputCassMapper;
    private CassandraObject outputCassActor;
    private CassandraObject outputCassLookupTable;
    private CassandraObject outputCassScalarBar;
    private Filter filterImpl;

    private vtkLineWidget lineWidget;
    
    Frame owner;

    public static final String PERSISTENCE_KEY_INPUT_DATASET = "persistence.key.inputVtkDataSet";
    public static final String PERSISTENCE_KEY_INOUT = "persistence.key.insideOut";
    public static final String PERSISTENCE_KEY_OUPUT_DATASET = "persistence.key.outputDataSet";
    public static final String PERSISTENCE_KEY_OUPUT_MAPPER = "persistence.key.outputMapper";
    public static final String PERSISTENCE_KEY_OUPUT_LOOKUP_TABLE = "persistence.key.outputlookUpTable";
    public static final String PERSISTENCE_KEY_OUTPUT_ACTOR = "persistence.key.outputActor";
    public static final String PERSISTENCE_KEY_OUTPUT_SCALAR_BAR = "persistence.key.ouputScalarBar";
    public static final String PERSISTENCE_KEY_CELL_POS_X = "persistence.key.cell.PosX";
    public static final String PERSISTENCE_KEY_CELL_POS_Y = "persistence.key.cell.PosY";
    
    public static final String PERSISTENCE_KEY_START_POINT_X = "persistence.key.start.point.x";
    public static final String PERSISTENCE_KEY_START_POINT_Y = "persistence.key.start.point.y";
    public static final String PERSISTENCE_KEY_START_POINT_Z = "persistence.key.start.point.z";
    
    public static final String PERSISTENCE_KEY_END_POINT_X = "persistence.key.end.point.x";
    public static final String PERSISTENCE_KEY_END_POINT_Y = "persistence.key.end.point.y";
    public static final String PERSISTENCE_KEY_END_POINT_Z = "persistence.key.end.point.z";
    
    public static final String PERSISTENCE_KEY_PROBE_RESOLUTION = "persistence.key.probe.resolution";

    /**
     * Main constructor and VTK pipeline definition.
     * 
     * @param pipelineManager
     *            is the central pipeline manager of Cassandra.
     * @param pluginManager
     *            is the central list of plugin instance, where a contextual
     *            menu access is given.
     */
    public ProbingLinePlugin(PipeLineManager pipelineManager, PluginManager pluginManager, Frame owner) {
        initPlugIn(pipelineManager, pluginManager, owner);
        initPipeline();
    }

    /**
     * Constructor used in the pipeline importer
     * 
     * @param pipelineManager
     * @param pluginManager
     * @param owner
     * @param initPipeline
     */
    public ProbingLinePlugin(PipeLineManager pipelineManager, PluginManager pluginManager, Frame owner, boolean initPipeline) {
        initPlugIn(pipelineManager, pluginManager, owner);
        if (initPipeline) {
            initPipeline();
        }
    }

    /**
     * Default constructor as used during the instantiation in Cassandra.
     * 
     * @param pipelineManager
     * @param pluginManager
     * @param owner
     * @param initPipeline
     */
    public ProbingLinePlugin(PipeLineManager pipelineManager, PluginManager pluginManager, Frame owner, int initPipeline) {
        initPlugIn(pipelineManager, pluginManager, owner);
        if (initPipeline == 1) {
            initPipeline();
        }
    }

    public void initPlugIn(PipeLineManager pipelineManager, PluginManager pluginManager, Frame owner) {
        
        this.owner = owner;
        
        this.name = "Probing Line";
        filterImpl = new FilterImpl();
        filterImpl.addRemoveListener(this);
        filterImpl.setParentPlugin(this);

        this.pipelineManager = pipelineManager;
        this.pluginManager = pluginManager;

        // Init control UI
        controlUI = new ProbingLineControlUI(pipelineManager, this, owner);

        // Init contextual menu
        contextualMenu = new JPopupMenu("Probing line menu");
        JMenuItem showControl = new JMenuItem("Show control");
        showControl.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                controlUI.setVisible(true);
                controlUI.update3DWidgetStatus();
            }
        });
        contextualMenu.add(showControl);
        contextualMenu.addSeparator();
        JMenuItem remove = new JMenuItem("Remove");
        remove.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                remove();
            }
        });
        contextualMenu.add(remove);
    }

    /**
     * initialises the processing pipeline it-self. Should be called after the
     * initPlugIn. If its elements (i.e internal vtk components and the
     * post-filter pipeline) are not set before, their are built as new
     * instances and registered into the pipeline.
     */
    public void initPipeline() {

        // Init pipeline
        startPt = new double[3];
        startPt[0] = 0.0;
        startPt[1] = 0.0;
        startPt[2] = 0.0;

        endPt = new double[3];
        endPt[0] = 10.0;
        endPt[1] = 10.0;
        endPt[2] = 10.0;

        // Create the line source to use for the probe lines.
        if (line == null) {
            line = new vtkLineSource();
            System.out.println("line: new component");
        }
        line.SetPoint1(startPt[0], startPt[1], startPt[2]);
        line.SetPoint2(endPt[0], endPt[1], endPt[2]);
        line.SetResolution(resol);
        
        /////////////////////////////////////
        if (probe == null) {
            probe = new vtkProbeFilter();
            probe.SetInput(line.GetOutput());
            this.outputCassDataset = pipelineManager.addDataSet(probe.GetOutput(), "Probe Output");            
        } else outputCassDataset = pipelineManager.getCassandraVtkObjectByTrueVtkObject(probe);
        /////////////////////////////////////

        if (lineMapper == null) {
            lineMapper = new vtkDataSetMapper();
            this.outputCassMapper = pipelineManager.addMapper(lineMapper, "Probe Mapper");
        } else outputCassMapper = pipelineManager.getCassandraVtkObjectByTrueVtkObject(lineMapper);
        
        lineMapper.SetInput(probe.GetOutput());
                
        if (lineActor == null) {
            lineActor = new vtkActor();
            outputCassActor = pipelineManager.addActor(lineActor, "Probe");
            System.out.println("actor: new component");
        } else outputCassActor = pipelineManager.getCassandraVtkObjectByTrueVtkObject(lineActor);
        lineActor.SetMapper(lineMapper);
        
        
        // Build lookupTable
        if (outputLookupTable == null) {
            outputLookupTable = new vtkLookupTable();
            outputCassLookupTable = pipelineManager.addLookupTable(outputLookupTable, "Clipping plane");
        } else outputCassLookupTable = pipelineManager.getCassandraVtkObjectByTrueVtkObject(outputLookupTable);
        outputLookupTable.SetHueRange(0.66667, 0);
        outputLookupTable.Build();
        lineMapper.SetLookupTable(outputLookupTable);
        
        // Scalar bar
        if (outputScalarBar == null) {
            outputScalarBar = new vtkScalarBarActor();
            outputCassScalarBar = pipelineManager.addScalarBar(outputScalarBar, "Clipping plane");
        } else outputCassScalarBar = pipelineManager.getCassandraVtkObjectByTrueVtkObject(outputScalarBar);
        outputScalarBar.SetLookupTable(outputLookupTable);
        
        // define the filter (i.e the yellow triangle)
        //filterImpl.getOutputDataSet().add(probe.GetOutput());
        //filterImpl.addRemoveListener(this);

        // define the filter (i.e the yellow triangle) and load it in the Cassandra pipeline       
        cassFilter = pipelineManager.addFilter(filterImpl, "Prober");
        cassFilter.getMetaData().put(CassandraObject.POPUP_MENU, getContextualMenu());
        
        // to display the plot of the probed data
        plotDialog = new JDialog(this.owner, "Probed data");
        x = new ArrayList();
        y = new ArrayList();
        plot = new Plot2D(x, y, "The value", "Probe", "Probe");
        plotDialog.getContentPane().add(plot.getChartPanel());
        plotDialog.setSize(512, 300);
        plotDialog.setLocationRelativeTo(null);

        //
        // actor.setValide(false);

        // set the 3D widget.
        if (lineWidget != null) {
            lineWidget.SetPoint1(line.GetPoint1());
            lineWidget.SetPoint2(line.GetPoint2());
        }

    }

    /**
     * update the processing done on inputDataSet.
     * 
     * @param inputDataSet
     * @param startPtIn
     * @param endPtIn
     * @param resolIn
     * @param viewPlot2D
     * @param plotType
     */
    public void updateProbe(vtkDataSet inputDataSet, double[] startPtIn, double[] endPtIn, int resolIn, boolean viewPlot2D, int plotType) {
        if (inputDataSet != null) {
            startPt = startPtIn;
            endPt = endPtIn;
            resol = resolIn;
            lastDataSet = inputDataSet;

            line.SetPoint1(startPt[0], startPt[1], startPt[2]);
            line.SetPoint2(endPt[0], endPt[1], endPt[2]);
            line.SetResolution(resol);

            probe.SetSource(inputDataSet);

            //filterImpl.getInputDataSet().clear();
            //filterImpl.getInputDataSet().add(inputDataSet);

            probe.Update();
            probe.GetOutput().UpdateData();

            int nbPts = probe.GetOutput().GetNumberOfPoints();

            x.clear();
            y.clear();

            // General abscisse structure, structured as follow
            // index, x, y, y, s
            Double[] abscisse = new Double[5];

            for (int i = 0; i < nbPts; i++) {
                abscisse[0] = (double) i;
                abscisse[1] = probe.GetOutput().GetPoint(i)[0];
                abscisse[2] = probe.GetOutput().GetPoint(i)[1];
                abscisse[3] = probe.GetOutput().GetPoint(i)[2];
                abscisse[4] = computeS(probe.GetOutput().GetPoint(i)[0], probe.GetOutput().GetPoint(i)[1], probe.GetOutput().GetPoint(i)[2]);

                x.add(abscisse[plotType]);
                y.add((double) probe.GetOutput().GetPointData().GetScalars().GetTuple1(i));
            }

            pipelineManager.notifyConnectivityChange(cassFilter);
            plot.updateCollection(x, y);
            plotDialog.setVisible(viewPlot2D);

            // Set the default actor visible by default and automatically hide
            // the source one
            if ((nbUpdate++ == 0) && pipelineManager.getActorList().getData().contains(outputCassActor)) {
                pipelineManager.setActorVisible(outputCassActor, true);
            }
            // not always relevant.
            // pipelineManager.hideInputActor(actor, inputDataSet);

            // update the 3D widget position if relevant
            if (lineWidget != null) {
                // then we orient the widgetLine like the source line
                lineWidget.SetPoint1(line.GetPoint1());
                lineWidget.SetPoint2(line.GetPoint2());
            }
            
            // registration of internal elements of the filter
            // useful for export of the detailed pipeline if needed
            filterImpl.getInputDataSet().clear();
            filterImpl.getInputDataSet().add(inputDataSet);
            filterImpl.getOutputDataSet().clear();
            filterImpl.getOutputDataSet().add(probe.GetOutput());
            filterImpl.getAlgorithm().add(probe);
            filterImpl.getVtkImplicitFunction().clear();
            filterImpl.getVtkImplicitFunction().add(line);
            pipelineManager.notifyConnectivityChange(cassFilter);
            
        }
    }

    /**
     * Export the probed data into ASCII colums-raw based format as follow index
     * x y z s value
     * 
     * Where: - index: index of the value - x, y, z: 3D absolute coordinates of
     * the value in the coordinate system of the entry data set. - s:
     * curvilineare coordinate along the line. - value: the value.
     */
    public void export() {
        Double[] abscisse = new Double[5];
        JFileChooser chooser = new JFileChooser();
        if (JFileChooser.APPROVE_OPTION == chooser.showSaveDialog(plotDialog)) {
            File fileToSave = chooser.getSelectedFile();
            if (fileToSave != null) {
                try {
                    FileWriter fw = new FileWriter(fileToSave);
                    fw.write("# index x y z s value \n");
                    int size = x.size();
                    for (int i = 0; i < size; i++) {
                        abscisse[0] = (double) i;
                        abscisse[1] = probe.GetOutput().GetPoint(i)[0];
                        abscisse[2] = probe.GetOutput().GetPoint(i)[1];
                        abscisse[3] = probe.GetOutput().GetPoint(i)[2];
                        abscisse[4] = (double) (computeS(probe.GetOutput().GetPoint(i)[0], probe.GetOutput().GetPoint(i)[1], probe.GetOutput().GetPoint(i)[2]));

                        fw.write(abscisse[0] + " " + abscisse[1] + " " + abscisse[2] + " " + abscisse[3] + " " + abscisse[4] + " "
                                + probe.GetOutput().GetPointData().GetScalars().GetTuple1(i) + "\n");
                    }

                    fw.close();
                } catch (IOException e) {
                    e.printStackTrace();
                    JOptionPane.showMessageDialog(plotDialog, "Error while trying to export: " + e.getMessage());
                }
            }
        }
    }

    /**
     * Compute the curvilinear abscissa.
     * 
     * @param x
     * @param y
     * @param z
     * @return
     */
    public double computeS(double x, double y, double z) {
        double s = 0.0;
        double max;
        int axeRef = 0;

        double[] pt = new double[3];
        pt[0] = x;
        pt[1] = y;
        pt[2] = z;
        double[] diff = new double[3];
        diff[0] = endPt[0] - startPt[0];
        diff[1] = endPt[1] - startPt[1];
        diff[2] = endPt[2] - startPt[2];

        if (diff[0] >= diff[1]) {
            if (diff[0] >= diff[2]) {
                max = diff[0];
                axeRef = 0;
            } else {
                max = diff[2];
                axeRef = 2;
            }
        } else if (diff[1] >= diff[2]) {
            max = diff[1];
            axeRef = 1;
        } else {
            max = diff[2];
            axeRef = 2;
        }

        s = pt[axeRef] - (startPt[axeRef] / max);

        return s;
    }

    public String getName() {
        return name;
    }

    public void remove() {
        pluginManager.removePlugin(this);
        pipelineManager.removeVtkObject(outputCassActor);
        pipelineManager.removeVtkObject(outputCassDataset);
        pipelineManager.removeVtkObject(outputCassMapper);
        pipelineManager.removeVtkObject(cassFilter);
    }

    public JPopupMenu getContextualMenu() {
        return contextualMenu;
    }

    public String toString() {
        return getName();
    }

    public CassandraObject getOutputDataSet() {
        return outputCassDataset;
    }

    /**
     * Show/hide (and switch On/Off) the 3D widget interactor.
     * 
     * @param b
     */
    void show3DWidget(boolean b) {

        if (b) {
            if (lineWidget == null) {
                init3DWidget();
            }
            // planWidget.PlaceWidget(lastDataSet.GetBounds());

            lineWidget.On();
        } else {
            if(lineWidget != null){
            lineWidget.Off();
            }
        }
    }

    /**
     * Initialise the 3D control widget.
     */
    void init3DWidget() {

        // System.out.println("initialisation of the widget");
        lineWidget = new vtkLineWidget();
        lineWidget.SetInteractor(pipelineManager.getCassandraView().getIren());

        // to make the interaction ON and be able yto control the widget
        lineWidget.EnabledOn();
        pipelineManager.getCassandraView().deepValidateView(); // Don t ask me
        // why, apparently needed, at least under MacOSX and the
        // default swing LAF, to activate the widget interactor.

        // size the plan on the input data set. Should be done in first
        // to allow the plan orientation AFTER.
        lineWidget.SetInput(lastDataSet);
        lineWidget.SetPlaceFactor(1.2);
        lineWidget.PlaceWidget();

        // then we orient the widgetLine like the source line
        lineWidget.SetPoint1(line.GetPoint1());
        lineWidget.SetPoint2(line.GetPoint2());

        // we add the local observer for interaction events, i.e the method name
        // in last argument of the current object.
        lineWidget.AddObserver("InteractionEvent", this, "interactionCallBack");

        // both not needed.
        // planWidget.AddObserver("CharEvent", this, "widgetCharEvent");
        // planWidget.AddObserver("StartInteractionEvent", this,
        // "startInteractionCallBack");
    }

    private void widgetCharEvent() {
        char code = Character.toLowerCase(pipelineManager.getCassandraView().getIren().GetKeyCode());
        System.out.println("touch typed:" + code);

        if (code == 'b') { // FIXME
            lineWidget.SetEnabled(1);
        }
    }

    // needed to initialise the interaction control on the widget.
    private void startInteractionCallBack() {
        System.out.println("wiget interaction started");
    }

    /**
    *  
    */
    private void interactionCallBack() {

        line.SetPoint1(lineWidget.GetPoint1());
        line.SetPoint2(lineWidget.GetPoint2());

        controlUI.setPoint1(lineWidget.GetPoint1());
        controlUI.setPoint2(lineWidget.GetPoint2());
        controlUI.performAction(controlUI.UPDATE);
    }

    public Filter getInternalFilter() {
        return filterImpl;
    }

    @Override
    public PlugInControlUI getControlUI() {
        return controlUI;
    }
    
    

    @Override
    public CassandraPlugInProperty getPlugInProperty() {

        //FIXME : should be moved / handle by the event lsitener of the pipeline. Not very clean.
        outputCassLookupTable = pipelineManager.getCassandraVtkObjectByTrueVtkObject((vtkLookupTable) lineMapper.GetLookupTable());
        outputLookupTable = (vtkLookupTable) outputCassLookupTable.getVtkObject();
        outputCassScalarBar = pipelineManager.getVtkObject(outputCassLookupTable.getOutputConnectivityList().get(0));
        outputScalarBar = (vtkScalarBarActor) outputCassScalarBar.getVtkObject();
        //
        
        SimplePlugInProperty prop = new SimplePlugInProperty();
        
        prop.put(PERSISTENCE_KEY_INPUT_DATASET, probe.GetInput());
        
        prop.put(PERSISTENCE_KEY_OUPUT_DATASET, probe.GetOutput());
        prop.put(PERSISTENCE_KEY_OUPUT_MAPPER, lineMapper);        
        prop.put(PERSISTENCE_KEY_OUPUT_LOOKUP_TABLE, outputCassLookupTable.getVtkObject());
        prop.put(PERSISTENCE_KEY_OUTPUT_ACTOR, outputCassActor.getVtkObject());
        prop.put(PERSISTENCE_KEY_OUTPUT_SCALAR_BAR, outputCassScalarBar.getVtkObject());
        
        prop.put(PERSISTENCE_KEY_START_POINT_X, line.GetPoint1()[0]);
        prop.put(PERSISTENCE_KEY_START_POINT_Y, line.GetPoint1()[1]);
        prop.put(PERSISTENCE_KEY_START_POINT_Z, line.GetPoint1()[2]);
        
        prop.put(PERSISTENCE_KEY_END_POINT_X, line.GetPoint2()[0]);
        prop.put(PERSISTENCE_KEY_END_POINT_Y, line.GetPoint2()[1]);
        prop.put(PERSISTENCE_KEY_END_POINT_Z, line.GetPoint2()[3]);
        
        prop.put(PERSISTENCE_KEY_PROBE_RESOLUTION, line.GetResolution());
        
        //FIXME : not handled ytet: boolean viewPlot2D, int plotType
        
        Point cellPosition = ((VtkObjectCellAdapter) cassFilter.getMetaData().get(CassandraObject.CELL)).getPosition();
        prop.put(PERSISTENCE_KEY_CELL_POS_X, cellPosition.x);
        prop.put(PERSISTENCE_KEY_CELL_POS_Y, cellPosition.y);
   
        return prop;
    }

    @Override
    public void initAndUpdate(CassandraPlugInProperty prop) {

       vtkDataSet tmpInputDataSet;
       
       int cellPosX;
       int cellPosY;

       this.probe = new vtkProbeFilter();
        //this.probe.setOuput //FIXME
        tmpInputDataSet = (vtkDataSet) prop.getSafely(PERSISTENCE_KEY_INPUT_DATASET, (vtkDataSet) (probe.GetInput()));
        
        lineMapper = (vtkDataSetMapper) prop.getSafely(PERSISTENCE_KEY_OUPUT_MAPPER, null); // FIXME
        outputLookupTable = (vtkLookupTable) prop.getSafely(PERSISTENCE_KEY_OUPUT_LOOKUP_TABLE, null); // FIXME
        lineActor = (vtkActor) prop.getSafely(PERSISTENCE_KEY_OUTPUT_ACTOR, null); // FIXME
        outputScalarBar = (vtkScalarBarActor) prop.getSafely(PERSISTENCE_KEY_OUTPUT_SCALAR_BAR, null); // FIXME
        
        line.SetPoint1(prop.getSafely(PERSISTENCE_KEY_START_POINT_X, 0.0), 
                prop.getSafely(PERSISTENCE_KEY_START_POINT_Y, 0.0), 
                prop.getSafely(PERSISTENCE_KEY_START_POINT_Z, 0.0));
        
        line.SetPoint2(prop.getSafely(PERSISTENCE_KEY_END_POINT_X, 0.0), 
                prop.getSafely(PERSISTENCE_KEY_END_POINT_Y, 0.0), 
                prop.getSafely(PERSISTENCE_KEY_END_POINT_Z, 0.0));        
        
        line.SetResolution(prop.getSafely(PERSISTENCE_KEY_PROBE_RESOLUTION, 256));
        
        this.initPipeline();
        controlUI.setPoint1(line.GetPoint1());
        controlUI.setPoint2(line.GetPoint2());
        controlUI.setSelectedInput(pipelineManager.getCassandraVtkObjectByTrueVtkObject(tmpInputDataSet)); //FIXME: nasty
        this.updateProbe(tmpInputDataSet, line.GetPoint1(), line.GetPoint2(), line.GetResolution(), false, 1);//FIXME PLOTTYPE and view2DPlot
        
        cellPosX = prop.getSafely(PERSISTENCE_KEY_CELL_POS_X, -1);
        cellPosY = prop.getSafely(PERSISTENCE_KEY_CELL_POS_Y, -1);
        if (cellPosX > 0 && cellPosY > 0) ((VtkObjectCellAdapter) cassFilter.getMetaData().get(CassandraObject.CELL)).setPosition(new Point(cellPosX, cellPosY));
    }

}
