#!/usr/bin/env python3
import pyqtgraph as pg
from pyqtgraph.Qt import QtWidgets, QtCore
import numpy as np
import sys, os

# -------------------- Fichiers de données --------------------
REF_FILE   = "constellation_ref.dat"
RX_FILE    = "constellation.dat"
ERROR_FILE = "pll_error.dat"

# -------------------- Fonctions de chargement --------------------
def load_points(filename):
    if os.path.exists(filename):
        return np.loadtxt(filename)
    else:
        return np.zeros((0,2))

def load_error(filename):
    if os.path.exists(filename):
        return np.loadtxt(filename)
    else:
        return np.zeros((0,2))

# -------------------- Application --------------------
app = QtWidgets.QApplication(sys.argv)
win = pg.GraphicsLayoutWidget(show=True, title="Constellation")
win.resize(900, 900)
win.setBackground('#0a0a0a')  # fond noir profond

plot = win.addPlot()
plot.setAspectLocked(True)  # axes égaux

# -------------------- Axes stylés --------------------
plot.getAxis('left').setPen(pg.mkPen('#AAA', width=2))
plot.getAxis('bottom').setPen(pg.mkPen('#AAA', width=2))
plot.getAxis('left').setTextPen(pg.mkPen('#EEE'))
plot.getAxis('bottom').setTextPen(pg.mkPen('#EEE'))
plot.setLabel('left', 'Quadrature (Q)', color='#EEE', size='12pt')
plot.setLabel('bottom', 'In-phase (I)', color='#EEE', size='12pt')

# -------------------- Grille subtile --------------------
grid = pg.GridItem()
grid.setPen(pg.mkPen('#444', width=1, style=QtCore.Qt.DotLine))
plot.addItem(grid)

# -------------------- Chargement initial --------------------
ref_data = load_points(REF_FILE)
rx_data  = load_points(RX_FILE)
error_data = load_error(ERROR_FILE)

# Points référence
ref_plot = plot.plot(ref_data[:,0], ref_data[:,1],
                     pen=None,
                     symbol='o',
                     symbolSize=10,
                     symbolBrush=pg.mkBrush('#1E90FF'),  # bleu vif
                     symbolPen=None,
                     name='Référence')

# Points reçus
rx_plot = plot.plot(rx_data[:,0], rx_data[:,1],
                    pen=None,
                    symbol='x',
                    symbolSize=6,
                    symbolBrush=pg.mkBrush('#FF4500'),  # orange vif
                    symbolPen=None,
                    name='Reçu')

# PLL error en vert
error_plot = plot.plot(error_data[:,0], error_data[:,1],
                       pen=pg.mkPen('#00FF00', width=2),
                       symbol=None,
                       name='PLL error')

# -------------------- Légende stylée --------------------
legend = plot.addLegend()
for item in legend.items:
    item[1].setPen(pg.mkPen('#FFF', width=2))

# -------------------- Timer pour mise à jour dynamique --------------------
def update():
    ref_data = load_points(REF_FILE)
    rx_data  = load_points(RX_FILE)
    error_data = load_error(ERROR_FILE)
    
    if ref_data.size > 0:
        ref_plot.setData(ref_data[:,0], ref_data[:,1])
    if rx_data.size > 0:
        rx_plot.setData(rx_data[:,0], rx_data[:,1])
    if error_data.size > 0:
        error_plot.setData(error_data[:,0], error_data[:,1])

timer = QtCore.QTimer()
timer.timeout.connect(update)
timer.start(500)  # ms

# -------------------- Anti-aliasing --------------------
pg.setConfigOptions(antialias=True)

# -------------------- Exécution --------------------
if __name__ == '__main__':
    sys.exit(app.exec_())

