---
title: ""

format:
  html:
    fig-width: 9
    fig-height: 8
    fig-dpi: 300
    # embed-resources: TRUE # Entwicklung
    # theme: "null" # Entwicklung
    embed-resources: FALSE # Veröffentlichung
    theme: none # Veröffentlichung
    # css: helpers/custom-maplibre.css
    header-includes: |
     <link rel="stylesheet" href="https://media.sciencemediacenter.de/static/fonts/circular/web.css">
     <script>document.addEventListener("DOMContentLoaded",function(){document.querySelectorAll("a").forEach(function(a){a.setAttribute("target","_blank");});});</script>

mainfont: CircularSMCWeb

execute:
  echo: FALSE
  output: asis
  warning: FALSE
  error: FALSE
---

```{r}
#| label: pakete_und_daten
#| output: false
library(tidyverse)
library(SMChelpR)
library(scales)
library(DT)
library(plotly)
library(SMCReichbR)
library(mapgl)
library(mapview)


## wichtige Story-Parameter
storyNo <- 26084
file_name_code <- "Regionale_Erreichbarkeitsanalysen.qmd" # "Quarto_Vorlage_R.qmd" ########################################
caption_Klinik <-
  "Quelle: ___, Berechnungen: Science Media Center Germany."
caption_test <-
  "Quelle: ___, Berechnungen/Darstellung: Science Media Center Germany."

caption_karte_1 <-
  "Quelle: Qualitätsberichte der Krankenhäuser (G-BA, 2023), perinatalzentren.org (IQTIQ), BKG, Zensus 2022\nBerechnungen/Darstellung: Science Media Center Germany."
caption_karte_2 <-
  "Quelle: Qualitätsberichte der Krankenhäuser (G-BA, 2023), perinatalzentren.org (IQTIQ), BKG, Zensus 2022\nBerechnungen/Darstellung: Science Media Center Germany."

Datumsprefix_files <- FALSE # FALSE, wenn keine regelmäßige Aussendung / keine tagesaktuellen Daten

##############################

imagepath <-
  file.path("reports", storyNo)
dir.create(imagepath, showWarnings = FALSE, recursive = TRUE)

## workspace directory in RStudio interaktiv
if (rstudioapi::isAvailable()) {
  setwd(dirname(rstudioapi::getActiveDocumentContext()$path))
}

if (is.na(file_name_code)) {
  stop("Dateiname der qmd nicht gesetzt")
}
if (!file.exists(file_name_code)) {
  stop("qmd existiert nicht. Dateiname falsch?")
}


file.copy(
  from = file_name_code,
  to = file.path(
    imagepath,
    paste0(today()[Datumsprefix_files], "_"[Datumsprefix_files], file_name_code)
  ),
  overwrite = TRUE
)
```

```{r}
#| label: set-graphic-parameters
#| output: false
options(scipen = 999) # set scientific notation to be off
SMC_theme_ggplot()

if (exists("caption_")) {
  stop("Caption wurde nicht angepasst")
}
```

```{r}
#| label: load data
#| output: false
server_url <- "https://grafzahl.smc.int/v1/graphql" # "https://data.smclab.io/v1/graphql" #
db_prefix <- "ds_" # "data_" #

szenario_standortnummer <- "772401000" # Sana Krankenhaus Templin

load(file.path("data", "Krankenhaus_Standortliste.RData")) # betrachtete Klinikstandorte (nur lokal)
load(file.path("data", "polygon_data_ausgangsszenario.RData")) # Fahrzeiten für Ausgangsszenario
load(file.path("data", "polygon_data_mit_szenario.RData")) # Fahrzeiten für Ausgangsszenario mit geschlossener Klinik
load(file.path("data", "polygon_data_differenz.RData")) # Fahrzeitdifferenzen für Vergleichsszenario

## Gemeindegrenzen
# Gemeindegrenzen_Polygone <- GraphQL_get_table_vec(
#   variablen = c(
#     "Gemeindeschluessel",
#     "geometry"
#   ),
#   tabellenname = paste0(db_prefix, "geodaten_gemeindegrenzen_polygone"),
#   datenserver = server_url,
#   page_size = 1000,
#   order_by = "Gemeindeschluessel: asc"
#   # max_pages = 5
# ) |>
#   convert_geometry_column()

# save(
#   Gemeindegrenzen_Polygone,
#   file = file.path("data", "Gemeindegrenzen_Polygone.RData")
# )
load(file.path("data", "Gemeindegrenzen_Polygone.RData"))

## Landesgrenzen laden
# Landesgrenzen_Polygone <- GraphQL_get_table_vec(
#   variablen = c(
#     "Bundesland_ID",
#     "geometry"
#   ),
#   tabellenname = paste0(db_prefix, "geodaten_landesgrenzen_polygone"),
#   datenserver = server_url,
#   page_size = 1000,
#   order_by = "Bundesland_ID: asc"
#   # max_pages = 5
# ) |>
#   convert_geometry_column()

# save(
#   Landesgrenzen_Polygone,
#   file = file.path("data", "Landesgrenzen_Polygone.RData")
# )
load(file.path("data", "Landesgrenzen_Polygone.RData"))
```

```{r}
#| label: kartenparameter
#| output: false
style_obj <- jsonlite::fromJSON(
  "https://tileserver.smc.report/styles/smc_customized/style.json",
  simplifyVector = FALSE
)

# Farbskala absolute Fahrzeiten
col <- c(
  "#eff3ff",
  "#c6dbef",
  "#9ecae1",
  "#6baed6",
  "#4292c6",
  "#2171b5",
  "#084594"
)

# Farbskala Fahrzeit-Differenzen
col_dif <- c(
  "#fff5f0",
  "#fee0d2",
  "#fcbba1",
  "#fc9272",
  "#fb6a4a",
  "#de2d26",
  "#a50f15"
)

fahrzeit_scale_expr <- step_expr(
  column = "Mittlere_Gewichtete_Fahrzeit",
  base = col[1], # < 10
  values = c(10, 20, 30, 40, 50, 60),
  stops = col[2:length(col)], # 10-20, 20-30, 30-40, 40-50, 50-60, >60
  na_color = "#d3d3d3"
)

fahrzeit_scale_expr_dif <- step_expr(
  column = "Mittlere_Gewichtete_Fahrzeit_Differenz",
  base = col_dif[1], # < 5
  values = c(5, 10, 15, 20, 25, 30),
  stops = col_dif[2:length(col_dif)], # 5-10, 10-15, 15-20, 20-25, 25-30, >30
  na_color = "#d3d3d3"
)


### Region-Maske + Grenzen (Brandenburg, Berlin, Mecklenburg-Vorpommern) ###

laender_region <- Landesgrenzen_Polygone |>
  filter(Bundesland_ID %in% c("12", "11", "13")) # BB, BE, MV

region_union <- sf::st_union(laender_region)

world_ring <- sf::st_polygon(list(matrix(
  c(-180, -85, 180, -85, 180, 85, -180, 85, -180, -85),
  ncol = 2,
  byrow = TRUE
)))

# Use planar (GEOS) geometry for the difference: sf's default s2 engine treats
# the full -180..180/-85..85 ring as degenerate and collapses the region hole,
# leaving the mask as a solid world-covering polygon.
.old_s2 <- sf::sf_use_s2()
sf::sf_use_s2(FALSE)
region_mask_sf <- sf::st_sf(
  geometry = sf::st_difference(
    sf::st_sfc(world_ring, crs = 4326),
    region_union
  )
)
sf::sf_use_s2(.old_s2)
rm(.old_s2)

region_outline_sf <- sf::st_sf(
  geometry = sf::st_cast(region_union, "MULTILINESTRING")
)


### Tooltip-HTML ###

# Re-wrap labels produced by create_polygon_label()/Datenvorverarbeitung so the
# popup uses the smc-maplibre-popup BEM class structure (see
# helpers/custom-maplibre.css and Kartenvorverarbeitung_combined.R in the knie
# repo). Applied inline per layer so the underlying data stays readable in the
# CSV/GeoJSON exports.
wrap_polygon_label <- function(df) {
  df #|>
  # mutate(
  #   label = paste0(
  #     '<div class="smc-maplibre-popup">',
  #     '<p class="smc-maplibre-popup__title">',
  #     str_extract(label, "(?<=<strong>|<b>)[^<]+"),
  #     "</p>",
  #     '<div class="smc-maplibre-popup__details">',
  #     str_replace(label, "^<(strong|b)>[^<]+</(strong|b)>(<br/?>)?", ""),
  #     "</div></div>"
  #   )
  # )
}


### Tooltip-Styling ###

# Popup CSS is loaded via the Quarto `css:` key in the YAML header
# (format.html.css -> helpers/custom-maplibre.css). Prepending the CSS via
# htmlwidgets::prependContent() was silently dropped during Quarto's render
# pipeline, so nothing R-side is needed here.

### JavaScript: Layer-Reihenfolge nach Load korrigieren ###

# Promotes OSM labels above the choropleth but below the region-mask (so labels
# get hidden outside BB/BE/MV). The region-mask sits above the labels; clinic
# markers, region-outline and state-borders sit on top of the mask. Reused by
# both map chunks below.
LAYER_ORDER_JS <- "
    function(el, x) {
      var map = this.getMap();
      map.on('load', function() {
        // 1. Promote the choropleth's companion lines and the style's label
        //    symbol layers above the choropleth fill.
        var labelAndBorderIds = [
          'region-outline', 'state-borders',
          'label-place-village', 'label-place-town', 'label-place-city',
          'label-place-statecapital', 'label-place-capital',
          'label-boundary-state',
          'label-boundary-country-small', 'label-boundary-country-medium',
          'label-boundary-country-large',
          'label-street-primary', 'label-street-trunk', 'label-motorway-shield'
        ];
        labelAndBorderIds.forEach(function(id) {
          if (map.getLayer(id)) map.moveLayer(id);
        });
        // 2. Lift the region-mask above the labels so the white fill hides
        //    anything outside Brandenburg/Berlin/Mecklenburg-Vorpommern.
        if (map.getLayer('region-mask')) map.moveLayer('region-mask');
        // 3. Keep the clinic markers, scenario annotation and the boundary
        //    lines on top of the mask.
        ['alle_krankenhausstandorte',
         'szenario_krankenhausstandort',
         'szenario_krankenhausstandort_label',
         'region-outline',
         'state-borders'].forEach(function(id) {
          if (map.getLayer(id)) map.moveLayer(id);
        });
      });
    }
    "
```

