quantum-catalyst-platform / export_utils.py
ZenkuIshigami09's picture
Upload 21 files
9fc3c5b verified
Raw
History Blame Contribute Delete
13.9 kB
"""
Export and Reporting Module
============================
Generate PDF reports and export data in various formats for analysis results.
"""
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.backends.backend_pdf import PdfPages
from datetime import datetime
import json
import pandas as pd
from typing import Dict, List
def create_pdf_report(results: Dict, filename: str = None) -> str:
"""
Generate comprehensive PDF report from analysis results.
Args:
results: Analysis results dictionary
filename: Output PDF filename (auto-generated if None)
Returns:
Path to generated PDF file
"""
if filename is None:
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
filename = f"quantum_catalyst_report_{timestamp}.pdf"
with PdfPages(filename) as pdf:
# Page 1: Title and Summary
fig = plt.figure(figsize=(8.5, 11))
fig.suptitle('Quantum Catalyst Analysis Report', fontsize=24, fontweight='bold')
ax = fig.add_subplot(111)
ax.axis('off')
# Report metadata
report_text = f"""
Generated: {datetime.now().strftime("%Y-%m-%d %H:%M:%S")}
Platform: Quantum Catalyst Discovery Platform
Analysis Type: {results.get('type', 'Unknown')}
─────────────────────────────────────────────────
EXECUTIVE SUMMARY
This report contains quantum computing and machine learning
analysis results for catalyst discovery and evaluation.
All energies calculated using real Variational Quantum
Eigensolver (VQE) algorithms running on Qiskit.
─────────────────────────────────────────────────
"""
ax.text(0.1, 0.8, report_text, transform=ax.transAxes,
fontsize=12, verticalalignment='top', family='monospace')
pdf.savefig(fig, bbox_inches='tight')
plt.close()
# Add result-specific pages
result_type = results.get('type', '')
if result_type == 'AI Discovery' and 'candidates' in results:
_add_discovery_pages(pdf, results)
elif result_type == 'Learning Game':
_add_learning_game_pages(pdf, results)
elif result_type == 'Comparison':
_add_comparison_pages(pdf, results)
# Final page: Methodology
_add_methodology_page(pdf)
return filename
def export_discovery_batch_to_csv(candidates: list) -> str:
"""
Export discovery candidates to CSV string.
Fields:
- SMILES
- QSVM Score
- Classification
"""
rows = []
for cand in candidates or []:
rows.append({
"SMILES": cand.get("smiles", ""),
"QSVM Score": cand.get("catalyst_score", ""),
"Classification": cand.get("classification", ""),
})
df = pd.DataFrame(rows, columns=["SMILES", "QSVM Score", "Classification"])
return df.to_csv(index=False)
def _add_discovery_pages(pdf: PdfPages, results: Dict):
"""Add AI discovery result pages to PDF."""
candidates = results.get('candidates', [])
# Candidates summary page
fig, ax = plt.subplots(figsize=(8.5, 11))
ax.text(0.5, 0.95, f'AI Catalyst Discovery Results',
ha='center', fontsize=18, fontweight='bold',
transform=ax.transAxes)
ax.text(0.5, 0.90, f'Reaction: {results.get("reaction", "Unknown")}',
ha='center', fontsize=14, transform=ax.transAxes)
# Table of candidates
table_data = []
for i, cand in enumerate(candidates[:10]):
table_data.append([
f"#{i+1}",
cand['smiles'],
cand.get('metal_type', 'N/A'),
f"{cand['catalyst_score']:.2f}",
cand['classification']
])
table = ax.table(cellText=table_data,
colLabels=['Rank', 'Catalyst', 'Metal', 'Score', 'Class'],
cellLoc='center',
loc='center',
bbox=[0.1, 0.3, 0.8, 0.5])
table.auto_set_font_size(False)
table.set_fontsize(10)
table.scale(1, 2)
ax.axis('off')
pdf.savefig(fig, bbox_inches='tight')
plt.close()
# Score comparison chart
fig, ax = plt.subplots(figsize=(8.5, 6))
scores = [c['catalyst_score'] for c in candidates[:10]]
labels = [f"#{i+1}\n{c['smiles']}" for i, c in enumerate(candidates[:10])]
colors = plt.cm.viridis(np.linspace(0.3, 0.9, len(scores)))
bars = ax.bar(range(len(scores)), scores, color=colors, edgecolor='black', linewidth=1.5)
for i, bar in enumerate(bars):
height = bar.get_height()
ax.text(bar.get_x() + bar.get_width()/2., height,
f'{scores[i]:.1f}',
ha='center', va='bottom', fontweight='bold')
ax.set_xticks(range(len(labels)))
ax.set_xticklabels(labels, rotation=45, ha='right', fontsize=9)
ax.set_ylabel('Catalyst Score (0-100)', fontsize=12, fontweight='bold')
ax.set_title('Generated Catalyst Candidates - Score Comparison', fontsize=14, fontweight='bold')
ax.grid(True, alpha=0.3, axis='y')
ax.set_ylim(0, 100)
plt.tight_layout()
pdf.savefig(fig, bbox_inches='tight')
plt.close()
def _add_learning_game_pages(pdf: PdfPages, results: Dict):
"""Add learning game result pages to PDF."""
fig, ax = plt.subplots(figsize=(8.5, 11))
ax.text(0.5, 0.95, 'Learning Game Results',
ha='center', fontsize=18, fontweight='bold',
transform=ax.transAxes)
score = results.get('score', 0)
# Score display
score_color = 'green' if score >= 80 else 'orange' if score >= 60 else 'red'
ax.text(0.5, 0.80, f'Final Score: {score:.1f}/100',
ha='center', fontsize=24, fontweight='bold',
color=score_color, transform=ax.transAxes)
ax.text(0.5, 0.70, f'Reaction: {results.get("reaction", "Unknown")}',
ha='center', fontsize=14, transform=ax.transAxes)
ax.text(0.5, 0.65, f'Your Catalyst: {results.get("user_catalyst", "Unknown")}',
ha='center', fontsize=14, transform=ax.transAxes)
# Performance assessment
if score >= 80:
assessment = "Excellent! You have a strong understanding of catalyst chemistry."
elif score >= 60:
assessment = "Good work! You're on the right track."
else:
assessment = "Keep learning! Review the ideal catalysts for this reaction."
ax.text(0.5, 0.50, assessment,
ha='center', fontsize=12, style='italic',
transform=ax.transAxes, wrap=True)
ax.axis('off')
pdf.savefig(fig, bbox_inches='tight')
plt.close()
def _add_comparison_pages(pdf: PdfPages, results: Dict):
"""Add comparison result pages to PDF."""
fig, ax = plt.subplots(figsize=(8.5, 11))
ax.text(0.5, 0.95, 'Quantum vs Classical Comparison',
ha='center', fontsize=18, fontweight='bold',
transform=ax.transAxes)
ax.text(0.5, 0.88, f'Analysis Type: {results.get("comparison_type", "Unknown")}',
ha='center', fontsize=14, transform=ax.transAxes)
ax.text(0.5, 0.83, f'Molecule: {results.get("molecule", "Unknown")}',
ha='center', fontsize=14, transform=ax.transAxes)
comparison_text = """
─────────────────────────────────────────────────
This comparison demonstrates the quantum advantage
in computational chemistry and machine learning.
Quantum methods (VQE, QSVM) provide more accurate
results compared to classical approximations.
─────────────────────────────────────────────────
"""
ax.text(0.5, 0.60, comparison_text,
ha='center', va='center', fontsize=11,
transform=ax.transAxes, family='monospace')
ax.axis('off')
pdf.savefig(fig, bbox_inches='tight')
plt.close()
def _add_methodology_page(pdf: PdfPages):
"""Add methodology explanation page."""
fig, ax = plt.subplots(figsize=(8.5, 11))
ax.text(0.5, 0.95, 'Methodology',
ha='center', fontsize=18, fontweight='bold',
transform=ax.transAxes)
methodology_text = """
QUANTUM ALGORITHMS
β€’ VQE (Variational Quantum Eigensolver)
- Hybrid quantum-classical algorithm
- Finds molecular ground state energies
- More accurate than Hartree-Fock
β€’ QSVM (Quantum Support Vector Machine)
- Quantum kernel methods for classification
- Enhanced pattern recognition
- Scores catalyst effectiveness
β€’ QGAN (Quantum Generative Adversarial Network)
- Generates novel catalyst candidates
- Quantum-enhanced feature learning
─────────────────────────────────────────────────
CLASSICAL BASELINES
β€’ Hartree-Fock (HF)
- Mean-field approximation
- Fast but less accurate
β€’ DFT (Density Functional Theory)
- Exchange-correlation functionals
- Balance of speed and accuracy
β€’ Classical ML
- Random Forest, SVM, Gradient Boosting
- Standard machine learning methods
─────────────────────────────────────────────────
CHEMISTRY MODELS
β€’ D-band Model
- Predicts catalyst-adsorbate binding
- NΓΈrskov's theoretical framework
β€’ BEP Relation
- BrΓΈnsted-Evans-Polanyi correlation
- Estimates activation energies
─────────────────────────────────────────────────
Platform: Quantum Catalyst Discovery Platform
Framework: Qiskit, RDKit, Scikit-learn
License: Educational & Research Use
"""
ax.text(0.1, 0.85, methodology_text,
verticalalignment='top', fontsize=9,
transform=ax.transAxes, family='monospace')
ax.axis('off')
pdf.savefig(fig, bbox_inches='tight')
plt.close()
def export_to_csv(results_history: List[Dict], filename: str = None) -> str:
"""
Export results history to CSV format.
Args:
results_history: List of result dictionaries
filename: Output CSV filename
Returns:
Path to generated CSV file
"""
if filename is None:
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
filename = f"quantum_catalyst_data_{timestamp}.csv"
# Flatten data
csv_data = []
for result in results_history:
row = {
'Timestamp': result.get('timestamp', ''),
'Type': result.get('type', ''),
'Reaction': result.get('reaction', 'N/A'),
}
if result.get('type') == 'AI Discovery' and 'candidates' in result:
row['Num_Candidates'] = len(result['candidates'])
if result['candidates']:
row['Top_Score'] = result['candidates'][0].get('catalyst_score', 0)
row['Top_Catalyst'] = result['candidates'][0].get('smiles', '')
elif result.get('type') == 'Learning Game':
row['User_Catalyst'] = result.get('user_catalyst', '')
row['Score'] = result.get('score', 0)
csv_data.append(row)
df = pd.DataFrame(csv_data)
df.to_csv(filename, index=False)
return filename
def export_to_json(results_history: List[Dict], filename: str = None) -> str:
"""
Export results history to JSON format.
Args:
results_history: List of result dictionaries
filename: Output JSON filename
Returns:
Path to generated JSON file
"""
if filename is None:
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
filename = f"quantum_catalyst_data_{timestamp}.json"
with open(filename, 'w') as f:
json.dump(results_history, f, indent=2)
return filename
def generate_summary_stats(results_history: List[Dict]) -> Dict:
"""
Generate summary statistics from results history.
Args:
results_history: List of result dictionaries
Returns:
Dictionary with summary statistics
"""
stats = {
'total_analyses': len(results_history),
'by_type': {},
'reactions_analyzed': set(),
'catalysts_tested': set(),
'avg_scores': {}
}
for result in results_history:
result_type = result.get('type', 'Unknown')
stats['by_type'][result_type] = stats['by_type'].get(result_type, 0) + 1
if 'reaction' in result:
stats['reactions_analyzed'].add(result['reaction'])
if result.get('type') == 'AI Discovery' and 'candidates' in result:
for cand in result['candidates']:
stats['catalysts_tested'].add(cand.get('smiles', ''))
elif result.get('type') == 'Learning Game':
if 'user_catalyst' in result:
stats['catalysts_tested'].add(result['user_catalyst'])
if 'score' in result:
if result_type not in stats['avg_scores']:
stats['avg_scores'][result_type] = []
stats['avg_scores'][result_type].append(result['score'])
# Convert sets to lists and calculate averages
stats['reactions_analyzed'] = list(stats['reactions_analyzed'])
stats['catalysts_tested'] = list(stats['catalysts_tested'])
for result_type, scores in stats['avg_scores'].items():
stats['avg_scores'][result_type] = np.mean(scores) if scores else 0
return stats