Multi-Week Plotting Helpers — Colab Notebook
This notebook provides reusable code for plotting \(J_{sc}\), PCE, and EQE data across multiple weeks. As you collect more data each week, these snippets make it easier to combine and visualize your results without manually adding lines for each new dataset.
You can copy any of these cells into your weekly Data Collection notebook.
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt1 Adding a Time Column to Your CSV Files
The \(J_{sc}\)/PCE CSV files you create each week need a Time (hr) column so you can plot values over time. The code below reads a CSV, adds the time column, and writes a new file.
# Update these variables for each week
date_str = "YYYY_MM_DD"
cell_id = "###"
# Read the CSV you created with Jsc and PCE values
# Your CSV must have columns: "Pixel Number", "Jsc (mA/cm^2)", "PCE"
df = pd.read_csv(f"{date_str}_jsc_pce_cell{cell_id}.csv")
# Set the time in hours since stressing began (update each week)
t = 168 # <-- update this
df["Time (hr)"] = t
# Write the updated DataFrame to a new CSV
out_name = f"{date_str}_jsc_pce_with_time_cell{cell_id}.csv"
df.to_csv(out_name, index=False)
print(f"[ok] Wrote {out_name}")2 \(J_{sc}\) Subplots
Plot \(J_{sc}\) vs. time for each pixel in a 4x2 grid. Add more CSV files to the list as you collect data each week.
# Load and combine data from all weeks (update file names)
week5data = pd.read_csv("YYYY_MM_DD_jsc_pce_with_time_cell###.csv") # baseline
week6data = pd.read_csv("YYYY_MM_DD_jsc_pce_with_time_cell###.csv") # Data Collection 1
# Add more weeks as needed:
# week7data = pd.read_csv("YYYY_MM_DD_jsc_pce_with_time_cell###.csv")
combined_df = pd.concat([week5data, week6data])
# Jsc subplots
fig, axes = plt.subplots(4, 2, figsize=(12, 16))
axes = axes.flatten()
for idx, pixel in enumerate(combined_df["Pixel Number"].unique()):
if idx >= len(axes):
break
subset = combined_df[combined_df["Pixel Number"] == pixel]
ax = axes[idx]
ax.scatter(subset["Time (hr)"], subset["Jsc (mA/cm^2)"], color="g")
ax.set_title(f"Pixel {pixel}")
ax.set_xlabel("Time (hr)")
ax.set_ylabel("Jsc (mA/cm\u00b2)")
plt.tight_layout()
plt.show()3 PCE Subplots
Plot PCE vs. time for each pixel, using the same combined data.
# PCE subplots
fig, axes = plt.subplots(4, 2, figsize=(12, 16))
axes = axes.flatten()
for idx, pixel in enumerate(combined_df["Pixel Number"].unique()):
if idx >= len(axes):
break
subset = combined_df[combined_df["Pixel Number"] == pixel]
ax = axes[idx]
ax.scatter(subset["Time (hr)"], subset["PCE"], color="b")
ax.set_title(f"Pixel {pixel}")
ax.set_xlabel("Time (hr)")
ax.set_ylabel("PCE")
plt.tight_layout()
plt.show()4 EQE Subplots
Compare EQE spectra across multiple weeks. This version uses a list of files and labels, making it easy to add new weeks without duplicating plot code.
# List your EQE CSV files and labels (update each week)
eqe_files = [
"YYYY_MM_DD_eqe_cell###.csv",
"YYYY_MM_DD_eqe_cell###.csv",
# Add more files as needed
]
labels = [
"Baseline",
"Data Collection 1",
# Add matching labels
]
# Load data
weeks = []
for lbl, f in zip(labels, eqe_files):
try:
df = pd.read_csv(f).sort_values("Wavelength (nm)").reset_index(drop=True)
keep = ["Wavelength (nm)"] + [f"eqe_pix{i}" for i in range(1, 9)]
df = df[[c for c in keep if c in df.columns]]
weeks.append((lbl, df))
print(f"[ok] Loaded {f}")
except FileNotFoundError:
print(f"[skip] Not found: {f}")
except Exception as ex:
print(f"[skip] Error reading {f}: {ex}")
if not weeks:
raise SystemExit("No valid EQE files loaded.")
# EQE subplots
fig, axes = plt.subplots(4, 2, figsize=(12, 16))
axes = axes.flatten()
for i in range(8):
ax = axes[i]
col = f"eqe_pix{i+1}"
plotted_any = False
for lbl, df in weeks:
if {"Wavelength (nm)", col}.issubset(df.columns):
ax.plot(df["Wavelength (nm)"], df[col], label=lbl)
plotted_any = True
ax.set_title(f"Pixel {i+1}")
ax.set_xlabel("Wavelength (nm)")
ax.set_ylabel("EQE")
if plotted_any:
ax.legend(loc="best")
plt.tight_layout()
plt.show()