CLI Workflow: Catalyst Screening Study#
This walkthrough demonstrates the complete jaxsr command-line workflow —
from study creation through adaptive experiments to final reporting —
without writing any Python code.
Scenario#
You’re screening three factors for a heterogeneous catalysis reaction:
Factor |
Range |
Type |
|---|---|---|
Temperature |
300–500 K |
Continuous |
Pressure |
1–10 bar |
Continuous |
Catalyst |
Pt, Pd, Rh |
Categorical |
The response is conversion (%).
Step 1: Create the Study#
!jaxsr init catalyst_screening \
-f "temperature:300:500" \
-f "pressure:1:10" \
-f "catalyst:Pt,Pd,Rh" \
-d "Screen catalyst type, temperature, and pressure for max conversion"
Created study 'catalyst_screening' with 3 factors.
Saved to: catalyst_screening.jaxsr
The .jaxsr file is a portable ZIP archive containing the study metadata.
Step 2: Generate an Experimental Design#
Create a 20-point Latin Hypercube design and export to an Excel template for lab use:
!jaxsr design catalyst_screening.jaxsr \
-m latin_hypercube \
-n 20 \
-s 42 \
--format xlsx \
-o lab_template.xlsx
WARNING:2026-02-25 10:29:08,374:jax._src.xla_bridge:905: Platform 'mps' is experimental and not all JAX functionality may be correctly supported!
Generated 20 design points using latin_hypercube.
Excel template written to: lab_template.xlsx
You can also preview the design as a table:
!jaxsr design catalyst_screening.jaxsr -n 20 -s 42
WARNING:2026-02-25 10:29:09,446:jax._src.xla_bridge:905: Platform 'mps' is experimental and not all JAX functionality may be correctly supported!
Generated 20 design points using latin_hypercube.
Run temperature pressure catalyst
--------------------------------------------
1 482.260 3.053 Rh
2 303.026 1.408 Pd
3 452.389 6.046 Pt
4 395.496 3.983 Pd
5 353.561 5.580 Pt
6 317.728 9.300 Pd
7 341.724 4.766 Rh
8 496.455 1.913 Pt
9 422.216 5.412 Rh
10 389.562 4.531 Pd
11 462.552 7.315 Pd
12 326.295 1.689 Pt
13 408.701 9.786 Pt
14 333.302 8.903 Rh
15 412.997 8.059 Pd
16 431.952 7.126 Rh
17 473.175 6.787 Pd
18 379.926 2.446 Pd
19 442.948 3.349 Pd
20 364.313 8.587 Pd
Or export to CSV for scripting:
!jaxsr design catalyst_screening.jaxsr -n 20 --format csv -o design.csv
WARNING:2026-02-25 10:29:10,493:jax._src.xla_bridge:905: Platform 'mps' is experimental and not all JAX functionality may be correctly supported!
Generated 20 design points using latin_hypercube.
Written to: design.csv
Simulating Lab Responses#
In a real workflow you would run actual experiments and fill in the Response column in the Excel template. Here we simulate synthetic conversion data so the notebook runs end-to-end.
# PREREQUISITES: This cell requires from earlier cells:
# - simulate_response(): function to simulate lab measurements (cell 11)
# - cat_map: dict mapping catalyst names to numeric codes (cell 11)
# For standalone execution, you would import these from a shared module.
# NOTE: This simulation function is used throughout the notebook
# to generate synthetic lab responses (cells 25, 26, 34).
# In practice, these would be actual experimental measurements.
import numpy as np
from openpyxl import load_workbook
rng = np.random.default_rng(42)
def simulate_response(T, P, catalyst_idx):
"""Synthetic conversion (%) for catalyst screening."""
base = 50 + 0.15 * (T - 300) + 2.5 * P - 0.0003 * (T - 400) ** 2
cat_effect = [0, 5, -3][catalyst_idx]
return base + cat_effect + rng.normal(0, 2)
cat_map = {"Pt": 0, "Pd": 1, "Rh": 2}
# Fill in lab_template.xlsx with synthetic responses
wb = load_workbook("lab_template.xlsx")
ws = wb["Design"]
for row in range(2, ws.max_row + 1):
T = float(ws.cell(row=row, column=2).value)
P = float(ws.cell(row=row, column=3).value)
cat = ws.cell(row=row, column=4).value
y = simulate_response(T, P, cat_map[cat])
ws.cell(row=row, column=5, value=round(y, 2))
wb.save("lab_template.xlsx")
print(f"Filled {ws.max_row - 1} response values in lab_template.xlsx")
Step 3: Run Experiments in the Lab#
Open
lab_template.xlsxFor each row, run the experiment at the specified conditions
Fill in the Response column with the measured conversion (%)
Save the file
The cell above simulated this step. In practice you would fill in real measurements.
Step 4: Import Results#
!jaxsr add catalyst_screening.jaxsr lab_template.xlsx \
--notes "Batch 1: initial screening, 2024-01-15"
Added 20 observations. Total: 20
20 design points still pending.
If you have a CSV instead:
jaxsr add catalyst_screening.jaxsr results.csv --notes "From CSV"
CSV format: columns must match factor names, with the last column as the response:
temperature,pressure,catalyst,Response
347.5,3.25,Pd,62.1
421.25,7.75,Pt,78.3
Step 5: Fit a Model#
!jaxsr fit catalyst_screening.jaxsr \
--max-terms 5 \
--strategy greedy_forward \
--criterion bic
WARNING:2026-02-25 10:29:12,739:jax._src.xla_bridge:905: Platform 'mps' is experimental and not all JAX functionality may be correctly supported!
/Users/jkitchin/Dropbox/projects/jaxsr/src/jaxsr/study.py:572: UserWarning: Removing 1 basis functions with non-finite values
model.fit(self._X_observed, self._y_observed)
Model: y = 4.073*sqrt(temperature) + 0.003166*temperature*pressure + 0.01653*I(catalyst=Pd)*temperature - 6442*1/temperature + 0.1201*pressure^2
MSE: 2.52649
AIC: 85.2941
BIC: 90.2728
Terms: 5
Choosing --criterion:#
Data Size |
Recommendation |
|---|---|
< 40 observations |
|
40–200 observations |
|
> 200 observations |
|
Choosing --strategy:#
Library Size |
Recommendation |
|---|---|
< 20 basis functions |
|
20–200 |
|
200+ |
|
Step 6: Check Study Status#
!jaxsr status catalyst_screening.jaxsr
WARNING:2026-02-25 10:29:16,311:jax._src.xla_bridge:905: Platform 'mps' is experimental and not all JAX functionality may be correctly supported!
============================================================
DOE Study: catalyst_screening
============================================================
Description: Screen catalyst type, temperature, and pressure for max conversion
Factors: temperature, pressure, catalyst
Bounds: [(300.0, 500.0), (1.0, 10.0), (0, 2)]
Feature types: ['continuous', 'continuous', 'categorical']
Categories: {2: ['Pt', 'Pd', 'Rh']}
Design: 20 points (0 completed, 20 pending)
Design method: latin_hypercube
Observations: 20
Model: y = 4.073*sqrt(temperature) + 0.003166*temperature*pressure + 0.01653*I(catalyst=Pd)*temperature - 6442*1/temperature + 0.1201*pressure^2
MSE: 2.52649
AIC: 85.2941
Terms: 5
Iterations: 1
Round 1: +20 points → y = 4.073*sqrt(temperature) + 0.003166*temperature*pressure + 0.01653*I(catalyst=Pd)*temperature - 6442*1/temperature + 0.1201*pressure^2 (Batch 1: initial screening, 2024-01-15)
Created: 2026-02-25T15:29:07.312830+00:00
Modified: 2026-02-25T15:29:15.190420+00:00
============================================================
Step 7: Suggest Next Experiments#
The model identifies where to measure next for maximum information gain:
!jaxsr suggest catalyst_screening.jaxsr \
-n 5 \
--strategy uncertainty
WARNING:2026-02-25 10:29:17,408:jax._src.xla_bridge:905: Platform 'mps' is experimental and not all JAX functionality may be correctly supported!
Suggested 5 next experiments:
Run temperature pressure catalyst
--------------------------------------------
1 333.326 9.936 Pd
2 316.223 9.819 Rh
3 313.755 9.800 Pt
4 314.454 9.841 Pd
5 308.075 9.809 Pd
Suggestion strategies:#
Strategy |
When to use |
|---|---|
|
No model yet, or want uniform coverage |
|
Reduce prediction uncertainty everywhere |
|
Fix regions where the model fits poorly |
|
Stabilize coefficient estimates |
Export as CSV for automation:
jaxsr suggest catalyst_screening.jaxsr -n 5 --format csv > next_batch.csv
Step 8: Add More Data and Refit#
After running the suggested experiments:
# PREREQUISITES: This cell requires from earlier cells:
# - simulate_response(): function to simulate lab measurements (cell 11)
# - cat_map: dict mapping catalyst names to numeric codes (cell 11)
# For standalone execution, you would import these from a shared module.
import csv, subprocess, io
# Get suggestions as CSV
result = subprocess.run(
["jaxsr", "suggest", "catalyst_screening.jaxsr", "-n", "5",
"--strategy", "uncertainty", "--format", "csv"],
capture_output=True, text=True
)
# Skip the "Suggested N next experiments:" header line
csv_lines = result.stdout.strip().split("\n")
csv_text = "\n".join(line for line in csv_lines if line.startswith("temperature") or "," in line and not line.startswith("Suggested"))
print("Suggested points (CSV):")
print(csv_text)
# Parse suggestions and simulate responses
try:
reader = csv.DictReader(io.StringIO(csv_text))
rows = list(reader)
if not rows or "temperature" not in rows[0]:
raise ValueError("Invalid CSV format from jaxsr suggest")
except (ValueError, KeyError) as e:
print(f"Error parsing suggestions: {e}")
print("CLI output format may have changed. Please check 'jaxsr suggest --help'")
raise
with open("batch2.csv", "w", newline="") as f:
writer = csv.writer(f)
writer.writerow(["temperature", "pressure", "catalyst", "Response"])
for row in rows:
T = float(row["temperature"])
P = float(row["pressure"])
cat = row["catalyst"]
y = simulate_response(T, P, cat_map[cat])
writer.writerow([T, P, cat, round(y, 2)])
print(f"\nWrote {len(rows)} simulated responses to batch2.csv")
!jaxsr add catalyst_screening.jaxsr batch2.csv --notes "Batch 2: uncertainty-guided"
!jaxsr fit catalyst_screening.jaxsr --max-terms 5 --criterion bic
!jaxsr status catalyst_screening.jaxsr
WARNING:2026-02-25 10:29:23,092:jax._src.xla_bridge:905: Platform 'mps' is experimental and not all JAX functionality may be correctly supported!
Added 5 observations. Total: 25
20 design points still pending.
WARNING:2026-02-25 10:29:24,206:jax._src.xla_bridge:905: Platform 'mps' is experimental and not all JAX functionality may be correctly supported!
/Users/jkitchin/Dropbox/projects/jaxsr/src/jaxsr/study.py:572: UserWarning: Removing 1 basis functions with non-finite values
model.fit(self._X_observed, self._y_observed)
Model: y = 2.42*sqrt(temperature) + 0.005878*temperature*pressure + 0.01705*I(catalyst=Pd)*temperature + 8.6992e-05*temperature^2 + 0.0003076*exp(pressure)
MSE: 4.61599
AIC: 119.1851
BIC: 125.2794
Terms: 5
WARNING:2026-02-25 10:29:27,810:jax._src.xla_bridge:905: Platform 'mps' is experimental and not all JAX functionality may be correctly supported!
============================================================
DOE Study: catalyst_screening
============================================================
Description: Screen catalyst type, temperature, and pressure for max conversion
Factors: temperature, pressure, catalyst
Bounds: [(300.0, 500.0), (1.0, 10.0), (0, 2)]
Feature types: ['continuous', 'continuous', 'categorical']
Categories: {2: ['Pt', 'Pd', 'Rh']}
Design: 20 points (0 completed, 20 pending)
Design method: latin_hypercube
Observations: 25
Model: y = 2.42*sqrt(temperature) + 0.005878*temperature*pressure + 0.01705*I(catalyst=Pd)*temperature + 8.6992e-05*temperature^2 + 0.0003076*exp(pressure)
MSE: 4.61599
AIC: 119.1851
Terms: 5
Iterations: 2
Round 1: +20 points → y = 4.073*sqrt(temperature) + 0.003166*temperature*pressure + 0.01653*I(catalyst=Pd)*temperature - 6442*1/temperature + 0.1201*pressure^2 (Batch 1: initial screening, 2024-01-15)
Round 2: +5 points → y = 2.42*sqrt(temperature) + 0.005878*temperature*pressure + 0.01705*I(catalyst=Pd)*temperature + 8.6992e-05*temperature^2 + 0.0003076*exp(pressure) (Batch 2: uncertainty-guided)
Created: 2026-02-25T15:29:07.312830+00:00
Modified: 2026-02-25T15:29:26.675524+00:00
============================================================
Repeat Steps 7–8 until the model is satisfactory.
When to stop:#
R² > 0.95 and model is physically sensible
Adding data doesn’t change the model expression
Prediction intervals are narrow enough for your application
Budget is exhausted
Step 9: Generate Reports#
Excel Report#
!jaxsr report catalyst_screening.jaxsr -o report.xlsx
WARNING:2026-02-25 10:29:28,923:jax._src.xla_bridge:905: Platform 'mps' is experimental and not all JAX functionality may be correctly supported!
Excel report written to: report.xlsx
The Excel workbook includes:
Study summary sheet
Design matrix with responses
Model coefficients and metrics
Pareto front (complexity vs. accuracy)
Word Report#
!jaxsr report catalyst_screening.jaxsr -o report.docx
WARNING:2026-02-25 10:29:30,106:jax._src.xla_bridge:905: Platform 'mps' is experimental and not all JAX functionality may be correctly supported!
Word report written to: report.docx
The Word document includes:
Formatted model equation
Coefficient table with standard errors
Diagnostic discussion
Embedded figures
Complete Session#
Here’s the entire workflow as a single script:
# Catalyst screening study — complete CLI workflow
import numpy as np, csv, io, subprocess, os
from openpyxl import load_workbook
# NOTE: Fresh RNG (rng2) for standalone execution of this complete workflow.
# Using separate state ensures results are reproducible when running this cell
# independently, without depending on earlier cells' RNG state progression.
rng2 = np.random.default_rng(42)
def sim_response(T, P, catalyst_idx):
base = 50 + 0.15 * (T - 300) + 2.5 * P - 0.0003 * (T - 400) ** 2
cat_effect = [0, 5, -3][catalyst_idx]
return base + cat_effect + rng2.normal(0, 2)
cmap = {"Pt": 0, "Pd": 1, "Rh": 2}
# 1. Setup
!jaxsr init catalyst_screening -f "temperature:300:500" -f "pressure:1:10" -f "catalyst:Pt,Pd,Rh" -d "Catalyst screening"
# 2. Design → Excel template
!jaxsr design catalyst_screening.jaxsr -n 20 -s 42 --format xlsx -o template.xlsx
# 3. Simulate lab responses
wb = load_workbook("template.xlsx")
ws = wb["Design"]
for row in range(2, ws.max_row + 1):
T = float(ws.cell(row=row, column=2).value)
P = float(ws.cell(row=row, column=3).value)
cat = ws.cell(row=row, column=4).value
ws.cell(row=row, column=5, value=round(sim_response(T, P, cmap[cat]), 2))
wb.save("template.xlsx")
print("Filled template with simulated responses")
# 4. Import results
!jaxsr add catalyst_screening.jaxsr template.xlsx --notes "Initial batch"
# 5. Fit
!jaxsr fit catalyst_screening.jaxsr --max-terms 5 --criterion bic
!jaxsr status catalyst_screening.jaxsr
# 6. Adaptive round — get suggestions and simulate
result = subprocess.run(
["jaxsr", "suggest", "catalyst_screening.jaxsr", "-n", "5",
"--strategy", "uncertainty", "--format", "csv"],
capture_output=True, text=True
)
csv_lines = result.stdout.strip().split("\n")
csv_text = "\n".join(line for line in csv_lines if "," in line and not line.startswith("Suggested"))
reader = csv.DictReader(io.StringIO(csv_text))
with open("batch2.csv", "w", newline="") as f:
writer = csv.writer(f)
writer.writerow(["temperature", "pressure", "catalyst", "Response"])
for r in reader:
T, P, cat = float(r["temperature"]), float(r["pressure"]), r["catalyst"]
writer.writerow([T, P, cat, round(sim_response(T, P, cmap[cat]), 2)])
# 7. Import batch 2 and refit
!jaxsr add catalyst_screening.jaxsr batch2.csv --notes "Adaptive batch"
!jaxsr fit catalyst_screening.jaxsr --max-terms 5 --criterion bic
# 8. Reports
!jaxsr report catalyst_screening.jaxsr -o final_report.xlsx
!jaxsr report catalyst_screening.jaxsr -o final_report.docx
Created study 'catalyst_screening' with 3 factors.
Saved to: catalyst_screening.jaxsr
WARNING:2026-02-25 10:29:32,908:jax._src.xla_bridge:905: Platform 'mps' is experimental and not all JAX functionality may be correctly supported!
Generated 20 design points using latin_hypercube.
Excel template written to: template.xlsx
Filled template with simulated responses
Added 20 observations. Total: 20
All design points completed!
WARNING:2026-02-25 10:29:35,090:jax._src.xla_bridge:905: Platform 'mps' is experimental and not all JAX functionality may be correctly supported!
/Users/jkitchin/Dropbox/projects/jaxsr/src/jaxsr/study.py:572: UserWarning: Removing 1 basis functions with non-finite values
model.fit(self._X_observed, self._y_observed)
Model: y = 4.073*sqrt(temperature) + 0.003166*temperature*pressure + 0.01653*I(catalyst=Pd)*temperature - 6442*1/temperature + 0.1201*pressure^2
MSE: 2.52649
AIC: 85.2941
BIC: 90.2728
Terms: 5
WARNING:2026-02-25 10:29:38,795:jax._src.xla_bridge:905: Platform 'mps' is experimental and not all JAX functionality may be correctly supported!
============================================================
DOE Study: catalyst_screening
============================================================
Description: Catalyst screening
Factors: temperature, pressure, catalyst
Bounds: [(300.0, 500.0), (1.0, 10.0), (0, 2)]
Feature types: ['continuous', 'continuous', 'categorical']
Categories: {2: ['Pt', 'Pd', 'Rh']}
Design: 20 points (20 completed, 0 pending)
Design method: latin_hypercube
Observations: 20
Model: y = 4.073*sqrt(temperature) + 0.003166*temperature*pressure + 0.01653*I(catalyst=Pd)*temperature - 6442*1/temperature + 0.1201*pressure^2
MSE: 2.52649
AIC: 85.2941
Terms: 5
Iterations: 1
Round 1: +20 points → y = 4.073*sqrt(temperature) + 0.003166*temperature*pressure + 0.01653*I(catalyst=Pd)*temperature - 6442*1/temperature + 0.1201*pressure^2 (Initial batch)
Created: 2026-02-25T15:29:31.865401+00:00
Modified: 2026-02-25T15:29:37.593133+00:00
============================================================
WARNING:2026-02-25 10:29:42,418:jax._src.xla_bridge:905: Platform 'mps' is experimental and not all JAX functionality may be correctly supported!
Added 5 observations. Total: 25
All design points completed!
WARNING:2026-02-25 10:29:43,514:jax._src.xla_bridge:905: Platform 'mps' is experimental and not all JAX functionality may be correctly supported!
/Users/jkitchin/Dropbox/projects/jaxsr/src/jaxsr/study.py:572: UserWarning: Removing 1 basis functions with non-finite values
model.fit(self._X_observed, self._y_observed)
Model: y = 2.53*sqrt(temperature) + 0.001786*temperature*pressure + 0.01653*I(catalyst=Pd)*temperature + 1.5746e-07*temperature^3 + 2.045*pressure
MSE: 4.86897
AIC: 120.5190
BIC: 126.6133
Terms: 5
WARNING:2026-02-25 10:29:47,160:jax._src.xla_bridge:905: Platform 'mps' is experimental and not all JAX functionality may be correctly supported!
Excel report written to: final_report.xlsx
WARNING:2026-02-25 10:29:48,341:jax._src.xla_bridge:905: Platform 'mps' is experimental and not all JAX functionality may be correctly supported!
Word report written to: final_report.docx
Tips#
Always use
--noteswhen adding data. It creates an audit trail inside the.jaxsrfile.The
.jaxsrfile is self-contained. Share it with collaborators — they can runjaxsr status,jaxsr fit, orjaxsr reporton their own machine.Seed the design with
-s 42(or any integer) for reproducibility.Start with fewer points. 15–20 points is enough for a first pass. Active learning (Step 7) tells you exactly where to measure next.
Don’t over-specify
--max-terms. Start with 5 and increase only if the model R² is poor. More terms = harder to interpret.