Files
seisee/simple_api.py

202 lines
6.5 KiB
Python

#!/usr/bin/env python3
from flask import Flask, jsonify, request
from flask_cors import CORS
import json
import h5py
import numpy as np
from pathlib import Path
from datetime import datetime
app = Flask(__name__)
CORS(app)
# Load index once at startup
with open('/data/index.json', 'r') as f:
INDEX = json.load(f)
H5_DIR = Path('/data/h5')
@app.route('/api/nodes', methods=['GET'])
def get_nodes():
nodes_list = []
for node_id, node_info in INDEX['nodes'].items():
file_count = len(node_info.get('files', []))
nodes_list.append({
'id': node_id,
'position': node_info.get('position', {}),
'file_count': file_count,
'hasDates': file_count > 0
})
return jsonify({
'nodes': nodes_list,
'sampleRateHz': 500
})
@app.route('/api/dates', methods=['GET'])
def get_dates():
return jsonify({'dates': INDEX['dates']})
@app.route('/api/migration-status', methods=['GET'])
def get_migration_status():
"""Status de la conversion RAW -> H5"""
total_files = 345 # Connu du projet
h5_files = list(H5_DIR.glob('*.h5'))
converted = len(h5_files)
return jsonify({
'summary': {
'total_files': total_files,
'converted_files': converted,
'percentage': round(converted / total_files * 100, 1),
'status': 'in_progress' if converted < total_files else 'complete'
},
'h5_files_available': converted
})
@app.route('/api/rms-timeline', methods=['GET'])
def get_rms_timeline():
"""Timeline RMS pour un channel et une date donnés"""
date = request.args.get('date')
channel = request.args.get('channel', 'ch0')
if not date:
return jsonify({'error': 'date parameter required'}), 400
# Chercher les fichiers H5 pour cette date
timeline = []
for node_id, node_info in INDEX['nodes'].items():
for file_info in node_info.get('files', []):
if file_info.get('date') == date:
# Pour l'instant, retourner des données mock
# TODO: Calculer le vrai RMS depuis les fichiers H5
timeline.append({
'node_id': node_id,
'timestamp': 0,
'rms': 0 # À calculer depuis H5
})
return jsonify({
'date': date,
'channel': channel,
'timeline': timeline
})
@app.route('/api/data', methods=['GET'])
def get_waveform_data():
"""Données waveform pour un node, date, channel, timestamp"""
node_id = request.args.get('node')
date = request.args.get('date')
channel = request.args.get('channel', 'ch0')
start = float(request.args.get('start', 0))
duration = float(request.args.get('duration', 10))
if not node_id or not date:
return jsonify({'error': 'node and date required'}), 400
# Chercher le fichier H5 correspondant
node_info = INDEX['nodes'].get(node_id)
if not node_info:
return jsonify({'error': 'node not found'}), 404
h5_file = None
for file_info in node_info.get('files', []):
if file_info.get('date') == date:
h5_file = H5_DIR / file_info.get('filename', '')
break
if not h5_file or not h5_file.exists():
return jsonify({'error': 'H5 file not found'}), 404
try:
with h5py.File(h5_file, 'r') as f:
sample_rate = f['metadata'].attrs['sample_rate_hz']
channel_num = int(channel.replace('ch', '').replace('CH', ''))
# Lire les données calibrées
dataset = f[f'calibrated_data/channel_{channel_num + 1}']
start_sample = int(start * sample_rate)
end_sample = int((start + duration) * sample_rate)
# Limiter à la taille du dataset
end_sample = min(end_sample, dataset.shape[0])
if start_sample >= dataset.shape[0]:
return jsonify({'error': 'start time out of range'}), 400
data = dataset[start_sample:end_sample]
# Calculer stats
rms = float(np.sqrt(np.mean(data ** 2)))
peak = float(np.max(np.abs(data)))
return jsonify({
'node_id': node_id,
'date': date,
'channel': channel,
'start': start,
'duration': duration,
'sample_rate': int(sample_rate),
'data': data.tolist(),
'stats': {
'rms': rms,
'peak': peak,
'samples': len(data)
}
})
except Exception as e:
return jsonify({'error': str(e)}), 500
@app.route('/api/h5/files', methods=['GET'])
def get_h5_files():
"""Liste des fichiers H5 disponibles avec métadonnées"""
files = []
for h5_path in H5_DIR.glob('*.h5'):
try:
with h5py.File(h5_path, 'r') as f:
files.append({
'filename': h5_path.name,
'size_mb': round(h5_path.stat().st_size / 1024 / 1024, 2),
'duration_sec': int(f['metadata'].attrs.get('duration_sec', 0)),
'sample_rate': int(f['metadata'].attrs.get('sample_rate_hz', 500)),
'channels': int(f['metadata'].attrs.get('n_channels', 4))
})
except:
pass
return jsonify({'files': files, 'count': len(files)})
@app.route('/api/h5/coverage', methods=['GET'])
def get_h5_coverage():
"""Matrice de couverture nodes x dates"""
coverage = {}
for node_id, node_info in INDEX['nodes'].items():
node_dates = [f['date'] for f in node_info.get('files', []) if 'date' in f]
coverage[node_id] = node_dates
return jsonify({
'coverage': coverage,
'total_nodes': len(coverage),
'total_dates': len(INDEX['dates'])
})
@app.route('/api/chat', methods=['POST'])
def chat():
"""Endpoint chat assistant (mock)"""
data = request.json
message = data.get('message', '')
return jsonify({
'response': f"[Mock] Vous avez dit: {message}",
'timestamp': datetime.now().isoformat()
})
@app.route('/health', methods=['GET'])
def health():
return jsonify({'status': 'ok', 'nodes': len(INDEX['nodes']), 'dates': len(INDEX['dates'])})
if __name__ == '__main__':
print(f"Loaded {len(INDEX['nodes'])} nodes, {len(INDEX['dates'])} dates")
print(f"H5 directory: {H5_DIR}")
app.run(host='0.0.0.0', port=3004)