File size: 2,716 Bytes
fd5ba83 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 | from __future__ import annotations
"""
Analyze a human parts-based formula with Pino.
This is a small utility for the user-supplied Matthew tea/woods formula. It:
1. Imports the parts-based JSON via pino.importer.
2. Runs the physical/IFRA verifier.
3. Runs the PIMT critic (cloud or local fallback).
4. Prints a compact human-readable summary.
"""
import json
import logging
import sys
from pathlib import Path
from pino.importer import import_formula
from pino.inference_cloud import predict_cloud
from pino.verifier import FragrancePipelineVerifier
logging.basicConfig(level=logging.INFO, format="%(asctime)s %(levelname)s %(name)s: %(message)s")
logger = logging.getLogger("pino.analyze_formula")
def analyze(path: str | Path) -> None:
imported = import_formula(path)
if imported["unresolved"]:
logger.warning("Unresolved materials: %s", imported["unresolved"])
formula = imported["formula"]
print(f"Imported formula with {len(formula)} ingredients; sum = {sum(i['weight_fraction'] for i in formula):.6f}")
verifier = FragrancePipelineVerifier(
temperature_k=298.15,
ambient_pressure_pa=101325.0,
headspace_volume_m3=1e-3,
liquid_volume_m3=1e-6,
density_g_ml=0.9,
surface_area_m2=1e-4,
mass_transfer_coefficient=1e-4,
)
result = verifier.run_sim(formula, duration_seconds=8 * 3600.0, interval_seconds=600.0)
print(f"Physical/IFRA status: {result['status']}")
print(f"IFRA passed: {result['ifra_report'].get('passed', False)}")
if not result["ifra_report"].get("passed", False):
print("IFRA violations:", json.dumps(result["ifra_report"].get("violations", []), indent=2))
if result["status"] in ("rejected", "depleted"):
logger.error("Formula rejected by verifier: %s", result.get("message"))
return
formula_payload = {
"formula": formula,
"trajectory": result["trajectory"],
"metadata": {"source": str(path), "analysis": True},
}
prediction = predict_cloud(formula_payload)
print("Prediction keys:", list(prediction.keys()))
print("Objective shape:", len(prediction.get("objective", [[]])[0][0]))
print("Subjective vector:", prediction.get("subjective", [[]])[0])
# Save full analysis
output = {
"imported": imported,
"verification": result,
"prediction": prediction,
}
out_path = Path("data/formulas/matthew_tea_woods_analysis.json")
out_path.write_text(json.dumps(output, indent=2, ensure_ascii=False))
print(f"Full analysis written to {out_path}")
if __name__ == "__main__":
analyze(sys.argv[1] if len(sys.argv) > 1 else "data/formulas/matthew_tea_woods.json")
|