a b/src/pages/Simulations/Simulations.tsx
1
import React, { useState, useCallback } from 'react';
2
import {
3
  Box,
4
  Typography,
5
  Paper,
6
  Grid,
7
  Card,
8
  CardContent,
9
  LinearProgress,
10
  Button,
11
  Stack,
12
  CircularProgress,
13
  Alert,
14
} from '@mui/material';
15
import {
16
  LineChart,
17
  Line,
18
  XAxis,
19
  YAxis,
20
  CartesianGrid,
21
  Tooltip,
22
  Legend,
23
  ResponsiveContainer,
24
  RadarChart,
25
  PolarGrid,
26
  PolarAngleAxis,
27
  PolarRadiusAxis,
28
  Radar,
29
} from 'recharts';
30
import { usePipeline, useSimulationResults } from '../../hooks/usePipeline';
31
import { mockGeneAssemblies, getRandomColor } from '../../data/mockData';
32
33
const Simulations: React.FC = () => {
34
  const [isSimulating, setIsSimulating] = useState(false);
35
  const [progress, setProgress] = useState(0);
36
  const { startPipeline, isProcessing, error, clearError } = usePipeline();
37
  const simulationResults = useSimulationResults();
38
39
  const startSimulation = useCallback(async () => {
40
    setIsSimulating(true);
41
    setProgress(0);
42
43
    const mockConfig = {
44
      id: Math.random().toString(36).substr(2, 9),
45
      name: 'Quantum Simulation',
46
      environmentalParams: {
47
        temperature: 25,
48
        humidity: 60,
49
        soilConditions: 'Controlled',
50
      },
51
      duration: 96,
52
      samplingFrequency: 24,
53
      baselineGenotypes: ['WT-Col-0'],
54
      targetTraits: ['stress_tolerance', 'growth_rate'],
55
    };
56
57
    // Use first gene assembly for simulation
58
    await startPipeline({
59
      experimentConfig: mockConfig,
60
      assembly: mockGeneAssemblies[0],
61
    });
62
63
    const interval = setInterval(() => {
64
      setProgress((prev) => {
65
        if (prev >= 100) {
66
          clearInterval(interval);
67
          setIsSimulating(false);
68
          return 100;
69
        }
70
        return prev + 10;
71
      });
72
    }, 500);
73
  }, [startPipeline]);
74
75
  const renderQuantumMetrics = (result: any) => {
76
    const data = [
77
      { name: 'Coherence', value: result.quantumMetrics.coherenceTime },
78
      { name: 'Gate Error', value: result.quantumMetrics.gateErrors * 100 },
79
      { name: 'Volume', value: result.quantumMetrics.quantumVolume / 10 },
80
      { name: 'Circuit', value: result.quantumMetrics.circuitDepth / 2 },
81
    ];
82
83
    return (
84
      <Box sx={{ height: 300, width: '100%' }}>
85
        <Typography variant="subtitle2" gutterBottom>
86
          Quantum Computing Metrics
87
        </Typography>
88
        <ResponsiveContainer>
89
          <RadarChart data={data}>
90
            <PolarGrid />
91
            <PolarAngleAxis dataKey="name" />
92
            <PolarRadiusAxis />
93
            <Radar
94
              name="Quantum Metrics"
95
              dataKey="value"
96
              stroke="#8884d8"
97
              fill="#8884d8"
98
              fillOpacity={0.6}
99
            />
100
          </RadarChart>
101
        </ResponsiveContainer>
102
      </Box>
103
    );
104
  };
105
106
  const renderOptimizationResults = (result: any) => {
107
    const data = result.optimizationMetrics.energyLandscape.map((value: number, index: number) => ({
108
      step: index,
109
      energy: value,
110
    }));
111
112
    return (
113
      <Box sx={{ height: 300, width: '100%' }}>
114
        <Typography variant="subtitle2" gutterBottom>
115
          Energy Landscape Optimization
116
        </Typography>
117
        <ResponsiveContainer>
118
          <LineChart data={data}>
119
            <CartesianGrid strokeDasharray="3 3" />
120
            <XAxis dataKey="step" />
121
            <YAxis />
122
            <Tooltip />
123
            <Legend />
124
            <Line
125
              type="monotone"
126
              dataKey="energy"
127
              stroke="#82ca9d"
128
              name="Energy Level"
129
            />
130
          </LineChart>
131
        </ResponsiveContainer>
132
      </Box>
133
    );
134
  };
135
136
  const renderPredictions = (result: any) => {
137
    return (
138
      <Box sx={{ height: 300, width: '100%' }}>
139
        <Typography variant="subtitle2" gutterBottom>
140
          Trait Predictions Over Time
141
        </Typography>
142
        <ResponsiveContainer>
143
          <LineChart data={result.results}>
144
            <CartesianGrid strokeDasharray="3 3" />
145
            <XAxis dataKey="timepoint" />
146
            <YAxis />
147
            <Tooltip />
148
            <Legend />
149
            {result.results[0].predictions.map((pred: any) => (
150
              <Line
151
                key={pred.trait}
152
                type="monotone"
153
                data={result.results.map((r: any) => ({
154
                  timepoint: r.timepoint,
155
                  value: r.predictions.find((p: any) => p.trait === pred.trait).value,
156
                }))}
157
                dataKey="value"
158
                name={pred.trait}
159
                stroke={getRandomColor()}
160
              />
161
            ))}
162
          </LineChart>
163
        </ResponsiveContainer>
164
      </Box>
165
    );
166
  };
167
168
  return (
169
    <Box>
170
      <Typography variant="h4" gutterBottom>
171
        Quantum-Enhanced Simulations
172
      </Typography>
173
174
      {error && (
175
        <Alert severity="error" onClose={clearError} sx={{ mb: 2 }}>
176
          {error}
177
        </Alert>
178
      )}
179
180
      <Grid container spacing={3}>
181
        <Grid item xs={12} md={4}>
182
          <Paper sx={{ p: 2 }}>
183
            <Typography variant="h6" gutterBottom>
184
              New Simulation
185
            </Typography>
186
            <Button
187
              variant="contained"
188
              fullWidth
189
              onClick={startSimulation}
190
              disabled={isSimulating || isProcessing}
191
              sx={{ mb: 2 }}
192
            >
193
              {isSimulating || isProcessing ? (
194
                <CircularProgress size={24} />
195
              ) : (
196
                'Start Simulation'
197
              )}
198
            </Button>
199
            {(isSimulating || isProcessing) && (
200
              <Box sx={{ width: '100%' }}>
201
                <LinearProgress variant="determinate" value={progress} />
202
                <Typography variant="body2" color="text.secondary" align="center" sx={{ mt: 1 }}>
203
                  {progress}% Complete
204
                </Typography>
205
              </Box>
206
            )}
207
          </Paper>
208
        </Grid>
209
210
        <Grid item xs={12} md={8}>
211
          <Stack spacing={2}>
212
            {simulationResults.map((result) => (
213
              <Card key={result.id}>
214
                <CardContent>
215
                  <Grid container spacing={3}>
216
                    <Grid item xs={12}>
217
                      <Typography variant="h6" gutterBottom>
218
                        Simulation Results
219
                      </Typography>
220
                      <Typography variant="body2" color="text.secondary">
221
                        {new Date(result.timestamp).toLocaleString()}
222
                      </Typography>
223
                    </Grid>
224
                    <Grid item xs={12}>
225
                      {renderQuantumMetrics(result)}
226
                    </Grid>
227
                    <Grid item xs={12} md={6}>
228
                      {renderOptimizationResults(result)}
229
                    </Grid>
230
                    <Grid item xs={12} md={6}>
231
                      {renderPredictions(result)}
232
                    </Grid>
233
                  </Grid>
234
                </CardContent>
235
              </Card>
236
            ))}
237
          </Stack>
238
        </Grid>
239
      </Grid>
240
    </Box>
241
  );
242
};
243
244
export default Simulations;