Tutorial: HER Catalyst Screening¶
This tutorial demonstrates a complete HER (Hydrogen Evolution Reaction) catalyst screening workflow using ASCICat.
Objectives¶
By the end of this tutorial, you will be able to:
- Initialize an ASCICat calculator
- Load and validate catalyst data
- Calculate ASCI scores with custom weights
- Analyze and visualize results
- Export findings for further analysis
Prerequisites¶
Step 1: Setup¶
from ascicat import ASCICalculator
from ascicat.visualizer import Visualizer
from pathlib import Path
import pandas as pd
# Create output directory
output_dir = Path('results/HER_tutorial')
output_dir.mkdir(parents=True, exist_ok=True)
print("Setup complete!")
Step 2: Initialize Calculator¶
# Initialize for HER with verbose output
calc = ASCICalculator(
reaction='HER',
scoring_method='linear',
verbose=True
)
Expected output:
================================================================================
ASCICat Calculator Initialized
================================================================================
🔬 Reaction: HER
Pathway: H adsorption
Optimal Energy: ΔE_opt = -0.270 eV
Description: Hydrogen Evolution Reaction (2H⁺ + 2e⁻ → H₂)
⚙️ Configuration:
Activity Width: σ_a = 0.150 eV
Scoring Method: LINEAR
Default Weights: w_a=0.33, w_s=0.33, w_c=0.34 (EQUAL)
================================================================================
Step 3: Load Data¶
# Load HER catalyst database
data_path = 'data/HER_clean.csv'
calc.load_data(data_path)
# Explore the data
print(f"\nDataset size: {len(calc.data):,} catalysts")
print(f"\nColumn names: {list(calc.data.columns)}")
# Check descriptor distributions
print("\nDescriptor Statistics:")
print(calc.data[['DFT_ads_E', 'surface_energy', 'Cost']].describe())
Step 4: Calculate ASCI Scores¶
Equal Weights (Unbiased Screening)¶
# Calculate with equal weights
results = calc.calculate_asci(
w_a=0.33, # Activity
w_s=0.33, # Stability
w_c=0.34 # Cost
)
print(f"\nASCI calculated for {len(results):,} catalysts")
print(f"ASCI range: [{results['ASCI'].min():.3f}, {results['ASCI'].max():.3f}]")
Activity-Focused Screening¶
# For fundamental research - prioritize activity
results_activity = calc.calculate_asci(
w_a=0.50,
w_s=0.30,
w_c=0.20
)
Cost-Focused Screening¶
# For large-scale deployment - prioritize cost
results_cost = calc.calculate_asci(
w_a=0.30,
w_s=0.20,
w_c=0.50
)
Step 5: Analyze Top Catalysts¶
# Get top 20 catalysts
top20 = calc.get_top_catalysts(n=20)
# Display detailed ranking
print("\n" + "="*85)
print("TOP 20 HER CATALYSTS (Equal Weights)")
print("="*85)
print(f"\n{'Rank':<6} {'Symbol':<14} {'ASCI':<8} {'S_a':<8} "
f"{'S_s':<8} {'S_c':<8} {'ΔE (eV)':<10}")
print("-"*85)
for i, (_, row) in enumerate(top20.iterrows(), 1):
print(f"{i:<6} {row['symbol']:<14} {row['ASCI']:.4f} "
f"{row['activity_score']:.4f} {row['stability_score']:.4f} "
f"{row['cost_score']:.4f} {row['DFT_ads_E']:+.3f}")
Compare Across Weight Scenarios¶
# Get top catalyst from each scenario
print("\n" + "="*60)
print("TOP CATALYST BY WEIGHT SCENARIO")
print("="*60)
scenarios = {
'Equal weights (0.33/0.33/0.34)': results,
'Activity-focused (0.50/0.30/0.20)': results_activity,
'Cost-focused (0.30/0.20/0.50)': results_cost
}
for name, res in scenarios.items():
top = res.iloc[0]
print(f"\n{name}:")
print(f" {top['symbol']} (ASCI={top['ASCI']:.3f})")
print(f" Activity: {top['activity_score']:.3f}, "
f"Stability: {top['stability_score']:.3f}, "
f"Cost: {top['cost_score']:.3f}")
Step 6: Generate Visualizations¶
# Initialize visualizer
viz = Visualizer(results, calc.config, auto_sample=True)
# Generate figures
print("\nGenerating figures...")
viz.generate_figures(
output_dir=str(output_dir),
dpi=600,
formats=['png', 'pdf']
)
# Generate interactive 3D plot
viz.create_interactive_3d(
output_path=str(output_dir / 'interactive_3d.html'),
title='HER Catalyst Screening Results'
)
print(f"\nFigures saved to: {output_dir}/")
Step 7: Export Results¶
# Save full results
results.to_csv(output_dir / 'HER_full_results.csv', index=False)
# Save top 100 catalysts
top100 = calc.get_top_catalysts(n=100)
top100.to_csv(output_dir / 'HER_top100.csv', index=False)
# Save summary statistics
summary = {
'n_catalysts': len(results),
'best_catalyst': results.iloc[0]['symbol'],
'best_asci': results.iloc[0]['ASCI'],
'mean_asci': results['ASCI'].mean(),
'std_asci': results['ASCI'].std(),
'weights': '0.33/0.33/0.34 (equal)'
}
pd.Series(summary).to_csv(output_dir / 'HER_summary.csv')
print("\nExported files:")
for f in output_dir.glob('*'):
print(f" {f.name}")
Step 8: Interpret Results¶
Understanding the Top Catalyst¶
# Detailed analysis of #1 catalyst
top1 = results.iloc[0]
print("\n" + "="*60)
print(f"DETAILED ANALYSIS: {top1['symbol']}")
print("="*60)
print(f"\n📊 ASCI Score: {top1['ASCI']:.4f}")
print(f"\n🎯 Score Breakdown:")
print(f" Activity (w=0.33): {top1['activity_score']:.4f} "
f"→ contributes {0.33*top1['activity_score']:.4f}")
print(f" Stability (w=0.33): {top1['stability_score']:.4f} "
f"→ contributes {0.33*top1['stability_score']:.4f}")
print(f" Cost (w=0.34): {top1['cost_score']:.4f} "
f"→ contributes {0.34*top1['cost_score']:.4f}")
print(f"\n📏 Raw Values:")
print(f" ΔE_H = {top1['DFT_ads_E']:+.3f} eV "
f"(optimal: -0.27 eV, deviation: {abs(top1['DFT_ads_E']+0.27):.3f} eV)")
print(f" γ = {top1['surface_energy']:.2f} J/m²")
print(f" Cost = ${top1['Cost']:,.0f}/kg")
# Identify limiting factor
scores = {
'Activity': top1['activity_score'],
'Stability': top1['stability_score'],
'Cost': top1['cost_score']
}
limiting = min(scores, key=scores.get)
print(f"\n⚠️ Limiting factor: {limiting} ({scores[limiting]:.3f})")
Complete Script¶
Here's the complete tutorial as a single script:
#!/usr/bin/env python3
"""
HER Catalyst Screening Tutorial
Complete workflow with ASCICat
"""
from ascicat import ASCICalculator
from ascicat.visualizer import Visualizer
from pathlib import Path
def main():
# Setup
output_dir = Path('results/HER_tutorial')
output_dir.mkdir(parents=True, exist_ok=True)
# Initialize
calc = ASCICalculator(reaction='HER', verbose=True)
# Load data
calc.load_data('data/HER_clean.csv')
# Calculate ASCI (equal weights)
results = calc.calculate_asci(w_a=0.33, w_s=0.33, w_c=0.34)
# Display top catalysts
print("\nTOP 10 HER CATALYSTS:")
print("-" * 50)
top10 = calc.get_top_catalysts(n=10)
for i, (_, row) in enumerate(top10.iterrows(), 1):
print(f"{i:2}. {row['symbol']:<12} ASCI={row['ASCI']:.3f}")
# Generate figures
viz = Visualizer(results, calc.config)
viz.generate_all_outputs(output_dir=str(output_dir))
# Export
results.to_csv(output_dir / 'HER_results.csv', index=False)
print(f"\n✓ Tutorial complete! Results in: {output_dir}/")
if __name__ == '__main__':
main()
Next Steps¶
- CO2RR Multi-Pathway Analysis - Screen multiple reaction pathways
- Sensitivity Analysis - Evaluate ranking robustness
- Figure Generation - Create high-quality graphics