Skip to content

Commit eae8151

Browse files
author
Billy Charlton
committed
4.0 blog
1 parent 5d7538e commit eae8151

15 files changed

+291
-26
lines changed

docs/CHANGELOG-header.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,4 @@ The list of changes is generated automatically based on the commit messages them
1010
- See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
1111

1212
- The SimWrapper code repository containing the full commit history is on GitHub at <https://github.com/simwrapper/simwrapper>.
13+

docs/CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,12 @@ The list of changes is generated automatically based on the commit messages them
1010
- See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
1111

1212
- The SimWrapper code repository containing the full commit history is on GitHub at <https://github.com/simwrapper/simwrapper>.
13+
1314
# Changelog
1415

1516
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
1617

17-
## 4.0.0 (2025-06-10)
18+
## 4.0.0 (2025-06-11)
1819

1920
Bump to version 4.0. New front page, file view, color scheme, event viewer (beta), map builder
2021
(beta), and updated Python (pip) package for running standalone or in server environments.

docs/assets/default-dashboard.png

305 KB
Loading

docs/assets/example-folder.jpg

2.84 KB
Loading

docs/guide-dashboards.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---
22
id: guide-dashboards
3-
title: 2. Dashboards in depth
3+
title: 3. Dashboards in depth
44
---
55

66
A dashboard is a page laid out with multiple charts, plots, and visualizations all together. You define the layout with a YAML configuration file which contains the types of plots and their configurations all in one place.

docs/guide-getting-started.md

Lines changed: 31 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3,42 +3,43 @@ id: guide-getting-started
33
title: 1. Getting started tutorial
44
---
55

6-
Welcome to SimWrapper! Let's get you up and running with the basics.
6+
Welcome to SimWrapper! Let's get you up and running with the basics. This guide uses sample data that's hopefully a lot like the data you have for your projects
77

8-
- This guide uses sample data that's hopefully a lot like the data you would have for your projects
9-
- Use Google Chrome or MS Edge for the guide. Other browsers (Firefox, Safari) require a [separate local HTTP server](file-management) to access local files; for now that's just a stumbling block to getting started.
8+
> ➡ Use a Chromium-based browser: **Chrome/Edge/Brave** and others, for this guide.<br/><br/>Other browsers (Firefox, Safari) can work, but require a [separate local HTTP server](file-management) to access local files on your computer. For now, that's just a stumbling block to getting started. Safari is a particularly bad browser for data visualization, since Apple doesn't support the latest APIs nor local file access, and Safari has the slowest Javascript engine! 🐳
109
1110
## How it works: SimWrapper and file-based configuration
1211

13-
Most MATSim/ActivitySim outputs such as the `*.xml.gz` files are too large to open in a web browser, so SimWrapper provides a set of _visualization plugins_ which can display something useful for you. Plugins exist for lots of things and the list is growing: link volumes, agent animations, aggregate area summaries, and more.
12+
Your transport simulation produces a lot of files for every run, some of them quite large! MATSim/ActivitySim outputs such as the `*.xml.gz` files are usually too big to open in a web browser. SimWrapper provides a set of _visualization plugins_ which load the raw data, or more often, load post-processed files which contain only the data that you wish to display. Plugins exist for lots of things and the list is growing: link volumes, agent animations, aggregate area summaries, and more.
1413

15-
Here's how it works: For every visualization you want to create, you write a small _configuration file_ and store it in the same folder as the inputs for that visualization. We use the YAML text format, which is a common configuration file format. For each properly named YAML file, one visualization thumbnail will appear in that folder when you navigate to the folder in SimWrapper. Clicking on the thumbnail will open that visualization full-screen.
14+
On top of this, you can collect various visualizations into _dashboards_ that you can lay out logically to help your users find the data they need.
1615

17-
Generally, a viz will require a specific set of inputs, and those inputs are usually the result of some _post-processing_ of the raw simulation outputs. It's up to you to do that post-processing and store the files in the same folder as your config file.
16+
Here's how it works: For every visualization or dashboard you want to create, you write a small _configuration file_ and store it in the same folder as the inputs for that visualization. These configs are in the simple [YAML text format](https://yaml.org/) and SimWrapper looks for YAML files with specific names to learn what it should read and display (more on this below).
17+
18+
Generally, a viz will require a specific set of inputs, and those inputs are either raw simulation outputs or the result of some _post-processing_ of the outputs. It's up to you to do that post-processing and store the resulting files in the same folder as your YAML config files.
1819

