SIA-CE Integration Tutorial
Learn how to create sophisticated analytical workflows combining SIA sample preparation with CE analysis.
Overview
This tutorial demonstrates advanced integration scenarios: - Multi-step sample preparation - Parallel processing during CE runs - Automated method development - Complex decision trees - Real-time optimization
Scenario: Protein Stability Study
We'll analyze protein samples under different conditions: - pH variations (5.0, 6.0, 7.0, 8.0) - Temperature stress (native, heated) - Time points (0h, 24h, 48h) - Automated sample preparation and analysis
Workflow Architecture
graph LR
A[Sample Preparation] --> B[CE Analysis]
B --> C[Data Collection]
C --> D[Decision Logic]
D --> A
D --> E[Report Generation]
Step 1: System Architecture
import time
import pandas as pd
import numpy as np
from datetime import datetime, timedelta
from ChemstationAPI import ChemstationAPI
from SIA_API.devices import SyringeController, ValveSelector
from SIA_API.methods import PreparedSIAMethods
class IntegratedAnalysisSystem:
"""Complete SIA-CE integration for automated analysis."""
def __init__(self):
# Initialize all components
print("Initializing Integrated Analysis System...")
self.ce = ChemstationAPI()
self.syringe = SyringeController(port="COM3", syringe_size=1000)
self.valve = ValveSelector(port="COM4", num_positions=8)
self.sia = PreparedSIAMethods(self.ce, self.syringe, self.valve)
# System configuration
self.config = {
'ports': {
'waste': 1,
'air': 2,
'water': 3,
'transfer': 4,
'buffer_ph5': 5,
'buffer_ph6': 6,
'buffer_ph7': 7,
'buffer_ph8': 8
},
'vials': {
'samples': list(range(10, 34)), # 24 sample positions
'standards': [1, 2],
'blanks': [3, 4],
'wash': 48,
'waste': 50
},
'methods': {
'native': 'CE_Protein_Native',
'denatured': 'CE_Protein_Denatured',
'fast_screen': 'CE_Protein_Fast'
}
}
# Analysis tracking
self.analysis_log = []
self.results_cache = {}
print("✓ System initialized")
def initialize_system(self):
"""Complete system initialization."""
self.sia.system_initialization_and_cleaning()
return self
# Create system instance
system = IntegratedAnalysisSystem()
system.initialize_system()
Step 2: Sample Preparation Workflows
class SamplePreparationWorkflows:
"""Advanced sample preparation methods."""
def __init__(self, system):
self.system = system
self.sia = system.sia
self.ce = system.ce
def prepare_ph_series(self, sample_vial, target_vials, volumes):
"""Prepare pH series from single sample."""
print(f"\nPreparing pH series from vial {sample_vial}")
ph_buffers = {
5.0: self.system.config['ports']['buffer_ph5'],
6.0: self.system.config['ports']['buffer_ph6'],
7.0: self.system.config['ports']['buffer_ph7'],
8.0: self.system.config['ports']['buffer_ph8']
}
preparations = []
for (target_vial, ph), (sample_vol, buffer_vol) in zip(
target_vials.items(), volumes
):
print(f" pH {ph} → Vial {target_vial}")
# Add buffer first
self.sia.prepare_batch_flow(solvent_port=ph_buffers[ph])
self.sia.batch_fill(
vial=target_vial,
volume=buffer_vol,
solvent_port=ph_buffers[ph],
unload=False
)
# Add sample (manual or automated)
print(f" Add {sample_vol} µL from vial {sample_vial}")
# Mix thoroughly
self.sia.homogenize_sample(
vial=target_vial,
speed=800,
homogenization_time=30
)
preparations.append({
'vial': target_vial,
'ph': ph,
'sample_vol': sample_vol,
'buffer_vol': buffer_vol,
'time': datetime.now()
})
return preparations
def thermal_stress_preparation(self, sample_vials, temperature=60, duration=30):
"""Prepare thermally stressed samples."""
print(f"\nThermal stress: {temperature}°C for {duration} min")
print("Remove samples for heating")
# Log sample removal
removal_time = datetime.now()
# Wait for thermal treatment
print(f"Heating samples...")
time.sleep(duration * 60) # In real scenario, use external heating
print("Return heated samples to carousel")
return_time = datetime.now()
# Quick-cool samples
for vial in sample_vials:
# Add cold buffer for quenching
self.sia.batch_fill(
vial=vial,
volume=100,
solvent_port=self.system.config['ports']['water'],
transfer_line_volume=300,
speed=3000 # Fast for quick cooling
)
stress_log = {
'vials': sample_vials,
'temperature': temperature,
'duration': duration,
'removed': removal_time,
'returned': return_time
}
return stress_log
def automated_dilution_series(self, stock_vial, target_vials, dilution_factors):
"""Create dilution series with mixing."""
print(f"\nCreating dilution series from vial {stock_vial}")
# Use continuous flow for efficiency
self.sia.prepare_continuous_flow(
solvent_port=self.system.config['ports']['water']
)
dilutions = []
for vial, factor in zip(target_vials, dilution_factors):
# Calculate volumes
final_volume = 1000 # µL
stock_volume = final_volume / factor
diluent_volume = final_volume - stock_volume
print(f" 1:{factor} dilution → Vial {vial}")
# Add diluent
self.sia.continuous_fill(
vial=vial,
volume=diluent_volume,
solvent_port=self.system.config['ports']['water']
)
dilutions.append({
'vial': vial,
'factor': factor,
'stock_vol': stock_volume,
'diluent_vol': diluent_volume
})
print(f"Add stock solution volumes as indicated")
return dilutions
# Add workflows to system
system.prep = SamplePreparationWorkflows(system)
Step 3: Intelligent CE Control
class IntelligentCEControl:
"""Smart CE control with decision logic."""
def __init__(self, system):
self.system = system
self.ce = system.ce
def adaptive_method_selection(self, sample_info):
"""Select optimal method based on sample properties."""
# Decision tree for method selection
if sample_info.get('screening', False):
method = self.system.config['methods']['fast_screen']
elif sample_info.get('denatured', False):
method = self.system.config['methods']['denatured']
else:
method = self.system.config['methods']['native']
# Adjust parameters based on pH
ph = sample_info.get('ph', 7.0)
if ph < 6.0:
# Low pH modifications
print(f"Adjusting for pH {ph}")
# In practice, modify method parameters here
return method
def parallel_sample_prep(self, current_vial, next_vial):
"""Prepare next sample during current analysis."""
print(f"\nParallel processing: Current={current_vial}, Next={next_vial}")
# Start CE analysis
self.ce.method.execution_method_with_parameters(
vial=current_vial,
method_name="CE_Protein_Analysis",
sample_name=f"Sample_{current_vial}"
)
# While CE is running, prepare next sample
print("CE running - preparing next sample...")
# Monitor CE and prepare when safe
while self.ce.system.method_on():
status = self.ce.system.status()
remaining = self.ce.system.get_remaining_analysis_time()
# Start prep when 5 minutes remaining
if remaining < 5 and remaining > 0:
print("Starting next sample preparation")
# Safe to use SIA during separation
self.system.sia.batch_fill(
vial=next_vial,
volume=500,
solvent_port=self.system.config['ports']['water']
)
self.system.sia.homogenize_sample(
vial=next_vial,
speed=1000,
homogenization_time=20
)
break
time.sleep(30)
# Wait for CE completion
while self.ce.system.method_on():
time.sleep(10)
return True
def automated_system_suitability(self):
"""Run system suitability before batch."""
print("\n=== System Suitability Test ===")
# Load standard
self.ce.ce.load_vial_to_position(1, "inlet")
self.ce.ce.load_vial_to_position(48, "outlet")
# Condition with method-specific parameters
self.ce.ce.flush_capillary(120) # 2 min conditioning
# Run suitability standard
self.ce.method.execution_method_with_parameters(
vial=1,
method_name="CE_System_Suitability",
sample_name="SST_Standard"
)
# Monitor and evaluate
while self.ce.system.method_on():
time.sleep(30)
# In practice, evaluate peak parameters here
print("✓ System suitability passed")
# Return vials
self.ce.ce.unload_vial_from_position("inlet")
self.ce.ce.unload_vial_from_position("outlet")
return True
# Add intelligent control
system.smart_ce = IntelligentCEControl(system)
Step 4: Complete Stability Study Workflow
def run_protein_stability_study(system):
"""Execute complete protein stability study."""
print("\n=== Protein Stability Study ===")
print(f"Start: {datetime.now()}")
# Study design
study_design = {
'time_points': [0, 24, 48], # hours
'ph_values': [5.0, 6.0, 7.0, 8.0],
'conditions': ['native', 'heat_stressed'],
'replicates': 2
}
# Calculate total samples
total_samples = (len(study_design['time_points']) *
len(study_design['ph_values']) *
len(study_design['conditions']) *
study_design['replicates'])
print(f"Total samples: {total_samples}")
# Run system suitability
system.smart_ce.automated_system_suitability()
# Time point 0 - Baseline
print("\n--- Time Point 0h ---")
# Prepare pH series for native
native_vials = {10: 5.0, 11: 6.0, 12: 7.0, 13: 8.0}
system.prep.prepare_ph_series(
sample_vial=1, # Original sample
target_vials=native_vials,
volumes=[(100, 900), (100, 900), (100, 900), (100, 900)]
)
# Prepare heat stressed samples
stressed_vials = [14, 15, 16, 17]
system.prep.thermal_stress_preparation(
sample_vials=stressed_vials,
temperature=60,
duration=30
)
# Analyze all T0 samples
all_t0_vials = list(native_vials.keys()) + stressed_vials
for i, vial in enumerate(all_t0_vials):
# Determine sample info
if vial in native_vials:
ph = native_vials[vial]
condition = 'native'
else:
idx = stressed_vials.index(vial)
ph = list(native_vials.values())[idx]
condition = 'stressed'
sample_info = {
'vial': vial,
'time_point': 0,
'ph': ph,
'condition': condition,
'denatured': condition == 'stressed'
}
# Select method adaptively
method = system.smart_ce.adaptive_method_selection(sample_info)
# Run with parallel prep if not last sample
if i < len(all_t0_vials) - 1:
system.smart_ce.parallel_sample_prep(
current_vial=vial,
next_vial=all_t0_vials[i + 1]
)
else:
# Last sample - no parallel prep
system.ce.method.execution_method_with_parameters(
vial=vial,
method_name=method,
sample_name=f"T0_{condition}_pH{ph}"
)
while system.ce.system.method_on():
time.sleep(30)
print("\n✓ Time point 0h complete")
# Store samples for next time points
print("\nStore remaining samples at 4°C")
print("Continue with 24h and 48h time points...")
# Generate report
generate_study_report(system, study_design)
def generate_study_report(system, study_design):
"""Generate comprehensive study report."""
report = f"""
Protein Stability Study Report
==============================
Generated: {datetime.now()}
Study Design:
- Time Points: {study_design['time_points']}
- pH Values: {study_design['ph_values']}
- Conditions: {study_design['conditions']}
- Replicates: {study_design['replicates']}
Analysis Summary:
- Total Samples: {len(system.analysis_log)}
- Methods Used: {set([log.get('method') for log in system.analysis_log])}
Preparation Log:
{pd.DataFrame(system.analysis_log).to_string()}
System Performance:
- Average Analysis Time: X minutes
- Total Runtime: Y hours
- Success Rate: Z%
"""
filename = f"stability_study_{datetime.now().strftime('%Y%m%d')}.txt"
with open(filename, 'w') as f:
f.write(report)
print(f"\n✓ Report saved: {filename}")
# Execute study
run_protein_stability_study(system)
Step 5: Advanced Integration Patterns
Real-time Method Optimization
class RealTimeOptimization:
"""Optimize methods based on real-time results."""
def __init__(self, system):
self.system = system
self.optimization_history = []
def analyze_separation_quality(self, data_file):
"""Analyze separation metrics."""
# In practice, parse ChemStation data file
# For demo, return mock metrics
return {
'resolution': 1.8,
'peak_symmetry': 1.1,
'runtime': 12.5,
'baseline_noise': 0.02
}
def optimize_next_run(self, current_metrics):
"""Adjust parameters for next run."""
adjustments = {}
# Resolution optimization
if current_metrics['resolution'] < 1.5:
adjustments['voltage'] = '+2kV'
adjustments['temperature'] = '-2°C'
# Speed optimization
if current_metrics['resolution'] > 2.0:
adjustments['voltage'] = '+5kV'
adjustments['runtime'] = '-20%'
# Noise reduction
if current_metrics['baseline_noise'] > 0.05:
adjustments['filter'] = 'increase'
self.optimization_history.append({
'metrics': current_metrics,
'adjustments': adjustments,
'timestamp': datetime.now()
})
return adjustments
# Add optimization capability
system.optimizer = RealTimeOptimization(system)
Conditional Workflow Branching
def intelligent_workflow_routing(system, sample_info):
"""Route samples based on previous results."""
# Check if screening is needed
if 'initial_screen' not in sample_info:
# Run fast screening
result = quick_screen_analysis(system, sample_info['vial'])
if result['complexity'] == 'high':
# Complex sample - full analysis
sample_info['method'] = 'comprehensive'
sample_info['prep'] = 'extensive'
elif result['complexity'] == 'medium':
# Standard analysis
sample_info['method'] = 'standard'
sample_info['prep'] = 'normal'
else:
# Simple sample - fast method
sample_info['method'] = 'rapid'
sample_info['prep'] = 'minimal'
# Execute appropriate workflow
execute_sample_workflow(system, sample_info)
def quick_screen_analysis(system, vial):
"""5-minute screening analysis."""
system.ce.method.execution_method_with_parameters(
vial=vial,
method_name="CE_Quick_Screen",
sample_name=f"Screen_{vial}"
)
# Wait and analyze
while system.ce.system.method_on():
time.sleep(10)
# Mock complexity assessment
complexity = np.random.choice(['low', 'medium', 'high'], p=[0.3, 0.5, 0.2])
return {'vial': vial, 'complexity': complexity}
Automated Troubleshooting
def automated_troubleshooting(system, error_type):
"""Automated error recovery procedures."""
recovery_procedures = {
'high_current': [
lambda: system.ce.ce.flush_capillary(300), # Extended flush
lambda: system.ce.ce.apply_pressure_to_capillary(-50, 60), # Vacuum
lambda: replace_buffer_vials(system)
],
'no_peaks': [
lambda: check_sample_preparation(system),
lambda: verify_injection_parameters(system),
lambda: system.sia.homogenize_sample(vial=current_vial, speed=1500, time=60)
],
'baseline_drift': [
lambda: system.ce.ce.flush_capillary(180),
lambda: equilibrate_temperature(system, duration=15),
lambda: check_buffer_levels(system)
]
}
if error_type in recovery_procedures:
print(f"\nTroubleshooting: {error_type}")
for i, procedure in enumerate(recovery_procedures[error_type]):
print(f" Step {i+1}: {procedure.__name__}")
procedure()
# Test if resolved
if test_system_recovery(system):
print("✓ Issue resolved")
return True
return False
Best Practices for Integration
1. Modular Design
# Separate concerns into modules
class AnalysisModule:
def __init__(self, system):
self.system = system
def execute(self, samples):
raise NotImplementedError
class ProteinModule(AnalysisModule):
def execute(self, samples):
# Protein-specific workflow
pass
class SmallMoleculeModule(AnalysisModule):
def execute(self, samples):
# Small molecule workflow
pass
2. State Management
class WorkflowState:
"""Track workflow state for recovery."""
def __init__(self):
self.current_step = None
self.completed_samples = []
self.pending_samples = []
self.errors = []
def checkpoint(self):
"""Save state for recovery."""
state_file = f"workflow_state_{datetime.now().strftime('%Y%m%d_%H%M')}.json"
# Save state to file
def recover(self, state_file):
"""Restore from checkpoint."""
# Load and resume from saved state
3. Performance Monitoring
class PerformanceMonitor:
"""Monitor system performance metrics."""
def __init__(self):
self.metrics = {
'sample_prep_time': [],
'analysis_time': [],
'total_throughput': 0,
'error_rate': 0
}
def log_operation(self, operation, duration):
"""Log operation timing."""
self.metrics[f'{operation}_time'].append(duration)
def generate_dashboard(self):
"""Create performance dashboard."""
# Calculate statistics and trends
pass
Conclusion
You've learned advanced SIA-CE integration including: - Multi-component system architecture - Parallel processing strategies - Intelligent method selection - Real-time optimization - Error recovery procedures - Complex workflow design
These patterns enable fully automated analytical workflows with minimal manual intervention.
Further Reading
- Explore the API Reference for detailed function documentation
- Review Hardware Setup for optimization tips
- Check FAQ for common integration questions