::: m-news-single__ce
- SMC stellt Online-Tool vor, mit dessen Hilfe eigene Berechnungen von Fahrzeiten zu Kliniken möglich werden
- die Anwendung bietet schnelle Analysen bei lokalen Recherchen zu Schließungen von Kliniken oder medizinischen Bereichen
- für größere Auswertungen können Daten und Code bereitgestellt werden

Eine Klinik schließt oder schränkt ihr Behandlungsangebot ein. Was bedeutet dies für die Versorgung der Menschen in der Region? Wie gut ist die Wohnbevölkerung durch umliegende Kliniken abgedeckt? Werden Empfehlungen zur Erreichbarkeit eingehalten? Das neue Online-Tool des Science Media Center Germany kann bei der Beantwortung derlei Fragen helfen. Es richtet sich primär an regional oder lokal recherchierende Journalistinnen und Journalisten, die vor Ort die Veränderungen in der Kliniklandschaft begleiten. Mit diesem Report möchten wir Ihnen die Möglichkeiten des Tools näherbringen und verdeutlichen, wie es bei der alltäglichen Recherche bei (anstehenden) Klinikschließungen helfen kann.

<a href="https://klinik-erreichbarkeit.smc.page/" target="_blank" style="display:inline-block;padding:10px 20px;background-color:#D7C455;color:white;font-weight:bold;text-decoration:none;border-radius:4px;">Zum Klinik-Erreichbarkeits-Tool →</a>

