Skip to content

Release v0.3.0

Latest

Choose a tag to compare

@stiles stiles released this 29 Aug 02:53

Added

  • --format flag and formats argument, taking a comma-separated list of png (default), svg and pdf. Each graphic is written once per format, so --format png,svg leaves map.svg beside map.png. SVG keeps the route, the chrome and the type as vectors for editing in Illustrator, with the type left as live text rather than outlines; the basemap rides along as an embedded raster, since that's what tiles are.
  • Origin and destination are marked on the map with a dot and their airport code. Labels sit under the dot, since most routes run east to west and a label set alongside lands on the line, and they move above the dot or hug the panel edge where they'd otherwise overflow. These are the first and last fix, which is close to the runway rather than the terminal.
  • in_progress argument to plot_flight_map, enhanced_plot_flight and export_flight_data, set from the summary record by smart-export, which distinguishes an aircraft still flying from one whose track merely ran out.
  • toplines.json carries in_progress, plus last_position_time and last_position_time_readable.
  • A real export is committed under examples/: the map, both charts and toplines.json from a San Francisco to New York flight that held at 39,000 feet south of Buffalo, so the output can be seen without installing or holding an API token. The data files and SVGs are left out, since points.geojson and map.svg alone would add 1.3 MB. examples/README.md works through why the dip under that hold is mostly a lost tailwind rather than braking.
  • The map is bordered in the same light gray as the chart gridlines, so it reads as a panel instead of bleeding into the page, and a map and a chart of the same flight sit together.

Changed

  • Deks spell out the tracked duration: "4 hours, 2 minutes tracked" rather than "4 hr 2 min tracked", with singulars handled so an hour and a minute don't come out plural.
  • Dropped geopandas and shapely from the dependencies. Both were there for a single coordinate transform, which the antimeridian fix had to replace anyway, and one of them drags in GDAL. numpy is now declared instead: viz imports it directly and it had been arriving only as a transitive dependency of matplotlib and pandas.
  • The version is defined once, in pyfr24/__init__.py, and setup.py parses it from there rather than carrying a second copy. Two hand-maintained literals is what let 0.2.0 ship reporting itself as 1.0.0. publish.sh now bumps a single file, and a test asserts the packaged version matches pyfr24.__version__.
  • python_requires is now >=3.9. The package imports zoneinfo for timezone conversion, which is standard library only from 3.9, so the advertised 3.8 support never worked. The CI matrix drops 3.8 and adds 3.12 and 3.13.
  • Publishing to PyPI happens once, in the release workflow. publish.sh uploaded with twine and then created a GitHub release that triggered a second upload, so every Publish run failed with "400 File already exists" after the package had already gone out.
  • Tests that call the live API are marked integration and deselected in CI, so the suite no longer depends on a given flight having operated on the day it runs.

Fixed

  • Flights that cross the antimeridian are drawn across the Pacific rather than the long way around the world (#2). Longitude is unwrapped so the path stays continuous past 180 degrees, and the extent that produces is wider than the one world tile servers publish, so the basemap is now fetched a world at a time and composited. Contextily can't do this itself: it hands the bounds to mercantile, which clamps them, and reports success after rendering nothing past the world's edge. The projection is also worked out directly instead of through a CRS transform, which folds longitude back inside 180 and undoes the unwrapping.
  • Maps and charts break where ADS-B coverage stops instead of ruling a straight line through the hole (#3). An Auckland-to-Los Angeles flight loses coverage over the South Pacific for hours, which the altitude chart drew as a slow, steady climb that never happened. The threshold scales with each flight's own median ping interval rather than being fixed, since cadence varies by region, and a break also has to cover ground, so an aircraft sitting at a gate between pings stays one line rather than fragmenting into dots.
  • A missing altitude or speed reading is plotted as missing rather than as zero. Substituting zero drew a cliff to sea level in the middle of a cruise.
  • A track that stops in the air is no longer labeled with the destination airport. A flight caught mid-air ends wherever the aircraft happened to be — DL691 was drawn with a dot and "KJFK" at 39,000 feet over Pennsylvania, two hundred miles short — and receivers routinely lose an aircraft before it lands. Above 5,000 feet the end of the line becomes an arrowhead turned the way the aircraft was heading, labeled "In flight" when the API says the flight hadn't landed and "Last contact" when the track simply ran out; the dek says "still in the air" for a flight in progress. Of 181 local exports, 42 ended at cruise altitude, so roughly one in four carried the wrong label.
  • A landing time now settles whether a flight is still airborne, ahead of the flight_ended flag. That flag marks a record as closed out rather than a flight as over, and Flightradar24 leaves it false for a while after touchdown: DL691 on Aug. 28, 2026 read flight_ended: false next to a landing time of 02:10 UTC, which would have had a parked aircraft reported as flying and its arrival time thrown away.
  • toplines.json no longer reports an arrival time for a flight that hadn't landed. arrival_time fell back to the moment the aircraft was last seen, which for a flight in progress is a point over open country at cruise. It's now null, and the last-seen time is carried as last_position_time.
  • A single implausible reading is dropped rather than drawn. NZ6 reported 30 knots at 35,000 feet between two readings near 500, which put a cliff to the floor of the speed chart; recovering from it would have taken 0.8 g. A reading goes only when the readings either side agree with each other and it departs from both by more than 200 knots or 5,000 feet, so a real and violent change, which plays out over several pings, is kept. Thirteen percent of local exports had at least one.
  • The speed chart notes when much of a track was fixed by multilateration, whose speeds are inferred from signal timing at several receivers and wobble by hundreds of knots. QR739 had 847 such fixes out of 2,229, and no point-by-point filter can rescue that; the graphic now says the speeds are estimated instead.
  • tests/ was listed in .gitignore, so only the handful of files committed before that line was added were ever in the repository or run by CI. New tests were silently untracked.