Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add LPV Panels #2183

Merged
merged 3 commits into from
Oct 28, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 1 addition & 19 deletions api/osrd_infra/migrations/0001_initial.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,25 +11,7 @@
import osrd_infra.schemas.rolling_stock
import osrd_infra.schemas.train_schedule
import osrd_infra.utils


def run_sql_add_foreign_key_infra(model_name: str):
return migrations.RunSQL(
f"""ALTER TABLE osrd_infra_{model_name}
ADD infra_id INTEGER,
ADD CONSTRAINT osrd_infra_{model_name}_fkey FOREIGN KEY (infra_id) REFERENCES osrd_infra_infra(id) ON DELETE CASCADE
""",
state_operations=[
migrations.AddField(
model_name=model_name,
name="infra",
field=models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
to="osrd_infra.infra",
),
),
],
)
from osrd_infra.migrations import run_sql_add_foreign_key_infra


class Migration(migrations.Migration):
Expand Down
33 changes: 33 additions & 0 deletions api/osrd_infra/migrations/0007_lpvpanellayer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Generated by Django 4.0.8 on 2022-10-26 09:27

import django.contrib.gis.db.models.fields
import django.db.models.deletion
from django.db import migrations, models

import osrd_infra.schemas.infra
import osrd_infra.utils
from osrd_infra.migrations import run_sql_add_foreign_key


class Migration(migrations.Migration):

dependencies = [
("osrd_infra", "0006_railjson_v3"),
]

operations = [
migrations.CreateModel(
name="LPVPanelLayer",
fields=[
("id", models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name="ID")),
("geographic", django.contrib.gis.db.models.fields.PointField(srid=3857)),
("schematic", django.contrib.gis.db.models.fields.PointField(srid=3857)),
(
"data",
models.JSONField(validators=[osrd_infra.utils.PydanticValidator(osrd_infra.schemas.infra.Panel)]),
),
],
),
run_sql_add_foreign_key("lpvpanellayer", "infra", "infra"),
run_sql_add_foreign_key("lpvpanellayer", "obj", "speedsectionmodel"),
]
26 changes: 26 additions & 0 deletions api/osrd_infra/migrations/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import django
from django.db import migrations, models


def run_sql_add_foreign_key(model_name: str, field_name: str, link_model: str):
return migrations.RunSQL(
f"""ALTER TABLE osrd_infra_{model_name}
ADD {field_name}_id INTEGER,
ADD CONSTRAINT osrd_{link_model}_{model_name}_fkey FOREIGN KEY ({field_name}_id)
REFERENCES osrd_infra_{link_model}(id) ON DELETE CASCADE
""",
state_operations=[
migrations.AddField(
model_name=model_name,
name=field_name,
field=models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
to=f"osrd_infra.{link_model}",
),
),
],
)


def run_sql_add_foreign_key_infra(model_name: str):
return run_sql_add_foreign_key(model_name, "infra", "infra")
11 changes: 9 additions & 2 deletions api/osrd_infra/models/generated.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,11 @@
from django.contrib.gis.db import models

from osrd_infra.schemas.generated import InfraError
from osrd_infra.schemas.infra import ALL_OBJECT_TYPES
from osrd_infra.schemas.infra import Panel
from osrd_infra.utils import PydanticValidator


class ErrorLayer(models.Model):
OBJ_TYPE_CHOICES = [(obj_type.__name__, obj_type.__name__) for obj_type in ALL_OBJECT_TYPES]
infra = models.ForeignKey("Infra", on_delete=models.CASCADE)
geographic = models.GeometryField(srid=settings.MAPBOX_SRID, null=True)
schematic = models.GeometryField(srid=settings.MAPBOX_SRID, null=True)
Expand Down Expand Up @@ -125,3 +124,11 @@ class CatenaryLayer(models.Model):
class Meta:
verbose_name_plural = "generated catenary layer"
unique_together = (("infra", "obj_id"),)


