Skip to content

Commit

Permalink
Merge pull request #27 from julianrojas87/dev
Browse files Browse the repository at this point in the history
v1.4.1
  • Loading branch information
julianrojas87 authored Mar 12, 2021
2 parents 5a3df03 + 64294cf commit 99aa1dc
Show file tree
Hide file tree
Showing 11 changed files with 146 additions and 29 deletions.
4 changes: 4 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
node_modules/
dist/
*.md
.env
29 changes: 29 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
### Multi-stage Docker image

# STAGE 1: Start from a Node.js ready container
FROM node:latest AS RCC
# Create a new directory for app files
RUN mkdir -p /opt/era-compatiblity-check
# Set working directory in the container
WORKDIR /opt/era-compatiblity-check
# Copy source files
COPY . .
# Install dependencies
RUN npm install
# Install envsub to parse environment variables
RUN npm install -g envsub
# Define config variables
ARG ERA_GEO_API=http://era.ilabt.imec.be/ldf
ARG ZOOM=10
ARG FACETED_BASE_URI=https://linked.ec-dataplatform.eu/describe/?url=
# Parse env variables and build app for production
RUN envsub ./src/config/config.js && npm run build

# STAGE 2: Start from NGINX ready container
FROM nginx
# Copy built application from stage 1
COPY --from=RCC /opt/era-compatiblity-check/dist /usr/share/nginx/html
# Expose HTTP default port
EXPOSE 80
# Start NGINX
CMD ["nginx", "-g", "daemon off;"]
70 changes: 69 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,70 @@
# era-compatibility-check
React application that performs route compatibility check over the ERA Knowledge Graph

