package uk.ac.ed.inf.biopepa.ui.wizards.export; import java.util.LinkedList; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.IPath; import org.eclipse.jface.wizard.Wizard; import org.eclipse.jface.wizard.WizardPage; import org.eclipse.swt.SWT; import org.eclipse.swt.events.ModifyEvent; import org.eclipse.swt.events.ModifyListener; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.events.SelectionListener; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Combo; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Text; import org.eclipse.ui.dialogs.SaveAsDialog; import uk.ac.ed.inf.biopepa.core.sba.FileStringConsumer; import uk.ac.ed.inf.biopepa.core.sba.SBAModel; import uk.ac.ed.inf.biopepa.core.sba.export.BioNessieTraceLog; import uk.ac.ed.inf.biopepa.core.sba.export.ManyTraceLogger; import uk.ac.ed.inf.biopepa.core.sba.export.SimulationTracer; import uk.ac.ed.inf.biopepa.core.sba.export.SimulationTracer.NullTraceLog; import uk.ac.ed.inf.biopepa.core.sba.export.SimulationTracer.SimulationTraceLog; import uk.ac.ed.inf.biopepa.core.sba.export.TraviandoExport.TraviandoTraceLog; import uk.ac.ed.inf.biopepa.ui.interfaces.BioPEPAModel; import uk.ac.ed.inf.biopepa.ui.interfaces.IResourceProvider; import uk.ac.ed.inf.biopepa.ui.wizards.timeseries.PhasesPage; public class SimulationDistributionsWizard extends Wizard implements IResourceProvider { BioPEPAModel model; private ExportPage exportPage; private PhasesPage phasesPage; public SimulationDistributionsWizard(BioPEPAModel model) { if(model == null) throw new NullPointerException("Error; model does not exist."); this.model = model; setHelpAvailable(false); setWindowTitle("Export options for Bio-PEPA"); } private class ExportPage extends WizardPage { private Combo targetNameCombo; private Text targetValueText; private Text stopTimeText; private Text dataPointsText; private Text numberRunsText; protected ExportPage(String pageName) { super(pageName); this.setTitle("Simulation Distributions"); this.setDescription("Use simulation runs to calculate the probability " + "for a species to reach a particular population " + "size by each time point"); } private int textStyle = SWT.RIGHT | SWT.BORDER; private int labelStyle = SWT.SINGLE | SWT.LEFT; private String[] combineStringArrays(String[] l, String[] r){ String[] result = new String[l.length + r.length]; for (int index = 0; index < l.length; index++){ result[index] = l[index]; } for (int index = 0; index < r.length; index++){ result[index + l.length] = r[index]; } return result; } public void createControl(Composite parent) { Composite composite = new Composite(parent, SWT.NONE); composite.setLayout(new GridLayout()); setControl(composite); // Create an inner composite for the labels and text fields Composite labelsComposite = new Composite(composite, SWT.NONE); GridLayout labelsCompLayout = new GridLayout(2, false); labelsComposite.setLayout(labelsCompLayout); Label targetNameLabel = new Label(labelsComposite, labelStyle); targetNameLabel.setText ("Choose the dynamic component: "); targetNameCombo = new Combo(labelsComposite, SWT.READ_ONLY); String[] varNames = model.getDynamicVariableNames(); String[] compNames = model.getComponentNames(); String[] choices = combineStringArrays(varNames, compNames); targetNameCombo.setItems(choices); targetNameCombo.select(0); Label targetValueLabel = new Label(labelsComposite, labelStyle); targetValueLabel.setText ("Enter target value"); targetValueText = new Text (labelsComposite, textStyle); targetValueText.setText (Integer.toString(this.defaultTargetValue)); Label stopTimeLabel = new Label(labelsComposite, labelStyle); stopTimeLabel.setText("Set the stop time"); stopTimeText = new Text(labelsComposite, textStyle); stopTimeText.setText(Double.toString(this.defaultStopTime)); stopTimeText.setLayoutData(newTextGridData()); stopTimeText.addModifyListener(modifyListener); Label explainNumberRuns = new Label (labelsComposite, labelStyle); explainNumberRuns.setText("The number of independent runs"); numberRunsText = new Text (labelsComposite, textStyle); numberRunsText.setText(Integer.toString(this.defaultNumberRuns)); numberRunsText.setLayoutData(newTextGridData()); numberRunsText.addModifyListener(modifyListener); Label explainDataPoints = new Label (labelsComposite, labelStyle); explainDataPoints.setText( "Set the increment in data point size for the graph"); // explainDataPoints.setEnabled(false); dataPointsText = new Text (labelsComposite, textStyle); dataPointsText.setText(Double.toString(this.defaultDataPointSize)); dataPointsText.setLayoutData(newTextGridData()); dataPointsText.addModifyListener(modifyListener); enableWidgets(); validate(); } /* * A simple method to create a grid data object for * text object, since I think it is better to create a * new one for each text object such that any changes are * not then global. */ private GridData newTextGridData (){ GridData textGridData = new GridData (); textGridData.widthHint = 80; textGridData.horizontalAlignment = GridData.FILL; textGridData.grabExcessHorizontalSpace = true; return textGridData; } private ModifyListener modifyListener = new ModifyListener (){ public void modifyText(ModifyEvent arg0) { validate (); } }; private void enableWidgets(){ /* if(displayGraph.getSelection()){ dataPointsText.setEnabled(true); } else { dataPointsText.setEnabled(false); } */ } private boolean isValidInt(Text textBox){ String text = textBox.getText().trim(); try { Integer.parseInt(text); } catch (Exception e){ return false; } return true; } private boolean isValidDouble(Text textBox){ String text = textBox.getText().trim(); try { Double.parseDouble(text); } catch (Exception e){ return false; } return true; } private void validate() { /* * I would actually prefer to set the page to * complete and then only set it to false if we * actually encounter an error. That way we could * report all errors. Unfortunately you can currently * only report one error. It doesn't really matter since * this gets called whenever the user makes a change * (eg. when fixing the current error) so they will always * be getting feedback. */ this.setPageComplete(false); this.setErrorMessage(null); // TODO: reorder these so that they are in the same // order as they appear on the page so that the user // can fix error in an intuitive order. if (!isValidDouble(dataPointsText)){ this.setPageComplete(false); this.setErrorMessage("Cannot parse data points"); return; } if (!isValidInt(targetValueText)){ this.setPageComplete(false); this.setErrorMessage ("Cannot parse target value"); return ; } if (!isValidDouble(stopTimeText)){ this.setPageComplete(false); this.setErrorMessage ("Cannot parse stop time"); return ; } if (!isValidInt(numberRunsText)){ this.setPageComplete(false); this.setErrorMessage ("Cannot parse number of runs"); return ; } // If we get this far without returning then the page // must be complete. this.setPageComplete(true); } public String getTargetIdentifier (){ int index = targetNameCombo.getSelectionIndex(); String[] items = targetNameCombo.getItems(); return items[index]; } private int defaultTargetValue = 20; public int getTargetValue (){ String text = targetValueText.getText().trim(); try { return Integer.parseInt(text); } catch (Exception e) { return this.defaultTargetValue; } } private double defaultStopTime = 20.0; public double getStopTime() { String text = stopTimeText.getText().trim(); try { return Double.parseDouble(text); } catch (Exception e) { return 0; } } private int defaultNumberRuns = 100; public int getNumberRuns (){ String runsText = numberRunsText.getText().trim(); if (!runsText.isEmpty()){ try{ return Integer.parseInt(runsText); } catch (Exception e){ return this.defaultNumberRuns; } } else { return this.defaultNumberRuns; } } /* public boolean getDisplayGraph(){ return displayGraph.getSelection(); } */ private double defaultDataPointSize = 0.1; public double getDataPointSize() { String text = dataPointsText.getText().trim(); if (text.isEmpty()) { return this.defaultDataPointSize; } else { try { return Double.parseDouble(text); } catch (Exception e) { return this.defaultDataPointSize; } } } } public void addPages (){ exportPage = new ExportPage("Export a Traviando Trace"); addPage (exportPage); /*phasesPage = new PhasesPage (model); addPage (phasesPage);*/ } @Override public boolean performFinish() { SBAModel sbaModel = model.getSBAModel(); IPath modelPath = model.getUnderlyingResource().getFullPath(); String modelName = modelPath.removeFileExtension().lastSegment(); SimulationTracer simTrace = new SimulationTracer(sbaModel); SimulationsDistributionJob simJob = new SimulationsDistributionJob(modelName); simJob.setTargetComp(exportPage.getTargetIdentifier()); simJob.setTargetValue(exportPage.getTargetValue()); simJob.setReplications(exportPage.getNumberRuns()); simTrace.setDataPointStep(exportPage.getDataPointSize()); // simTrace.setFiringsLimit(exportPage.getFiringsLimit()); simTrace.setTimeLimit(exportPage.getStopTime()); // Now we set up any defined phases, if these aren't // defined then they should be null and the // simulation trace engine will take care of that and // create one large phase lasting the entire simulation. // simTrace.setDelays(phasesPage.getDelays()); // simTrace.setPhaseLines(phasesPage.getPhaseLines()); // simJob.setDoGraph(exportPage.getDisplayGraph()); simJob.setSimulationTracer(simTrace); simJob.schedule(); return true; } public IResource getUnderlyingResource() { return model.getUnderlyingResource(); } }