class LPVPanelLayer(models.Model):
infra = models.ForeignKey("Infra", on_delete=models.CASCADE)
obj = models.ForeignKey("SpeedSectionModel", on_delete=models.CASCADE)
geographic = models.PointField(srid=settings.MAPBOX_SRID)
schematic = models.PointField(srid=settings.MAPBOX_SRID)
data = models.JSONField(validators=[PydanticValidator(Panel)])
13 changes: 13 additions & 0 deletions chartos/chartos.yml
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,19 @@
joins:
- inner join osrd_infra_catenarymodel catenary on catenary.obj_id = layer.obj_id and catenary.infra_id = layer.infra_id

- name: lpv_panels
table_name: osrd_infra_lpvpanellayer
id_field: id
views:
- name: geo
on_field: geographic
cache_duration: 3600
data_expr: layer.data
- name: sch
on_field: schematic
cache_duration: 3600
data_expr: layer.data

- name: errors
table_name: osrd_infra_errorlayer
id_field: id
Expand Down
3 changes: 2 additions & 1 deletion editoast/src/chartos/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use serde_json::json;

use crate::client::ChartosConfig;

const LAYERS: [&str; 11] = [
const LAYERS: [&str; 12] = [
"track_sections",
"signals",
"speed_sections",
Expand All @@ -19,6 +19,7 @@ const LAYERS: [&str; 11] = [
"routes",
"operational_points",
"catenaries",
"lpv_panels",
"errors",
];

Expand Down
59 changes: 59 additions & 0 deletions editoast/src/generated_data/lpv_panel.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
use crate::infra_cache::InfraCache;
use crate::schema::ObjectType;

use super::utils::InvolvedObjects;
use super::GeneratedData;
use diesel::result::Error;
use diesel::sql_types::{Array, Integer, Text};
use diesel::{sql_query, PgConnection, RunQueryDsl};

pub struct LPVPanelLayer;

impl GeneratedData for LPVPanelLayer {
fn table_name() -> &'static str {
"osrd_infra_lpvpanellayer"
}

fn generate(conn: &PgConnection, infra: i32, _infra_cache: &InfraCache) -> Result<(), Error> {
sql_query(include_str!("sql/generate_lpv_panel_layer.sql"))
.bind::<Integer, _>(infra)
.execute(conn)?;
Ok(())
}

fn update(
conn: &PgConnection,
infra: i32,
operations: &[crate::schema::operation::OperationResult],
infra_cache: &crate::infra_cache::InfraCache,
) -> Result<(), Error> {
let involved_objects =
InvolvedObjects::from_operations(operations, infra_cache, ObjectType::SpeedSection);

// Delete elements
if !involved_objects.is_empty() {
// We must delete both updated and deleted lpv panels because we can only insert them and not update
let objs = involved_objects
.deleted
.iter()
.chain(involved_objects.updated.iter());

sql_query(format!(
"DELETE FROM {} WHERE infra_id = $1 AND obj_id = ANY($2)",
Self::table_name()
))
.bind::<Integer, _>(infra)
.bind::<Array<Text>, _>(objs.into_iter().collect::<Vec<_>>())
.execute(conn)?;
}

// Insert involved elements
if !involved_objects.updated.is_empty() {
sql_query(include_str!("sql/insert_lpv_panel_layer.sql"))
.bind::<Integer, _>(infra)
.bind::<Array<Text>, _>(involved_objects.updated.into_iter().collect::<Vec<_>>())
.execute(conn)?;
}
Ok(())
}
}
5 changes: 5 additions & 0 deletions editoast/src/generated_data/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ mod buffer_stop;
mod catenary;
mod detector;
mod error;
mod lpv_panel;
mod operational_point;
mod route;
mod signal;
Expand All @@ -16,6 +17,7 @@ use buffer_stop::BufferStopLayer;
use catenary::CatenaryLayer;
use detector::DetectorLayer;
use error::ErrorLayer;
use lpv_panel::LPVPanelLayer;
use operational_point::OperationalPointLayer;
use route::RouteLayer;
use signal::SignalLayer;
Expand Down Expand Up @@ -77,6 +79,7 @@ pub fn refresh_all(
OperationalPointLayer::refresh(conn, infra, infra_cache)?;
TrackSectionLinkLayer::refresh(conn, infra, infra_cache)?;
RouteLayer::refresh(conn, infra, infra_cache)?;
LPVPanelLayer::refresh(conn, infra, infra_cache)?;
ErrorLayer::refresh(conn, infra, infra_cache)?;
Ok(())
}
Expand All @@ -93,6 +96,7 @@ pub fn clear_all(conn: &PgConnection, infra: i32) -> Result<(), Box<dyn ApiError
OperationalPointLayer::clear(conn, infra)?;
TrackSectionLinkLayer::clear(conn, infra)?;
RouteLayer::clear(conn, infra)?;
LPVPanelLayer::clear(conn, infra)?;
ErrorLayer::clear(conn, infra)?;
Ok(())
}
Expand All @@ -114,6 +118,7 @@ pub fn update_all(
OperationalPointLayer::update(conn, infra, operations, infra_cache)?;
TrackSectionLinkLayer::update(conn, infra, operations, infra_cache)?;
RouteLayer::update(conn, infra, operations, infra_cache)?;
LPVPanelLayer::update(conn, infra, operations, infra_cache)?;
ErrorLayer::update(conn, infra, operations, infra_cache)?;
Ok(())
}
Expand Down
2 changes: 1 addition & 1 deletion editoast/src/generated_data/operational_point.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ impl GeneratedData for OperationalPointLayer {
.execute(conn)?;
}

