In January 2021 we will introduce a 10 GB quota for project repositories. Higher limits for individual projects will be available on request. Please see https://doku.lrz.de/display/PUBLIC/GitLab for more information.

Commit 51b9e6f8 authored by Stefan Schuhbaeck's avatar Stefan Schuhbaeck

Merge branch 'gui_simulation_result' into 'master'

Gui simulation result

See merge request !139
parents 5f782e0c 689dd20e
Pipeline #309420 passed with stages
in 126 minutes and 11 seconds
......@@ -148,7 +148,14 @@
<artifactId>TableLayout</artifactId>
<version>20050920</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.jfree/jfreechart -->
<dependency>
<groupId>org.jfree</groupId>
<artifactId>jfreechart</artifactId>
<version>1.5.0</version>
</dependency>
<!-- movie & screenshot -->
<dependency>
<groupId>org.jcodec</groupId>
......
......@@ -79,12 +79,14 @@ ProjectView.startDialog.button2=Create Project
ProjectView.btnNewButton.text=New button
ProjectView.btnRunAllTests.text=Run all scenarios
ProjectView.mntmRunSelectetTests.text=Run selected scenario
ProjectView.mntmRunRepeatedlyTests.text=Run scenario 10x
ProjectView.mntmRunSelectedTests.text=Run selected scenarios
ProjectView.mntmSimulationResult.text=Show summary after simulation
ProjectView.btnToggleScenarioChecker.text=Activate ScenarioChecker
ProjectView.btnPauseRunningTests.text=Pause
ProjectView.btnRunSelectedTest.text=Run selected scenario
ProjectView.btnRunSelectedTest.toolTipText=Run selected scenario
ProjectView.btnRunRepeatedlyTest.toolTipText=Run scenario 10x
ProjectView.btnPauseRunningTests.toolTipText=Pause the scenario run
ProjectView.btnStopRunningTests.text=Stop running scenarios
ProjectView.btnResumeNormalSpeed.text=Resume
......
package org.vadere.gui.projectview.control;
import org.vadere.gui.projectview.model.ProjectViewModel;
import org.vadere.gui.projectview.view.VTable;
import org.vadere.simulator.projects.Scenario;
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.util.Collection;
public class ActionRunRepeatedlyScenarios extends AbstractAction {
private final ProjectViewModel model;
private final VTable scenarioTable;
private final int repetitions;
public ActionRunRepeatedlyScenarios(final String name, final ProjectViewModel model, final VTable scenarioTable, final int repetitions) {
super(name);
this.model = model;
this.repetitions = repetitions;
this.scenarioTable = scenarioTable;
}
@Override
public void actionPerformed(final ActionEvent e) {
if (model.runScenarioIsOk()) {
Collection<Scenario> scenarios = model.getScenarios(scenarioTable.getSelectedRows());
// make sure only one scenario is chosen
if(scenarios.size()>1){
throw new IllegalArgumentException("Please select a single scenario for the stochastic evaluation");
}
Scenario singleScenario = scenarios.iterator().next();
for(int i_rep = 0; i_rep < repetitions; i_rep++)
scenarios.add(singleScenario);
model.getProject().runScenarios(scenarios);
model.getProject().getSimulationResults();
}
}
}
package org.vadere.gui.projectview.view;
import org.apache.commons.collections.MultiMap;
import org.apache.commons.collections.map.MultiValueMap;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.StandardXYBarPainter;
import org.jfree.chart.renderer.xy.XYBarRenderer;
import org.jfree.data.statistics.HistogramDataset;
import org.vadere.gui.components.utils.Messages;
import org.vadere.gui.projectview.model.ProjectViewModel;
import org.vadere.simulator.projects.ProjectFinishedListener;
......@@ -16,7 +24,11 @@ import java.io.OutputStreamWriter;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.LinkedList;
import java.util.*;
import java.util.stream.Collectors;
import org.jfree.data.xy.DefaultXYDataset;
import org.jfree.data.xy.XYDataset;
import org.jfree.chart.ChartPanel;
import javax.swing.*;
......@@ -66,7 +78,8 @@ public class ProjectRunResultDialog implements ProjectFinishedListener {
class ResultDialog extends JDialog {
Button btnOk, btnCsv;
private JTable table;
JPanel main;
JPanel main_panel;
JPanel plots_panel;
JScrollPane scrollPane;
JPanel btnPane;
LinkedList<SimulationResult> data;
......@@ -75,14 +88,66 @@ public class ProjectRunResultDialog implements ProjectFinishedListener {
ResultDialog(ProjectView projectView, LinkedList<SimulationResult> data) {
super(projectView);
this.data = data;
main = new JPanel();
main.setLayout(new BoxLayout(main, BoxLayout.PAGE_AXIS));
main_panel = new JPanel();
main_panel.setLayout(new BoxLayout(main_panel, BoxLayout.PAGE_AXIS));
table = new JTable(getData(data), data.getFirst().getHeaders());
table.setFillsViewportHeight(true);
table.doLayout();
scrollPane = new JScrollPane(table);
main.add(scrollPane);
main_panel.add(scrollPane);
// add new panel for results plots
plots_panel = new JPanel();
FlowLayout plots = new FlowLayout(); // next to each other
plots_panel.setLayout(plots);
JScrollPane sPannel = new JScrollPane(plots_panel);
// Code histograms
// collect scenario names that are in the ProjectRunResultDialog
Set<String> scenarios = data.stream().map(SimulationResult::getScenarioName).collect(Collectors.toSet());
if( scenarios.size() == 1 && data.size() > 1) { // only one scenario was run, but multiple times
// merge results from all runs into one MultiValueMap (allows duplicate entries)
MultiMap mergedResults = new MultiValueMap();
data.forEach(d -> mergedResults.putAll(d.getData()));
Iterator iterator = mergedResults.entrySet().iterator();
// collect all results for one processor
while(iterator.hasNext()) {
Map.Entry element = (Map.Entry) iterator.next();
ArrayList<Double> values = (ArrayList) element.getValue();
double[] values_arr = values.stream().mapToDouble(Double::doubleValue).toArray();
var dataset = new HistogramDataset();
double mean = values.stream().mapToDouble(d->d).sum()/values.size();
dataset.addSeries("mean="+mean, values_arr, 10);
JFreeChart histogram = ChartFactory.createHistogram((String) element.getKey(),
"", "", dataset);
XYPlot xyplot = histogram.getXYPlot();
xyplot.setForegroundAlpha(0.7F);
xyplot.setBackgroundPaint(Color.WHITE);
xyplot.setDomainGridlinePaint(new Color(150, 150, 150));
xyplot.setRangeGridlinePaint(new Color(150, 150, 150));
XYBarRenderer renderer = (XYBarRenderer) xyplot.getRenderer();
renderer.setShadowVisible(false);
renderer.setDrawBarOutline(true);
renderer.setBarPainter(new StandardXYBarPainter());
ChartPanel cp_hist = new ChartPanel(histogram);
cp_hist.setPreferredSize(new Dimension(500/mergedResults.size(), 500/mergedResults.size()));
plots_panel.add(cp_hist);
}
main_panel.add(sPannel);
}
btnOk = new Button(Messages.getString("SettingsDialog.btnClose.text"));
btnOk.addActionListener(this::btnOKListener);
......@@ -96,22 +161,110 @@ public class ProjectRunResultDialog implements ProjectFinishedListener {
btnPane.add(btnCsv);
Container c = getContentPane();
c.add(main, BorderLayout.CENTER);
c.add(main_panel, BorderLayout.CENTER);
c.add(btnPane, BorderLayout.PAGE_END);
setTitle(Messages.getString("ProjectView.label.simResults"));
setSize(600, 200);
setSize(600, 400);
}
Object[][] getData(LinkedList<SimulationResult> data) {
Object[][] res = new Object[data.size()][5];
int n_rows = data.size();
Set<String> scenarios = data.stream().map(SimulationResult::getScenarioName).collect(Collectors.toSet());
if( scenarios.size() == 1 && data.size() > 1) { // only one scenario was run, but multiple times
n_rows += 5; // for mean, min, max, std
}
// todo: adapt for different processors among scenarios or make sure that all scenarios have the same processors defined
Object[][] res = new Object[n_rows][5]; // todo: replace static limitation of 5 (processors?)
int rowIdx = 0;
for (SimulationResult d : data) {
res[rowIdx] = d.getAsTableRow();
rowIdx++;
}
// collect scenario names that are in the ProjectRunResultDialog
if( scenarios.size() == 1 && data.size() > 1) { // only one scenario was run, but multiple times
// merge results from all runs into one MultiValueMap (allows duplicate entries)
MultiMap mergedResults = new MultiValueMap();
data.forEach(d -> mergedResults.putAll(d.getData()));
// iterate over keys
Iterator it = mergedResults.entrySet().iterator();
int n = mergedResults.entrySet().size();
Map<Object, Map> summaryStat = new HashMap();
String[] stats = new String[]{"min","max","mean","std"};
while (it.hasNext()) {
Map.Entry mapEntry = (Map.Entry) it.next();
if(mapEntry.getValue() instanceof ArrayList) {
ArrayList tmp_val = (ArrayList) mapEntry.getValue();
double min = -1;
double max = -1;
double mean = -1;
double std = -1;
HashMap tmp_summary = new HashMap<>();
if(tmp_val.get(0) instanceof Double){
ArrayList<Double> values = (ArrayList<Double>) mapEntry.getValue(); // todo: what if there is another data type (e.g. Long)
min= Collections.min(values); // min
max = Collections.max(values); // max
mean= 0; // mean
std = 0; // std
for (Double val : values) {
mean += val;
}
mean = mean / values.size();
for (Double val : values) {
std += (val - mean) * (val - mean);
}
std = std / (values.size() - 1);
std = Math.sqrt(std);
}else{
System.out.println("ProjectRunResultDialog: Type is not yet supported \n " + tmp_val.get(0).getClass());
}
tmp_summary.put("mean",mean);
tmp_summary.put("min", min);
tmp_summary.put("std", std);
tmp_summary.put("max", max);
summaryStat.put(mapEntry.getKey(), tmp_summary);
}else{
System.out.println("ProjectRunResultDialog: Type is not yet supported \n " + mapEntry.getValue().getClass());
}
}
String[] emptyString = new String[n+3];
java.util.Arrays.fill(emptyString,"");
res[rowIdx++] = emptyString; // separate summary stat.
for(int i_stat = 0; i_stat < stats.length; i_stat++){
int icol = 0;
String[] tmp_stat = new String[n+3];
tmp_stat[icol++] = "summaryStats: " + stats[i_stat];
tmp_stat[icol++] = "-";
for(int i_proc = 2; i_proc < data.getFirst().getHeaders().length-1; i_proc++){
tmp_stat[icol++] = summaryStat.get(data.getFirst().getHeaders()[i_proc]).get(stats[i_stat]).toString();
}
tmp_stat[icol] = "-";
res[rowIdx++] = tmp_stat;
}
}
return res;
}
......
......@@ -4,37 +4,7 @@ package org.vadere.gui.projectview.view;
import org.jetbrains.annotations.NotNull;
import org.vadere.gui.components.utils.Messages;
import org.vadere.gui.postvisualization.control.Player;
import org.vadere.gui.projectview.control.ActionAddScenario;
import org.vadere.gui.projectview.control.ActionCloneScenario;
import org.vadere.gui.projectview.control.ActionCloseApplication;
import org.vadere.gui.projectview.control.ActionCreateProject;
import org.vadere.gui.projectview.control.ActionDeleteOutputDirectories;
import org.vadere.gui.projectview.control.ActionDeleteScenarios;
import org.vadere.gui.projectview.control.ActionEditScenarioDescription;
import org.vadere.gui.projectview.control.ActionGenerateScenarioFromOutputFile;
import org.vadere.gui.projectview.control.ActionInterruptScenarios;
import org.vadere.gui.projectview.control.ActionLoadProject;
import org.vadere.gui.projectview.control.ActionLoadRecentProject;
import org.vadere.gui.projectview.control.ActionNextTimeStep;
import org.vadere.gui.projectview.control.ActionOpenInExplorer;
import org.vadere.gui.projectview.control.ActionOutputToScenario;
import org.vadere.gui.projectview.control.ActionPauseScenario;
import org.vadere.gui.projectview.control.ActionRenameOutputFile;
import org.vadere.gui.projectview.control.ActionRenameProject;
import org.vadere.gui.projectview.control.ActionRenameScenario;
import org.vadere.gui.projectview.control.ActionResumeNormalSpeed;
import org.vadere.gui.projectview.control.ActionRunAllScenarios;
import org.vadere.gui.projectview.control.ActionRunOutput;
import org.vadere.gui.projectview.control.ActionRunSelectedScenarios;
import org.vadere.gui.projectview.control.ActionSaveAsProject;
import org.vadere.gui.projectview.control.ActionSaveProject;
import org.vadere.gui.projectview.control.ActionSeeDiscardChanges;
import org.vadere.gui.projectview.control.ActionShowAboutDialog;
import org.vadere.gui.projectview.control.ActionToClipboard;
import org.vadere.gui.projectview.control.IOutputFileRefreshListener;
import org.vadere.gui.projectview.control.IProjectChangeListener;
import org.vadere.gui.projectview.control.ShowResultDialogAction;
import org.vadere.gui.projectview.control.ToggleScenarioManagerAction;
import org.vadere.gui.projectview.control.*;
import org.vadere.gui.projectview.model.ProjectViewModel;
import org.vadere.gui.projectview.model.ProjectViewModel.OutputBundle;
import org.vadere.gui.projectview.model.ProjectViewModel.ScenarioBundle;
......@@ -91,6 +61,8 @@ public class ProjectView extends JFrame implements ProjectFinishedListener, Sing
*/
private ProjectViewModel model;
private final int n_repetitions = 10;
/**
* GUI elements (part of the view) of the {@link ProjectView}
*
......@@ -104,6 +76,7 @@ public class ProjectView extends JFrame implements ProjectFinishedListener, Sing
private VTable scenarioTable;
private VTable outputTable;
private JButton btnRunSelectedScenario;
private JButton btnRunRepeatedlyScenario;
private JButton btnRunAllScenarios;
private JButton btnStopRunningScenarios;
private JButton btnPauseRunningScenarios;
......@@ -337,6 +310,7 @@ public class ProjectView extends JFrame implements ProjectFinishedListener, Sing
scenariosRunning = flag;
btnRunAllScenarios.setVisible(!flag);
btnRunSelectedScenario.setVisible(!flag);
btnRunRepeatedlyScenario.setVisible(!flag);
btnStopRunningScenarios.setVisible(flag);
btnPauseRunningScenarios.setVisible(flag);
btnNextSimulationStep.setVisible(flag);
......@@ -729,6 +703,8 @@ public class ProjectView extends JFrame implements ProjectFinishedListener, Sing
new ActionDeleteScenarios(Messages.getString("ProjectView.mntmDelete.text"), model, scenarioTable);
ActionRunSelectedScenarios runSelectedScenarios = new ActionRunSelectedScenarios(
Messages.getString("ProjectView.mntmRunSelectetTests.text"), model, scenarioTable);
ActionRunRepeatedlyScenarios runRepeatedlyScenarios = new ActionRunRepeatedlyScenarios(
Messages.getString("ProjectView.mntmRunRepeatedlyTests.text"), model, scenarioTable, n_repetitions);
ActionSeeDiscardChanges seeDiscardChangesAction = new ActionSeeDiscardChanges(
Messages.getString("ActionSeeDiscardChanges.menu.title"), model, scenarioTable);
......@@ -781,6 +757,17 @@ public class ProjectView extends JFrame implements ProjectFinishedListener, Sing
addToProjectSpecificActions(runSelectedScenarios);
mainButtonsGroup.add(btnRunSelectedScenario);
ActionRunRepeatedlyScenarios runRepeatedlyScenarios = new ActionRunRepeatedlyScenarios(
Messages.getString("ProjectView.mntmRunRepeatedlyTests.text"), model, scenarioTable, n_repetitions);
runRepeatedlyScenarios.putValue(Action.SHORT_DESCRIPTION,
Messages.getString("ProjectView.btnRunRepeatedlyTest.toolTipText"));
runRepeatedlyScenarios.putValue(Action.LARGE_ICON_KEY,
new ImageIcon(ProjectView.class.getResource("/icons/greenarrow_right_small.png")));
btnRunRepeatedlyScenario = new JButton(runRepeatedlyScenarios);
toolBar.add(btnRunRepeatedlyScenario);
addToProjectSpecificActions(runRepeatedlyScenarios);
mainButtonsGroup.add(btnRunRepeatedlyScenario);
Action interruptScenariosAction =
new ActionInterruptScenarios(Messages.getString("ProjectView.btnStopRunningTests.text"), model);
interruptScenariosAction.putValue(Action.LARGE_ICON_KEY,
......
......@@ -29,6 +29,14 @@ public class SimulationResult {
this.data = new TreeMap<>();
}
public String getScenarioName(){
return this.scenarioName;
}
public TreeMap<String,Object> getData(){
return this.data;
}
public void addData(@NotNull final String header, @NotNull final Object value) {
assert !data.containsKey(header);
if(data.containsKey(header)) {
......
......@@ -15,7 +15,7 @@ import java.util.OptionalDouble;
*
*/
@DataProcessorClass()
public class FlowProcessor extends DataProcessor<NoDataKey, Double> {
public class FlowProcessor extends NoDataKeyProcessor<Double> {
private PedestrianLineCrossProcessor pedLineCross;
public FlowProcessor() {
......
......@@ -28,6 +28,7 @@ public abstract class NoDataKeyProcessor<V> extends DataProcessor<NoDataKey, V>
@Override
public void postLoopAddResultInfo(@NotNull final SimulationState state, @NotNull final SimulationResult result){
result.addData(getSimulationResultHeader(), getValue(NoDataKey.key()));
result.addData(getSimulationResultHeader() + " (PID" + getId() + ")", getValue(NoDataKey.key()));
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment