From ec51069f1d56cc95f6bb2302a5f5be32ead6961f Mon Sep 17 00:00:00 2001 From: eneller Date: Tue, 20 Jan 2026 23:49:51 +0100 Subject: [PATCH 1/3] wip: fix: trajectory stats for single aircraft --- src/app.Rmd | 24 +++--------------------- src/main.Rmd | 25 ++++++++++++++++++++++--- 2 files changed, 25 insertions(+), 24 deletions(-) diff --git a/src/app.Rmd b/src/app.Rmd index 7cf976f..d2b4869 100644 --- a/src/app.Rmd +++ b/src/app.Rmd @@ -39,7 +39,7 @@ ui <- fluidPage( hr(), h4("Batch Analysis"), - numericInput("batch_size", "Number of flights to analyze:", value = 10, min = 2, max = 50), + numericInput("batch_size", "Days of flights to analyze:", value = 5, min = 1, max = 30), actionButton("batch_analyze", "Run Batch Analysis", class = "btn-warning"), hr(), @@ -144,6 +144,7 @@ server <- function(input, output, session) { data.frame( Index = i, ICAO24 = dep[["ICAO24"]] %||% NA, + #FIXME Callsign, Origin, Destination Callsign = dep[["callsign"]] %||% NA, Origin = dep[["estDepartureAirport"]] %||% NA, Destination = dep[["estArrivalAirport"]] %||% NA, @@ -248,28 +249,9 @@ server <- function(input, output, session) { status("Running batch analysis...") tryCatch({ - all_trajectories <- list() - n_departures <- min(length(rv$departures), input$batch_size) withProgress(message = 'Analyzing flights', value = 0, { - for (i in 1:n_departures) { - dep <- rv$departures[[i]] - icao24 <- dep[["ICAO24"]] - dep_time <- dep[["departure_time"]] - - incProgress(1/n_departures, detail = paste("Processing", icao24)) - - if (is.null(dep_time)) next - - # Use calculate_trajectory_params from main.Rmd - params <- calculate_trajectory_params(icao24, dep_time, rv$creds) - - if (!is.null(params)) { - all_trajectories[[length(all_trajectories) + 1]] <- params - } - - Sys.sleep(0.3) - } + all_trajectories <- getAircraftTrajectories(rv$current_icao, time = Sys.time(), creds, days = input$batch_size) }) if (length(all_trajectories) > 0) { diff --git a/src/main.Rmd b/src/main.Rmd index 1001590..18d15e5 100644 --- a/src/main.Rmd +++ b/src/main.Rmd @@ -52,6 +52,8 @@ getAircraftTrack <- function(icao, time, creds) { } return(NULL) } + + ``` ## Trajectory Conversion Functions @@ -86,7 +88,6 @@ getTrajFromRoute <- function(route_df) { # Calculate trajectory characteristics # Input: either route_df (data.frame with lat/lon) or trj (trajr object) # format: "row" for batch analysis (one row per flight), "table" for single flight display -# FIXME for batch analysis: use the same aircraft calculateTrajectoryStats <- function(input, icao = NULL, format = "row") { # Determine if input is route_df or trj if (inherits(input, "Trajectory")) { @@ -165,6 +166,21 @@ calculate_trajectory_params <- function(icao, departure_time, creds) { return(NULL) }) } + +getAircraftTrajectories <- function(icao, time, creds, days = 5){ + tracks <- list() + for (i in 0: (days-1)) { + flights <- getFlights(icao,time - days(i),creds) + for (f in flights){ + track <- calculate_trajectory_params(icao, f[["departure_time"]], creds) + if (!is.null(track)){ + tracks[[length(tracks)+1]] <- track + } + Sys.sleep(0.5) # API courtesy + } + } + return(tracks) +} ``` ## Statistical Helper Functions @@ -313,7 +329,10 @@ generateInterpretation <- function(trajectory_stats_df) { # Set eval=TRUE to run this demo # Get credentials -creds <- getCredentials() +creds <- getCredentials( + client_id = Sys.getenv('OPENSKY_CLIENT_ID'), + client_secret = Sys.getenv('OPENSKY_CLIENT_SECRET') +) # Get departures from Frankfurt airport time_now <- Sys.time() @@ -343,7 +362,7 @@ if (length(departures) > 0) { xlab = "Time (Unix)", ylab = "Height (Meter)") # Get summary - print(getRouteSummary(route_df, icao)) + print(calculateTrajectoryStats(route_df, icao)) # Plot trajectory trj <- getTrajFromRoute(route_df) From 2757a86383ee759190e794fd479d4417e4a6afb1 Mon Sep 17 00:00:00 2001 From: lukasadrion Date: Wed, 21 Jan 2026 13:12:34 +0100 Subject: [PATCH 2/3] :bug: add getAircraftTrajectories function --- src/main.Rmd | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/main.Rmd b/src/main.Rmd index 3a4aea3..0a58f22 100644 --- a/src/main.Rmd +++ b/src/main.Rmd @@ -166,6 +166,21 @@ calculate_trajectory_params <- function(icao, departure_time, creds) { return(NULL) }) } + +getAircraftTrajectories <- function(icao, time, creds, days = 5){ + tracks <- list() + for (i in 0: (days-1)) { + flights <- getFlights(icao,time - days(i),creds) + for (f in flights){ + track <- calculate_trajectory_params(icao, f[["departure_time"]], creds) + if (!is.null(track)){ + tracks[[length(tracks)+1]] <- track + } + Sys.sleep(0.5) # API courtesy + } + } + return(tracks) +} ``` ```{r stat-functions, include=FALSE} From f4955af7f46009de4b7f525ea499a529fc2e0bfa Mon Sep 17 00:00:00 2001 From: eneller Date: Wed, 21 Jan 2026 13:13:23 +0100 Subject: [PATCH 3/3] build: exclude demo chunks from purl --- src/main.Rmd | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/src/main.Rmd b/src/main.Rmd index 0a58f22..63f1a44 100644 --- a/src/main.Rmd +++ b/src/main.Rmd @@ -9,6 +9,11 @@ date: "`r Sys.Date()`" ```{r setup, include=FALSE} knitr::opts_chunk$set(echo = TRUE) +# include `eval=isArtifact()` to check if pdf/html is being produced +isArtifact <- function(){ + isOutput <-knitr::is_html_output() || knitr::is_latex_output() + return(isOutput) +} ``` ```{r preamble, message=FALSE, include=FALSE} @@ -383,7 +388,7 @@ The full analysis is also available in the GUI-based Shiny application. The `getCredentials()` function retrieves API credentials from environment variables, ensuring secure credential management. -```{r} +```{r, purl=FALSE} creds <- getCredentials( client_id = Sys.getenv("OPENSKY_CLIENT_ID"), client_secret = Sys.getenv("OPENSKY_CLIENT_SECRET") @@ -394,7 +399,7 @@ creds <- getCredentials( Recent departures from Frankfurt Airport (ICAO: EDDF) are queried for a two-hour time window. This airport was selected due to its high traffic volume, ensuring sufficient data availability. -```{r demo-departures} +```{r demo-departures, purl=FALSE} time_now <- Sys.time() departures <- getAirportDepartures( airport = "EDDF", @@ -409,7 +414,7 @@ cat("Departures retrieved:", length(departures), "\n") The `getAircraftTrack()` function retrieves detailed waypoint data for individual aircraft. The function iterates through available departures until valid track data is obtained. -```{r demo-track} +```{r demo-track, purl=FALSE} route_df <- NULL icao <- "N/A" @@ -436,7 +441,7 @@ if (is.null(route_df)) { The geographic trajectory is visualized in a Cartesian coordinate system. Green and red markers indicate departure and current/final position, respectively. -```{r demo-route-plot, fig.width=7, fig.height=5} +```{r demo-route-plot, fig.width=7, fig.height=5, purl=FALSE} if (!is.null(route_df)) { plot(route_df$lon, route_df$lat, type = "o", pch = 20, col = "blue", main = paste("Flight Trajectory -", icao), @@ -454,7 +459,7 @@ if (!is.null(route_df)) { The altitude profile reveals distinct flight phases: climb, cruise, and descent. This temporal representation provides insight into vertical movement patterns. -```{r demo-altitude-plot, fig.width=7, fig.height=4} +```{r demo-altitude-plot, fig.width=7, fig.height=4, purl=FALSE} if (!is.null(route_df)) { time_minutes <- (route_df$time - route_df$time[1]) / 60 plot(time_minutes, route_df$alt, type = "l", col = "red", lwd = 2, @@ -470,7 +475,7 @@ if (!is.null(route_df)) { The `getTrajFromRoute()` function transforms geographic coordinates into a metric coordinate system and constructs a `trajr` trajectory object. This transformation is necessary for accurate distance calculations. -```{r demo-trajectory-plot, fig.width=7, fig.height=5} +```{r demo-trajectory-plot, fig.width=7, fig.height=5, purl=FALSE} if (!is.null(route_df)) { trj <- getTrajFromRoute(route_df) plot(trj, main = paste("Metric Trajectory -", icao)) @@ -484,7 +489,7 @@ if (!is.null(route_df)) { The `calculateTrajectoryStats()` function computes comprehensive trajectory metrics. The table format provides a clear overview of individual flight characteristics. -```{r demo-stats-table} +```{r demo-stats-table, purl=FALSE} if (!is.null(route_df)) { stats_table <- calculateTrajectoryStats(route_df, icao = icao, format = "table") knitr::kable(stats_table, caption = paste("Trajectory Metrics for Aircraft", icao)) @@ -497,7 +502,7 @@ if (!is.null(route_df)) { To enable statistical inference, trajectory data is collected for multiple flights. The algorithm attempts to retrieve valid track data for up to five departures in this example. -```{r demo-multiple-tracks} +```{r demo-multiple-tracks, purl=FALSE} flight_data <- list() successful_flights <- 0 @@ -542,7 +547,7 @@ if (length(departures) > 0) { The following table presents computed metrics for all successfully analyzed flights. -```{r demo-all-stats-table} +```{r demo-all-stats-table, purl=FALSE} if (!is.null(all_flights_stats)) { display_stats <- all_flights_stats display_stats$diffusion_distance_km <- round(display_stats$diffusion_distance_km, 2) @@ -564,7 +569,7 @@ if (!is.null(all_flights_stats)) { The `calculateStatsSummary()` function computes central tendency and dispersion measures for each trajectory parameter. -```{r demo-summary-stats} +```{r demo-summary-stats, purl=FALSE} if (!is.null(all_flights_stats) && nrow(all_flights_stats) >= 2) { summary_stats <- calculateStatsSummary(all_flights_stats) knitr::kable(summary_stats, caption = "Descriptive Statistics Summary") @@ -577,7 +582,7 @@ if (!is.null(all_flights_stats) && nrow(all_flights_stats) >= 2) { Boxplots provide a robust visualization of parameter distributions, displaying median, interquartile range, and potential outliers. The red diamond indicates the arithmetic mean. -```{r demo-boxplots, fig.width=10, fig.height=8} +```{r demo-boxplots, fig.width=10, fig.height=8, purl=FALSE} if (!is.null(all_flights_stats) && nrow(all_flights_stats) >= 2) { createBoxplots(all_flights_stats) } else { @@ -589,7 +594,7 @@ if (!is.null(all_flights_stats) && nrow(all_flights_stats) >= 2) { Density plots employ kernel density estimation to approximate the probability distribution of each parameter. Vertical lines indicate mean (red, dashed) and median (green, dotted). -```{r demo-density, fig.width=10, fig.height=8} +```{r demo-density, fig.width=10, fig.height=8, purl=FALSE} if (!is.null(all_flights_stats) && nrow(all_flights_stats) >= 3) { createDensityPlots(all_flights_stats) } else { @@ -601,7 +606,7 @@ if (!is.null(all_flights_stats) && nrow(all_flights_stats) >= 3) { Histograms with overlaid density curves provide an alternative visualization of parameter distributions. -```{r demo-histograms, fig.width=10, fig.height=8} +```{r demo-histograms, fig.width=10, fig.height=8, purl=FALSE} if (!is.null(all_flights_stats) && nrow(all_flights_stats) >= 3) { createHistograms(all_flights_stats) } else { @@ -613,7 +618,7 @@ if (!is.null(all_flights_stats) && nrow(all_flights_stats) >= 3) { The `generateInterpretation()` function provides contextual analysis of the computed trajectory metrics. -```{r demo-interpretation} +```{r demo-interpretation, purl=FALSE} if (!is.null(all_flights_stats) && nrow(all_flights_stats) >= 2) { interpretation <- generateInterpretation(all_flights_stats) cat(interpretation)