// Update elements
// Insert elements
if !involved_objects.updated.is_empty() {
sql_query(include_str!("sql/insert_operational_point_layer.sql"))
.bind::<Integer, _>(infra)
Expand Down
69 changes: 69 additions & 0 deletions editoast/src/generated_data/sql/generate_lpv_panel_layer.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
WITH panels AS (
SELECT id AS sc_id,
(
jsonb_array_elements(data->'extensions'->'lpv_sncf'->'announcement')->'position'
)::float AS position,
jsonb_array_elements(data->'extensions'->'lpv_sncf'->'announcement')->>'track' AS track_id,
jsonb_array_elements(data->'extensions'->'lpv_sncf'->'announcement') AS data
FROM osrd_infra_speedsectionmodel
WHERE infra_id = $1
AND osrd_infra_speedsectionmodel.data @? '$.extensions.lpv_sncf.z'
UNION
SELECT id AS sc_id,
(
jsonb_array_elements(data->'extensions'->'lpv_sncf'->'r')->'position'
)::float AS position,
jsonb_array_elements(data->'extensions'->'lpv_sncf'->'r')->>'track' AS track_id,
jsonb_array_elements(data->'extensions'->'lpv_sncf'->'r') AS data
FROM osrd_infra_speedsectionmodel
WHERE infra_id = $1
AND osrd_infra_speedsectionmodel.data @? '$.extensions.lpv_sncf.z'
UNION
SELECT id AS sc_id,
(data->'extensions'->'lpv_sncf'->'z'->'position')::float AS position,
data->'extensions'->'lpv_sncf'->'z'->>'track' AS track_id,
data->'extensions'->'lpv_sncf'->'z' AS data
FROM osrd_infra_speedsectionmodel
WHERE infra_id = $1
AND osrd_infra_speedsectionmodel.data @? '$.extensions.lpv_sncf.z'
),
collect AS (
SELECT panels.sc_id,
panels.data,
ST_Transform(
ST_LineInterpolatePoint(
ST_GeomFromGeoJSON(tracks.data->'geo'),
LEAST(
GREATEST(
panels.position / (tracks.data->'length')::float,
0.
),
1.
)
),
3857
) AS geo,
ST_Transform(
ST_LineInterpolatePoint(
ST_GeomFromGeoJSON(tracks.data->'sch'),
LEAST(
GREATEST(
panels.position / (tracks.data->'length')::float,
0.
),
1.
)
),
3857
) AS sch
FROM panels
INNER JOIN osrd_infra_tracksectionmodel AS tracks ON tracks.obj_id = panels.track_id
AND tracks.infra_id = $1
)
INSERT INTO osrd_infra_lpvpanellayer (obj_id, infra_id, geographic, schematic, data)
SELECT sc_id,
$1,
geo,
sch,
data
FROM collect
Loading