Merge "Delete old Python plotter"
diff --git a/frc971/analysis/BUILD b/frc971/analysis/BUILD
index f56c429..7cb0b4d 100644
--- a/frc971/analysis/BUILD
+++ b/frc971/analysis/BUILD
@@ -6,13 +6,6 @@
 load("@com_github_google_flatbuffers//:build_defs.bzl", "flatbuffer_cc_library", "flatbuffer_ts_library")
 load("//aos:config.bzl", "aos_config")
 
-py_library(
-    name = "python_init",
-    srcs = ["__init__.py"],
-    target_compatible_with = ["@platforms//os:linux"],
-    deps = ["//frc971:python_init"],
-)
-
 cc_binary(
     name = "py_log_reader.so",
     srcs = ["py_log_reader.cc"],
@@ -40,36 +33,6 @@
     deps = ["//aos:configuration_fbs_python"],
 )
 
-py_proto_library(
-    name = "plot_config_proto",
-    srcs = ["plot_config.proto"],
-    target_compatible_with = ["@platforms//os:linux"],
-)
-
-py_binary(
-    name = "plot",
-    srcs = ["plot.py"],
-    data = [
-        ":py_log_reader.so",
-    ] + glob(["plot_configs/**"]),
-    target_compatible_with = ["@platforms//os:linux"],
-    deps = [
-        ":plot_config_proto",
-        ":python_init",
-        "@matplotlib_repo//:matplotlib3",
-    ],
-)
-
-py_test(
-    name = "plot_test",
-    srcs = ["plot_test.py"],
-    data = [
-        "@sample_logfile//file",
-    ],
-    target_compatible_with = ["@platforms//os:linux"],
-    deps = [":plot"],
-)
-
 ts_library(
     name = "plot_index",
     srcs = ["plot_index.ts"],
diff --git a/frc971/analysis/__init__.py b/frc971/analysis/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/frc971/analysis/__init__.py
+++ /dev/null
diff --git a/frc971/analysis/drivetrain_down_stripped b/frc971/analysis/drivetrain_down_stripped
deleted file mode 100644
index 3b3e43d..0000000
--- a/frc971/analysis/drivetrain_down_stripped
+++ /dev/null
@@ -1,4 +0,0 @@
-drivetrain.stripped output left_voltage
-drivetrain.stripped output right_voltage
-
-drivetrain.stripped status ground_angle
diff --git a/frc971/analysis/drivetrain_plot_stripped b/frc971/analysis/drivetrain_plot_stripped
deleted file mode 100644
index 3c24485..0000000
--- a/frc971/analysis/drivetrain_plot_stripped
+++ /dev/null
@@ -1,20 +0,0 @@
-drivetrain.stripped output left_voltage
-drivetrain.stripped output right_voltage
-
-drivetrain.stripped status profiled_left_position_goal
-drivetrain.stripped status profiled_right_position_goal
-drivetrain.stripped status profiled_left_velocity_goal
-drivetrain.stripped status profiled_right_velocity_goal
-
-drivetrain.stripped status estimated_left_position
-drivetrain.stripped status estimated_right_position
-drivetrain.stripped status estimated_left_velocity
-drivetrain.stripped status estimated_right_velocity
-
-drivetrain.stripped goal left_goal
-drivetrain.stripped goal right_goal
-
-drivetrain.stripped status left_voltage_error -m 0.1
-drivetrain.stripped status right_voltage_error -m 0.1
-
-drivetrain.stripped using accelerometer_y -m -10
diff --git a/frc971/analysis/drivetrain_test_plot b/frc971/analysis/drivetrain_test_plot
deleted file mode 100644
index 0b2cc2a..0000000
--- a/frc971/analysis/drivetrain_test_plot
+++ /dev/null
@@ -1,16 +0,0 @@
-drivetrain_lib_test output left_voltage
-drivetrain_lib_test output right_voltage
-
-drivetrain_lib_test status estimated_left_position
-drivetrain_lib_test status estimated_right_position
-drivetrain_lib_test status estimated_left_velocity
-drivetrain_lib_test status estimated_right_velocity
-
-drivetrain_lib_test goal left_goal
-drivetrain_lib_test goal right_goal
-drivetrain_lib_test status profiled_left_position_goal
-drivetrain_lib_test status profiled_right_position_goal
-drivetrain_lib_test status profiled_left_velocity_goal
-drivetrain_lib_test status profiled_right_velocity_goal
-
-robot_state browned_out
diff --git a/frc971/analysis/plot.py b/frc971/analysis/plot.py
deleted file mode 100644
index efe86f4..0000000
--- a/frc971/analysis/plot.py
+++ /dev/null
@@ -1,306 +0,0 @@
-#!/usr/bin/python3
-# Sample usage:
-# bazel run -c opt //frc971/analysis:plot  -- --logfile /tmp/log.fbs --config gyro.pb
-import argparse
-import json
-import os.path
-from pathlib import Path
-import sys
-
-from frc971.analysis.py_log_reader import LogReader
-from frc971.analysis.plot_config_pb2 import PlotConfig, Signal, Line
-from google.protobuf import text_format
-
-import numpy as np
-import matplotlib
-from matplotlib import pyplot as plt
-
-
-class Plotter:
-    def __init__(self, plot_config: PlotConfig, reader: LogReader):
-        self.config = plot_config
-        self.reader = reader
-        # Data streams, indexed by alias.
-        self.data = {}
-
-    def process_logfile(self):
-        aliases = set()
-        for channel in self.config.channel:
-            if channel.alias in aliases:
-                raise ValueError("Duplicate alias " + channel.alias)
-            if not self.reader.subscribe(channel.name, channel.type):
-                print("Warning: No such channel with name " + channel.name +
-                      " and type " + channel.type)
-                continue
-            aliases.add(channel.alias)
-
-        self.reader.process()
-
-        for channel in self.config.channel:
-            self.data[channel.alias] = []
-            if channel.alias not in aliases:
-                print("Unable to plot channel alias " + channel.alias)
-                continue
-            for message in self.reader.get_data_for_channel(
-                    channel.name, channel.type):
-                valid_json = message[2].replace('nan', '"nan"')
-                valid_json = valid_json.replace(' inf', ' "inf"')
-                valid_json = valid_json.replace('-inf', '"-inf"')
-                try:
-                    parsed_json = json.loads(valid_json)
-                except json.decoder.JSONDecodeError as ex:
-                    print("JSON Decode failed:")
-                    print(valid_json)
-                    raise ex
-                self.data[channel.alias].append(
-                    (message[0], message[1], parsed_json))
-        self.calculate_signals()
-
-    def calculate_down_estimator_signals(self):
-        if 'DrivetrainStatus' in self.data:
-            # Calculates a rolling mean of the acceleration output from
-            # the down estimator.
-            entries = []
-            buffer_len = 100
-            last_100_accels = np.zeros((buffer_len, 3))
-            accels_next_row = 0
-            for entry in self.data['DrivetrainStatus']:
-                msg = entry[2]
-                new_msg = {}
-                if 'down_estimator' not in msg:
-                    continue
-                down_estimator = msg['down_estimator']
-                new_msg['down_estimator'] = {}
-                accel_x = 'accel_x'
-                accel_y = 'accel_y'
-                accel_z = 'accel_z'
-                if (accel_x in down_estimator and accel_y in down_estimator
-                        and accel_x in down_estimator):
-                    last_100_accels[accels_next_row, :] = [
-                        down_estimator[accel_x], down_estimator[accel_y],
-                        down_estimator[accel_z]
-                    ]
-
-                    accels_next_row += 1
-                    accels_next_row = accels_next_row % buffer_len
-                    mean_accels = np.mean(last_100_accels, axis=0)
-                    new_msg['down_estimator'][
-                        'accel_x_rolling_mean'] = mean_accels[0]
-                    new_msg['down_estimator'][
-                        'accel_y_rolling_mean'] = mean_accels[1]
-                    new_msg['down_estimator'][
-                        'accel_z_rolling_mean'] = mean_accels[2]
-                entries.append((entry[0], entry[1], new_msg))
-            if 'CalcDrivetrainStatus' in self.data:
-                raise RuntimeError(
-                    'CalcDrivetrainStatus is already a member of data.')
-            self.data['CalcDrivetrainStatus'] = entries
-
-    def calculate_imu_signals(self):
-        if 'IMU' in self.data:
-            entries = []
-            # Calculates a rolling mean of the raw output from the IMU.
-            buffer_len = 1000
-            last_1000_accels = np.zeros((buffer_len, 3))
-            accels_next_row = 0
-            last_1000_gyros = np.zeros((buffer_len, 3))
-            gyros_next_row = 0
-            for entry in self.data['IMU']:
-                for msg in entry[2]['readings']:
-                    accel_x = 'accelerometer_x'
-                    accel_y = 'accelerometer_y'
-                    accel_z = 'accelerometer_z'
-                    gyro_x = 'gyro_x'
-                    gyro_y = 'gyro_y'
-                    gyro_z = 'gyro_z'
-                    temp = 'temperature'
-                    new_msg = {}
-                    if temp in msg:
-                        new_msg[temp] = msg[temp]
-                    if accel_x in msg and accel_y in msg and accel_x in msg:
-                        last_1000_accels[accels_next_row, :] = [
-                            msg[accel_x], msg[accel_y], msg[accel_z]
-                        ]
-                        total_acceleration = np.linalg.norm(
-                            last_1000_accels[accels_next_row, :])
-                        new_msg['total_acceleration'] = total_acceleration
-
-                        accels_next_row += 1
-                        accels_next_row = accels_next_row % buffer_len
-                        std_accels = np.std(last_1000_accels, axis=0)
-                        new_msg['accel_x_rolling_std'] = std_accels[0]
-                        new_msg['accel_y_rolling_std'] = std_accels[1]
-                        new_msg['accel_z_rolling_std'] = std_accels[2]
-                        mean_accels = np.mean(last_1000_accels, axis=0)
-                        new_msg['accel_x_rolling_mean'] = mean_accels[0]
-                        new_msg['accel_y_rolling_mean'] = mean_accels[1]
-                        new_msg['accel_z_rolling_mean'] = mean_accels[2]
-                        new_msg[accel_x] = msg[accel_x]
-                        new_msg[accel_y] = msg[accel_y]
-                        new_msg[accel_z] = msg[accel_z]
-                    if gyro_x in msg and gyro_y in msg and gyro_z in msg:
-                        last_1000_gyros[gyros_next_row, :] = [
-                            msg[gyro_x], msg[gyro_y], msg[gyro_z]
-                        ]
-                        gyros_next_row += 1
-                        gyros_next_row = gyros_next_row % buffer_len
-                        std_gyros = np.std(last_1000_gyros, axis=0)
-                        new_msg['gyro_x_rolling_std'] = std_gyros[0]
-                        new_msg['gyro_y_rolling_std'] = std_gyros[1]
-                        new_msg['gyro_z_rolling_std'] = std_gyros[2]
-                        mean_gyros = np.mean(last_1000_gyros, axis=0)
-                        new_msg['gyro_x_rolling_mean'] = mean_gyros[0]
-                        new_msg['gyro_y_rolling_mean'] = mean_gyros[1]
-                        new_msg['gyro_z_rolling_mean'] = mean_gyros[2]
-                        new_msg[gyro_x] = msg[gyro_x]
-                        new_msg[gyro_y] = msg[gyro_y]
-                        new_msg[gyro_z] = msg[gyro_z]
-                    timestamp = 'monotonic_timestamp_ns'
-                    if timestamp in msg:
-                        timestamp_sec = msg[timestamp] * 1e-9
-                        new_msg['monotonic_timestamp_sec'] = timestamp_sec
-                    entries.append((entry[0], entry[1], new_msg))
-            if 'CalcIMU' in self.data:
-                raise RuntimeError('CalcIMU is already a member of data.')
-            self.data['CalcIMU'] = entries
-
-    def calculate_signals(self):
-        """Calculate any derived signals for plotting.
-
-        See calculate_imu_signals for an example, but the basic idea is that
-        for any data that is read in from the logfile, we may want to calculate
-        some derived signals--possibly as simple as doing unit conversions,
-        or more complicated version where we do some filtering or the such.
-        The way this will work is that the calculate_* functions will, if the
-        raw data is available, calculate the derived signals and place them into
-        fake "messages" with an alias of "Calc*". E.g., we currently calculate
-        an overall magnitude for the accelerometer readings, which is helpful
-        to understanding how some internal filters work."""
-        self.calculate_imu_signals()
-        self.calculate_down_estimator_signals()
-
-    def extract_field(self, message: dict, field: str):
-        """Extracts a field with the given name from the message.
-
-        message will be a dictionary with field names as the keys and then
-        values, lists, or more dictionaries as the values. field is the full
-        path to the field to extract, with periods separating sub-messages."""
-        field_path = field.split('.')
-        value = message
-        for name in field_path:
-            # If the value wasn't populated in a given message, fill in
-            # NaN rather than crashing.
-            if name in value:
-                value = value[name]
-            else:
-                return None
-        # Catch NaNs and convert them to floats.
-        return float(value)
-
-    def plot_line(self, axes: matplotlib.axes.Axes, line: Line):
-        if not line.HasField('y_signal'):
-            raise ValueError("No y_channel specified for line.")
-        y_signal = line.y_signal
-        if not y_signal.channel in self.data:
-            raise ValueError("No channel alias " + y_signal.channel)
-        x_signal = line.x_signal if line.HasField('x_signal') else None
-        if x_signal is not None and not x_signal.channel in self.data:
-            raise ValueError("No channel alias " + x_signal.channel)
-        y_messages = self.data[y_signal.channel]
-        x_messages = self.data[
-            x_signal.channel] if x_signal is not None else None
-        if x_messages is not None and len(x_messages) != len(y_messages):
-            raise ValueError(
-                "X and Y signal lengths don't match. X channel is " +
-                x_signal.channel + " Y channel is " + y_signal.channel)
-        x_data = []
-        y_data = []
-        for ii in range(len(y_messages)):
-            y_entry = y_messages[ii]
-            if x_signal is None:
-                x_data.append(y_entry[0] * 1e-9)
-            else:
-                x_entry = x_messages[ii]
-                x_data.append(self.extract_field(x_entry[2], x_signal.field))
-            y_data.append(self.extract_field(y_entry[2], y_signal.field))
-            if x_data[-1] is None and y_data[-1] is not None:
-                raise ValueError(
-                    "Only one of the x and y signals is present. X " +
-                    x_signal.channel + "." + x_signal.field + " Y " +
-                    y_signal.channel + "." + y_signal.field)
-        label_name = y_signal.channel + "." + y_signal.field
-        axes.plot(x_data, y_data, marker='o', label=label_name)
-
-    def plot(self):
-        shared_axis = None
-        for figure_config in self.config.figure:
-            fig = plt.figure()
-            num_subplots = len(figure_config.axes)
-            for ii in range(num_subplots):
-                axes_config = figure_config.axes[ii]
-                share_axis = axes_config.share_x_axis
-                axes = fig.add_subplot(
-                    num_subplots,
-                    1,
-                    ii + 1,
-                    sharex=shared_axis if share_axis else None)
-                if share_axis and shared_axis is None:
-                    shared_axis = axes
-                for line in axes_config.line:
-                    self.plot_line(axes, line)
-                # Make the legend transparent so we can see behind it.
-                legend = axes.legend(framealpha=0.5, loc='upper right')
-                axes.set_xlabel(axes_config.xlabel)
-                axes.grid(True)
-                if axes_config.HasField("ylabel"):
-                    axes.set_ylabel(axes_config.ylabel)
-
-
-def main(argv):
-    parser = argparse.ArgumentParser(
-        description="Plot data from an aos logfile.")
-    parser.add_argument("--logfile",
-                        type=str,
-                        required=True,
-                        help="Path to the logfile to parse.")
-    parser.add_argument("--config",
-                        type=str,
-                        required=True,
-                        help="Name of the plot config to use.")
-    parser.add_argument("--config_dir",
-                        type=str,
-                        default="frc971/analysis/plot_configs",
-                        help="Directory to look for plot configs in.")
-    args = parser.parse_args(argv[1:])
-
-    if not os.path.isdir(args.config_dir):
-        print(args.config_dir + " is not a directory.")
-        return 1
-    config_path = os.path.join(args.config_dir, args.config)
-    if not os.path.isfile(config_path):
-        print(config_path +
-              " does not exist or is not a file--available configs are")
-        for file_name in os.listdir(args.config_dir):
-            print(os.path.basename(file_name))
-        return 1
-
-    config = PlotConfig()
-    with open(config_path) as config_file:
-        text_format.Merge(config_file.read(), config)
-
-    if not os.path.isfile(args.logfile):
-        print(args.logfile + " is not a file.")
-        return 1
-
-    reader = LogReader(args.logfile)
-
-    plotter = Plotter(config, reader)
-    plotter.process_logfile()
-    plotter.plot()
-    plt.show()
-
-    return 0
-
-
-if __name__ == '__main__':
-    sys.exit(main(sys.argv))
diff --git a/frc971/analysis/plot_config.proto b/frc971/analysis/plot_config.proto
deleted file mode 100644
index cd01f73..0000000
--- a/frc971/analysis/plot_config.proto
+++ /dev/null
@@ -1,64 +0,0 @@
-syntax = "proto2";
-
-package frc971.analysis;
-
-// Specification fo a Channel to pull from the logfile. The name and type will
-// be the full name/type of the channel to pull from the logfile. The alias is a
-// shorter, easier to type, name that the rest of the logfile will use to refer
-// to the channel.
-message Channel {
-  optional string name = 1;
-  optional string type = 2;
-  optional string alias = 3;
-}
-
-// A specification for a single signal within a Channel.
-message Signal {
-  // Alias for the channel to pull the signal from--this should match an alias
-  // specified in one of the Channels.
-  optional string channel = 1;
-  // Specification of the field to plot. Currently, this only supports simple
-  // submessages, using dots. To access, e.g., the "bar" member of the "foo"
-  // submessage, field would be "foo.bar". This does not currently support
-  // working with repeated fields.
-  optional string field = 2;
-}
-
-// A single line to plot.
-message Line {
-  // The signal to plot on the y-axis.
-  optional Signal y_signal = 1;
-  // If set, we will use this signal for the x-axis of the plot. By default, we
-  // will use the monotonic sent time of the message. This is helpful for both
-  // plotting against non-time based signals (e.g., plotting x/y robot position)
-  // as well as plotting against times other than the message sent time (e.g.,
-  // for the IMU where the sample capture time is separate from the actual
-  // sent time.
-  // Note that the x and y signals should have exactly the same number of
-  // entries--otherwise, we need to write logic to handle resampling one signal
-  // to a different rate.
-  optional Signal x_signal = 2;
-}
-
-// Message representing a single pyplot Axes, with specifications for exactly
-// which signals to show in the supplied subplot.
-message Axes {
-  repeated Line line = 1;
-  optional string ylabel = 2;
-  optional string xlabel = 3 [default = "Monotonic Time (sec)"];
-  // Whether to share an x-axis with all the other axes.
-  optional bool share_x_axis = 4 [default = true];
-}
-
-// Message representing a single pyplot figure.
-message Figure {
-  repeated Axes axes = 1;
-}
-
-// This configuration specifies what to plot when reading from a logfile.
-message PlotConfig {
-  // List of channels and their aliases to use in the plot.
-  repeated Channel channel = 1;
-  // Figures to plot.
-  repeated Figure figure = 2;
-}
diff --git a/frc971/analysis/plot_configs/down_estimator.pb b/frc971/analysis/plot_configs/down_estimator.pb
deleted file mode 100644
index 48cf2ef..0000000
--- a/frc971/analysis/plot_configs/down_estimator.pb
+++ /dev/null
@@ -1,187 +0,0 @@
-channel {
-  name: "/drivetrain"
-  type: "frc971.control_loops.drivetrain.Status"
-  alias: "DrivetrainStatus"
-}
-
-figure {
-  axes {
-    line {
-      y_signal {
-        channel: "DrivetrainStatus"
-        field: "down_estimator.yaw"
-      }
-    }
-    line {
-      y_signal {
-        channel: "DrivetrainStatus"
-        field: "down_estimator.lateral_pitch"
-      }
-    }
-    line {
-      y_signal {
-        channel: "DrivetrainStatus"
-        field: "down_estimator.longitudinal_pitch"
-      }
-    }
-    ylabel: "rad"
-  }
-  axes {
-    line {
-      y_signal {
-        channel: "DrivetrainStatus"
-        field: "down_estimator.quaternion_x"
-      }
-    }
-    line {
-      y_signal {
-        channel: "DrivetrainStatus"
-        field: "down_estimator.quaternion_y"
-      }
-    }
-    line {
-      y_signal {
-        channel: "DrivetrainStatus"
-        field: "down_estimator.quaternion_z"
-      }
-    }
-    line {
-      y_signal {
-        channel: "DrivetrainStatus"
-        field: "down_estimator.quaternion_w"
-      }
-    }
-  }
-  axes {
-    line {
-      y_signal {
-        channel: "DrivetrainStatus"
-        field: "down_estimator.accel_x"
-      }
-    }
-    line {
-      y_signal {
-        channel: "DrivetrainStatus"
-        field: "down_estimator.accel_y"
-      }
-    }
-    line {
-      y_signal {
-        channel: "DrivetrainStatus"
-        field: "down_estimator.accel_z"
-      }
-    }
-    ylabel: "m/s/s"
-  }
-  axes {
-    line {
-      y_signal {
-        channel: "DrivetrainStatus"
-        field: "down_estimator.velocity_x"
-      }
-    }
-    line {
-      y_signal {
-        channel: "DrivetrainStatus"
-        field: "down_estimator.velocity_y"
-      }
-    }
-    line {
-      y_signal {
-        channel: "DrivetrainStatus"
-        field: "down_estimator.velocity_z"
-      }
-    }
-  }
-  axes {
-    line {
-      y_signal {
-        channel: "DrivetrainStatus"
-        field: "down_estimator.position_x"
-      }
-    }
-    line {
-      y_signal {
-        channel: "DrivetrainStatus"
-        field: "down_estimator.position_y"
-      }
-    }
-    line {
-      y_signal {
-        channel: "DrivetrainStatus"
-        field: "down_estimator.position_z"
-      }
-    }
-  }
-}
-
-figure {
-  axes {
-    line {
-      y_signal {
-        channel: "DrivetrainStatus"
-        field: "zeroing.gyro_x_average"
-      }
-    }
-    line {
-      y_signal {
-        channel: "DrivetrainStatus"
-        field: "zeroing.gyro_y_average"
-      }
-    }
-    line {
-      y_signal {
-        channel: "DrivetrainStatus"
-        field: "zeroing.gyro_z_average"
-      }
-    }
-  }
-  axes {
-    line {
-      y_signal {
-        channel: "DrivetrainStatus"
-        field: "down_estimator.expected_accel_x"
-      }
-    }
-    line {
-      y_signal {
-        channel: "DrivetrainStatus"
-        field: "down_estimator.expected_accel_y"
-      }
-    }
-    line {
-      y_signal {
-        channel: "DrivetrainStatus"
-        field: "down_estimator.expected_accel_z"
-      }
-    }
-  }
-  axes {
-    line {
-      y_signal {
-        channel: "DrivetrainStatus"
-        field: "down_estimator.gravity_magnitude"
-      }
-    }
-  }
-  axes {
-    line {
-      y_signal {
-        channel: "CalcDrivetrainStatus"
-        field: "down_estimator.accel_x_rolling_mean"
-      }
-    }
-    line {
-      y_signal {
-        channel: "CalcDrivetrainStatus"
-        field: "down_estimator.accel_y_rolling_mean"
-      }
-    }
-    line {
-      y_signal {
-        channel: "CalcDrivetrainStatus"
-        field: "down_estimator.accel_z_rolling_mean"
-      }
-    }
-  }
-}
diff --git a/frc971/analysis/plot_configs/drivetrain.pb b/frc971/analysis/plot_configs/drivetrain.pb
deleted file mode 100644
index 0335da8..0000000
--- a/frc971/analysis/plot_configs/drivetrain.pb
+++ /dev/null
@@ -1,463 +0,0 @@
-channel {
-  name: "/aos"
-  type: "aos.JoystickState"
-  alias: "JoystickState"
-}
-channel {
-  name: "/aos"
-  type: "aos.RobotState"
-  alias: "RobotState"
-}
-channel {
-  name: "/drivetrain"
-  type: "frc971.control_loops.drivetrain.Goal"
-  alias: "Goal"
-}
-channel {
-  name: "/drivetrain"
-  type: "frc971.control_loops.drivetrain.Status"
-  alias: "Status"
-}
-channel {
-  name: "/drivetrain"
-  type: "frc971.control_loops.drivetrain.Output"
-  alias: "Output"
-}
-channel {
-  name: "/drivetrain"
-  type: "frc971.IMUValues"
-  alias: "IMU"
-}
-
-figure {
-  axes {
-    line {
-      y_signal {
-        channel: "JoystickState"
-        field: "test_mode"
-      }
-    }
-    line {
-      y_signal {
-        channel: "JoystickState"
-        field: "autonomous"
-      }
-    }
-    line {
-      y_signal {
-        channel: "RobotState"
-        field: "browned_out"
-      }
-    }
-    line {
-      y_signal {
-        channel: "JoystickState"
-        field: "enabled"
-      }
-    }
-    ylabel: "[bool]"
-  }
-  axes {
-    line {
-      y_signal {
-        channel: "RobotState"
-        field: "voltage_battery"
-      }
-    }
-    ylabel: "[V]"
-  }
-  axes {
-    line {
-      y_signal {
-        channel: "Status"
-        field: "line_follow_logging.frozen"
-      }
-    }
-    line {
-      y_signal {
-        channel: "Goal"
-        field: "quickturn"
-      }
-    }
-    ylabel: "[bool]"
-  }
-}
-
-figure {
-  axes {
-    line {
-      y_signal {
-        channel: "Status"
-        field: "poly_drive_logging.ff_left_voltage"
-      }
-    }
-    line {
-      y_signal {
-        channel: "Status"
-        field: "poly_drive_logging.ff_right_voltage"
-      }
-    }
-    line {
-      y_signal {
-        channel: "Output"
-        field: "left_voltage"
-      }
-    }
-    line {
-      y_signal {
-        channel: "Output"
-        field: "right_voltage"
-      }
-    }
-    ylabel: "[V]"
-  }
-  axes {
-    line {
-      y_signal {
-        channel: "Status"
-        field: "theta"
-      }
-    }
-    ylabel: "[rad]"
-  }
-  axes {
-    line {
-      y_signal {
-        channel: "Status"
-        field: "robot_speed"
-      }
-    }
-    line {
-      y_signal {
-        channel: "Status"
-        field: "trajectory_logging.left_velocity"
-      }
-    }
-    line {
-      y_signal {
-        channel: "Status"
-        field: "poly_drive_logging.goal_left_velocity"
-      }
-    }
-    line {
-      y_signal {
-        channel: "Status"
-        field: "estimated_left_velocity"
-      }
-    }
-    line {
-      y_signal {
-        channel: "Status"
-        field: "trajectory_logging.right_velocity"
-      }
-    }
-    line {
-      y_signal {
-        channel: "Status"
-        field: "poly_drive_logging.goal_right_velocity"
-      }
-    }
-    line {
-      y_signal {
-        channel: "Status"
-        field: "estimated_right_velocity"
-      }
-    }
-    ylabel: "[m/s]"
-  }
-}
-
-figure {
-  axes {
-    line {
-      y_signal {
-        channel: "IMU"
-        field: "gyro_x"
-      }
-      x_signal {
-        channel: "CalcIMU"
-        field: "monotonic_timestamp_sec"
-      }
-    }
-    line {
-      y_signal {
-        channel: "IMU"
-        field: "gyro_y"
-      }
-      x_signal {
-        channel: "CalcIMU"
-        field: "monotonic_timestamp_sec"
-      }
-    }
-    line {
-      y_signal {
-        channel: "IMU"
-        field: "gyro_z"
-      }
-      x_signal {
-        channel: "CalcIMU"
-        field: "monotonic_timestamp_sec"
-      }
-    }
-    ylabel: "rad / sec"
-  }
-  axes {
-    line {
-      y_signal {
-        channel: "CalcIMU"
-        field: "total_acceleration"
-      }
-      x_signal {
-        channel: "CalcIMU"
-        field: "monotonic_timestamp_sec"
-      }
-    }
-    line {
-      y_signal {
-        channel: "IMU"
-        field: "accelerometer_x"
-      }
-      x_signal {
-        channel: "CalcIMU"
-        field: "monotonic_timestamp_sec"
-      }
-    }
-    line {
-      y_signal {
-        channel: "IMU"
-        field: "accelerometer_y"
-      }
-      x_signal {
-        channel: "CalcIMU"
-        field: "monotonic_timestamp_sec"
-      }
-    }
-    line {
-      y_signal {
-        channel: "IMU"
-        field: "accelerometer_z"
-      }
-      x_signal {
-        channel: "CalcIMU"
-        field: "monotonic_timestamp_sec"
-      }
-    }
-    ylabel: "g"
-  }
-}
-
-figure {
-  axes {
-    line {
-      y_signal {
-        channel: "Status"
-        field: "down_estimator.yaw"
-      }
-    }
-    line {
-      y_signal {
-        channel: "Status"
-        field: "down_estimator.lateral_pitch"
-      }
-    }
-    line {
-      y_signal {
-        channel: "Status"
-        field: "down_estimator.longitudinal_pitch"
-      }
-    }
-    ylabel: "rad"
-  }
-  axes {
-    line {
-      y_signal {
-        channel: "Status"
-        field: "down_estimator.quaternion_x"
-      }
-    }
-    line {
-      y_signal {
-        channel: "Status"
-        field: "down_estimator.quaternion_y"
-      }
-    }
-    line {
-      y_signal {
-        channel: "Status"
-        field: "down_estimator.quaternion_z"
-      }
-    }
-    line {
-      y_signal {
-        channel: "Status"
-        field: "down_estimator.quaternion_w"
-      }
-    }
-  }
-  axes {
-    line {
-      y_signal {
-        channel: "Status"
-        field: "down_estimator.velocity_x"
-      }
-    }
-    line {
-      y_signal {
-        channel: "Status"
-        field: "down_estimator.velocity_y"
-      }
-    }
-  }
-  axes {
-    line {
-      y_signal {
-        channel: "Status"
-        field: "down_estimator.position_x"
-      }
-    }
-    line {
-      y_signal {
-        channel: "Status"
-        field: "down_estimator.position_y"
-      }
-    }
-  }
-}
-
-figure {
-  axes {
-    line {
-      y_signal {
-        channel: "CalcIMU"
-        field: "accel_x_rolling_mean"
-      }
-      x_signal {
-        channel: "CalcIMU"
-        field: "monotonic_timestamp_sec"
-      }
-    }
-    line {
-      y_signal {
-        channel: "CalcIMU"
-        field: "accel_y_rolling_mean"
-      }
-      x_signal {
-        channel: "CalcIMU"
-        field: "monotonic_timestamp_sec"
-      }
-    }
-    line {
-      y_signal {
-        channel: "CalcIMU"
-        field: "accel_z_rolling_mean"
-      }
-      x_signal {
-        channel: "CalcIMU"
-        field: "monotonic_timestamp_sec"
-      }
-    }
-    ylabel: "g"
-  }
-  axes {
-    line {
-      y_signal {
-        channel: "CalcIMU"
-        field: "accel_x_rolling_std"
-      }
-      x_signal {
-        channel: "CalcIMU"
-        field: "monotonic_timestamp_sec"
-      }
-    }
-    line {
-      y_signal {
-        channel: "CalcIMU"
-        field: "accel_y_rolling_std"
-      }
-      x_signal {
-        channel: "CalcIMU"
-        field: "monotonic_timestamp_sec"
-      }
-    }
-    line {
-      y_signal {
-        channel: "CalcIMU"
-        field: "accel_z_rolling_std"
-      }
-      x_signal {
-        channel: "CalcIMU"
-        field: "monotonic_timestamp_sec"
-      }
-    }
-    ylabel: "g"
-  }
-}
-
-figure {
-  axes {
-    line {
-      y_signal {
-        channel: "CalcIMU"
-        field: "gyro_x_rolling_mean"
-      }
-      x_signal {
-        channel: "CalcIMU"
-        field: "monotonic_timestamp_sec"
-      }
-    }
-    line {
-      y_signal {
-        channel: "CalcIMU"
-        field: "gyro_y_rolling_mean"
-      }
-      x_signal {
-        channel: "CalcIMU"
-        field: "monotonic_timestamp_sec"
-      }
-    }
-    line {
-      y_signal {
-        channel: "CalcIMU"
-        field: "gyro_z_rolling_mean"
-      }
-      x_signal {
-        channel: "CalcIMU"
-        field: "monotonic_timestamp_sec"
-      }
-    }
-    ylabel: "rad / sec"
-  }
-  axes {
-    line {
-      y_signal {
-        channel: "CalcIMU"
-        field: "gyro_x_rolling_std"
-      }
-      x_signal {
-        channel: "CalcIMU"
-        field: "monotonic_timestamp_sec"
-      }
-    }
-    line {
-      y_signal {
-        channel: "CalcIMU"
-        field: "gyro_y_rolling_std"
-      }
-      x_signal {
-        channel: "CalcIMU"
-        field: "monotonic_timestamp_sec"
-      }
-    }
-    line {
-      y_signal {
-        channel: "CalcIMU"
-        field: "gyro_z_rolling_std"
-      }
-      x_signal {
-        channel: "CalcIMU"
-        field: "monotonic_timestamp_sec"
-      }
-    }
-    ylabel: "rad / sec"
-  }
-}
diff --git a/frc971/analysis/plot_configs/gyro.pb b/frc971/analysis/plot_configs/gyro.pb
deleted file mode 100644
index 70c6480..0000000
--- a/frc971/analysis/plot_configs/gyro.pb
+++ /dev/null
@@ -1,238 +0,0 @@
-channel {
-  name: "/drivetrain"
-  type: "frc971.IMUValuesBatch"
-  alias: "IMU"
-}
-
-figure {
-  axes {
-    line {
-      y_signal {
-        channel: "CalcIMU"
-        field: "gyro_x"
-      }
-      x_signal {
-        channel: "CalcIMU"
-        field: "monotonic_timestamp_sec"
-      }
-    }
-    line {
-      y_signal {
-        channel: "CalcIMU"
-        field: "gyro_y"
-      }
-      x_signal {
-        channel: "CalcIMU"
-        field: "monotonic_timestamp_sec"
-      }
-    }
-    line {
-      y_signal {
-        channel: "CalcIMU"
-        field: "gyro_z"
-      }
-      x_signal {
-        channel: "CalcIMU"
-        field: "monotonic_timestamp_sec"
-      }
-    }
-    ylabel: "rad / sec"
-  }
-  axes {
-    line {
-      y_signal {
-        channel: "CalcIMU"
-        field: "total_acceleration"
-      }
-      x_signal {
-        channel: "CalcIMU"
-        field: "monotonic_timestamp_sec"
-      }
-    }
-    line {
-      y_signal {
-        channel: "CalcIMU"
-        field: "accelerometer_x"
-      }
-      x_signal {
-        channel: "CalcIMU"
-        field: "monotonic_timestamp_sec"
-      }
-    }
-    line {
-      y_signal {
-        channel: "CalcIMU"
-        field: "accelerometer_y"
-      }
-      x_signal {
-        channel: "CalcIMU"
-        field: "monotonic_timestamp_sec"
-      }
-    }
-    line {
-      y_signal {
-        channel: "CalcIMU"
-        field: "accelerometer_z"
-      }
-      x_signal {
-        channel: "CalcIMU"
-        field: "monotonic_timestamp_sec"
-      }
-    }
-    ylabel: "g"
-  }
-}
-
-figure {
-  axes {
-    line {
-      y_signal {
-        channel: "CalcIMU"
-        field: "accel_x_rolling_mean"
-      }
-      x_signal {
-        channel: "CalcIMU"
-        field: "monotonic_timestamp_sec"
-      }
-    }
-    line {
-      y_signal {
-        channel: "CalcIMU"
-        field: "accel_y_rolling_mean"
-      }
-      x_signal {
-        channel: "CalcIMU"
-        field: "monotonic_timestamp_sec"
-      }
-    }
-    line {
-      y_signal {
-        channel: "CalcIMU"
-        field: "accel_z_rolling_mean"
-      }
-      x_signal {
-        channel: "CalcIMU"
-        field: "monotonic_timestamp_sec"
-      }
-    }
-    ylabel: "g"
-  }
-  axes {
-    line {
-      y_signal {
-        channel: "CalcIMU"
-        field: "accel_x_rolling_std"
-      }
-      x_signal {
-        channel: "CalcIMU"
-        field: "monotonic_timestamp_sec"
-      }
-    }
-    line {
-      y_signal {
-        channel: "CalcIMU"
-        field: "accel_y_rolling_std"
-      }
-      x_signal {
-        channel: "CalcIMU"
-        field: "monotonic_timestamp_sec"
-      }
-    }
-    line {
-      y_signal {
-        channel: "CalcIMU"
-        field: "accel_z_rolling_std"
-      }
-      x_signal {
-        channel: "CalcIMU"
-        field: "monotonic_timestamp_sec"
-      }
-    }
-    ylabel: "g"
-  }
-}
-
-figure {
-  axes {
-    line {
-      y_signal {
-        channel: "CalcIMU"
-        field: "gyro_x_rolling_mean"
-      }
-      x_signal {
-        channel: "CalcIMU"
-        field: "monotonic_timestamp_sec"
-      }
-    }
-    line {
-      y_signal {
-        channel: "CalcIMU"
-        field: "gyro_y_rolling_mean"
-      }
-      x_signal {
-        channel: "CalcIMU"
-        field: "monotonic_timestamp_sec"
-      }
-    }
-    line {
-      y_signal {
-        channel: "CalcIMU"
-        field: "gyro_z_rolling_mean"
-      }
-      x_signal {
-        channel: "CalcIMU"
-        field: "monotonic_timestamp_sec"
-      }
-    }
-    ylabel: "rad / sec"
-  }
-  axes {
-    line {
-      y_signal {
-        channel: "CalcIMU"
-        field: "gyro_x_rolling_std"
-      }
-      x_signal {
-        channel: "CalcIMU"
-        field: "monotonic_timestamp_sec"
-      }
-    }
-    line {
-      y_signal {
-        channel: "CalcIMU"
-        field: "gyro_y_rolling_std"
-      }
-      x_signal {
-        channel: "CalcIMU"
-        field: "monotonic_timestamp_sec"
-      }
-    }
-    line {
-      y_signal {
-        channel: "CalcIMU"
-        field: "gyro_z_rolling_std"
-      }
-      x_signal {
-        channel: "CalcIMU"
-        field: "monotonic_timestamp_sec"
-      }
-    }
-    ylabel: "rad / sec"
-  }
-}
-
-figure {
-  axes {
-    line {
-      y_signal {
-        channel: "CalcIMU"
-        field: "temperature"
-      }
-      x_signal {
-        channel: "CalcIMU"
-        field: "monotonic_timestamp_sec"
-      }
-    }
-    ylabel: "C"
-  }
-}
diff --git a/frc971/analysis/plot_configs/gyro_temp.pb b/frc971/analysis/plot_configs/gyro_temp.pb
deleted file mode 100644
index 02c8c3b..0000000
--- a/frc971/analysis/plot_configs/gyro_temp.pb
+++ /dev/null
@@ -1,21 +0,0 @@
-channel {
-  name: "/drivetrain"
-  type: "frc971.IMUValues"
-  alias: "IMU"
-}
-
-figure {
-  axes {
-    line {
-      y_signal {
-        channel: "IMU"
-        field: "temperature"
-      }
-      x_signal {
-        channel: "CalcIMU"
-        field: "monotonic_timestamp_sec"
-      }
-    }
-    ylabel: "C"
-  }
-}
diff --git a/frc971/analysis/plot_configs/localizer.pb b/frc971/analysis/plot_configs/localizer.pb
deleted file mode 100644
index 6181e11..0000000
--- a/frc971/analysis/plot_configs/localizer.pb
+++ /dev/null
@@ -1,322 +0,0 @@
-channel {
-  name: "/drivetrain"
-  type: "frc971.control_loops.drivetrain.Status"
-  alias: "DrivetrainStatus"
-}
-channel {
-  name: "/drivetrain/truth"
-  type: "frc971.control_loops.drivetrain.Status"
-  alias: "DrivetrainTruthStatus"
-}
-channel {
-  name: "/drivetrain"
-  type: "frc971.control_loops.drivetrain.Position"
-  alias: "DrivetrainPosition"
-}
-channel {
-  name: "/drivetrain"
-  type: "frc971.control_loops.drivetrain.Output"
-  alias: "DrivetrainOutput"
-}
-
-figure {
-  axes {
-    line {
-      y_signal {
-        channel: "DrivetrainStatus"
-        field: "trajectory_logging.y"
-      }
-      x_signal {
-        channel: "DrivetrainStatus"
-        field: "trajectory_logging.x"
-      }
-    }
-    line {
-      y_signal {
-        channel: "DrivetrainTruthStatus"
-        field: "y"
-      }
-      x_signal {
-        channel: "DrivetrainTruthStatus"
-        field: "x"
-      }
-    }
-    line {
-      y_signal {
-        channel: "DrivetrainStatus"
-        field: "y"
-      }
-      x_signal {
-        channel: "DrivetrainStatus"
-        field: "x"
-      }
-    }
-    share_x_axis: false
-    xlabel: "x (m)"
-    ylabel: "y (m)"
-  }
-}
-
-figure {
-  axes {
-    line {
-      y_signal {
-        channel: "DrivetrainStatus"
-        field: "down_estimator.yaw"
-      }
-    }
-    line {
-      y_signal {
-        channel: "DrivetrainStatus"
-        field: "trajectory_logging.theta"
-      }
-    }
-    line {
-      y_signal {
-        channel: "DrivetrainTruthStatus"
-        field: "theta"
-      }
-    }
-    line {
-      y_signal {
-        channel: "DrivetrainStatus"
-        field: "localizer.theta"
-      }
-    }
-    line {
-      y_signal {
-        channel: "DrivetrainStatus"
-        field: "down_estimator.lateral_pitch"
-      }
-    }
-    line {
-      y_signal {
-        channel: "DrivetrainStatus"
-        field: "down_estimator.longitudinal_pitch"
-      }
-    }
-    ylabel: "rad"
-  }
-  axes {
-    line {
-      y_signal {
-        channel: "DrivetrainStatus"
-        field: "down_estimator.position_x"
-      }
-    }
-    line {
-      y_signal {
-        channel: "DrivetrainStatus"
-        field: "down_estimator.position_y"
-      }
-    }
-    line {
-      y_signal {
-        channel: "DrivetrainStatus"
-        field: "trajectory_logging.x"
-      }
-    }
-    line {
-      y_signal {
-        channel: "DrivetrainStatus"
-        field: "trajectory_logging.y"
-      }
-    }
-    line {
-      y_signal {
-        channel: "DrivetrainTruthStatus"
-        field: "x"
-      }
-    }
-    line {
-      y_signal {
-        channel: "DrivetrainTruthStatus"
-        field: "y"
-      }
-    }
-    line {
-      y_signal {
-        channel: "DrivetrainStatus"
-        field: "trajectory_logging.x"
-      }
-    }
-    line {
-      y_signal {
-        channel: "DrivetrainStatus"
-        field: "trajectory_logging.y"
-      }
-    }
-    line {
-      y_signal {
-        channel: "DrivetrainStatus"
-        field: "localizer.x"
-      }
-    }
-    line {
-      y_signal {
-        channel: "DrivetrainStatus"
-        field: "localizer.y"
-      }
-    }
-    ylabel: "m"
-  }
-  axes {
-    line {
-      y_signal {
-        channel: "DrivetrainStatus"
-        field: "down_estimator.velocity_x"
-      }
-    }
-    line {
-      y_signal {
-        channel: "DrivetrainStatus"
-        field: "down_estimator.velocity_y"
-      }
-    }
-    line {
-      y_signal {
-        channel: "DrivetrainStatus"
-        field: "localizer.longitudinal_velocity_offset"
-      }
-    }
-    line {
-      y_signal {
-        channel: "DrivetrainStatus"
-        field: "localizer.lateral_velocity"
-      }
-    }
-    ylabel: "m/s"
-  }
-  axes {
-    line {
-      y_signal {
-        channel: "DrivetrainStatus"
-        field: "down_estimator.accel_x"
-      }
-    }
-    line {
-      y_signal {
-        channel: "DrivetrainStatus"
-        field: "down_estimator.accel_y"
-      }
-    }
-    line {
-      y_signal {
-        channel: "DrivetrainStatus"
-        field: "down_estimator.accel_z"
-      }
-    }
-    ylabel: "m/s/s"
-  }
-}
-
-figure {
-  axes {
-    line {
-      y_signal {
-        channel: "DrivetrainStatus"
-        field: "trajectory_logging.left_velocity"
-      }
-    }
-    line {
-      y_signal {
-        channel: "DrivetrainStatus"
-        field: "trajectory_logging.right_velocity"
-      }
-    }
-    line {
-      y_signal {
-        channel: "DrivetrainStatus"
-        field: "localizer.left_velocity"
-      }
-    }
-    line {
-      y_signal {
-        channel: "DrivetrainStatus"
-        field: "localizer.right_velocity"
-      }
-    }
-    ylabel: "m/s"
-  }
-  axes {
-    line {
-      y_signal {
-        channel: "DrivetrainPosition"
-        field: "left_encoder"
-      }
-    }
-    line {
-      y_signal {
-        channel: "DrivetrainPosition"
-        field: "right_encoder"
-      }
-    }
-    line {
-      y_signal {
-        channel: "DrivetrainStatus"
-        field: "localizer.left_encoder"
-      }
-    }
-    line {
-      y_signal {
-        channel: "DrivetrainStatus"
-        field: "localizer.right_encoder"
-      }
-    }
-    ylabel: "m"
-  }
-  axes {
-    line {
-      y_signal {
-        channel: "DrivetrainStatus"
-        field: "localizer.angular_error"
-      }
-    }
-    ylabel: "rad / sec"
-  }
-}
-
-figure {
-  axes {
-    line {
-      y_signal {
-        channel: "DrivetrainOutput"
-        field: "left_voltage"
-      }
-    }
-    line {
-      y_signal {
-        channel: "DrivetrainOutput"
-        field: "right_voltage"
-      }
-    }
-    ylabel: "V"
-  }
-  axes {
-    line {
-      y_signal {
-        channel: "DrivetrainStatus"
-        field: "left_voltage_error"
-      }
-    }
-    line {
-      y_signal {
-        channel: "DrivetrainStatus"
-        field: "right_voltage_error"
-      }
-    }
-    line {
-      y_signal {
-        channel: "DrivetrainStatus"
-        field: "localizer.left_voltage_error"
-      }
-    }
-    line {
-      y_signal {
-        channel: "DrivetrainStatus"
-        field: "localizer.right_voltage_error"
-      }
-    }
-    ylabel: "V"
-  }
-}
diff --git a/frc971/analysis/plot_configs/turret_plot.pb b/frc971/analysis/plot_configs/turret_plot.pb
deleted file mode 100644
index 64c5f22..0000000
--- a/frc971/analysis/plot_configs/turret_plot.pb
+++ /dev/null
@@ -1,128 +0,0 @@
-channel {
-  name: "/roborio/aos"
-  type: "aos.JoystickState"
-  alias: "JoystickState"
-}
-channel {
-  name: "/superstructure"
-  type: "y2020.control_loops.superstructure.Status"
-  alias: "Status"
-}
-channel {
-  name: "/superstructure"
-  type: "y2020.control_loops.superstructure.Output"
-  alias: "Output"
-}
-channel {
-  name: "/superstructure"
-  type: "y2020.control_loops.superstructure.Position"
-  alias: "Position"
-}
-channel {
-  name: "/superstructure"
-  type: "y2020.control_loops.superstructure.Goal"
-  alias: "Goal"
-}
-
-figure {
-  axes {
-    line {
-      y_signal {
-        channel: "Status"
-        field: "turret.goal_velocity"
-      }
-    }
-    line {
-      y_signal {
-        channel: "Status"
-        field: "turret.unprofiled_goal_velocity"
-      }
-    }
-    line {
-      y_signal {
-        channel: "Status"
-        field: "aimer.turret_velocity"
-      }
-    }
-    line {
-      y_signal {
-        channel: "Status"
-        field: "turret.velocity"
-      }
-    }
-  }
-  axes {
-    line {
-      y_signal {
-        channel: "Status"
-        field: "turret.goal_position"
-      }
-    }
-    line {
-      y_signal {
-        channel: "Status"
-        field: "turret.unprofiled_goal_position"
-      }
-    }
-    line {
-      y_signal {
-        channel: "Status"
-        field: "aimer.turret_position"
-      }
-    }
-    line {
-      y_signal {
-        channel: "Status"
-        field: "turret.position"
-      }
-    }
-  }
-}
-
-figure {
-  axes {
-    line {
-      y_signal {
-        channel: "Status"
-        field: "aimer.aiming_for_inner_port"
-      }
-    }
-#    line {
-#      y_signal {
-#        channel: "JoystickState"
-#        field: "alliance"
-#      }
-#    }
-  }
-  axes {
-    line {
-      y_signal {
-        channel: "Status"
-        field: "aimer.shot_distance"
-      }
-    }
-    line {
-      y_signal {
-        channel: "Status"
-        field: "aimer.target_distance"
-      }
-    }
-  }
-}
-
-figure {
-  axes {
-    line {
-      y_signal {
-        channel: "Output"
-        field: "turret_voltage"
-      }
-    }
-    line {
-      y_signal {
-        channel: "Status"
-        field: "turret.voltage_error"
-      }
-    }
-  }
-}
diff --git a/frc971/analysis/plot_test.py b/frc971/analysis/plot_test.py
deleted file mode 100644
index 1c57ae2..0000000
--- a/frc971/analysis/plot_test.py
+++ /dev/null
@@ -1,23 +0,0 @@
-#!/usr/bin/python3
-import unittest
-
-import matplotlib
-# Use a non-interactive backend so that the test can actually run...
-matplotlib.use('Agg')
-
-import frc971.analysis.plot
-
-
-class PlotterTest(unittest.TestCase):
-    def test_plotter(self):
-        """Basic test that makes sure that we can run the test without crashing."""
-        self.assertEqual(0,
-                         frc971.analysis.plot.main([
-                             "binary", "--logfile",
-                             "external/sample_logfile/file/log.fbs",
-                             "--config", "gyro.pb"
-                         ]))
-
-
-if __name__ == '__main__':
-    unittest.main()
diff --git a/frc971/analysis/py_log_reader.cc b/frc971/analysis/py_log_reader.cc
index 5b32ed6..6a6c767 100644
--- a/frc971/analysis/py_log_reader.cc
+++ b/frc971/analysis/py_log_reader.cc
@@ -1,6 +1,11 @@
 // This file provides a Python module for reading logfiles. See
 // log_reader_test.py for usage.
 //
+// NOTE: This code has not been maintained recently, and so is missing key
+// features to support reading multi-node logfiles (namely, it assumes the the
+// logfile is just a single file). Updating this code should not be difficult,
+// but hasn't been needed thus far.
+//
 // This reader works by having the user specify exactly what channels they want
 // data for. We then process the logfile and store all the data on that channel
 // into a list of timestamps + JSON message data. The user can then use an