diff --git a/.gitignore b/.gitignore index 698d8c1..fc93087 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,5 @@ venv/ *.txt *.csv +*.png +!requirements.txt diff --git a/cv_plot.py b/cv_plot.py new file mode 100644 index 0000000..93d3f38 --- /dev/null +++ b/cv_plot.py @@ -0,0 +1,91 @@ +"""Genera un grafico Potenziale normalizzato vs Current/sqrt(v)/v per ogni ciclo. + +Legge la colonna C (Potential normalized/V) e la colonna E +(Current/sqrt(scan rate)/scan rate) dai file *_ultimo_ciclo.csv e salva, +per ciascuno, un PNG ad alta risoluzione con lo stesso nome del CSV. +""" + +import csv +import sys +from pathlib import Path + +import matplotlib +matplotlib.use("Agg") +import matplotlib.pyplot as plt +import matplotlib.ticker as mticker + +INPUT_SUFFIX = "_ultimo_ciclo" +X_COLUMN = "Potential normalized/V" +Y_COLUMN = "Current/sqrt(scan rate)/scan rate" + +X_LABEL = "$E - E_{ref}$ (V)" +Y_LABEL = r"$i \, / \, v^{3/2}$ (A$\cdot$V$^{-3/2}\cdot$s$^{3/2}$)" + + +def read_columns(path: Path) -> tuple[list[float], list[float]]: + with path.open("r", encoding="utf-8", newline="") as f: + reader = csv.reader(f, delimiter=";") + header = next(reader) + try: + x_idx = header.index(X_COLUMN) + y_idx = header.index(Y_COLUMN) + except ValueError as e: + raise ValueError( + f"colonna mancante ({e}); esegui prima cv_normalize_potential.py e cv_current_over_sqrt_scanrate.py" + ) + + x_vals, y_vals = [], [] + for row in reader: + x_vals.append(float(row[x_idx].replace(",", "."))) + y_vals.append(float(row[y_idx].replace(",", "."))) + + return x_vals, y_vals + + +def plot_file(csv_path: Path, output_path: Path) -> None: + x_vals, y_vals = read_columns(csv_path) + + fig, ax = plt.subplots(figsize=(8, 6), dpi=300) + + ax.plot(x_vals, y_vals, color="#1f4e79", linewidth=1.6) + + ax.set_title(csv_path.stem.replace(INPUT_SUFFIX, ""), fontsize=13, fontweight="bold", pad=12) + ax.set_xlabel(X_LABEL, fontsize=11) + ax.set_ylabel(Y_LABEL, fontsize=11) + + ax.axhline(0, color="black", linewidth=0.8, alpha=0.5) + ax.axvline(0, color="black", linewidth=0.8, alpha=0.5) + + ax.yaxis.set_major_formatter(mticker.ScalarFormatter(useMathText=True)) + ax.ticklabel_format(axis="y", style="sci", scilimits=(0, 0)) + + ax.grid(True, linestyle="--", linewidth=0.5, alpha=0.6) + ax.spines["top"].set_visible(False) + ax.spines["right"].set_visible(False) + + fig.tight_layout() + fig.savefig(output_path, dpi=300) + plt.close(fig) + + +def main(argv: list[str]) -> None: + folder = Path(argv[1]) if len(argv) > 1 else Path(__file__).parent + csv_files = sorted( + p for p in folder.glob("*.csv") if p.stem.endswith(INPUT_SUFFIX) + ) + + if not csv_files: + print(f"Nessun file *{INPUT_SUFFIX}.csv trovato in {folder}") + return + + for csv_file in csv_files: + output_path = csv_file.with_suffix(".png") + try: + plot_file(csv_file, output_path) + print(f"OK {csv_file.name} -> {output_path.name}") + except ValueError as e: + print(f"SKIP {csv_file.name}: {e}") + + +if __name__ == "__main__": + main(sys.argv) diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..6ccafc3 --- /dev/null +++ b/requirements.txt @@ -0,0 +1 @@ +matplotlib