deeplycloudy / xlma-python

A future, Python-based version of xlma?
MIT License
6 stars 6 forks source link

Interactive xlma plot in Jupyter widget #20

Closed deeplycloudy closed 1 year ago

deeplycloudy commented 2 years ago

This PR introduces a couple classes that handle interactive updating of all of the xlma panels after using the standard tools in the Matplotlib widget.

Usage is straightforward:

from pyxlma.plot.interactive import InteractiveLMAPlot
ds = xr.open_dataset('LYLOUT_220604_190000_18000_map500m.nc')
interactive_lma = InteractiveLMAPlot(ds)

All of the usual Matplotlib commands for changing axis limits automatically generate the necessary updates on the data side. It is therefore possible to programmatically control the axis limits and save, for example, an animation, with a handful of lines of code.

The built-in plotting routine works on any cf-lma-format NetCDF file from that branch, and can be overridden to add additional things, e.g.,

class AnnotatedLMAPlot(InteractiveLMAPlot):
    # @output.capture()
    def make_plot(self):
        super(AnnotatedLMAPlot, self).make_plot()

        for track_df, track_highlight_color, whole_track_color in zip(
                (convair_track_df, lear_track_df), ('red', 'blue'), ((.9,.8,.8), (.8,.8,.9))):
            time_pad = pd.to_timedelta('3 min')
            track_in_time = ((track_df.time >= (self.bounds['t'][0]-time_pad)) & 
                             (track_df.time <= (self.bounds['t'][1]+time_pad)) &
                             (track_df.Lon >= self.bounds['x'][0]) & (track_df.Lon <= self.bounds['x'][1]) &
                             (track_df.Lat >= self.bounds['y'][0]) & (track_df.Lat <= self.bounds['y'][1])
                            )

            current_track = track_df[track_in_time]
            c0, = self.lma_plot.ax_plan.plot(track_df.Lon, track_df.Lat, color=whole_track_color, zorder=-10)
            c1, = self.lma_plot.ax_plan.plot(current_track.Lon, current_track.Lat, color=track_highlight_color)
            c2, = self.lma_plot.ax_th.plot(track_df.time, track_df.AltM/1000.0, color=whole_track_color, zorder=-10)
            c3, = self.lma_plot.ax_th.plot(current_track.time, current_track.AltM/1000.0, color=track_highlight_color)
            c4, = self.lma_plot.ax_lon.plot(track_df.Lon, track_df.AltM/1000.0, color=whole_track_color, zorder=-10)
            c5, = self.lma_plot.ax_lon.plot(current_track.Lon, current_track.AltM/1000.0, color=track_highlight_color)
            c6, = self.lma_plot.ax_lat.plot(track_df.AltM/1000.0, track_df.Lat, color=whole_track_color, zorder=-10)
            c7, = self.lma_plot.ax_lat.plot(current_track.AltM/1000.0, current_track.Lat, color=track_highlight_color)
            track_artists = [c0,c1,c2,c3,c4,c5,c6,c7]
            self.data_artists.extend(track_artists)

I'd be curious to hear your thoughts and suggestions, @vbalderdash, @tjlang, @mikestock, and @ronthomaslightning. It would also be good to get some other users to put some mileage on this to find all of my bugs.

deeplycloudy commented 1 year ago

Full example of usage is in our TRACER analysis repo - see LMA-radar-aircraft-quicklook.ipynb

deeplycloudy commented 1 year ago

Merging after some offline conversation.