Files
seisee/frontend_src/components/DataDocumentation.tsx

207 lines
11 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import React, { useState } from 'react';
interface Props {
onClose: () => void;
}
export default function DataDocumentation({ onClose }: Props) {
const [activeTab, setActiveTab] = useState<'overview' | 'channels' | 'pipeline' | 'conversion' | 'format'>('overview');
const tabs = [
{ id: 'overview' as const, label: 'Vue d\'ensemble', icon: '📋' },
{ id: 'channels' as const, label: 'Canaux', icon: '📊' },
{ id: 'pipeline' as const, label: 'Pipeline', icon: '🔄' },
{ id: 'conversion' as const, label: 'Conversion', icon: '⚙️' },
{ id: 'format' as const, label: 'Format H5', icon: '📦' }
];
return (
<div style={{ position: 'fixed', top: 0, left: 0, right: 0, bottom: 0, background: 'rgba(0,0,0,0.5)', zIndex: 10000, display: 'flex', justifyContent: 'center', alignItems: 'center', padding: '20px' }}>
<div style={{ background: 'white', borderRadius: '12px', maxWidth: '900px', width: '100%', maxHeight: '90vh', overflow: 'hidden', display: 'flex', flexDirection: 'column' }}>
{/* Header */}
<div style={{ padding: '20px', borderBottom: '2px solid #e2e8f0', display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
<h2 style={{ fontSize: '1.5rem', fontWeight: 'bold', color: '#1e293b', margin: 0 }}>
Documentation Technique
</h2>
<button onClick={onClose} style={{ background: '#ef4444', color: 'white', border: 'none', padding: '8px 16px', borderRadius: '6px', cursor: 'pointer', fontWeight: 'bold' }}>
Fermer
</button>
</div>
{/* Tabs */}
<div style={{ display: 'flex', borderBottom: '2px solid #e2e8f0', overflowX: 'auto' }}>
{tabs.map(tab => (
<button
key={tab.id}
onClick={() => setActiveTab(tab.id)}
style={{
padding: '12px 20px',
background: activeTab === tab.id ? '#3b82f6' : 'transparent',
color: activeTab === tab.id ? 'white' : '#64748b',
border: 'none',
borderBottom: activeTab === tab.id ? '3px solid #2563eb' : '3px solid transparent',
cursor: 'pointer',
fontWeight: activeTab === tab.id ? 'bold' : 'normal',
fontSize: '0.9rem',
whiteSpace: 'nowrap'
}}
>
{tab.icon} {tab.label}
</button>
))}
</div>
{/* Content */}
<div style={{ flex: 1, overflowY: 'auto', padding: '30px' }}>
{activeTab === 'overview' && (
<div>
<h3 style={{ fontSize: '1.3rem', fontWeight: 'bold', color: '#1e293b', marginBottom: '15px' }}>Campagne SeaKESP - Sète 2020</h3>
<p style={{ fontSize: '1rem', color: '#475569', marginBottom: '20px' }}>
Campagne d'acquisition sismique Ocean Bottom Node (OBN) réalisée en août-septembre 2020.
</p>
<h4 style={{ fontSize: '1.1rem', fontWeight: 'bold', color: '#334155', marginTop: '20px', marginBottom: '10px' }}>Données acquises</h4>
<ul style={{ color: '#475569', lineHeight: '1.8' }}>
<li><strong>345 fichiers RAW</strong> propriétaires (2.7 TB)</li>
<li><strong>Durée totale :</strong> ~800 heures d'enregistrements continus</li>
<li><strong>Plus long fichier :</strong> 60 heures (217k secondes)</li>
<li><strong>Fréquence d'échantillonnage :</strong> 500 Hz</li>
</ul>
<h4 style={{ fontSize: '1.1rem', fontWeight: 'bold', color: '#334155', marginTop: '20px', marginBottom: '10px' }}>État de conversion</h4>
<p style={{ color: '#475569' }}>
Conversion RAW → H5 en cours sur VM .81 (4 workers parallèles).
</p>
</div>
)}
{activeTab === 'channels' && (
<div>
<h3 style={{ fontSize: '1.3rem', fontWeight: 'bold', color: '#1e293b', marginBottom: '15px' }}>Canaux d'acquisition</h3>
<div style={{ marginBottom: '25px' }}>
<h4 style={{ fontSize: '1.1rem', fontWeight: 'bold', color: '#0369a1', marginBottom: '10px' }}>Géophones (Canaux 1-3)</h4>
<p style={{ color: '#475569', marginBottom: '10px' }}>Capteurs de vitesse particulaire 3 composantes (X, Y, Z)</p>
<ul style={{ color: '#475569', lineHeight: '1.8' }}>
<li><strong>Type :</strong> Géophones 15.6 V/(m/s)</li>
<li><strong>Unité finale :</strong> m/s (mètres par seconde)</li>
<li><strong>Sensibilité ADC :</strong> 3.576e-7 V/bit</li>
<li><strong>Calibration :</strong> m/s = (ADC × 3.576e-7) / 15.6</li>
</ul>
</div>
<div>
<h4 style={{ fontSize: '1.1rem', fontWeight: 'bold', color: '#7c2d12', marginBottom: '10px' }}>Hydrophone (Canal 4)</h4>
<p style={{ color: '#475569', marginBottom: '10px' }}>Capteur de pression acoustique</p>
<ul style={{ color: '#475569', lineHeight: '1.8' }}>
<li><strong>Type :</strong> Hydrophone 8.9 V/bar</li>
<li><strong>Unité finale :</strong> Pa (Pascals)</li>
<li><strong>Sensibilité ADC :</strong> 2.841e-6 V/bit</li>
<li><strong>Calibration :</strong> Pa = (ADC × 2.841e-6 / 8.9) × 100000</li>
<li><strong>Note :</strong> 1 bar = 100000 Pa</li>
</ul>
</div>
</div>
)}
{activeTab === 'pipeline' && (
<div>
<h3 style={{ fontSize: '1.3rem', fontWeight: 'bold', color: '#1e293b', marginBottom: '15px' }}>Pipeline de traitement</h3>
<div style={{ background: '#f8fafc', padding: '20px', borderRadius: '8px', marginBottom: '20px' }}>
<h4 style={{ fontSize: '1rem', fontWeight: 'bold', color: '#475569', marginBottom: '15px' }}>Étapes de conversion</h4>
<ol style={{ color: '#475569', lineHeight: '2', paddingLeft: '20px' }}>
<li><strong>Fichier source :</strong> RAW propriétaire (format binaire non documenté)</li>
<li><strong>Conversion initiale :</strong> RAW SEGY via MantaSegy</li>
<li><strong>Parsing SEGY :</strong> Extraction headers + données ADC brutes</li>
<li><strong>Calibration :</strong> Application formules ADC unités physiques</li>
<li><strong>Export H5 :</strong> Sauvegarde données brutes + calibrées</li>
<li><strong>Validation :</strong> Vérification précision (erreur &lt; 10¹¹)</li>
</ol>
</div>
<h4 style={{ fontSize: '1.1rem', fontWeight: 'bold', color: '#334155', marginTop: '20px', marginBottom: '10px' }}>Objectif du traitement</h4>
<p style={{ color: '#475569' }}>Convertir les fichiers RAW propriétaires en format HDF5 standardisé avec :</p>
<ul style={{ color: '#475569', lineHeight: '1.8' }}>
<li>Données ADC brutes (int32) pour archivage</li>
<li>Données calibrées en unités physiques (float32)</li>
<li>Métadonnées complètes (sample rate, durée, calibration)</li>
</ul>
</div>
)}
{activeTab === 'conversion' && (
<div>
<h3 style={{ fontSize: '1.3rem', fontWeight: 'bold', color: '#1e293b', marginBottom: '15px' }}>Détails de conversion</h3>
<h4 style={{ fontSize: '1.1rem', fontWeight: 'bold', color: '#334155', marginBottom: '10px' }}>Configuration actuelle</h4>
<ul style={{ color: '#475569', lineHeight: '1.8' }}>
<li><strong>Machine :</strong> VM .81 (osboxes@192.168.0.81)</li>
<li><strong>Workers :</strong> 4 processus parallèles</li>
<li><strong>Stockage source :</strong> NFS depuis Pi 52 (/mnt/seismic-data)</li>
<li><strong>Stockage destination :</strong> Local VM puis rsync vers Pi 27</li>
</ul>
<h4 style={{ fontSize: '1.1rem', fontWeight: 'bold', color: '#334155', marginTop: '20px', marginBottom: '10px' }}>Formules de calibration</h4>
<div style={{ background: '#f1f5f9', padding: '15px', borderRadius: '8px', fontFamily: 'monospace', fontSize: '0.9rem' }}>
<p style={{ color: '#0369a1', marginBottom: '10px' }}><strong>Géophones (canaux 1-3) :</strong></p>
<p style={{ color: '#475569' }}>m/s = (ADC_value × 3.576e-7 V/bit) / (15.6 V/(m/s))</p>
<p style={{ color: '#7c2d12', marginTop: '15px', marginBottom: '10px' }}><strong>Hydrophone (canal 4) :</strong></p>
<p style={{ color: '#475569' }}>Pa = (ADC_value × 2.841e-6 V/bit / 8.9 V/bar) × 100000 Pa/bar</p>
</div>
<h4 style={{ fontSize: '1.1rem', fontWeight: 'bold', color: '#334155', marginTop: '20px', marginBottom: '10px' }}>Validation qualité</h4>
<p style={{ color: '#475569' }}>
Précision de conversion vérifiée : erreur &lt; 10¹¹ entre calcul Python et valeurs attendues.
</p>
</div>
)}
{activeTab === 'format' && (
<div>
<h3 style={{ fontSize: '1.3rem', fontWeight: 'bold', color: '#1e293b', marginBottom: '15px' }}>Structure fichier H5</h3>
<div style={{ background: '#0f172a', padding: '20px', borderRadius: '8px', color: '#e2e8f0', fontFamily: 'monospace', fontSize: '0.85rem', marginBottom: '20px' }}>
<pre style={{ margin: 0 }}>{`/
├── metadata (group)
│ ├── @duration_sec: 20.0
│ ├── @sample_rate_hz: 500
│ ├── @n_channels: 4
│ └── @n_samples: 10000
├── calibration (group)
│ ├── @geophone_v_per_bit: 3.576e-7
│ ├── @geophone_v_per_ms: 15.6
│ ├── @hydrophone_v_per_bit: 2.841e-6
│ └── @hydrophone_v_per_bar: 8.9
├── raw_data (group)
│ ├── channel_1 (dataset int32)
│ ├── channel_2 (dataset int32)
│ ├── channel_3 (dataset int32)
│ └── channel_4 (dataset int32)
└── calibrated_data (group)
├── channel_1 (dataset float32, unit: m/s)
├── channel_2 (dataset float32, unit: m/s)
├── channel_3 (dataset float32, unit: m/s)
└── channel_4 (dataset float32, unit: Pa)`}</pre>
</div>
<h4 style={{ fontSize: '1.1rem', fontWeight: 'bold', color: '#334155', marginBottom: '10px' }}>Avantages du format H5</h4>
<ul style={{ color: '#475569', lineHeight: '1.8' }}>
<li><strong>Compression efficace :</strong> Réduction ~30% taille fichiers</li>
<li><strong>Accès rapide :</strong> Lecture sélective par canal/plage temporelle</li>
<li><strong>Métadonnées intégrées :</strong> Toutes les infos de calibration dans le fichier</li>
<li><strong>Interopérabilité :</strong> Compatible Python, MATLAB, Julia, C++</li>
<li><strong>Archivage :</strong> Données brutes + calibrées dans un seul fichier</li>
</ul>
</div>
)}
</div>
</div>
</div>
);
}