From Track Workout to Ridgelines with Gemini CLI
There's a unique satisfaction that comes from a tough track workout. Is there a better recovery protocol than using Gemini CLI to draw beautiful plots from the data? You tell me!
Yesterday, I ran a series of 800-meter repeats that left my legs feeling it. Here's the plot:
I love ridgeline plots for their visual aesthetic. This plot provides several key insights into my workout:
- Interval Representation: Each ridgeline represents a distinct interval, with its shape illustrating the frequency of different power outputs (the power distribution).
- Pacing Stability: The multiple bumps within each curve suggest my pacing wasn't perfectly stable. Instead of a single peak that would indicate a consistent effort, the variations show fluctuations in my power output.
- Effort Comparison: The color of each ridge corresponds to the median power, which helps compare my overall effort across intervals. You can see how the median power increases with each interval, culminating in a final, intense 400-meter push.
In a previous post, I showed in more detail how I downloaded a .FIT file from Garmin Connect and created a heart rate to power scatter plot with the help of Gemini CLI.
Today, I followed the same process, but initially, I didn't get the results I wanted. Let me tell you how I resolved that.
Debugging in a Refinement Loop
I started by asking for a scatterplot of heart rate versus power for the series of 800-meter repeats, with each interval colored differently. Gemini CLI quickly wrote an executable Python script, but the initial plot was empty.
When I asked it to read the image and fix the script, Gemini CLI started a refinement loop, repeating the following actions until it produced a plot with data:
- Propose and apply changes to the script.
- Execute the script.
- Analyze the resulting image to check if it contained data.
During the process, I paid close attention and occasionally canceled an edit when I thought it was going in the wrong direction, explaining my reasoning before telling it to continue.
A few times, I nudged it to add more verbose logging. Because Gemini CLI adds the script's output to the conversation history, it can learn directly from the debug logs.
Eventually, the plot showed data. Although Gemini CLI initially misunderstood how intervals were represented in the data file, it figured it out through this iterative process.
This process highlights Gemini CLI's ability to work with images, a feature powered by the underlying Gemini 2.5 Pro model, which can process information from text, code, images, and more. You can learn more from the Gemini 2.5 Pro model card.
Asking for Options
The scatter plot was a blob of overlapping, multicolored dots. I didn't like it, so I asked Gemini CLI for some options:
"Can you inspire me with other ways to plot this data in visually interesting ways to uncover patterns, that are not the usual plots?"
It returned several interesting suggestions, including the idea for the ridgeline plot. Among its other ideas were:
- A polar power plot: a circular graph where power radiates from the center over time, creating a unique fingerprint of a session's intensity.
- A power-cadence density heatmap, a 2D heatmap that reveals the most frequently used power and cadence combinations.
- A GPS power map, a geographical map where the route is colored by power output, connecting effort directly to the terrain.
I really liked the options. I've found that asking for different options is a great way to kick-start my own creative process, and I'm using this technique often when prompting.
Summary
I highlighted two key techniques I like using when working with Gemini CLI:
- The refinement loop, where Gemini CLI iteratively debugs a script by executing it and analyzing the output (and verbose logging) until it achieves the desired result.
- Prompting for options, which led me to discover that a ridgeline plot is a more effective visualization than a standard scatter plot.
Also I'm really hoping my legs feel better tomorrow.
* * *
More on: Gemini CLI: Google's coding agent for the terminal →