Web application to perform route compatibility checks based on data from the [ERA Knowledge Graph](https://linked.ec-dataplatform.eu/sparql).

## Deploy WITH Docker

This application has been _dockerized_ to facilitate its deployment. We use a [multi-stage approach](https://docs.docker.com/develop/develop-images/multistage-build/) to build a container that makes publishes a build of this Web application via a NGINX instance.

To deploy this container follow these steps:

1. Make sure to have a recent version of [Docker](https://docs.docker.com/engine/install/) installed.

2. Set the application's configuration parameters and build the Docker image:

```bash
docker build -t era-rcc \
--build-arg ERA_GEO_API=http://era.ilabt.imec.be/ldf \
--build-arg ZOOM=10 \
--build-arg FACETED_BASE_URI=https://linked.ec-dataplatform.eu/describe/?url= \
./
```

Three configuration parameters need to be when building this image:

- `ERA_GEO_API`: URL of the [geospatial API](https://github.com/julianrojas87/era-ldf/) that runs over the ERA KG.
- `ZOOM`: Zoom level at which the geospatial data tiles are defined. According to the [Slippy Tiles spec](https://wiki.openstreetmap.org/wiki/Slippy_map_tilenames#Zoom_levels), the zoom parameter is an integer between 0 (zoomed out) and 18 (zoomed in).
- `FACETED_BASE_URI`: Base URL to make entities in the application dereferenceable over the configured triple store.

3. Start the application:

```bash
docker run -p ${PORT}:80 era-rcc
```

Replace `${PORT}` for the TCP port where you want to run the application.

## Deploy WITHOUT Docker

To directly build this application you need to install first:

- [Node.js](https://nodejs.org/en/download/) at least v12.

Then follow these steps:

1. Clone this repository:

```bash
git clone https://github.com/julianrojas87/era-compatibility-check.git
```

2. Go inside the cloned folder and install the dependencies:

```bash
npm install
```

3. Build the application:

```bash
npm run build
```

4. Publish the compiled static site:

```bash
cd dist
npx http-server -p 8080
```

The above commands will publish the application at `http://localhost:8080`.
4 changes: 2 additions & 2 deletions src/algorithm/PathFinder.js
Original file line number Diff line number Diff line change
Expand Up @@ -240,8 +240,8 @@ export class PathFinder extends EventEmitter {
});

if (npt) {
const lat = parseFloat(npt[np][WGS84.latitude]);
const long = parseFloat(npt[np][WGS84.longitude]);
const lat = parseFloat(npt[np][WGS84.lat]);
const long = parseFloat(npt[np][WGS84.long]);
await this.props.fetchAbstractionTile({ coords: [long, lat], force: force });
}
}
Expand Down
12 changes: 6 additions & 6 deletions src/components/RoutesInfo.js
Original file line number Diff line number Diff line change
Expand Up @@ -169,22 +169,22 @@ export class RoutesInfo extends Component {
// Implementation tile for this OP hasn't been fetched yet
const npDetails = Utils.getNodePortInfo(np, this.props.graphStore);
await this.props.fetchImplementationTile([
parseFloat(npDetails[WGS84.longitude]),
parseFloat(npDetails[WGS84.latitude])
parseFloat(npDetails[WGS84.long]),
parseFloat(npDetails[WGS84.lat])
]);
op = Utils.getOperationalPointFromMicroNode(mn, this.props.graphStore);

// Force tile fetch, most likely necessary due to wrong caching
if (!op) {
await Promise.all([
this.props.fetchImplementationTile([
parseFloat(npDetails[WGS84.longitude]),
parseFloat(npDetails[WGS84.latitude])
parseFloat(npDetails[WGS84.long]),
parseFloat(npDetails[WGS84.lat])
], true),
this.props.fetchAbstractionTile({
coords: [
parseFloat(npDetails[WGS84.longitude]),
parseFloat(npDetails[WGS84.latitude])
parseFloat(npDetails[WGS84.long]),
parseFloat(npDetails[WGS84.lat])
],
force: true
})
Expand Down
24 changes: 14 additions & 10 deletions src/config/config.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@

export const ERA_VOCABULARY = 'http://era.ilabt.imec.be/ldf/vocabulary';
export const ERA_VEHICLE_TYPES = 'http://era.ilabt.imec.be/ldf/vehicle-types';
export const ERA_VEHICLES = 'http://era.ilabt.imec.be/ldf/vehicles';
export const ABSTRACTION_TILES = 'http://era.ilabt.imec.be/ldf/sparql-tiles/abstraction';
export const ABSTRACTION_ZOOM = 10;
export const IMPLEMENTATION_TILES = 'http://era.ilabt.imec.be/ldf/sparql-tiles/implementation';
export const IMPLEMENTATION_ZOOM = 10;
//export const FACETED_BASE_URI = 'https://test-linked.ec-dataplatform.eu/describe/?url=';
export const FACETED_BASE_URI = 'http://era.ilabt.imec.be/resource?uri=';
export const APP_PATH = '/compatibility-check-demo';
const ERA_GEO_API = '${ERA_GEO_API}';
const ZOOM = '${ZOOM}';
export const FACETED_BASE_URI = '${FACETED_BASE_URI}'
//export const FACETED_BASE_URI = 'https://linked.ec-dataplatform.eu/describe/?url='; for Virtuoso
//export const FACETED_BASE_URI = 'http://era.ilabt.imec.be/resource?uri='; for GraphDB

export const APP_PATH = '/compatibility-check-demo';
export const ERA_VOCABULARY = ERA_GEO_API + '/vocabulary';
export const ERA_VEHICLE_TYPES = ERA_GEO_API + '/vehicle-types';
export const ERA_VEHICLES = ERA_GEO_API + '/vehicles';
export const ABSTRACTION_TILES = ERA_GEO_API + '/sparql-tiles/abstraction';
export const IMPLEMENTATION_TILES = ERA_GEO_API + '/sparql-tiles/implementation';
export const ABSTRACTION_ZOOM = ZOOM;
export const IMPLEMENTATION_ZOOM = ZOOM;
28 changes: 20 additions & 8 deletions src/docs/help-page.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,26 +47,38 @@ Route planning queries are not something that can be trivially solved on KG data
\
This enables our application to perform any kind of processing on the data, such as a graph shortest-path algorithm. In this case, we perform an [A* algorithm](https://en.wikipedia.org/wiki/A*_search_algorithm) that progressively downloads data tiles containing the railway topology data from the KG that it needs to find routes between two selected operational points. When the maximum number of routes is selected to be more than 1, the application performs [Yen's algorithm](https://en.wikipedia.org/wiki/Yen%27s_algorithm) for finding the top-k shortest paths in a graph.

#### Step 3: Select a vehicle type
#### Step 3: Check the route's _internal connectivity_ inside operational points

> **DO**\
After a route is calculated, click on the `See internal connectivity` option next to the operational points that conform the route to see how this route goes through them.

> **OBSERVE**\
Here you can see highlighted the specific [node ports](https://linked.ec-dataplatform.eu/describe/?url=http%3A%2F%2Fera.europa.eu%2Fns%23NodePort) and [internal node link](https://linked.ec-dataplatform.eu/describe/?url=http%3A%2F%2Fera.europa.eu%2Fns%23InternalNodeLink) that were calculated as part of the route. You may also click on the other node ports to see how they connect to each other inside the operational point.
![Step 3](img/step3.gif)

> **UNDER THE HOOD**\
Node ports represent the operational point borders and the point where tracks start or end. To represent the changes of direction that are possible inside operational points, internal node links are defined between the different node ports that belong to a operational point. The route planning algorithm takes into account these internal connections for calculating possible routes.

#### Step 4: Select a vehicle type

> **DO**\
Click on the menu `Select a Vehicle Type` and choose a vehicle type.

> **OBSERVE**\
Now on the route description you see on which tracks of the route the selected vehicle can go and if not why. This way you see the compatibility between the selected vehicle type and the selected route, track by track, parameter by parameter. In the example below, for the first track, the train detection system is compatible but the energy supply system is not. A `no data` value will show when information about a certain parameter is not available. This will render an `UNKNOWN` compatibility result.
![Step 3](img/step3.gif)
![Step 4](img/step4.gif)

> **UNDER THE HOOD**\
During the route calculation process, the application fetches all the data (KG's triples) associated with every single operational point and track of the found route(s). Thanks to this it is possible to select any vehicle type (whose data were fetched from the start during application loading) and perform a comparison of their characteristics. Since all the data is already present in the application _in-memory_, the comparison process is executed very efficiently and vehicle types can be switched without requiring new data requests to the KG data store.

#### Step 4: Select a vehicle
#### Step 5: Select a vehicle

> **DO**\
Click on the menu `Select a Vehicle` and choose a vehicle.

> **OBSERVE**\
This step displays the same behavior as the previous one, with the difference of showing additional compatibility parameters that are only available for specific vehicles. In the example below, the “operational restriction” parameter is exclusive of vehicle `238029424542`. When a vehicle is selected, the application will automatically select its associated vehicle type (if this information is available in the KG).
![Step 4](img/step4.gif)
![Step 5](img/step5.gif)

> **UNDER THE HOOD**\
When the application is loaded, it requests the set of vehicles and vehicle types to the backend API. Since the amount of entities is considerably high (+1600 vehicle types +800,000 vehicles), these data are loaded in a streaming fashion, using [Web Workers](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API) to prevent blocking the user interface of the application.
Expand All @@ -89,13 +101,13 @@ Select a vehicle or vehicle type first and then proceed to calculate a route. Th

#### Explore the ERA Knowledge Graph

You have probably noticed that many of the items in the comparison table of each track are clickable. These are not just links to pages but links to the edges and nodes of the KG. Edges are in the column `Properties`. The properties link in a meaningful way a node, such as a track, to another node. This other node can be a value, for example:
You have probably noticed that many of the items in the comparison table of each track are _clickable_. These are not just links to pages but links to the edges and nodes of the KG. Edges are in the column `Properties`. The properties link in a meaningful way a node, such as a track, to another node. This other node can be a value, for example:

> [`T_81527_358_81534`](http://era.ilabt.imec.be/resource?uri=http%3A%2F%2Fera.europa.eu%2Fimplementation%23T_81527_358_81534) - [`maximum temperature`](http://era.ilabt.imec.be/resource?uri=http%3A%2F%2Fera.europa.eu%2Fns%23maximumTemperature) -> `40`
> [`T_ATBm_1_ATUe`](https://linked.ec-dataplatform.eu/describe/?url=http%3A%2F%2Fera.europa.eu%2Fimplementation%23T_ATBm_1_ATUe) - [`maximum temperature`](https://linked.ec-dataplatform.eu/describe/?url=http%3A%2F%2Fera.europa.eu%2Fns%23maximumTemperature) -> `40`
Or another node identified with a URI, for example:
Or to another node identified with a URI, for example:

> [`T_81527_358_81534`](http://era.ilabt.imec.be/resource?uri=http%3A%2F%2Fera.europa.eu%2Fimplementation%23T_81527_358_81534) - [`train detection system`](http://era.ilabt.imec.be/resource?uri=http%3A%2F%2Fera.europa.eu%2Fns%23trainDetectionSystem) -> [`track circuit`](http://era.ilabt.imec.be/resource?uri=http%3A%2F%2Fera.europa.eu%2Fconcepts%2Ftrain-detection%23track_circuit).
> [`T_ATBm_1_ATUe`](https://linked.ec-dataplatform.eu/describe/?url=http%3A%2F%2Fera.europa.eu%2Fimplementation%23T_ATBm_1_ATUe) - [`train detection system`](https://linked.ec-dataplatform.eu/describe/?url=http%3A%2F%2Fera.europa.eu%2Fns%23trainDetectionSystem) -> [`track circuit`](https://linked.ec-dataplatform.eu/describe/?url=http%3A%2F%2Fera.europa.eu%2Fconcepts%2Ftrain-detection%23track_circuit).
Each property has meaning defined by the [ERA vocabulary](http://era.ilabt.imec.be/era-vocabulary/index-en.html). With them, both humans and machines can _understand_ that a node is of a specific type (e.g., track, operational point, or vehicle type) or the meaning of a statement such as the examples above.

Expand Down
Binary file modified src/docs/img/step3.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified src/docs/img/step4.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/docs/img/step5.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions src/utils/NameSpaces.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ export const GEOSPARQL = {
}

export const WGS84 = {
latitude: 'http://www.w3.org/2003/01/geo/wgs84_pos#latitude',
longitude: 'http://www.w3.org/2003/01/geo/wgs84_pos#longitude',
lat: 'http://www.w3.org/2003/01/geo/wgs84_pos#lat',
long: 'http://www.w3.org/2003/01/geo/wgs84_pos#long',
location: 'http://www.w3.org/2003/01/geo/wgs84_pos#location'
}

Expand Down

0 comments on commit 99aa1dc

Please sign in to comment.