"""E7b: how do the smell features relate to the food-science measurements? python experiments/e7b_correlation.py data/demo_banana Spearman correlation (rank based, fine for curved relationships) between every odour feature and brown_pct, brix, ph, weight_loss_pct. Destructive measurements (brix, pH) usually come from the sacrificed "companion" bananas; leave those cells empty for the tracked bananas and pandas skips them automatically. """ from __future__ import annotations import argparse import sys from pathlib import Path sys.path.insert(0, str(Path(__file__).resolve().parents[1])) from enose.common import load_table, output_dir, plt, save_figure # noqa: E402 QUALITY: tuple[str, ...] = ("brown_pct", "brix", "ph", "weight_loss_pct") def main() -> None: parser = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter) parser.add_argument("folder", type=Path) arguments = parser.parse_args() table, _, _, names = load_table(arguments.folder / "features.csv") quality = [column for column in QUALITY if column in table] matrix = table[names + quality].corr(method="spearman").loc[names, quality] results = output_dir(arguments.folder / "results") matrix.to_csv(results / "e7b_correlation.csv") print(matrix.round(2).to_string()) figure, axis = plt.subplots(figsize=(1.4 * len(quality) + 2, 0.45 * len(names) + 1.5)) image = axis.imshow(matrix.to_numpy(), cmap="RdBu_r", vmin=-1, vmax=1) axis.set_xticks(range(len(quality)), quality, rotation=30) axis.set_yticks(range(len(names)), names) for row in range(len(names)): for column in range(len(quality)): axis.text(column, row, f"{matrix.iat[row, column]:.2f}", ha="center", va="center", fontsize=8) figure.colorbar(image, ax=axis, label="Spearman ρ") axis.set_title("氣味特徵 × 食品指標") save_figure(figure, results / "e7b_correlation.png") if __name__ == "__main__": main()