import React, { useEffect, useRef, useState } from 'react';
import { motion, AnimatePresence } from 'framer-motion';
import { BarChart3, Activity, Zap, Info, Maximize2 } from 'lucide-react';
import PropTypes from 'prop-types';
import FullscreenCircuitViewer from './FullscreenCircuitViewer';
const QuantumVisualization = ({ result, type = 'auto' }) => {
const [activeVisualization, setActiveVisualization] = useState('circuit');
const [showFullscreen, setShowFullscreen] = useState(false);
// Bloch Sphere Visualization
const BlochSphere = ({ stateVector }) => {
const canvasRef = useRef(null);
useEffect(() => {
if (!canvasRef.current || !stateVector) return;
const canvas = canvasRef.current;
const ctx = canvas.getContext('2d');
const centerX = canvas.width / 2;
const centerY = canvas.height / 2;
const radius = Math.min(centerX, centerY) - 20;
// Clear canvas
ctx.clearRect(0, 0, canvas.width, canvas.height);
// Draw sphere outline
ctx.beginPath();
ctx.arc(centerX, centerY, radius, 0, 2 * Math.PI);
ctx.strokeStyle = '#e5e7eb';
ctx.lineWidth = 2;
ctx.stroke();
// Draw axes
ctx.strokeStyle = '#9ca3af';
ctx.lineWidth = 1;
// X axis
ctx.beginPath();
ctx.moveTo(centerX - radius, centerY);
ctx.lineTo(centerX + radius, centerY);
ctx.stroke();
// Y axis (vertical)
ctx.beginPath();
ctx.moveTo(centerX, centerY - radius);
ctx.lineTo(centerX, centerY + radius);
ctx.stroke();
// Calculate state vector position on Bloch sphere
if (stateVector && stateVector.length >= 2) {
const alpha = stateVector[0];
const beta = stateVector[1];
// Convert to Bloch sphere coordinates
const theta = 2 * Math.acos(Math.abs(alpha));
const phi = Math.arg ? Math.arg(beta / alpha) : 0;
const x = radius * Math.sin(theta) * Math.cos(phi);
const z = radius * Math.cos(theta);
// Project to 2D (simple projection)
const projX = centerX + x;
const projY = centerY - z; // Flip Y for canvas coordinates
// Draw state vector
ctx.beginPath();
ctx.moveTo(centerX, centerY);
ctx.lineTo(projX, projY);
ctx.strokeStyle = '#6366f1';
ctx.lineWidth = 3;
ctx.stroke();
// Draw state point
ctx.beginPath();
ctx.arc(projX, projY, 6, 0, 2 * Math.PI);
ctx.fillStyle = '#6366f1';
ctx.fill();
}
// Add labels
ctx.fillStyle = '#374151';
ctx.font = '12px Inter';
ctx.textAlign = 'center';
ctx.fillText('|0⟩', centerX, centerY - radius - 10);
ctx.fillText('|1⟩', centerX, centerY + radius + 20);
ctx.textAlign = 'left';
ctx.fillText('|+⟩', centerX + radius + 10, centerY + 5);
ctx.textAlign = 'right';
ctx.fillText('|-⟩', centerX - radius - 10, centerY + 5);
}, [stateVector]);
return (
);
};
// Probability Bar Chart
const ProbabilityChart = ({ probabilities }) => {
if (!probabilities || typeof probabilities !== 'object') return null;
const entries = Object.entries(probabilities);
const maxProb = Math.max(...entries.map(([, prob]) => prob));
return (
{entries.map(([state, probability]) => (
|{state}⟩
{(probability * 100).toFixed(1)}%
))}
);
};
// Circuit SVG Display
const CircuitDisplay = ({ circuitSvg }) => {
const [zoom, setZoom] = useState(1);
const [isDragging, setIsDragging] = useState(false);
const [dragStart, setDragStart] = useState({ x: 0, y: 0 });
const [scrollPos, setScrollPos] = useState({ x: 0, y: 0 });
const containerRef = useRef(null);
if (!circuitSvg) return null;
const handleZoomIn = () => setZoom(prev => Math.min(prev + 0.2, 3));
const handleZoomOut = () => setZoom(prev => Math.max(prev - 0.2, 0.5));
const handleResetZoom = () => setZoom(1);
const handleMouseDown = (e) => {
setIsDragging(true);
setDragStart({ x: e.clientX, y: e.clientY });
};
const handleMouseMove = (e) => {
if (!isDragging || !containerRef.current) return;
const deltaX = e.clientX - dragStart.x;
const deltaY = e.clientY - dragStart.y;
containerRef.current.scrollLeft = scrollPos.x - deltaX;
containerRef.current.scrollTop = scrollPos.y - deltaY;
};
const handleMouseUp = () => {
if (containerRef.current) {
setScrollPos({
x: containerRef.current.scrollLeft,
y: containerRef.current.scrollTop
});
}
setIsDragging(false);
};
return (
Quantum Circuit Diagram
Scroll or drag to navigate • Use zoom controls for better viewing
{/* Controls */}
{/* Zoom Controls */}
{Math.round(zoom * 100)}%
{/* Fullscreen Button */}
{
const touch = e.touches[0];
handleMouseDown({ clientX: touch.clientX, clientY: touch.clientY });
}}
onTouchMove={(e) => {
const touch = e.touches[0];
handleMouseMove({ clientX: touch.clientX, clientY: touch.clientY });
}}
onTouchEnd={handleMouseUp}
>
{/* Navigation hints */}
Drag to pan • Scroll to navigate
Drag or swipe to navigate
Use zoom controls for detail
);
};
const visualizations = [
{
id: 'circuit',
label: 'Circuit',
icon: ,
component: ,
available: !!result?.output?.circuit_svg,
},
{
id: 'probabilities',
label: 'Probabilities',
icon: ,
component: ,
available: !!result?.output?.probabilities,
},
{
id: 'bloch',
label: 'Bloch Sphere',
icon: ,
component: ,
available: !!result?.output?.state_vector,
},
];
const availableVisualizations = visualizations.filter(viz => viz.available);
if (!result || availableVisualizations.length === 0) {
return (
No visualization data available
Run a simulation to see results
);
}
return (
{availableVisualizations.length > 1 && (
{availableVisualizations.map((viz) => (
))}
)}
{availableVisualizations.map((viz) => (
viz.id === activeVisualization && (
{viz.component}
)
))}
{/* Fullscreen Circuit Viewer */}
setShowFullscreen(false)}
/>
);
};
QuantumVisualization.propTypes = {
result: PropTypes.object,
type: PropTypes.string,
};
export default QuantumVisualization;