Skip to content

Commit 0891eee

Browse files
Merge pull request #23 from geo-engine/esa-bic
ESA BIC post
2 parents c016965 + 071a7e1 commit 0891eee

File tree

11 files changed

+149
-24
lines changed

11 files changed

+149
-24
lines changed

.github/workflows/check.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ jobs:
1313
steps:
1414
- name: Checkout code
1515
uses: actions/checkout@v4
16+
- name: Setup Node.js
17+
uses: actions/setup-node@v4
18+
with:
19+
node-version: '22'
1620
- name: Install
1721
run: npm install
1822
- name: Check formatting and lints

.github/workflows/deploy.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ jobs:
2323
uses: withastro/action@v3
2424
with:
2525
path: . # The root location of your Astro project inside the repository. (optional)
26-
# node-version: 20 # The specific version of Node that should be used to build your site. Defaults to 20. (optional)
26+
node-version: 22 # The specific version of Node that should be used to build your site. Defaults to 20. (optional)
2727
package-manager: npm # The Node package manager that should be used to install dependencies and build your site. Automatically detected based on your lockfile. (optional)
2828

2929
deploy:

astro.config.mjs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import tailwindcss from '@tailwindcss/vite';
33
import pagefind from 'astro-pagefind';
44
import icon from 'astro-icon';
55
import cookieconsent from '@jop-software/astro-cookieconsent';
6+
import equalPageNameValidator from './src/integrations/equal-page-name-validator';
67