Das SMC führt regelmäßig deutschlandweite Analysen zur Klinikversorgung durch. So haben wir die Erreichbarkeit von Geburtskliniken für die Behandlung [extremer Frühchen](https://www.sciencemediacenter.de/angebote/auswirkungen-der-neuen-mindestmenge-fuer-die-behandlung-von-fruehchen-unter-1250-gramm-23184) ermittelt, ebenso für [Geburtskliniken](https://www.sciencemediacenter.de/angebote/geburtshilfe-in-deutschland--fahrzeiten-fallzahlen-versorgungslevel-25121) im Allgemeinen und für Kliniken, die [Schlaganfälle](https://www.sciencemediacenter.de/angebote/schlaganfallversorgung-in-deutschland-interaktive-karten-zu-stroke-units-und-fahrzeiten-24161) versorgen. Für die [Krankenhausreform in NRW](https://krankenhausplanung-nrw.smc.report/) haben wir ein Dashboard zur Verfügung gestellt, mit dem die Erreichbarkeiten mit Blick auf die einzelnen Leistungsgruppen samt historischer Fallzahlen dargestellt werden können. **Am Donnerstag folgt zudem ein Report zur künftigen Versorgungslandschaft bei Knie-Operationen, wenn die gesetzlichen jährlichen Mindestfallzahlen für die Kliniken nun schrittweise erhöht werden, um die Qualität der Versorgung für Patientinnen und Patienten insgesamt zu verbessern.** Das neue Online-Tool vereint all diese Recherchen und bietet darüber hinaus die Möglichkeit, eigene Szenarien zu erstellen.

Die Reform der Gesundheitsversorgung in Deutschland bietet aktuell viele Anlässe, unser Tool zu nutzen: Durch die Klinikreform sollen sich Krankenhäuser spezialisieren, neue Leistungsgruppen werden vergeben, nicht jede Klinik soll künftig alles machen. Gleichzeitig kämpfen vor allem kleine Häuser oder Fachabteilungen gegen den wirtschaftlichen Ruin, und neue Mindestkriterien an Personal und Ausstattung sowie mögliche verpflichtende Zweitmeinungen vor planbaren Eingriffen wirken ebenfalls auf die Versorgung. Eine denkbare Anwendung für unser Tool möchten wir Ihnen im Folgenden einmal exemplarisch darstellen.

### Anwendungsbeispiel Kreißsaal-Schließung

Im April 2024 wurde der Kreißsaal des Sana-Krankenhauses Templin [endgültig geschlossen](https://www.rbb24.de/panorama/beitrag/2024/04/brandenburg-templin-kreisssaal-schlielung-fachkraeftemangel-krankenhaus-sana-geburtshilfe.html) – Fachkräftemangel. Geburten müssen spätestens seitdem in den umliegenden Kliniken stattfinden. Inwieweit sich durch die Schließung des Kreißsaals die Fahrzeiten für werdende Eltern in der Region nun verlängert haben, beleuchtet das neue SMC-Tool.

So betrug die durchschnittliche Fahrzeit zur nächstgelegenen Geburtsklinik in der Gemeinde Templin vor der Schließung rund sechs Minuten. In den Nachbargemeinden lagen die Werte bei rund 27 Minuten. Nach der Schließung erhöhte sich die Fahrzeit in Templin um rund 45 Minuten. In Summe benötigen werdende Eltern dort also heute gut 50 Minuten bis zur nächstgelegenen Klinik mit Kreißsaal.

Schließungen von Kliniken oder Fachabteilungen sind ein hochemotionales Thema für die jeweilige Region. Die Erreichbarkeit der übrigbleibenden Häuser ist dabei ein wichtiger Aspekt, der aber in der Berichterstattung manchmal untergeht. Denn grundsätzlich erscheinen längere Fahrzeiten dann hinnehmbar, wenn dadurch die Qualität der Versorgung insgesamt steigt, weil Geburten zum Beispiel vermehrt in größeren und erfahreneren Kliniken mit höheren Fallzahlen stattfinden.

Unser Anwendungsbeispiel lässt sich mithilfe des Tools auf eine Vielzahl von Behandlungsszenarien übertragen. Im Zentrum der Analyse steht dabei stets die (gedankliche) Schließung einer oder mehrerer Kliniken. Als Basis für die Klinikauswahl dient das [Standortverzeichnis](https://krankenhausstandorte.de/login) des Instituts für das Entgeltsystem im Krankenhaus GmbH (InEK). Im Verzeichnis stehen oft mehr Krankenhäuser als nötig, etwa Reha-Kliniken, die für viele klinische Fragen nicht relevant sind. Eine Auswahl kann entweder über eine komplett eigen zusammengesetzte Liste erfolgen oder über eine thematisch vorgefilterte Liste. Das SMC bietet zurzeit eine Liste mit Geburtskliniken oder mit Kliniken, die Schlaganfälle behandeln, an.

Als Kartenvisualisierung bieten wir mit dem Tool nicht nur die Erreichbarkeitskarten zweier Szenarien – Status quo zu einem beliebigen Status –, sondern auch eine sogenannte Differenzkarte, die die zusätzliche Fahrzeit im zweiten Szenario darstellt.

***Fahrzeiten vor der Kreißsaal-Schließung des Sana-Krankenhauses Templin***

```{r}
#| label: bsp_fahrzeitenkarte
########################
### Fahrzeiten-Karte ###
########################

map <- maplibre(
  style = style_obj,
  projection = "mercator",
  center = c(13.5, 53.1),
  zoom = 6,
  minZoom = 5,
  maxZoom = 10,
  maxBounds = list(c(8.5, 51.0), c(17.5, 55.0)),
  height = "700px"
) |>
  add_fill_layer(
    id = "region-mask",
    source = region_mask_sf,
    fill_color = "#ffffff",
    fill_opacity = 1
  ) |>
  add_fill_layer(
    id = "status_quo",
    source = polygon_data_mit |>
      filter(
        Bundesland %in%
          c(
            "Brandenburg",
            "Berlin",
            "Mecklenburg-Vorpommern"
          )
      ) |>
      wrap_polygon_label(),
    fill_color = fahrzeit_scale_expr,
    fill_opacity = 0.6,
    tooltip = get_column("label"),
    hover_options = list(
      fill_color = "#d7c455",
      fill_opacity = 0.6
    )
  ) |>
  add_line_layer(
    id = "region-outline",
    source = region_outline_sf,
    line_color = "#888888",
    line_width = 1.5
  ) |>
  add_line_layer(
    id = "state-borders",
    source = laender_region,
    line_color = "#555555",
    line_width = 1
  ) |>
  add_circle_layer(
    id = "alle_krankenhausstandorte",
    source = Krankenhaus_Standortliste |>
      filter(
        !Krankenhaus_Standortnummer %in% szenario_standortnummer,
        Bundesland %in%
          c(
            "Brandenburg",
            "Berlin",
            "Mecklenburg-Vorpommern"
          )
      ) |>
      wrap_polygon_label(),
    circle_color = "#0fa10f",
    circle_radius = 4,
    circle_stroke_color = "white",
    circle_stroke_width = 1,
    tooltip = get_column("label"),
    hover_options = list(
      circle_radius = 6
    )
  ) |>
  add_circle_layer(
    id = "szenario_krankenhausstandort",
    source = Krankenhaus_Standortliste |>
      filter(Krankenhaus_Standortnummer %in% szenario_standortnummer) |>
      wrap_polygon_label(),
    circle_color = "white",
    circle_radius = 4,
    circle_stroke_color = "black",
    circle_stroke_width = 1,
    tooltip = get_column("label"),
    hover_options = list(
      circle_radius = 6
    )
  ) |>
  add_symbol_layer(
    id = "szenario_krankenhausstandort_label",
    source = Krankenhaus_Standortliste |>
      filter(Krankenhaus_Standortnummer %in% szenario_standortnummer),
    text_field = get_column("Bezeichnung"),
    text_size = 11,
    text_anchor = "left",
    text_offset = c(0.6, 0),
    text_halo_color = "white",
    text_halo_width = 2
  ) |>
  add_categorical_legend(
    legend_title = "Fahrtzeit",
    values = c(
      "0 - 10 Minuten",
      "10 - 20 Minuten",
      "20 - 30 Minuten",
      "30 - 40 Minuten",
      "40 - 50 Minuten",
      "50 - 60 Minuten",
      "\u00fcber 60 Minuten",
      "Keine Daten"
    ),
    colors = c(col, "#d3d3d3"),
    position = "bottom-right",
    width = "160px",
    style = list(
      background_color = "#ffffff",
      background_opacity = 0.92,
      border_radius = 8,
      border_color = "#eeeeee",
      border_width = 1,
      padding = 10,
      shadow = TRUE,
      shadow_size = 8,
      shadow_color = "rgba(0,0,0,0.12)"
    ),
    margin_bottom = 24
  ) |>
  add_navigation_control(position = "top-right") |>
  add_reset_control(position = "top-right") |>
  add_fullscreen_control(position = "top-right") |>
  htmlwidgets::onRender(LAYER_ORDER_JS)

map
```


```{r}
filename <- "vor_der_Schließung"

data_choropleth <- tibble(
  fileformat = c("geojson", "csv", "geojson", "csv"),
  filename_suffix = c("Kliniken", "Kliniken", "Fahrzeiten", "Fahrzeiten")
)

images_choropleth <- tibble(
  # fileformat = c("html", "pdf", "png"),
  fileformat = c("html", "png"),
  filename_suffix = c("")
)

htmlpfad <- file.path(imagepath, paste0(filename, ".html"))
pngpfad <- file.path(imagepath, paste0(filename, ".png"))
# pdfpfad <- file.path(imagepath, paste0(filename, ".pdf"))

datenpfad_markers <- file.path(imagepath, paste0(filename, "_Kliniken.geojson"))
datenpfad_polygons <- file.path(
  imagepath,
  paste0(filename, "_Fahrzeiten.geojson")
)

datenpfad_markers_csv <- file.path(imagepath, paste0(filename, "_Kliniken.csv"))
datenpfad_polygons_csv <- file.path(
  imagepath,
  paste0(filename, "_Fahrzeiten.csv")
)

mapshot(map, url = htmlpfad)

mapshot2(
  map,
  file = pngpfad,
  vwidth = 750,
  vheight = 750,
  delay = 10,
  zoom = 10,
  selector = ".maplibregl-map",
)

# magick::image_read(pngpfad) |>
#   magick::image_write(pdfpfad, format = "pdf")

polygon_data_mit |>
  sf::st_drop_geometry() |>
  write_csv(datenpfad_polygons_csv)

Krankenhaus_Standortliste |>
  sf::st_drop_geometry() |>
  write_csv(datenpfad_markers_csv)

polygon_data_mit |>
  sf::st_write(datenpfad_polygons, delete_dsn = TRUE, quiet = TRUE)

Krankenhaus_Standortliste |>
  sf::st_write(datenpfad_markers, delete_dsn = TRUE, quiet = TRUE)

image_helper_light(
  filename = filename,
  filepath = imagepath,
  data = data_choropleth,
  images = images_choropleth,
  captions = caption_karte_1
)
```


***Zusätzliche Fahrzeiten nach der Kreißsaal-Schließung***

```{r}
#| label: bsp_differenzenkarte
###################
### Differenzen ###
###################

map <- maplibre(
  style = style_obj,
  projection = "mercator",
  center = c(13.5, 53.1),
  zoom = 6,
  minZoom = 5,
  maxZoom = 10,
  maxBounds = list(c(8.5, 51.0), c(17.5, 55.0)),
  height = "700px"
) |>
  add_fill_layer(
    id = "region-mask",
    source = region_mask_sf,
    fill_color = "#ffffff",
    fill_opacity = 1
  ) |>
  add_fill_layer(
    id = "status_quo",
    source = polygon_differenz |>
      filter(
        Bundesland %in%
          c(
            "Brandenburg",
            "Berlin",
            "Mecklenburg-Vorpommern"
          )
      ) |>
      wrap_polygon_label(),
    fill_color = fahrzeit_scale_expr_dif,
    fill_opacity = 0.6,
    tooltip = get_column("label"),
    hover_options = list(
      fill_color = "#d7c455",
      fill_opacity = 0.6
    )
  ) |>
  add_line_layer(
    id = "region-outline",
    source = region_outline_sf,
    line_color = "#888888",
    line_width = 1.5
  ) |>
  add_line_layer(
    id = "state-borders",
    source = laender_region,
    line_color = "#555555",
    line_width = 1
  ) |>
  add_circle_layer(
    id = "alle_krankenhausstandorte",
    source = Krankenhaus_Standortliste |>
      filter(
        !Krankenhaus_Standortnummer %in% szenario_standortnummer,
        Bundesland %in%
          c(
            "Brandenburg",
            "Berlin",
            "Mecklenburg-Vorpommern"
          )
      ) |>
      wrap_polygon_label(),
    circle_color = "#0fa10f",
    circle_radius = 4,
    circle_stroke_color = "white",
    circle_stroke_width = 1,
    tooltip = get_column("label"),
    hover_options = list(
      circle_radius = 6
    )
  ) |>
  add_circle_layer(
    id = "szenario_krankenhausstandort",
    source = Krankenhaus_Standortliste |>
      filter(Krankenhaus_Standortnummer %in% szenario_standortnummer) |>
      wrap_polygon_label(),
    circle_color = "white",
    circle_radius = 4,
    circle_stroke_color = "black",
    circle_stroke_width = 1,
    tooltip = get_column("label"),
    hover_options = list(
      circle_radius = 6
    )
  ) |>
  add_symbol_layer(
    id = "szenario_krankenhausstandort_label",
    source = Krankenhaus_Standortliste |>
      filter(Krankenhaus_Standortnummer %in% szenario_standortnummer),
    text_field = get_column("Bezeichnung"),
    text_size = 11,
    text_anchor = "left",
    text_offset = c(0.6, 0),
    text_halo_color = "white",
    text_halo_width = 2
  ) |>
  add_categorical_legend(
    legend_title = "Fahrtzeitver\u00e4nderung",
    values = c(
      "0 - 5 Minuten",
      "5 - 10 Minuten",
      "10 - 15 Minuten",
      "15 - 20 Minuten",
      "20 - 25 Minuten",
      "25 - 30 Minuten",
      "\u00fcber 30 Minuten",
      "Keine Daten"
    ),
    colors = c(col_dif, "#d3d3d3"),
    position = "bottom-right",
    width = "160px",
    style = list(
      background_color = "#ffffff",
      background_opacity = 0.92,
      border_radius = 8,
      border_color = "#eeeeee",
      border_width = 1,
      padding = 10,
      shadow = TRUE,
      shadow_size = 8,
      shadow_color = "rgba(0,0,0,0.12)"
    ),
    margin_bottom = 24
  ) |>
  add_navigation_control(position = "top-right") |>
  add_reset_control(position = "top-right") |>
  add_fullscreen_control(position = "top-right") |>
  htmlwidgets::onRender(LAYER_ORDER_JS)

map
```


```{r}
filename <- "nach_der_Schließung"

data_choropleth <- tibble(
  fileformat = c("geojson", "csv", "geojson", "csv"),
  filename_suffix = c("Kliniken", "Kliniken", "Fahrzeiten", "Fahrzeiten")
)

images_choropleth <- tibble(
  # fileformat = c("html", "pdf", "png"),
  fileformat = c("html", "png"),
  filename_suffix = c("")
)

htmlpfad <- file.path(imagepath, paste0(filename, ".html"))
pngpfad <- file.path(imagepath, paste0(filename, ".png"))
# pdfpfad <- file.path(imagepath, paste0(filename, ".pdf"))

datenpfad_markers <- file.path(imagepath, paste0(filename, "_Kliniken.geojson"))
datenpfad_polygons <- file.path(
  imagepath,
  paste0(filename, "_Fahrzeiten.geojson")
)

datenpfad_markers_csv <- file.path(imagepath, paste0(filename, "_Kliniken.csv"))
datenpfad_polygons_csv <- file.path(
  imagepath,
  paste0(filename, "_Fahrzeiten.csv")
)

mapshot(map, url = htmlpfad)

mapshot2(
  map,
  file = pngpfad,
  vwidth = 750,
  vheight = 750,
  delay = 10,
  zoom = 10,
  selector = ".maplibregl-map",
)

# magick::image_read(pngpfad) |>
#   magick::image_write(pdfpfad, format = "pdf")

polygon_differenz |>
  sf::st_drop_geometry() |>
  write_csv(datenpfad_polygons_csv)

Krankenhaus_Standortliste |>
  sf::st_drop_geometry() |>
  write_csv(datenpfad_markers_csv)


polygon_differenz |>
  sf::st_write(datenpfad_polygons, delete_dsn = TRUE, quiet = TRUE)

Krankenhaus_Standortliste |>
  sf::st_write(datenpfad_markers, delete_dsn = TRUE, quiet = TRUE)

image_helper_light(
  filename = filename,
  filepath = imagepath,
  data = data_choropleth,
  images = images_choropleth,
  captions = caption_karte_2
)
```



Das konkrete Szenario können Sie auch im [Tool betrachten](https://klinik-erreichbarkeit.smc.page/?bundesland=Brandenburg%2CMecklenburg-Vorpommern%2CBerlin&main_hash=9cf84e0014194e0fc42fd9f8c810a32345fc5ba2497699e4a1552ade1bba73ac_e0c2fd4a5291005ed33e75359d590b161dc5600182568144ce431002c1b38821). Auch selbst erstellte Szenarien lassen sich per URL festhalten.


### Exakte Werte, Datenupdates und eigene Analysen

Die Kliniklisten im Tool werden von unserem Datenteam in unregelmäßigen Abständen aktualisiert. Insbesondere für neue Klinikstandorte muss dann die zugrundeliegende Erreichbarkeitsberechnung erneuert werden. Da eine vollständige Berechnung der Erreichbarkeit für alle Gitterzellen im Tool zu aufwendig ist, wird dort nur eine Näherung berechnet, die für die meisten Recherchen aber zunächst ausreichend ist. Vollständige Karten für die Publikation können jederzeit bei uns angefragt werden. Dazu nutzen Sie bitte gern einfach die Option des Datenexports im Tool und schicken Sie ihn per Mail an lab\@sciencemediacenter.de. Wir berechnen daraus die Erreichbarkeiten aus dem vollständigen Datensatz aktuell neu und stellen die Ergebnisse als Tabellen und (interaktive) Grafiken zur Verfügung. Bei bestimmten Fragen, bei denen zum Beispiel konkrete Richtlinien für die Erreichbarkeit bestehen, können wir auch berechnen, wie viele Personen im Vergleichsszenario zusätzlich über der Fahrzeit von X Minuten liegen. Für weitere Auswertungsmöglichkeiten sprechen Sie uns gern an.

Für Redaktionen, die selbst Analysen rechnen wollen, stellen wir Code und Daten zur Verfügung. Auf GitHub betreuen wir eine kollaborative [Code-Sammlung für InEK-Klinikstandortliste und Qualitätsberichte des G-BA](https://github.com/sciencemediacenter/Klinikliste). Auch den Datensatz für die Erreichbarkeit aller Klinikstandorte teilen wir gern. Wir können daraus einen Datenauszug bereitstellen, etwa auch ein Bundesland oder eine vorgefilterte Klinikliste. Auch ein vollständiger Datenexport ist möglich. Je nach Format umfasst dieser allerdings rund 200 Gigabyte Daten.

### Methodik und Limitationen

Unsere Berechnungen basieren aktuell noch auf einem älteren Straßennetz samt Verkehrsdaten (2017). Die Daten zur Wohnbevölkerung stammen aus dem Zensus 2022. Gebiete, in denen es seitdem größere Bauprojekte gab, können in der Fahrzeitberechnung deutlich abweichen. Insgesamt ist das deutsche Straßennetz allerdings unverändert. Wir planen, im Laufe des Jahres ein Update der Daten auf ein aktuelles Netz durchzuführen. Bei Fragen oder lokalen Unplausibilitäten kontaktieren Sie uns gerne.

Eine Erreichbarkeitsanalyse ist nur eine Facette einer guten Klinikversorgung. So wird die Kapazität einzelner Krankenhäuser in dieser Berechnung nicht berücksichtigt. Bei einer Klinikschließung kann es notwendig sein, benachbarte Kliniken oder deren Leistungsangebot zu vergrößern. Insbesondere bei der Schließung einzelner Abteilungen in einem Krankenhaus kann es zu Wechselwirkungen mit anderen Abteilungen kommen, die dadurch vielleicht nicht mehr wirtschaftlich arbeiten können. Qualität und Ausstattung der Krankenhäuser werden auch nicht direkt betrachtet, können aber ein Auswahlkriterium der Krankenhäuser für die Szenarienberechnung sein.

Im zugrundeliegenden Datensatz wird für jeden Klinikstandort die Fahrzeit zu jeder bewohnten 100-mal-100-Meter-Gitterzelle in einem großen Radius bereitgehalten. Mit der für eine spezifische Analyse ausgewählten Liste an Kliniken wird für jede bewohnte Gitterzelle in Deutschland oder der ausgewählten Region überprüft, welcher der Klinikstandorte die kürzeste Fahrzeit bietet. Um den Effekt von Ungenauigkeiten aufgrund von Datenfehlern etwas auszugleichen, werden diese Fahrzeiten auf Gemeindeebene aggregiert. Dabei wird der Mittelwert über die Wohnbevölkerung gebildet, stärker besiedelte Gitterzellen fallen also auch stärker ins Gewicht.

Die Daten zu den Fahrzeiten stammen aktuell von Tim Holthaus vom Lehrstuhl für Güterverkehr und Transportlogistik an der Universität Wuppertal. Die Fahrzeit bezieht sich auf eine Fahrt mit dem Pkw an einem Werktag zwischen sieben und elf Uhr. Grundlage für die Routenberechnung ist ein OpenStreetMap-Straßennetz, in dem für alle 100-Meter-Segmente die mittlere Geschwindigkeit aus Navigationsdaten aus dem Jahr 2017 verwendet wurde. Als Startpunkt der Routenberechnung wurde immer der Straßenknoten gewählt, der dem Mittelpunkt der Gitterzelle am nächsten liegt. Es existiert ein [Preprint](https://www.researchgate.net/publication/342211628_Evaluation_of_driven_speed_on_German_motorways_without_speed_limits_-_a_new_approach) mit einer detaillierten Beschreibung der Methodik.

Weitere Ausführungen zur Umsetzung und zu Limitationen finden Sie auch in unseren vorherigen Reports, etwa zur [Geburtshilfe in Deutschland](https://www.sciencemediacenter.de/angebote/geburtshilfe-in-deutschland--fahrzeiten-fallzahlen-versorgungslevel-25121#25121_methodik_und_limitationen).

### Datengrundlage und Code

Den Code für diesen Data Report stellen wir [hier]( `r file.path(imagepath, paste0(today()[Datumsprefix_files], "_"[Datumsprefix_files], file_name_code))` ){target="_blank"} zur Verfügung. Neben Standard R-Paketen wird ein eigenes Paket verwendet, das [hier](https://github.com/sciencemediacenter/SMChelpR){target="_blank"} bereitgestellt wird.

### Ihre Ansprechpersonen in Redaktion und SMC Lab

Wenn Sie Fragen zu diesen Daten haben oder weitere Auswertungen erhalten wollen, kann das SMC Lab Auswertungen erzeugen.

*Redaktion*\
Philipp Jacobs, Redakteur für Medizin und Lebenswissenschaften\
[redaktion\@sciencemediacenter.de](mailto:redaktion@sciencemediacenter.de){.email}

*Datenauswertung*\
Simon Essink\
Lars Koppers\
[lab\@sciencemediacenter.de](mailto:lab@sciencemediacenter.de){.email}

Telefon: +49 221 8888 25-0\
E-Mail Inhalt: [redaktion\@sciencemediacenter.de](mailto:redaktion@sciencemediacenter.de){.email}\
E-Mail Datenauswertung: [lab\@sciencemediacenter.de](mailto:lab@sciencemediacenter.de){.email}
:::