TEM Viewer
Log-log plot with measured vs modeled data, station switching, and scale options.
TEM Decay Curves
Source Code
#include <QApplication>
#include <QWidget>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QComboBox>
#include <QLabel>
#include <QPushButton>
#include <cmath>
#include <cstdlib>
#include "AZPlottingClass.h"
void loadTEMData(AZPlottingClass *plot, int stationIndex)
{
QVector<double> time, measured, model;
double baseAmplitude = 1000 + stationIndex * 200;
double tau = 0.02 + stationIndex * 0.005;
for (double t = 0.01; t <= 100; t *= 1.08) {
time.append(t);
// Measured with noise
double r = baseAmplitude * std::exp(-t / 1000.0 / tau);
r *= (1 + 0.05 * (std::rand() % 100 - 50) / 50.0);
measured.append(r);
// Clean model
model.append(baseAmplitude * std::exp(-t / 1000.0 / tau));
}
plot->clearData();
plot->clearMarkerLines();
// Measured data with markers
plot->addLineMarkerSeries(time, measured, "Measured", Qt::blue,
AZPlottingClass::LineStyle::None,
AZPlottingClass::MarkerStyle::Circle,
1.5, 5.0);
// Model line (dashed)
plot->addDataSeries(time, model, "Model", Qt::red,
AZPlottingClass::LineStyle::Dashed, 1.5);
// Noise floor reference
plot->addHorizontalLine(1.0, Qt::gray, "Noise Floor", 0.5);
plot->setTitle(QString("TEM Decay - Station %1").arg((stationIndex + 1) * 100));
plot->autoScaleAll();
}
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QWidget window;
window.setWindowTitle("TEM Decay Viewer");
window.resize(800, 550);
QVBoxLayout *mainLayout = new QVBoxLayout(&window);
mainLayout->setContentsMargins(10, 10, 10, 10);
// Control bar
QHBoxLayout *controlLayout = new QHBoxLayout();
QLabel *label = new QLabel("Station:");
QComboBox *stationCombo = new QComboBox();
stationCombo->addItems({"Station 100", "Station 200", "Station 300", "Station 400"});
QLabel *scaleLabel = new QLabel("Y Scale:");
QComboBox *scaleCombo = new QComboBox();
scaleCombo->addItems({"Logarithmic", "Linear", "SymLog"});
QPushButton *resetBtn = new QPushButton("Reset View");
controlLayout->addWidget(label);
controlLayout->addWidget(stationCombo);
controlLayout->addSpacing(20);
controlLayout->addWidget(scaleLabel);
controlLayout->addWidget(scaleCombo);
controlLayout->addStretch();
controlLayout->addWidget(resetBtn);
mainLayout->addLayout(controlLayout);
// Plot
AZPlottingClass *plot = new AZPlottingClass(&window);
plot->setXAxisScale(AZPlottingClass::ScaleType::Logarithmic);
plot->setYAxisScale(AZPlottingClass::ScaleType::Logarithmic);
plot->setXAxisLabel("Time (ms)");
plot->setYAxisLabel("dB/dt (nV/m²)");
plot->applyProfessionalStyle();
plot->setInteractive(true, true);
plot->setCrosshairEnabled(true);
plot->setStatsVisible(true);
plot->setStatsPosition(Qt::AlignBottom | Qt::AlignLeft);
mainLayout->addWidget(plot, 1);
loadTEMData(plot, 0);
// Connect station selector
QObject::connect(stationCombo, QOverload<int>::of(&QComboBox::currentIndexChanged),
[plot](int idx) { loadTEMData(plot, idx); });
// Connect scale selector
QObject::connect(scaleCombo, QOverload<int>::of(&QComboBox::currentIndexChanged),
[plot](int idx) {
switch (idx) {
case 0: plot->setYAxisScale(AZPlottingClass::ScaleType::Logarithmic); break;
case 1: plot->setYAxisScale(AZPlottingClass::ScaleType::Linear); break;
case 2: plot->setYAxisScale(AZPlottingClass::ScaleType::SymLog); break;
}
plot->autoScaleAll();
});
QObject::connect(resetBtn, &QPushButton::clicked, [plot]() { plot->resetZoom(); });
window.show();
return app.exec();
}