78
// https://astro.build/config
89
export default defineConfig({
@@ -14,6 +15,8 @@ export default defineConfig({
1415
},
1516

1617
integrations: [
18+
equalPageNameValidator('posts/', 'en/posts/'),
19+
equalPageNameValidator('data/', 'en/data/'),
1720
icon({
1821
iconDir: './src/images/icons',
1922
}),

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@
77
"build": "astro build",
88
"preview": "astro preview",
99
"astro": "astro",
10-
"check": "prettier --check . && eslint 'src/**/*.{js,astro}'"
10+
"check": "prettier --check . && eslint 'src/**/*.{js,astro}'",
11+
"prettier": "prettier"
1112
},
1213
"dependencies": {
1314
"@fontsource/poppins": "^5.2.7",

src/components/Post.astro

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,12 @@ const pageDescription = pageBody.slice(0, 200) + '…';
3434
font-size: 1.5rem;
3535
font-weight: s emibold;
3636
}
37+
div :global(h3) {
38+
margin-top: 1rem;
39+
margin-bottom: 1rem;
40+
font-size: 1.25rem;
41+
font-weight: semibold;
42+
}
3743
div :global(ul) {
3844
list-style-type: disc;
3945
padding-left: 1.5rem;
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
---
2+
title: 'Abschluss der ESA BIC Inkubation: ML-Pipeline für Erdbeobachtungsdaten'
3+
date: 2025-10-15
4+
image: ../../../images/posts/esa-bic-2025.png
5+
---
6+
7+
Wir haben unsere Inkubationsphase im ESA BIC Hessen (European Space Agency Business Incubation Centre) erfolgreich abgeschlossen.
8+
Das Programm stellte die notwendigen Ressourcen bereit, um die Geo Engine-Plattform zu einem leistungsstarken und benutzerfreundlichen Dienst für Machine Learning auf Erdbeobachtungsdaten auszubauen und die technologischen Grundlagen zu festigen.
9+
10+
Im Zentrum der Entwicklung stand eine Pipeline für Random Forest (RF) Machine Learning (ML), die es Nutzern erlaubt, moderne ML-Techniken direkt auf umfangreiche Satellitenbild-Zeitreihen anzuwenden.
11+
12+
### Wesentliche Erfolge und technologische Fortschritte
13+
14+
1. Standardisierter ML-Modellaustausch:
15+
Um eine maximale Flexibilität und Zukunftsfähigkeit zu gewährleisten, wurde das offene [ONNX-Format](https://onnx.ai/) integriert.
16+
Dies ermöglicht den standardisierten und effizienten Austausch sowie die Bereitstellung verschiedenster Machine-Learning-Modelle wie Random Forest, Gradient Boosted Trees und Convolutional Neural Networks.
17+
18+
2. Blaupausen für Anwender:
19+
Wir haben die Interaktion mit der Geo Engine durch die Bereitstellung von Modelltrainingsbeispielen in Form von Jupyter Notebooks (Blaupausen) vereinfacht.
20+
Diese Vorlagen ermöglichen es Nutzern, verfügbare Pipelines leicht anzupassen und auf ihre spezifischen Datensätze anzuwenden.
21+
22+
3. Fokus auf Copernicus-Daten:
23+
Die Pipeline nutzt die frei verfügbaren und hochauflösenden Sentinel-2-Daten des europäischen Copernicus-Programms.
24+
Validierte Anwendungsfälle umfassen die Landbedeckungsklassifizierung und die [Identifizierung dominanter Baumarten](/posts/dominant-tree-types) in Deutschland.
25+
26+
### Ausrichtung auf Nachhaltigkeit (ESG)
27+
28+
Die erfolgreiche Inkubation positioniert uns als entscheidenden Akteur für die datengestützte Nachhaltigkeitsanalyse.
29+
Die Plattform liefert präzise, faktenbasierte Erkenntnisse aus der Erdbeobachtung, die Unternehmen und Organisationen helfen, ihren Beitrag zu ESG-Zielen (Environmental, Social, Governance) nachzuweisen.
30+
Wir werden im kommenden Jahr eine Reihe von ESG-bezogenen Projekten starten, die auf den Fähigkeiten der Geo Engine aufbauen.
31+
32+
Die Inkubation wird von uns und dem ESA BIC als voller Erfolg gewertet und markiert einen bedeutenden Meilenstein in der Entwicklung der Geo Engine.
33+
34+
🛰️ Hier finden Sie das Video zum Projektabschluss: <https://youtu.be/1186CBUKm8Y> (englisch)
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
---
2+
title: 'Completion of ESA BIC Incubation: ML Pipeline for Earth Observation Data'
3+
date: 2025-10-15
4+
image: ../../../images/posts/esa-bic-2025.png
5+
---
6+
7+
We have successfully completed our incubation phase at the ESA BIC Hessen (European Space Agency Business Incubation Centre).
8+
The program provided the necessary resources to develop the Geo Engine platform into a powerful and user-friendly service for machine learning on Earth observation data and to solidify its technological foundation.
9+
10+
At the core of the development was a pipeline for Random Forest (RF) Machine Learning (ML), enabling users to apply modern ML techniques directly to extensive satellite image time series.
11+
12+
### Key Achievements and Technological Advances
13+
14+
1. Standardized ML Model Exchange:
15+
To ensure maximum flexibility and future-proofing, the open [ONNX format](https://onnx.ai/) was integrated.
16+
This allows for the standardized and efficient exchange and deployment of various machine learning models such as Random Forest, Gradient Boosted Trees, and Convolutional Neural Networks.
17+
18+
2. Blueprints for Users:
19+
We simplified interaction with the Geo Engine by providing model training examples in the form of Jupyter Notebooks (blueprints).
20+
These templates enable users to easily adapt available pipelines to their specific datasets.
21+
22+
3. Focus on Copernicus Data:
23+
The pipeline leverages the freely available and high-resolution Sentinel-2 data from the European Copernicus program.
24+
Validated use cases include land cover classification and the [identification of dominant tree species](/en/posts/dominant-tree-types) in Germany.
25+
26+
### Focus on Sustainability (ESG)
27+
28+
The successful incubation positions us as a relevant player in data-driven sustainability analysis.
29+
The platform delivers precise, fact-based insights from Earth observation, helping companies and organizations demonstrate their contributions to ESG (Environmental, Social, Governance) goals.
30+
In the coming year, we will launch a series of ESG-related projects built on the capabilities of the Geo Engine.
31+
32+
The incubation is considered a complete success by both us and the ESA BIC, marking a significant milestone in the development of the Geo Engine.
33+
34+
🛰️ Watch the project completion video here: <https://youtu.be/1186CBUKm8Y>

src/i18n/utils.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import {getRelativeLocaleUrl} from 'astro:i18n';
22
import {translations, defaultLang, pages} from './translations';
3-
import {redirectSearchParam} from '../pages/404.astro';
43

54
// export function getLangFromUrl(url: URL) {
65
// const [, lang] = url.pathname.split('/');
@@ -61,7 +60,7 @@ export function pageInOtherLocale(lang: LocaleString, currentPath: string) {
6160
if (path.startsWith('/en/')) {
6261
path = path.substring(4); // remove /en/
6362
}
64-
return getRelativeLocaleUrl(lang, path) + '?' + redirectSearchParam;
63+
return getRelativeLocaleUrl(lang, path);
6564
}
6665

6766
function localePagePrefix(lang: LocaleString): string {

src/images/posts/esa-bic-2025.png

1.04 MB
Loading
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
import type {AstroIntegration} from 'astro';
2+
3+
/**
4+
* Validates that for every page under pathA there is a corresponding page under pathB and vice versa.
5+
*/
6+
export default function equalPageNameValidator(pathA: string, pathB: string): AstroIntegration {
7+
if (!pathA || !pathB) {
8+
throw new Error('Both paths must be provided');
9+
}
10+
if (pathA === pathB) {
11+
throw new Error('The two paths must be different');
12+
}
13+
14+
// Canonicalize paths to always end with a slash
15+
if (!pathA.endsWith('/')) {
16+
pathA += '/';
17+
}
18+
if (!pathB.endsWith('/')) {
19+
pathB += '/';
20+
}
21+
22+
return {
23+
name: 'equal-page-name-validator',
24+
hooks: {
25+
'astro:build:done': ({logger, dir, pages}) => {
26+
logger.info(`Validating equal page names between ${pathA} and ${pathB}…`);
27+
28+
const aPages = new Set<string>();
29+
const bPages = new Set<string>();
30+
31+
for (const page of pages) {
32+
if (page.pathname.startsWith(pathA)) {
33+
aPages.add(page.pathname.substring(pathA.length));
34+
} else if (page.pathname.startsWith(pathB)) {
35+
bPages.add(page.pathname.substring(pathB.length));
36+
}
37+
}
38+
39+
if (aPages.size === 0) {
40+
logger.warn(`No pages found for path A: ${pathA}`);
41+
}
42+
if (bPages.size === 0) {
43+
logger.warn(`No pages found for path B: ${pathB}`);
44+
}
45+
46+
const difference = aPages.difference(bPages);
47+
const reverseDifference = bPages.difference(aPages);
48+
const totalDifferences = difference.size + reverseDifference.size;
49+
if (totalDifferences > 0) {
50+
logger.error(`Found ${totalDifferences} page(s) that do not have a counterpart:`);
51+
for (const page of difference) {
52+
logger.error(` - ${pathA}${page}`);
53+
}
54+
for (const page of reverseDifference) {
55+
logger.error(` - ${pathB}${page}`);
56+
}
57+
throw new Error(`Validation failed: ${totalDifferences} page(s) do not have a counterpart.`);
58+
}
59+
60+
logger.info(`All ${aPages.size} page(s) in ${pathA} have a counterpart in ${pathB} and vice versa.`);
61+
},
62+
},
63+
};
64+
}

0 commit comments

Comments
 (0)