From 0765c47e4a5d072b8a43a43256132a0a4b901f13 Mon Sep 17 00:00:00 2001 From: YoungSoo Shin Date: Thu, 20 Nov 2025 09:01:51 +0900 Subject: [PATCH] example: add plot option Signed-off-by: YoungSoo Shin --- example/logger/README.md | 2 +- example/logger/csv_2_plot.py | 81 +++++++++++++++++++++--------------- 2 files changed, 48 insertions(+), 35 deletions(-) diff --git a/example/logger/README.md b/example/logger/README.md index edd95b8..8150a40 100644 --- a/example/logger/README.md +++ b/example/logger/README.md @@ -35,7 +35,7 @@ python3 logger.py -u admin -p password -o test.csv 192.168.30.5 #### Plot data ```shell -python3 csv_2_plot.py test.csv plot.png +python3 csv_2_plot.py test.csv plot.png [--type power voltage current] ``` ![plot.png](plot.png) \ No newline at end of file diff --git a/example/logger/csv_2_plot.py b/example/logger/csv_2_plot.py index 5bcb5d0..0f1ad20 100644 --- a/example/logger/csv_2_plot.py +++ b/example/logger/csv_2_plot.py @@ -1,17 +1,19 @@ import argparse + import matplotlib.dates as mdates import matplotlib.pyplot as plt -import os import pandas as pd -def plot_power_data(csv_path, output_path): +def plot_power_data(csv_path, output_path, plot_types): """ Reads power data from a CSV file and generates a plot image. Args: csv_path (str): The path to the input CSV file. output_path (str): The path to save the output plot image. + plot_types (list): A list of strings indicating which plots to generate + (e.g., ['power', 'voltage', 'current']). """ try: # Read the CSV file into a pandas DataFrame @@ -25,44 +27,47 @@ def plot_power_data(csv_path, output_path): print(f"An error occurred while reading the CSV file: {e}") return - # Create a figure and a set of subplots (3 rows, 1 column) + # --- Plotting Configuration --- + plot_configs = { + 'power': {'title': 'Power Consumption', 'ylabel': 'Power (W)', + 'cols': ['vin_power', 'main_power', 'usb_power']}, + 'voltage': {'title': 'Voltage', 'ylabel': 'Voltage (V)', + 'cols': ['vin_voltage', 'main_voltage', 'usb_voltage']}, + 'current': {'title': 'Current', 'ylabel': 'Current (A)', 'cols': ['vin_current', 'main_current', 'usb_current']} + } + channel_labels = ['VIN', 'MAIN', 'USB'] + channel_colors = ['red', 'green', 'blue'] + + num_plots = len(plot_types) + if num_plots == 0: + print("No plot types selected. Exiting.") + return + + # Create a figure and a set of subplots based on the number of selected plot types. # sharex=True makes all subplots share the same x-axis (time) - fig, axes = plt.subplots(3, 1, figsize=(15, 18), sharex=True) + # squeeze=False ensures that 'axes' is always a 2D array, even if num_plots is 1. + fig, axes = plt.subplots(num_plots, 1, figsize=(15, 6 * num_plots), sharex=True, squeeze=False) + axes = axes.flatten() # Flatten the 2D array to 1D for easier iteration - # --- Plot 1: Power (W) --- - ax1 = axes[0] - ax1.plot(df['timestamp'], df['vin_power'], label='VIN', color='red') - ax1.plot(df['timestamp'], df['main_power'], label='MAIN', color='green') - ax1.plot(df['timestamp'], df['usb_power'], label='USB', color='blue') - ax1.set_title('Power Consumption') - ax1.set_ylabel('Power (W)') - ax1.legend() - ax1.grid(True, which='both', linestyle='--', linewidth=0.5) + # --- Loop through selected plot types and generate plots --- + for i, plot_type in enumerate(plot_types): + ax = axes[i] + config = plot_configs[plot_type] - # --- Plot 2: Voltage (V) --- - ax2 = axes[1] - ax2.plot(df['timestamp'], df['vin_voltage'], label='VIN', color='red') - ax2.plot(df['timestamp'], df['main_voltage'], label='MAIN', color='green') - ax2.plot(df['timestamp'], df['usb_voltage'], label='USB', color='blue') - ax2.set_title('Voltage') - ax2.set_ylabel('Voltage (V)') - ax2.legend() - ax2.grid(True, which='both', linestyle='--', linewidth=0.5) + for j, col_name in enumerate(config['cols']): + ax.plot(df['timestamp'], df[col_name], label=channel_labels[j], color=channel_colors[j]) - # --- Plot 3: Current (A) --- - ax3 = axes[2] - ax3.plot(df['timestamp'], df['vin_current'], label='VIN', color='red') - ax3.plot(df['timestamp'], df['main_current'], label='MAIN', color='green') - ax3.plot(df['timestamp'], df['usb_current'], label='USB', color='blue') - ax3.set_title('Current') - ax3.set_ylabel('Current (A)') - ax3.legend() - ax3.grid(True, which='both', linestyle='--', linewidth=0.5) + ax.set_title(config['title']) + ax.set_ylabel(config['ylabel']) + ax.legend() + ax.grid(True, which='both', linestyle='--', linewidth=0.5) # --- Formatting the x-axis (Time) --- # Improve date formatting on the x-axis - ax3.xaxis.set_major_formatter(mdates.DateFormatter('%H:%M:%S')) - ax3.xaxis.set_major_locator(plt.MaxNLocator(15)) # Limit the number of ticks + # Apply formatting to the last subplot's x-axis + last_ax = axes[-1] + last_ax.xaxis.set_major_formatter(mdates.DateFormatter('%H:%M:%S')) + last_ax.xaxis.set_major_locator(plt.MaxNLocator(15)) # Limit the number of ticks plt.xlabel('Time') plt.xticks(rotation=45) @@ -86,9 +91,17 @@ def main(): parser = argparse.ArgumentParser(description="Generate a plot from an Odroid PowerMate CSV log file.") parser.add_argument("input_csv", help="Path to the input CSV log file.") parser.add_argument("output_image", help="Path to save the output plot image (e.g., plot.png).") + parser.add_argument( + "-t", "--type", + nargs='+', + choices=['power', 'voltage', 'current'], + default=['power', 'voltage', 'current'], + help="Types of plots to generate. Choose from 'power', 'voltage', 'current'. " + "Default is to generate all three." + ) args = parser.parse_args() - plot_power_data(args.input_csv, args.output_image) + plot_power_data(args.input_csv, args.output_image, args.type) if __name__ == "__main__":