Apr 20, 2025

3 min read

England is My Polluted City

JavaFX app to display historical air pollution data of the whole UK on an interactive map.

England is My Polluted City post cover image

This project implements a fully functional JavaFX Application to display historical Air Pollution Data of the whole United Kingdom on an interactive map. Users are able to explore the historic pollution levels between 2018 and 2023 on a colour coded map, as well as view detailed location and pollution data at specific data points. There are many quality of life features implemented, such as a robust GUI to filter through different years and pollutants, an extensive statistics framework, as well as a “colourblind mode” to make the pollution viewer more accessible.

As a group, we actually made something great. We went over and beyond — as we head out from the very start. The project has over 8.5 thousand lines of code. And it has a lot of fascinating features: LODs, entire map, API integration, polygon culling, multithreading, and caching of many of the calculations.

polluted-2.png

polluted-5.png

Me

What I contributed to the project is the statistics framework and caching.

Statistics

As you can see from the tree structure of the statistics package, I tried making the framework as modular as possible, where it’s really easy to add an additional statistical data to the UI.

1
statistics
2
├── back
3
│ ├── calculators
4
│ │ ├── AllPollutionsCalculator.java
5
│ │ ├── DistributionAnalysisCalculator.java
6
│ │ ├── HistogramCalculator.java
7
│ │ ├── PollutionExtremesCalculator.java
8
│ │ └── TrendsCalculator.java
9
│ ├── StatisticsCalculator.java
10
│ └── StatisticsManager.java
11
├── types
12
│ ├── AllPollutionsResult.java
13
│ ├── DistributionAnalysisResult.java
14
│ ├── DistributionYearlyMetric.java
15
│ ├── HistogramResult.java
16
│ ├── PollutionExtremesResult.java
17
│ ├── StatisticsResult.java
18
│ └── TrendsResult.java
19
└── ui
20
├── components
21
│ ├── DataTablePanel.java
22
│ ├── HistogramChartPanel.java
23
│ ├── LineChartPanel.java
24
│ └── LogarithmicAxis.java
25
├── panels
26
│ ├── AllPollutionsPanel.java
27
│ ├── DistributionAnalysisPanel.java
28
│ ├── HistogramPanel.java
29
│ ├── PollutionExtremesPanel.java
30
│ └── TrendsPanel.java
31
├── StatisticsPanel.java
32
└── StatisticsPanelFactory.java
33
34
7 directories, 25 files

After creating the Calculator, Panel, and the Result type , you can add it into the panel factory and it’s all done:

1
return switch (result) {
2
case TrendsResult stResult -> new TrendsPanel(stResult);
3
case PollutionExtremesResult peResult -> new PollutionExtremesPanel(peResult);
4
case AllPollutionsResult apResult -> new AllPollutionsPanel(apResult);
5
case DistributionAnalysisResult daResult -> new DistributionAnalysisPanel(daResult);
6
case HistogramResult hResult -> new HistogramPanel(hResult);
7
default -> throw new IllegalArgumentException("Unsupported statistics result type: " + result.getClass().getName());
8
};

polluted-3.png

polluted-4.png

Caching

One thing I did throughout the codebase is to cache a lot of the results, including statistical, csv data, and LOD. Well, it does take up around 3GB of memory, so maybe not the best of ideas. But, it still speeds up the app considerable, especially going back and forth between the statistics and map views.

Concurrency is a lie

I tried adding some proper threading into the application, but I just couldn’t manage to do it. I tried having JavaFX on a different thread and fiddled with CompletableFuture objects, but to no avail.


§