example: add plot option

Signed-off-by: YoungSoo Shin <shinys000114@gmail.com>
This commit is contained in:
2025-11-20 09:01:51 +09:00
parent e7d97c1d6f
commit 0765c47e4a
2 changed files with 48 additions and 35 deletions

View File

@@ -35,7 +35,7 @@ python3 logger.py -u admin -p password -o test.csv 192.168.30.5
#### Plot data #### Plot data
```shell ```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) ![plot.png](plot.png)

View File

@@ -1,17 +1,19 @@
import argparse import argparse
import matplotlib.dates as mdates import matplotlib.dates as mdates
import matplotlib.pyplot as plt import matplotlib.pyplot as plt
import os
import pandas as pd 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. Reads power data from a CSV file and generates a plot image.
Args: Args:
csv_path (str): The path to the input CSV file. csv_path (str): The path to the input CSV file.
output_path (str): The path to save the output plot image. 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: try:
# Read the CSV file into a pandas DataFrame # 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}") print(f"An error occurred while reading the CSV file: {e}")
return 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) # 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) --- # --- Loop through selected plot types and generate plots ---
ax1 = axes[0] for i, plot_type in enumerate(plot_types):
ax1.plot(df['timestamp'], df['vin_power'], label='VIN', color='red') ax = axes[i]
ax1.plot(df['timestamp'], df['main_power'], label='MAIN', color='green') config = plot_configs[plot_type]
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)
# --- Plot 2: Voltage (V) --- for j, col_name in enumerate(config['cols']):
ax2 = axes[1] ax.plot(df['timestamp'], df[col_name], label=channel_labels[j], color=channel_colors[j])
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)
# --- Plot 3: Current (A) --- ax.set_title(config['title'])
ax3 = axes[2] ax.set_ylabel(config['ylabel'])
ax3.plot(df['timestamp'], df['vin_current'], label='VIN', color='red') ax.legend()
ax3.plot(df['timestamp'], df['main_current'], label='MAIN', color='green') ax.grid(True, which='both', linestyle='--', linewidth=0.5)
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)
# --- Formatting the x-axis (Time) --- # --- Formatting the x-axis (Time) ---
# Improve date formatting on the x-axis # Improve date formatting on the x-axis
ax3.xaxis.set_major_formatter(mdates.DateFormatter('%H:%M:%S')) # Apply formatting to the last subplot's x-axis
ax3.xaxis.set_major_locator(plt.MaxNLocator(15)) # Limit the number of ticks 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.xlabel('Time')
plt.xticks(rotation=45) 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 = 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("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("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() 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__": if __name__ == "__main__":