1920
Let's get started with some sample data.
2021

2122
## 1. Get the sample data and open it in SimWrapper
2223

2324
- Download [simwrapper-example-project.zip](https://github.com/simwrapper/simwrapper-example-project/archive/refs/heads/main.zip) from GitHub
2425
- Unzip the file somewhere you can find it easily - Desktop, home folder, etc.
25-
- Go to [simwrapper.github.io](https://simwrapper.github.io/site) and click `Add folder...` and browse to the folder you just created. Grant access to the folder so the SimWrapper site can see the files!
26-
- (If you are using Firefox, `cd` to the data folder and run `simwrapper here` to start the local HTTP server)
26+
- Go to https://simwrapper.app and click `View local files...` and browse to the folder you just created. Grant access to the folder so the SimWrapper website can see the files!
27+
- Click on the `data` folder. You will find dashboard examples and some raw data from a few MATSim runs.
28+
29+
If you are using Firefox, there is no "View local files" button. Instead `cd` to the data folder and run `simwrapper here` to start the local HTTP server. This requires first running `pip install simwrapper` to get the simwrapper command-line helper app. I suggest you use Chrome/Edge/Brave for this tutorial!
2730

2831
You should now see something similar to this:
2932

3033
<img src="assets/example-folder.jpg" style="border: 1px solid #ccc"><i>Example data folder</i></img>
3134

32-
## 2. Explore the samples
33-
3435
Each of the subfolders in the example project shows different map views and capabilities of SimWrapper -- network link plots, statistical charts, area maps (shapefiles), dashboards, and so on.
3536

36-
- Experiment with the various knobs and configuration settings to see how the visualizations can be manipulated
37-
- From your PC file browser, open up the `viz-*.yaml` files in each subfolder to see how each of the visualizations is defined in a readable text format.
37+
- Experiment with the various knobs and configuration settings in the visualizations to see how they can be manipulated
38+
- From your PC file explorer / Finder, find the YAML text files named`viz-*.yaml` in each subfolder to see how each of the visualizations is defined in a clear, readable text format.
3839
- Every visualization type has a different filename "prefix" to help you find them: e.g, `viz-map-*.yaml` are for shapefiles, `viz-link-*.yaml` are for MATSim network plots, and so on.
39-
- You can edit these YAML files, save, and click Reload on your browser to see how your changes affect the visualizations.
40+
- Try making a copy and editing these YAML files. Save and click `Reload` on your browser to see how your changes affect the visualizations.
4041

41-
## 3. Create a dashboard with some charts
42+
## 2. Create a dashboard with some charts
4243

4344
The dashboards subfolder shows how you can combine multiple visualizations into cohesive dashboards.
4445

@@ -49,17 +50,29 @@ See the [Dashboards in Depth](guide-dashboards) article to learn more about buil
4950

5051
## 4. Configuring dashboard templates for multiple run folders
5152

52-
In SimWrapper, everything is folder-based. So `viz-*.yaml` and `dashboard-*.yaml` files in a folder will automatically be detected and loaded based on their filenames.
53+
In SimWrapper, everything is file- and folder-based. So `viz-*.yaml` and `dashboard-*.yaml` files in a folder will automatically be detected and loaded, based on their filenames.
5354

5455
If you want to define dashboards that will be used for **multiple folders**, such as several runs for a particular project:
5556

56-
- **Create a folder** named `simwrapper` in the parent project directory.
57+
- **Create a folder** named `simwrapper` or `.simwrapper` in the parent project directory.
5758
- Move all dashboard, viz, and template YAMLs into that folder
5859
- Tweak any file paths as necessary, so that relative file names resolve properly.
5960
- The base folder for a dashboard is the _folder you are viewing_, not the dashboard template folder.
60-
- You can have multiple `simwrapper` folders all the way up your folder hierarchy; dashboard panels will be generated based on filename, and each found dashboard will be displayed as a tab on the folder view.
61+
- You can have multiple `simwrapper` folders all the way up your folder hierarchy; dashboard panels will be generated based on filename, and each found dashboard will be displayed as a tab on the dashboard.
62+
63+
## 5. More on YAML filenames
6164

62-
## 5. More details on visualizations and their YAML files
65+
SimWrapper looks in your folder for YAML files that follow specific naming conventions. That way, it won't try to read unrelated YAML files that you might have. But this means you must name your configuration files carefully! SimWrapper will **silently ignore all YAML files** that do not match these conventions:
66+
67+
- **`dashboard-*.yaml`** - these contain the configuration settings for dashboard panes. Each found file results in a left-side tab on the dashboard page, and that tab contains the dashboard contents specified in this file. For this reason, many users tend to number their dashboard configs so that the tabs always appear in a predictable order: `dashboard-1-summary.yaml`, `dashboard-2-mode-choice.yaml`, `dashboard-3-traffic.yaml` and so on.
68+
- **`viz-*.yaml`** - these contain individual map-based visualizations. Each of these will appear on the Files tab of a folder.
69+
- Each visualization plugin has a specific subname that must follow `viz-subname-...` in the filename: for example, the shapefile viewer would be `viz-map-*.yaml` while the xy-hexagon viewer is `viz-xy-*.yaml`. See the API reference for each plugin for examples.
70+
- Use these `viz-*` configs if you don't have the need to collate multiple vizes into dashboards, or if you want single visualizations to have their own URL that you can link to directly.
71+
- **`simwrapper-config.yaml`** - is a special top-level configuration for project sites that is described in detail on [Building a project site](guide-project-sites).
72+
73+
Note that in most cases, both `.yaml` and `.yml` file extensions are valid and honored.
74+
75+
## 6. Example roadway links visualization
6376

6477
Here is an example YAML config file for a link-volume summary:
6578

@@ -80,8 +93,6 @@ If you wanted to look at several different link volume plots from the same model
8093

8194
This is a very different paradigm than most "point and click" GIS tools, but we have found that the ability to script and cut/paste the config files has been a huge time saver and also reduces manual errors.
8295

83-
> Make sure that your files are allowed to be "world-readable" before you publish anything to public-svn! Once files are pushed to public-svn, they are not secured in any way; anyone on the internet can access them!
84-
8596
### Visualization types
8697

8798
Each visualization is described in the API Reference section of this documentation, including how to post-process your outputs if necessary, and how to define any configuration settings for your visualizations.
Lines changed: 198 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,198 @@
1+
---
2+
id: guide-dashboards-from-code
3+
title: 2. MATSim dashboards from code
4+
---
5+
6+
MATSim users should take advantage of the [MATSim SimWrapper Contrib](https://github.com/matsim-org/matsim-libs/tree/main/contribs/simwrapper) which makes building SimWrapper dashboards very easy.
7+
8+
Including the simwrapper contrib allows you to write Java code directly in your simulation that builds dashboards for you -- in most cases you don't need to write any YAML at all.
9+
10+
By adding a single line to your MATSim project config, you will get a _default SimWrapper dashboard_ that gets built automatically when you run your simulation. From there, you can add further project-specific dashboards as needed.
11+
12+
## Including the SimWrapper contrib
13+
14+
First, make sure the simwrapper contrib is included and activated in your project `pom.xml`:
15+
16+
```xml
17+
<dependencies>
18+
<!-- ... -->
19+
<dependency>
20+
<groupId>org.matsim.contrib</groupId>
21+
<artifactId>simwrapper</artifactId>
22+
<version>${matsim.version}</version>
23+
</dependency>
24+
</dependencies>
25+
```
26+
27+
Then, in your run class, add this one line wherever you add your other project modules:
28+
29+
```java
30+
controler.addOverridingModule(new SimWrapperModule())
31+
```
32+
33+
That's it. When you run your simulation, the contrib will automatically generate the necessary `dashboard-*.yaml` files in your output folder.<br/>Open [simwrapper.app](https://simwrapper.app), open your local output folder, and the dashboards should be there.
34+
35+
![default dashboard](assets/default-dashboard.png)
36+
37+
## Creating your own dashboards from code
38+
39+
Now that you have the default dashboard working, you can start adding your own dashboards.
40+
41+
There are fully-executed examples in the following open scenarios:
42+
43+
- https://github.com/matsim-scenarios/matsim-berlin
44+
- https://github.com/matsim-scenarios/matsim-leipzig
45+
46+
Explore the files in `src/main/java/org/matsim/dashboard` for examples on creating post-processed CSV outputs and the dashboard configurations.
47+
- In particular this example dashboard is very feature-rich: https://github.com/matsim-scenarios/matsim-leipzig/blob/main/src/main/java/org/matsim/dashboard/CycleHighwayDashboard.java
48+
49+
### IntelliJ autocomplete
50+
51+
While writing your dashboard code, take advantage of IntelliJ's autocomplete feature. At each step of writing the code below, pressing `Tab` after any of the dots will drop down an autocomplete with all of the YAML parameters available on that object. This is far less error-prone than trying to decipher the YAML configuration options from the SimWrapper documentation itself.
52+
53+
The SimWrapper docs are the primary source of truth, however. If you find discrepancies between what IntelliJ thinks and what the SimWrapper docs say, try both and report back to us if there are problems!
54+
55+
**Example dashboard-building Java code:**
56+
```java
57+
Config config = ConfigUtils.createConfig();
58+
59+
SimWrapper sw = SimWrapper.create(config);
60+
61+
SimWrapperConfigGroup simwrapperCfg = ConfigUtils.addOrGetModule(config, SimWrapperConfigGroup.class);
62+
simwrapperCfg.defaultDashboards = SimWrapperConfigGroup.Mode.disabled;
63+
simwrapperCfg.sampleSize = 0.25;
64+
simwrapperCfg.defaultParams().mapCenter = "12.38,51.34";
65+
simwrapperCfg.defaultParams().mapZoomLevel = 6.8;
66+
67+
//skip default dashboards
68+
simwrapperCfg.defaultDashboards = SimWrapperConfigGroup.Mode.disabled;
69+
70+
//add dashboards according to command line parameters
71+
if (cycleHighwayAnalysis == CycleHighwayAnalysis.ENABLED) {
72+
sw.addDashboard(Dashboard.customize(new CycleHighwayDashboard(baseDir, shp.getShapeFile(), highwaysShpPath)).context("cycle-highway"));
73+
}
74+
75+
try {
76+
sw.generate(runDirectory);
77+
sw.run(runDirectory);
78+
} catch (IOException e) {
79+
throw new InterruptedIOException();
80+
}
81+
```
82+
83+
**Snippet from CycleHighwayDashboard.java:**
84+
```java
85+
package org.matsim.dashboard;
86+
87+
import org.matsim.analysis.CycleHighwayAnalysis;
88+
import org.matsim.application.analysis.traffic.TrafficAnalysis;
89+
import org.matsim.application.prepare.network.CreateGeoJsonNetwork;
90+
import org.matsim.simwrapper.Dashboard;
91+
import org.matsim.simwrapper.Header;
92+
import org.matsim.simwrapper.Layout;
93+
import org.matsim.simwrapper.viz.*;
94+
import tech.tablesaw.plotly.traces.BarTrace;
95+
96+
import java.util.ArrayList;
97+
import java.util.List;
98+
99+
/**
100+
* Shows information about an optional policy case, which implements cycle highways in Leipzig.
101+
* It also compares the agents and their trips using the cycle highways with their respective trips in the base case.
102+
*/
103+
public class CycleHighwayDashboard implements Dashboard {
104+
private final String basePath;
105+
private final String shp;
106+
private final String highwaysShp;
107+
108+
CycleHighwayDashboard(String basePath, String shp, String highwaysShp) {
109+
if (!basePath.endsWith("/")) basePath += "/";
110+
this.basePath = basePath;
111+
this.shp = shp;
112+
this.highwaysShp = highwaysShp;
113+
}
114+
115+
@Override
116+
public void configure(Header header, Layout layout) {
117+
header.title = "Cycle Highways Dashboard";
118+
header.description = "Shows statistics about agents, who used the newly implemented cycle highway " +
119+
"and compares to the corresponding trips in the base case.";
120+
121+
String[] args = new ArrayList<>(List.of("--base-path", basePath, "--shp", shp, "--highways-shp-path", highwaysShp)).toArray(new String[0]);
122+
123+
layout.row("first")
124+
.el(Tile.class, (viz, data) -> {
125+
viz.dataset = data.compute(CycleHighwayAnalysis.class, "mean_travel_stats.csv", args);
126+
viz.height = 0.1;
127+
});
128+
129+
layout.row("modalSplit")
130+
.el(Plotly.class, (viz, data) -> {
131+
viz.title = "Modal split";
132+
133+
viz.layout = tech.tablesaw.plotly.components.Layout.builder()
134+
.barMode(tech.tablesaw.plotly.components.Layout.BarMode.STACK)
135+
.build();
136+
137+
Plotly.DataSet ds = viz.addDataset(data.compute(CycleHighwayAnalysis.class, "mode_share.csv", args))
138+
.constant(SOURCE, "Policy")
139+
.aggregate(List.of(MAIN_MODE), SHARE, Plotly.AggrFunc.SUM);
140+
141+
Plotly.DataSet dsBase = viz.addDataset(data.compute(CycleHighwayAnalysis.class, "mode_share_base.csv", args))
142+
.constant(SOURCE, "Base")
143+
.aggregate(List.of(MAIN_MODE), SHARE, Plotly.AggrFunc.SUM);
144+
145+
viz.mergeDatasets = true;
146+
147+
viz.addTrace(BarTrace.builder(Plotly.OBJ_INPUT, Plotly.INPUT).orientation(BarTrace.Orientation.HORIZONTAL).build(),
148+
ds.mapping()
149+
.name(MAIN_MODE)
150+
.y(SOURCE)
151+
.x(SHARE)
152+
);
153+
154+
layout.row("locations")
155+
.el(Hexagons.class, (viz, data) -> {
156+
157+
viz.title = "Cycle highway trips - Origins";
158+
viz.center = data.context().getCenter();
159+
viz.zoom = data.context().mapZoomLevel;
160+
viz.height = 7.5;
161+
viz.width = 2.0;
162+
viz.file = data.compute(CycleHighwayAnalysis.class, "cycle_highway_agents_trip_start_end.csv");
163+
viz.projection = CRS;
164+
viz.addAggregation("trip origins", "person", "start_x", "start_y");
165+
})
166+
.el(Hexagons.class, (viz, data) -> {
167+
viz.title = "Cycle highway trips - Destinations";
168+
viz.center = data.context().getCenter();
169+
viz.zoom = data.context().mapZoomLevel;
170+
viz.height = 7.5;
171+
viz.width = 2.0;
172+
viz.file = data.compute(CycleHighwayAnalysis.class, "cycle_highway_agents_trip_start_end.csv");
173+
viz.projection = CRS;
174+
viz.addAggregation("trip destinations", "person", "end_x", "end_y");
175+
})
176+
177+
layout.row("volumes")
178+
.el(MapPlot.class, (viz, data) -> {
179+
viz.title = "Simulated traffic volume by bike";
180+
viz.center = data.context().getCenter();
181+
viz.zoom = data.context().mapZoomLevel;
182+
viz.height = 7.5;
183+
viz.width = 2.0;
184+
viz.setShape(data.compute(CreateGeoJsonNetwork.class, "network.geojson", "--with-properties", "--mode-filter", "car,freight,drt,bike"), "id");
185+
viz.addDataset(TRAFFIC, data.compute(TrafficAnalysis.class, "traffic_stats_by_link_daily.csv", "--transport-modes" , "car,bike,freight"));
186+
187+
viz.display.lineColor.dataset = TRAFFIC;
188+
viz.display.lineColor.columnName = "vol_bike";
189+
viz.display.lineColor.join = "link_id";
190+
viz.display.lineColor.setColorRamp(ColorScheme.RdYlBu, 5, true);
191+
viz.display.lineWidth.dataset = TRAFFIC;
192+
viz.display.lineWidth.columnName = "vol_bike";
193+
viz.display.lineWidth.scaleFactor = 20000d;
194+
viz.display.lineWidth.join = "link_id";
195+
});
196+
}
197+
}
198+
```

0 commit comments

Comments
 (0)