-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathevolution.py
More file actions
126 lines (105 loc) · 3.87 KB
/
evolution.py
File metadata and controls
126 lines (105 loc) · 3.87 KB
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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
import pandas as pd
import numpy as np
from scipy.signal import savgol_filter
import plotly.graph_objects as go
from datetime import datetime
def validate_fractions(df):
"""Validate that fractions sum to approximately 1"""
structures = ['sheets', 'vesicles', 'tubes', 'fibers']
fraction_sum = sum(df[f'{s}_fraction'] for s in structures)
tolerance = 0.01 # 1% tolerance
if not np.allclose(fraction_sum, 1, rtol=tolerance):
max_deviation = np.max(np.abs(fraction_sum - 1))
print(f"Warning: Fractions don't sum to 1. Maximum deviation: {max_deviation:.3f}")
return False
return True
def load_and_process_data():
"""Load structure data and calculate fractions"""
try:
# Load all structure files
dfs = {
'sheets': pd.read_csv('sfi_output.csv'),
'vesicles': pd.read_csv('vfi_output.csv'),
'tubes': pd.read_csv('tfi_output.csv'),
'fibers': pd.read_csv('ffi_output.csv')
}
# Combine into single dataframe
df = pd.DataFrame()
df['Frame'] = dfs['sheets']['Frame']
# Calculate fractions
total = sum(dfs[s][f'total_peptides_in_{s}'] for s in dfs.keys())
if total <= 0:
raise ValueError("Total number of peptides is zero or negative")
for structure in dfs.keys():
col = f'total_peptides_in_{structure}'
df[col] = dfs[structure][col]
df[f'{structure}_fraction'] = df[col] / total
# Apply smoothing
df[f'{structure}_smooth'] = savgol_filter(
df[f'{structure}_fraction'],
window_length=21, # Adjust window size as needed
polyorder=3
)
# Validate fractions
if not validate_fractions(df):
print("Warning: Data validation failed. Results may be unreliable.")
return df
except Exception as e:
print(f"Error loading data: {e}")
return None
def plot_evolution(df, timestamp):
"""Create interactive visualization of structure evolution"""
fig = go.Figure()
colors = {
'sheets': '#1f77b4',
'vesicles': '#2ca02c',
'tubes': '#ff7f0e',
'fibers': '#d62728'
}
for structure in colors.keys():
# Add smooth line
fig.add_trace(go.Scatter(
x=df['Frame'],
y=df[f'{structure}_smooth'],
name=f"{structure.capitalize()} (Smoothed)",
line=dict(color=colors[structure], width=2),
hovertemplate="Frame: %{x}<br>Fraction: %{y:.3f}<extra></extra>"
))
# Add raw data with lower opacity
fig.add_trace(go.Scatter(
x=df['Frame'],
y=df[f'{structure}_fraction'],
name=f"{structure.capitalize()} (Raw)",
line=dict(color=colors[structure], width=1, dash='dot'),
opacity=0.3,
hovertemplate="Frame: %{x}<br>Raw Fraction: %{y:.3f}<extra></extra>"
))
fig.update_layout(
title='Self-Assembly Evolution',
xaxis_title='Simulation Time (frames)',
yaxis_title='Population Fraction',
hovermode='x unified',
legend=dict(
yanchor="top",
y=0.99,
xanchor="left",
x=1.05
)
)
# Save as interactive HTML
fig.write_html(f'assembly_evolution_{timestamp}.html')
# Also save as static image for backup
fig.write_image(f'assembly_evolution_{timestamp}.png')
def main():
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
# Load and process data
df = load_and_process_data()
if df is None:
return
# Create visualization
plot_evolution(df, timestamp)
# Save processed data
df.to_csv(f'evolution_data_{timestamp}.csv', index=False)
print(f"Analysis complete. Files saved with timestamp: {timestamp}")
if __name__ == "__main__":
main()