blob: 0d3a81e329fa4ef5190e754f913837d4ca8ddd90 [file] [log] [blame]
// EstimatorControl.java
package org.eclipse.stem.util.analysis.views;
/*******************************************************************************
* Copyright (c) 2007, 2008 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.eclipse.birt.chart.model.attribute.ColorDefinition;
import org.eclipse.birt.chart.model.attribute.impl.ColorDefinitionImpl;
import org.eclipse.emf.common.util.EList;
import org.eclipse.jface.dialogs.ProgressMonitorDialog;
import org.eclipse.stem.analysis.ScenarioInitializationException;
import org.eclipse.stem.diseasemodels.Activator;
import org.eclipse.stem.util.analysis.CSVAnalysisWriter;
import org.eclipse.stem.util.analysis.PhaseSpaceCoordinate;
import org.eclipse.stem.util.analysis.ScenarioAnalysisSuite;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.FormAttachment;
import org.eclipse.swt.layout.FormData;
import org.eclipse.swt.layout.FormLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.DirectoryDialog;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
/**
* This class is a SWT GUI component that uses BIRT to plot
*/
public class LyapunovControl extends AnalysisControl {
/**
* used to identify user preferences for this class
* This String is not human readable so does not need to be NLS'd. It is a key in a map
*/
private static final String CONSUMER = "LYAPUNOV_CONTROL";
/**
* used to remember the primary directory in the user preferences
* This String is not human readable so does not need to be NLS'd. It is a key in a map
*/
private static final String PRIMARY_FOLDER_KEY = CONSUMER+"_PRIMARY";
/**
* used to remember the secondary directory in the user preferences
* This String is not human readable so does not need to be NLS'd. It is a key in a map
*/
private static final String SECONDARY_FOLDER_KEY = CONSUMER+"_SECONDARY";
/**
* First Scenario Label - indicates number of regions being watched for analysis.
* There are locations with relative value history providers attached
*/
Label firstScenarioFolderLabel;
/**
* Second Scenario Label - indicates number of regions being watched for analysis.
* There are locations with relative value history providers attached
*/
Label secondScenarioFolderLabel;
/**
* A Label to give feedbak on the computation action
*/
//Label userFeedbackLabel;
/**
* First input text field for the scenario folder of data to use in making the estimation
*/
Text text1;
/**
* Second Input text field for the scenario folder of data to be compared
**/
Text text2;
/**
* A label to report status (not yet used)
*/
Label statusLabel;
/**
* Results of analysis
*/
Label resultsLabel;
/**
* the chart of two (or more) trajectories in phase space
*/
LyapunovTrajectoryCanvas lyapunovTrajectoryCanvas;
/**
* the time series chart of the divergence of the Lyapunov trajectory(ies) from the reference trajectory
*/
TimeSeriesCanvas timeSeriesCanvas;
/**
* Colors for the time series chart
*/
static final ColorDefinition foreGround = ColorDefinitionImpl.create(180, 0, 0);
static final ColorDefinition backgroundGround = ColorDefinitionImpl.create(255, 255, 225);
static final ColorDefinition frameColor = ColorDefinitionImpl.WHITE();
/**
* Label for line series Data (legend)
*/
/**
* the results of various scenario comparisons
* TODO: eventually this might be a map keyed by comparison id
* for now there is only one comparison, the mean square difference.
*/
List<PhaseSpaceCoordinate[]> comparisonValues = new ArrayList<PhaseSpaceCoordinate[]>();
/**
* this is the cumulative deviation between the trajectories (relative to the reference
* trajectory
*/
List<EList<Double>> cumulativeDeviation = new ArrayList<EList<Double>>();
protected static final String LYAPUNOV_FILE_PREFIX = Messages.getString("LYA.TITLE");
protected static final String LYAPUNOV_DEVIATION_FILE_PREFIX = Messages.getString("LYA.DEVIATION");
protected static final String SELECT_FOLDER_DIALOG_TEXT = Messages.getString("LYA.SELECTFOLDERDIALG");
ScenarioAnalysisSuite analyzer = new ScenarioAnalysisSuite(this);
Composite parentComposite;
/**
*
* @param parent
*/
public LyapunovControl(final Composite parent) {
super(parent, SWT.None);
parentComposite = parent;
createContents();
} // EstimatorControl
/**
* Create the contents of the plotter
*/
private void createContents() {
setLayout(new FormLayout());
Display display = this.getDisplay();
identifiableTitle = new Label(this, SWT.BORDER);
identifiableTitle.setText(Messages.getString("LYA.TITLE"));
identifiableTitle.setFont(getLargerFont(18, display));
statusLabel = new Label(this, SWT.BORDER);
statusLabel.setText("");
firstScenarioFolderLabel = new Label(this, SWT.NONE);
//firstScenarioFolderLabel.setBackground(labelBackground);
firstScenarioFolderLabel.setText(Messages.getString("LYA.FOLDER1LABEL"));
text1 = new Text(this, SWT.BORDER);
text1.setBounds(10, 10, 100, 20);
String primaryDir=prefs.getRecentFolder(PRIMARY_FOLDER_KEY);
text1.setText(primaryDir);
secondScenarioFolderLabel = new Label(this, SWT.NONE);
// secondScenarioFolderLabel.setBackground(labelBackground);
secondScenarioFolderLabel.setText(Messages.getString("LYA.FOLDER2LABEL"));
text2 = new Text(this, SWT.BORDER);
text2.setBounds(10, 10, 100, 20);
String secondaryDir=prefs.getRecentFolder(SECONDARY_FOLDER_KEY);
text2.setText(secondaryDir);
Composite analyzeButtonComposite = getAnalyzeButtonComposite(this,Messages.getString("LYA.COMPARISON"));
resultsLabel = new Label(this, SWT.SHADOW_OUT);
resultsLabel.setText("");
final FormData titleFormData = new FormData();
identifiableTitle.setLayoutData(titleFormData);
titleFormData.top = new FormAttachment(0, 0);
titleFormData.left = new FormAttachment(0, 0);
titleFormData.right = new FormAttachment(25, 0);
final FormData resultsFormData = new FormData();
resultsLabel.setLayoutData(resultsFormData);
resultsFormData.top = new FormAttachment(0, 0);
resultsFormData.left = new FormAttachment(25, 0);
resultsFormData.right = new FormAttachment(75, 0);
int spacer = 10;
int buttonspacer = 5;
/////////////////////////////////////////////////////////////////////////
// TextField folder label
final FormData firstScenarioFolderLabelFormData = new FormData();
// propertySelectorFormData.top = new FormAttachment(cSVLoggerCanvas,
// 0);
firstScenarioFolderLabelFormData.top = new FormAttachment(identifiableTitle, spacer);
//firstScenarioFolderLabelFormData.bottom = new FormAttachment(bottom, 0);
firstScenarioFolderLabelFormData.left = new FormAttachment(0, 0);
firstScenarioFolderLabelFormData.right = new FormAttachment(15, 0);
firstScenarioFolderLabel.setLayoutData(firstScenarioFolderLabelFormData);
// first text field for parameter Estimator
final FormData text1FormData = new FormData();
text1FormData.top = new FormAttachment(identifiableTitle, spacer);
text1FormData.left = new FormAttachment(firstScenarioFolderLabel, 5);
text1FormData.right = new FormAttachment(85, 0);
text1.setLayoutData(text1FormData);
Button selectFolder1Button = new Button(this, SWT.NONE);
selectFolder1Button.setText(Messages.getString("LYA.SELECTFOLDER"));
final FormData selectFolder1FormData = new FormData();
selectFolder1FormData.top = new FormAttachment(identifiableTitle, buttonspacer);
//selectFolder1FormData.bottom = new FormAttachment(bottom, 0);
selectFolder1FormData.left = new FormAttachment(text1, 5);
selectFolder1Button.setLayoutData(selectFolder1FormData);
final Shell shell = this.getShell();
selectFolder1Button.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(@SuppressWarnings("unused")
final SelectionEvent e) {
final DirectoryDialog dd = new DirectoryDialog(
shell, SWT.OPEN);
dd.setText(Messages.getString("LYA.SELECTFOLDERDIALOG")); //$NON-NLS-1$
String beginSearch = text1.getText();
if((beginSearch==null)||(beginSearch.length()<1)) beginSearch = ROOT_PATH;
dd.setFilterPath(beginSearch);
final String selected = dd.open();
if(selected!=null) text1.setText(selected);
}
});
/////////////////////////////////////////////////////////////////////////
// bottom += deltaBottom;
/////////////////////////////////////////////////////////////////////////
// TextField folder label
final FormData secondScenarioFolderLabelFormData = new FormData();
// propertySelectorFormData.top = new FormAttachment(cSVLoggerCanvas,
// 0);
secondScenarioFolderLabelFormData.top = new FormAttachment(firstScenarioFolderLabel, spacer);
secondScenarioFolderLabelFormData.left = new FormAttachment(0, 0);
secondScenarioFolderLabelFormData.right = new FormAttachment(15, 0);
secondScenarioFolderLabel.setLayoutData(secondScenarioFolderLabelFormData);
// first text field for parameter Estimator
final FormData text2FormData = new FormData();
text2FormData.top = new FormAttachment(firstScenarioFolderLabel, spacer);
text2FormData.left = new FormAttachment(secondScenarioFolderLabel, 5);
text2FormData.right = new FormAttachment(85, 0);
text2.setLayoutData(text2FormData);
Button selectFolder2Button = new Button(this, SWT.NONE);
selectFolder2Button.setText(Messages.getString("LYA.SELECTFOLDER"));
final FormData selectFolder2FormData = new FormData();
selectFolder2FormData.top = new FormAttachment(firstScenarioFolderLabel, buttonspacer);
selectFolder2FormData.left = new FormAttachment(text2, 5);
selectFolder2Button.setLayoutData(selectFolder2FormData);
selectFolder2Button.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(@SuppressWarnings("unused")
final SelectionEvent e) {
final DirectoryDialog dd = new DirectoryDialog(
shell, SWT.OPEN);
dd.setText(SELECT_FOLDER_DIALOG_TEXT); //$NON-NLS-1$
String beginSearch = text2.getText();
if((beginSearch==null)||(beginSearch.length()<1)) beginSearch = ROOT_PATH;
dd.setFilterPath(beginSearch);
final String selected = dd.open();
if(selected!=null) text2.setText(selected);
}
});
/////////////////////////////////////////////////////////////////////////
// bottom += deltaBottom;
// AnalyzeButton
final FormData analysisButtonFormData = new FormData();
// propertySelectorFormDataX.top = new FormAttachment(propertySelectorY,
// 0);
analysisButtonFormData.top = new FormAttachment(secondScenarioFolderLabel, spacer);
//analysisButtonFormData.bottom = new FormAttachment(bottom, 0);
analysisButtonFormData.left = new FormAttachment(0, 0);
analysisButtonFormData.right = new FormAttachment(100, 0);
analyzeButtonComposite.setLayoutData(analysisButtonFormData);
// Trajectories
lyapunovTrajectoryCanvas = new LyapunovTrajectoryCanvas(this);
final FormData trajectoryChartFormData = new FormData();
lyapunovTrajectoryCanvas.setLayoutData(trajectoryChartFormData);
trajectoryChartFormData.top = new FormAttachment(analyzeButtonComposite, 0);
trajectoryChartFormData.bottom = new FormAttachment(100, 0);
trajectoryChartFormData.left = new FormAttachment(0, 0);
trajectoryChartFormData.right = new FormAttachment(50, 0);
// divergence graph
timeSeriesCanvas = new TimeSeriesCanvas(this,
Messages.getString("LYA.DIVERGENCELEGEND"),
Messages.getString("LYA.DIVERGENCEYAXIS"),
Messages.getString("LYA.DIVERGENCEYAXIS"),
foreGround,
backgroundGround,
frameColor, 0);
final FormData analysisChartFormData = new FormData();
timeSeriesCanvas.setLayoutData(analysisChartFormData);
analysisChartFormData.top = new FormAttachment(analyzeButtonComposite, 0);
analysisChartFormData.bottom = new FormAttachment(100, 0);
analysisChartFormData.left = new FormAttachment(50, 0);
analysisChartFormData.right = new FormAttachment(100, 0);
final ProgressMonitorDialog progressDialog = new ProgressMonitorDialog(this.getShell());
analyzeButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(@SuppressWarnings("unused")
final SelectionEvent e) {
String referenceDirectory = text1.getText();
String comparisonDirectory = text2.getText();
Display display = parentComposite.getDisplay();
/*
* reset the label text
*/
identifiableTitle.setText(Messages.getString("LYA.TITLE"));
resultsLabel.setText(Messages.getString("LYA.WORKING"));
/*
* reinitialize the graph
*/
comparisonValues.clear();
cumulativeDeviation.clear();
lyapunovTrajectoryCanvas.reset();
/*
* VALIDATE the text input Fields
*/
if(!analyzer.validate(referenceDirectory)) {
identifiableTitle.setText(ScenarioAnalysisSuite.NOT_FOUND_MSG);
text1.setText("");
}
if(!analyzer.validate(comparisonDirectory)) {
identifiableTitle.setText(ScenarioAnalysisSuite.NOT_FOUND_MSG);
text2.setText("");
}
if((!analyzer.validate(referenceDirectory)) || (!analyzer.validate(comparisonDirectory))) {
return;
}
try {
List<PhaseSpaceCoordinate[]> data = analyzer.getLyapunovTrajectory(referenceDirectory, comparisonDirectory, progressDialog);
if(data==null) {
resultsLabel.setBackground(display.getSystemColor(SWT.COLOR_RED));
resultsLabel.setText(Messages.getString("LYA.ERROR1"));
} else {
comparisonValues.addAll(data);
//success... remember the users prefs
prefs.setRecentFolder(PRIMARY_FOLDER_KEY,referenceDirectory);
prefs.setRecentFolder(SECONDARY_FOLDER_KEY,comparisonDirectory);
cumulativeDeviation.addAll(ScenarioAnalysisSuite.getCumulativePhaseSpaceDeviation(comparisonValues));
//
// now udate everything
//
lyapunovTrajectoryCanvas.draw();
// Log the trajectory data
String outFileName = LYAPUNOV_FILE_PREFIX+"_"+
getScenarioNameFromDirectoryName(referenceDirectory)+
"_"+
getScenarioNameFromDirectoryName(comparisonDirectory);
CSVAnalysisWriter writer = new CSVAnalysisWriter(outFileName);
writer.logData(2,comparisonValues);
// Log the cumulative deviation data
outFileName = LYAPUNOV_DEVIATION_FILE_PREFIX+"_"+
getScenarioNameFromDirectoryName(referenceDirectory)+
"_"+
getScenarioNameFromDirectoryName(comparisonDirectory);
CSVAnalysisWriter writer2 = new CSVAnalysisWriter(outFileName);
writer2.logData(cumulativeDeviation);
timeSeriesCanvas.draw();
resultsLabel.setText(Messages.getString("LYA.COMPLETE"));
}
} catch(ScenarioInitializationException sie) {
Activator.logError("", sie);
}
// done
}
});
} // createContents
/**
* @param dirName
* @return short name of scenario
*/
public static String getScenarioNameFromDirectoryName(String dirName) {
int last = dirName.lastIndexOf("/");
int last2 = dirName.lastIndexOf("\\");
if (last2 > last)
last = last2;
if (last <= 0)
last = 0;
String retVal = dirName.substring(last + 1, dirName.length());
return retVal;
}
/**
* This returns the results of a comparison of type comparisonType
* as an array of double.
*
* @param trajectory the trajectory to return
* @return comparison
*/
public PhaseSpaceCoordinate[] getPointValues(int trajectory) {
return comparisonValues.get(trajectory);
}
/**
* returns the analysis of lyapunov tractory(ies) relative to reference.
* @param chartIndex not used (only one chart)
* @param trajectory
* @return Cumulative deviation from reference trajectory
*/
@SuppressWarnings("boxing")
@Override
public double[] getValues(int chartIndex, int trajectory) {
EList<Double> l = cumulativeDeviation.get(trajectory);
double [] res = new double[l.size()];
for(int i=0;i<res.length;++i) res[i] = l.get(i);
return res;
}
/**
* Not used
* @param chartIndex not used (only one chart)
* @param state
* @return property name
*/
@Override
public String getProperty(int chartIndex, int state) {
return Messages.getString("LYA.DIVERGENCEYAXIS");
}
/**
* Only one property to plot = the RMS difference
* @param chartIndex not used (only one chart)
* @return the number of properties
* @see org.eclipse.stem.util.analysis.views.AnalysisControl#getNumProperties(int chartIndex)
*/
@Override
public int getNumProperties(int chartIndex) {
return 1;
}
/**
* to remove the control e.g. by a remove button event
*/
@Override
public void remove() {
updateStatusLabel();
}
protected void updateStatusLabel() {
statusLabel.setText(Messages.getString("COMMON.STATUS"));
}
/**
* Initialize the header label
*
* @param folderName
*/
@Override
protected void initializeHeader(String folderName) {
simulationNameLabel.setText("analyzing "+folderName);
} // initializeFromSimulation
/**
* @see org.eclipse.swt.widgets.Widget#dispose()
*/
@Override
public void dispose() {
super.dispose();
} // dispose
/**
* Each Control class may add objects to this map
* @return the control parameters maps
*/
public Map<String, Object> getControlParametersMap() {
// add nothing for now
return controlParametersMap;
}
} // EstimatorControl