working RMS readout

This commit is contained in:
Blake Leverington 2024-02-01 18:45:41 +01:00
parent 8187bf4a40
commit 87e271be1f
63 changed files with 5369 additions and 621 deletions

View File

@ -0,0 +1,320 @@
915
917
947
971
981
964
977
980
965
969
965
975
961
967
979
959
978
978
982
976
964
962
971
976
948
957
977
970
950
981
978
962
983
960
980
958
980
978
973
949
963
969
970
982
982
978
971
974
979
976
976
980
982
968
972
961
973
976
982
983
948
981
952
969
992
990
1028
1032
1030
1033
1034
1023
1036
1024
1032
1030
1032
1026
1026
1026
1033
1033
1025
1039
1035
1041
1034
1055
1027
1036
1024
1021
1037
1028
1021
1033
1030
1047
1035
1037
1011
1049
1044
1028
1042
1032
1065
1035
1033
1033
1026
1037
1046
1039
1047
1035
1037
1023
1019
1046
1030
1031
1017
1038
1035
1036
1039
1008
990
992
1011
1050
1048
1043
1033
1051
1024
1040
1013
1015
1024
1054
1034
1046
1029
1041
1057
1053
1035
1045
1046
1047
1051
1064
1024
1037
1030
1040
1049
1049
1050
1023
1043
1053
1051
1045
1048
1056
1038
1020
1057
1033
1041
1029
1015
1043
1030
1033
1039
1047
1049
1075
1051
1040
1046
1051
1049
1038
1019
1044
1016
1040
947
960
958
1018
981
1005
984
982
998
983
993
981
981
985
986
1011
1002
982
986
988
992
988
1001
1002
998
996
993
1002
996
1001
992
996
993
979
978
974
1004
1013
1013
1005
988
982
1002
1010
988
1008
1011
1015
997
989
984
985
1020
1008
980
993
993
1012
1002
1001
1021
1001
1002
977
957
936
994
988
996
984
976
1005
1003
999
988
991
979
988
998
1002
1003
1001
1011
1011
989
998
1017
989
999
985
996
1013
996
999
993
991
1005
1004
1007
1001
1002
1013
987
983
997
1008
1011
1005
1011
983
978
999
1011
1013
999
1021
993
1007
1035
980
1012
1014
999
1007
1014
983
1014
972

View File

@ -0,0 +1,320 @@
889
855
854
864
880
904
876
867
877
888
885
903
873
899
905
889
864
905
886
867
889
903
888
867
892
902
889
886
891
906
917
874
902
914
915
923
887
888
879
902
906
901
876
881
886
899
888
926
904
901
894
897
898
900
892
882
888
895
893
886
864
887
897
868
863
880
883
898
867
878
888
879
882
903
899
893
886
879
873
889
900
891
877
883
895
892
897
889
885
887
880
881
898
884
901
881
914
900
900
886
894
902
891
889
883
884
899
902
873
885
878
886
882
898
895
900
897
898
902
898
895
901
881
891
889
887
903
890
836
827
847
854
865
853
866
860
870
874
860
876
845
856
853
847
846
858
852
855
853
858
867
869
855
848
850
862
867
873
864
862
865
844
851
867
841
874
890
868
867
855
895
888
868
870
871
867
885
862
881
882
860
869
865
863
889
870
854
863
883
892
868
837
922
931
949
950
957
957
953
935
942
950
950
961
962
956
956
954
951
982
955
974
962
962
957
954
963
964
973
962
963
969
950
955
958
957
947
964
968
953
948
959
958
963
969
969
966
971
961
972
970
972
966
968
971
956
957
949
944
929
935
973
964
942
959
947
929
921
922
953
921
948
943
947
968
957
950
941
929
937
940
936
941
960
956
952
932
928
921
944
951
946
935
941
943
962
952
946
940
931
935
952
942
931
946
928
943
944
949
958
941
956
925
937
942
957
950
946
944
964
939
933
969
945
953
951
956
942
948
948

View File

@ -0,0 +1,320 @@
292
2236
3354
3105
7221
9400
12401
13631
13691
13931
13820
14226
14262
14193
13841
12164
13073
14288
14708
14846
14607
14566
16327
16197
14976
13606
15111
15600
15104
15385
15585
15691
14442
15071
15404
14670
15226
15735
15885
15240
15421
15632
16418
16190
16396
16544
15611
16341
16292
15607
16837
16770
17584
17644
17259
16397
16245
16194
15645
15465
15829
16301
16352
15458
15709
16213
16426
14934
15597
15333
16580
15002
14353
13799
13907
14830
14998
14885
14920
14767
14467
13557
14248
14618
14087
14110
15946
16737
16667
16772
16794
16640
16436
16972
17241
16229
15695
14983
15890
16107
16291
16408
16613
14740
15041
17430
16539
15153
15607
15691
15877
16761
16481
15689
14962
15481
16829
17368
16976
16109
16325
17517
17986
17005
17225
17085
17721
17587
17660
17752
17974
18675
18316
17720
17612
17516
17415
17155
16846
14949
15134
16036
15515
14420
15595
15455
15903
15503
15831
15713
16079
15529
14932
15400
14932
14402
14036
13638
13295
11983
10865
12046
11275
10381
9449
8657
7414
8355
9042
7945
7151
7311
7157
7315
7118
7585
8448
10341
11301
10958
11201
10929
9803
8871
8421
8223
8315
7874
8251
7806
6670
6201
7470
7852
8363
8779
9532
11717
13115
11629
11103
10523
10391
10007
9355
7557
8805
8827
8506
8555
9192
9727
9243
8690
8686
8946
12062
15079
15874
15861
15842
16140
16235
16183
15863
16392
16435
15995
15766
16034
15759
15705
15344
15735
15857
15828
15255
14959
15338
15305
15537
15569
15663
15587
15485
14371
13474
13601
14865
15566
15473
14871
14575
14644
14473
14564
13554
13925
14119
13024
13263
13568
14021
13893
13724
13961
14120
14174
14798
14344
13661
13864
13873
13606
13835
13521
13510
13778
13621
13414
13537
13965
13682
13210
13867
14077
13843
13429
13986
13597
13745
14710
14062
13379
14384
13555
12435
12032
11849
12379
12928
13152
13373
13553
13792
13937
13379
13194
13383
13745
14034
14075
13900
13894
13561
13498
13373
12896
12759
13234

View File

@ -0,0 +1,320 @@
59
55
47
143
1221
4897
7637
11168
11616
11369
12995
14242
14300
15020
15670
15970
14825
15092
14423
14866
14131
14001
14161
14692
14121
14361
14495
14560
14560
14874
15295
15315
15335
15286
15077
13436
14987
14864
15092
15088
15300
15640
14271
15287
14538
14542
14180
14552
14665
13472
14836
14487
14001
14458
14442
14343
14528
14850
14372
15499
15323
15927
15899
16312
13760
13304
14078
13889
13917
13645
13786
14058
14011
13613
13661
13601
13703
13696
13843
13412
13311
13138
13396
13666
13831
13608
13748
13496
13764
13425
13614
13681
13285
13598
12987
13401
13088
12708
12927
13305
13256
13804
13891
13589
13084
12591
12189
12709
12716
12901
12823
13200
12987
13111
12949
12452
12073
12455
12980
13014
12724
12018
12189
12898
12054
12934
12521
12539
11278
11403
11340
11581
12107
11512
10728
11544
11225
11326
11323
11108
10458
10325
9554
10385
9803
7493
7532
10147
10140
10072
8807
8059
10109
10568
10439
11157
11312
11461
11417
11340
11348
11533
11505
11331
11152
11347
11915
11433
9679
10555
10725
11267
11366
11493
11161
11189
10803
10730
10840
10392
10619
10472
10304
10912
10703
10166
9948
8960
10034
9990
10197
10416
8959
8766
9190
9298
9236
8596
9092
9482
9790
9835
10088
9971
10062
10324
10341
9748
10072
10245
9441
9085
9683
9372
9169
9679
9806
8914
9044
8748
8290
8307
7325
7790
8837
9100
8261
8705
9385
9137
9316
9145
8356
8819
8496
8663
8133
7898
8784
9043
8561
8698
7944
7502
6689
7456
8129
8513
7800
8585
8504
8531
8308
8743
9198
9331
9113
8516
8569
8816
8617
9481
8963
8757
9096
9167
8956
8145
8567
8684
8800
9469
9210
9628
9948
9339
9643
9619
9925
9934
10249
10236
10815
10931
11116
10594
10234
10688
10141
10435
10545
10446
10467
10294
10355
10757
10567
10697
10606
10658
10497
10770
10869
11193
11234
11400
11468
11357
10930
10093
10511
10475
11062
10557
10463
10689
10545
10386
10344
10567

View File

@ -25,8 +25,8 @@ SlaveDelay=1
[Trigger]
Period=8999
Tint=8491
Gain=1
Period_v2=2500
Gain=0
Period_v2=2499
Tint_v2=336
Gain_v2=1

View File

@ -0,0 +1,31 @@
[Global]
NrDevices=2
HostIp=10.0.7.1
[Device0]
IP=10.0.7.17
HardwareVer=2
Plane=0
Position=0
Sensors=5
Master=1
MasterDelay=62
SlaveDelay=34
[Device1]
IP=10.0.7.18
HardwareVer=2
Plane=1
Position=0
Sensors=5
Master=0
MasterDelay=7
SlaveDelay=1
[Trigger]
Period=9000
Tint=1000
Gain=1
Period_v2=2500
Tint_v2=336
Gain_v2=1

View File

@ -0,0 +1,230 @@
#include "dialogtiscan.h"
#include "ui_dialogtiscan.h"
#define RUNNING 1
#define STOPPED 0
#define STOP_ISSUED -1
DialogTiScan::DialogTiScan(QWidget *parent) :
QDialog(parent),
ui(new Ui::DialogTiScan)
{
ui->setupUi(this);
runState = STOPPED;
}
DialogTiScan::~DialogTiScan()
{
delete ui;
}
void DialogTiScan::showEvent(QShowEvent * event)
{
if (!event->spontaneous())
{
if (!theKeithley->isOpen)
ui->checkUseLED->setEnabled(false);
}
QDialog::showEvent(event);
}
//************** Processing ***************
void DialogTiScan::run()
{
runState = RUNNING;
qInfo("Starting integration time scan...");
//Prepare measurement
ui->plotResultsMean->clearGraphs();
ui->plotResultsStd->clearGraphs();
results.clear();
int nr_devices = theHW->devices.length();
int use_led = ui->checkUseLED->isChecked();
double ledv = ui->doubleSpinLEDV->value();
int decimation = ui->spinPLotDecimation->value();
int nacqs = ui->spinAcquisitions->value();
int tstart = ui->spintStart->value();
int tend = ui->spinTEnd->value();
int tinc = ui->spinTIncrement->value();
int tcurrent = tstart;
//Plot data
QVector<double> xdata;
QList<QVector<double>> ymeandata;
QList<QVector<double>> ystddata;
for (int ch = 0; ch < (nr_devices*128); ch+= decimation)
{
ymeandata.append(xdata); //just add empty vectors to the list
ystddata.append(xdata); //just add empty vectors to the list
}
//The number of plotted lines is smaller than number of channels - see decimation
for (int plotnr = 0; plotnr < nr_devices*128; plotnr++)
{
ui->plotResultsMean->addGraph();
ui->plotResultsStd->addGraph();
}
double xmin = 1e+10;
double xmax = -1e+10;
double ymeanmin = 1e+10;
double ymeanmax = -1e+10;
double ystdmin = 1e+10;
double ystdmax = -1e+10;
if (use_led)
{
theKeithley->setVoltage(ledv);
theKeithley->on(1);
}
theHW->run();
//Measure!
while ((runState != STOP_ISSUED) && (tcurrent <= tend))
{
//Set LED voltage
qInfo(qPrintable(QString("Integration time: %1 ").arg(tcurrent)));
//set up integration time for all devices
theHW->stop();
for (int dev_nr = 0; dev_nr < theHW->devices.length(); dev_nr++)
{
DeviceConfig dc = theHW->devices[dev_nr]->deviceConfig;
dc.tint = tcurrent;
theHW->devices[dev_nr]->configure(dc);
}
theHW->run();
TiScanResult result;
//Collect sensor data
histoReady = 0;
connect(&(theHW->eventBuilder), EventBuilder::sigHistoCompleted, this, DialogTiScan::onHistogramCompleted);
theHW->eventBuilder.startTakingHistos(nacqs);
while (!histoReady)
{
QCoreApplication::processEvents();
QThread::msleep(10);
}
disconnect(&(theHW->eventBuilder), EventBuilder::sigHistoCompleted, this, DialogTiScan::onHistogramCompleted);
QVector<Histogram> histos = theHW->eventBuilder.getHistos();
result.mean.fill(0, nr_devices*128);
result.std.fill(0, nr_devices*128);
for (int i = 0; i < result.mean.length(); i++)
{
histos[i].MS(&(result.mean[i]), &(result.std[i]));
//result.mean[i] = histos[i].mean();
//result.std[i] = histos[i].stdev();
}
//Add information on integration time
result.tint = tcurrent;
results.append(result);
//Plot data...
xdata.append(result.tint);
if (result.tint > xmax)
xmax = result.tint;
if (result.tint < xmin)
xmin = result.tint;
for (int ch = 0, i = 0; ch < (nr_devices*128); ch+= decimation, i++)
{
ymeandata[i].append(result.mean[ch]);
if (result.mean[ch] > ymeanmax)
ymeanmax = result.mean[ch];
if (result.mean[ch] < ymeanmin)
ymeanmin = result.mean[ch];
ystddata[i].append(result.std[ch]);
if (result.std[ch] > ystdmax)
ystdmax = result.std[ch];
if (result.std[ch] < ystdmin)
ystdmin = result.std[ch];
}
ui->plotResultsMean->xAxis->setRange(xmin, xmax);
ui->plotResultsMean->yAxis->setRange(ymeanmin, ymeanmax);
ui->plotResultsStd->xAxis->setRange(xmin, xmax);
ui->plotResultsStd->yAxis->setRange(ystdmin, ystdmax);
for (int ch = 0, i = 0; ch < (nr_devices*128); ch+= decimation, i++)
{
ui->plotResultsMean->graph(i)->setData(xdata, ymeandata[i]);
ui->plotResultsStd->graph(i)->setData(xdata, ystddata[i]);
}
ui->plotResultsMean->replot();
ui->plotResultsStd->replot();
//Roll over
tcurrent += tinc;
QCoreApplication::processEvents();
}
if (use_led)
theKeithley->on(0);
theHW->stop();
qInfo("Integration time scan finished!");
runState = STOPPED;
}
//************** Slots ****************
void DialogTiScan::onHistogramCompleted()
{
histoReady = 1;
}
void DialogTiScan::on_pushRun_pressed()
{
if (runState)
{
runState = STOP_ISSUED;
}
else
{
ui->pushRun->setText("Stop");
ui->pushSave->setEnabled(false);
run();
ui->pushRun->setText("Run");
ui->pushSave->setEnabled(true);
}
}
void DialogTiScan::on_pushSave_pressed()
{
QString filename = QFileDialog::getSaveFileName(this, "Select file for saving data", "", tr("Comma separated files (*.csv)"));
QString delimiter = QString(",");
if (filename.length() == 0)
return;
QFile file(filename);
if (!file.open(QIODevice::WriteOnly | QIODevice::Text))
return;
QTextStream out(&file);
out << qSetFieldWidth(14) << qSetRealNumberPrecision(8);
for (int row = 0; row < results.length(); row++)
{
out << results[row].tint;
for (int col = 0; (col < results[row].mean.length()) && (col < results[row].std.length()); col++)
out << delimiter << results[row].mean[col] << delimiter << results[row].std[col];
out << QString("\n");
}
file.close();
}

View File

@ -3,6 +3,7 @@
#include <QMessageBox>
#include <QFileDialog>
#include <QCheckBox>
#include <iostream>
BPMDisplay::BPMDisplay(QWidget *parent) :
QDialog(parent),
@ -32,6 +33,7 @@ BPMDisplay::BPMDisplay(QWidget *parent) :
connect(ui->checkBox_subbkg, &QCheckBox::stateChanged, this, &BPMDisplay::onCheckBoxStateChanged);
connect(ui->pushButton_savecalib, &QPushButton::clicked, this, &BPMDisplay::onSaveCalibrationClicked);
connect(ui->pushButton_loadcalib, &QPushButton::clicked, this, &BPMDisplay::onLoadCalibrationClicked);
connect(ui->checkBox_enablecalib, &QCheckBox::stateChanged, this, &BPMDisplay::onCalibrationCheckBoxChanged);
connect(ui->checkBox_expertmode, &QCheckBox::stateChanged, this, &BPMDisplay::onExpertModeStateChanged);
// Enable or disable the "Save Background" and "Save Calib" buttons accordingly
@ -54,7 +56,7 @@ void BPMDisplay::showEvent(QShowEvent * event)
{
if (!event->spontaneous())
{
ui->plot->addGraph();
ui->plot->addGraph();
}
QDialog::showEvent(event);
@ -64,7 +66,7 @@ void BPMDisplay::showEvent(QShowEvent * event)
void BPMDisplay::plot(const QVector<unsigned short> &data)
{
//resize data vectors and fill X values - only if needed
//resize data vectors and fill X values - only if needed
if (data.length() != nrPoints)
{
nrPoints = data.length();
@ -80,7 +82,7 @@ void BPMDisplay::plot(const QVector<unsigned short> &data)
dataX[i] = i;
}
//fill Y values
//fill Y values
double min = 65535;
double max = 0;
for (int i = 0; i < nrPoints; i++)
@ -112,17 +114,16 @@ void BPMDisplay::plot(const QVector<unsigned short> &data)
// Check if calibration is enabled and the checkbox is checked
// Check if calibration data exists
if (calibrationDataMap.contains(planeName) ){
const QVector<unsigned short> &calibrationData = calibrationDataMap[planeName];
const QVector<float> &calibrationData = calibrationDataMap[planeName];
// Apply calibration to the current data
for (int i = 0; i < nrPoints; ++i) {
dataY[i] = dataY[i] / calibrationData[i];
dataY[i] = int(dataY[i] * calibrationData[i]);
}
}
}
//set Y range
//set Y range
if (ui->radioButtonAutoscale->isChecked())
ui->plot->yAxis->setRange(min-0.05*(max-min),max+0.05*(max-min));
@ -131,10 +132,10 @@ void BPMDisplay::plot(const QVector<unsigned short> &data)
else
ui->plot->yAxis->setRange(-1000,66000);
//feed plotter
//feed plotter
ui->plot->graph(0)->setData(dataX, dataY);
//plot
//plot
ui->plot->replot();
}
@ -261,6 +262,10 @@ void BPMDisplay::onSaveCalibrationClicked()
return;
}
// Get the plane's name (you might need to adjust how you retrieve it)
QString planeName = ui->lineTitle->text();
@ -272,12 +277,16 @@ void BPMDisplay::onSaveCalibrationClicked()
// Open the file for writing
QFile file(filename);
const QVector<unsigned short> &backgroundData = backgroundDataMap[planeName];
if (file.open(QIODevice::WriteOnly | QIODevice::Text)) {
QTextStream stream(&file);
// Write the data to the file
for (int i = 0; i < buffer.size(); ++i) {
stream << QString::number(buffer[i]) << "\n";
stream << QString::number(buffer[i] - backgroundData[i]) << "\n";
}
// Close the file
@ -308,10 +317,10 @@ void BPMDisplay::onLoadCalibrationClicked()
QTextStream stream(&file);
// Read the data from the file and store it in a vector
QVector<unsigned short> calibrationData;
QVector<float> calibrationData;
while (!stream.atEnd()) {
QString line = stream.readLine();
unsigned short value = line.toUShort();
float value = line.toFloat();
calibrationData.append(value);
}
@ -319,8 +328,8 @@ void BPMDisplay::onLoadCalibrationClicked()
file.close();
// Normalize the calibration data to the median value of all values greater than zero
QVector<unsigned short> normalizedCalibrationData = calibrationData; // Copy the data
QVector<unsigned short> normalizedCalibrationData2 = calibrationData; // Copy the data again
QVector<float> normalizedCalibrationData = calibrationData; // Copy the data
QVector<float> normalizedCalibrationData2 = calibrationData; // Copy the data again
// Remove values less than 50 (noise or dead channels) before determining the median for live channels
normalizedCalibrationData.erase(std::remove_if(normalizedCalibrationData.begin(), normalizedCalibrationData.end(), [](unsigned short value) {
@ -329,7 +338,7 @@ void BPMDisplay::onLoadCalibrationClicked()
std::sort(normalizedCalibrationData.begin(), normalizedCalibrationData.end()); // Sort the data
int size = normalizedCalibrationData.size();
unsigned short medianValue = 0;
float medianValue = 0;
if (size % 2 == 0) {
// If the size is even, take the average of the two middle values
@ -339,25 +348,33 @@ void BPMDisplay::onLoadCalibrationClicked()
medianValue = normalizedCalibrationData[size / 2];
}
//use the second copy to return the scaled calibration values.
for (unsigned short &value : normalizedCalibrationData2) {
if (value > 50) {
value /= medianValue;
}
else
{
value = 0;
if (medianValue>100){
//use the second copy to return the scaled calibration values.
for (auto &value : normalizedCalibrationData2) {
if (value > 50) {
value = medianValue / value;
}
else
{
value = 0;
}
// std::cerr << value << " ";
}
// std::cerr << std::endl;
// Store the normalized calibration data in the map
calibrationDataMap[planeName] = normalizedCalibrationData2;
// Notify the user that the data has been loaded and normalized
qInfo() << "Calibration data loaded and normalized for" << planeName;
}
else{
qWarning() << " Warning: MedianValue of calibration data too low. Not applied. ";
}
// Store the normalized calibration data in the map
calibrationDataMap[planeName] = normalizedCalibrationData2;
// Notify the user that the data has been loaded and normalized
qInfo() << "Calibration data loaded and normalized for" << planeName;
} else {
// Failed to open the file
qWarning() << "Error: Failed to open" << filename << "for reading";
qWarning() << "Warning: Failed to open" << filename << "for reading";
}
}

View File

@ -51,9 +51,9 @@ private:
QMap<QString, QVector<unsigned short>> backgroundDataMap; // Map to store background data for each plane
bool subtractBackground = false; // Flag to track if background subtraction is enabled
QMap<QString, QVector<unsigned short>> calibrationDataMap; // Map to store calibration data for each plane
QMap<QString, QVector<float>> calibrationDataMap; // Map to store calibration data for each plane
bool applyCalibration = false; // Flag to track if calibration should be applied
QVector<unsigned short> calibrationData; // Stores the loaded calibration data
QVector<float> calibrationData; // Stores the loaded calibration data
QCheckBox *checkBoxExpertMode; // Expert Mode checkbox
bool expertModeEnabled = false; // Flag to track if expert mode is enabled
};

View File

@ -0,0 +1,61 @@
#ifndef DISPLAY_H
#define DISPLAY_H
#include <QDialog>
#include <QVector>
#include <QRadioButton>
#include <QButtonGroup>
#include <QTextStream>
#include <QFile>
#include <QCheckBox>
namespace Ui {
class display;
}
class Display : public QDialog
{
Q_OBJECT
public:
explicit Display(QWidget *parent = 0);
~Display();
void plot(const QVector<unsigned short> &data);
void plot();
void setTitle(QString title);
QVector<unsigned short> buffer;
public slots:
void showEvent(QShowEvent *event);
void onButtonClicked(QAbstractButton *button);
void onSaveBackgroundClicked();
void onLoadBackgroundClicked();
void onCheckBoxStateChanged(int state);
void onSaveCalibrationClicked();
void onLoadCalibrationClicked();
void onCalibrationCheckBoxChanged(int state);
void onExpertModeStateChanged(int state);
protected:
int nrPoints = 0;
QVector<double> dataX;
QVector<double> dataY;
private:
Ui::display *ui;
QRadioButton *radioButtonFixedScale; // Pointer to the Fixed Scale radio button
QRadioButton *radioButtonAutoscale; // Pointer to the Autoscale radio button
QButtonGroup *buttonGroup;
QMap<QString, QVector<unsigned short>> backgroundDataMap; // Map to store background data for each plane
bool subtractBackground = false; // Flag to track if background subtraction is enabled
QMap<QString, QVector<unsigned short>> calibrationDataMap; // Map to store calibration data for each plane
bool applyCalibration = false; // Flag to track if calibration should be applied
QVector<unsigned short> calibrationData; // Stores the loaded calibration data
QCheckBox *checkBoxExpertMode; // Expert Mode checkbox
bool expertModeEnabled = false; // Flag to track if expert mode is enabled
};
#endif // DISPLAY_H

View File

@ -27,12 +27,71 @@ EventBuilder::~EventBuilder()
}
void addArrays(unsigned short int* arr1, const unsigned short int* arr2, int length) {
int simdLength = length / 8; // Process 8 elements at a time (SSE2)
for (int i = 0; i < simdLength; ++i) {
__m128i xmm1 = _mm_loadu_si128((__m128i*)(arr1 + i * 8)); // Load 8 elements from arr1
__m128i xmm2 = _mm_loadu_si128((__m128i*)(arr2 + i * 8)); // Load 8 elements from arr2
__m128i xmmResult = _mm_add_epi16(xmm1, xmm2); // Add arr1 to arr2
_mm_storeu_si128((__m128i*)(arr1 + i * 8), xmmResult); // Store the result
}
// Process the remaining elements
for (int i = simdLength * 8; i < length; ++i) {
arr1[i] = arr1[i] + arr2[i];
}
}
void subtractArrays( unsigned short int* arr1, const unsigned short int* arr2, const int length, short int* result) {
int simdLength = length / 8; // Process 8 elements at a time (SSE2)
for (int i = 0; i < simdLength; ++i) {
__m128i xmm1 = _mm_loadu_si128((__m128i*)(arr1 + i * 8)); // Load 8 elements from arr1
__m128i xmm2 = _mm_loadu_si128((__m128i*)(arr2 + i * 8)); // Load 8 elements from arr2
__m128i xmmResult = _mm_sub_epi16(xmm1, xmm2); // Subtract arr2 from arr1
_mm_storeu_si128((__m128i*)(result + i * 8), xmmResult); // Store the result
}
// Process the remaining elements
for (int i = simdLength * 8; i < length; ++i) {
result[i] = (arr2[i] > arr1[i]) ? 0 : (arr1[i] - arr2[i]);
}
}
void divideArray(unsigned short int* arr, int length, const short int divisor) {
int simdLength = length / 8; // Process 8 elements at a time (SSE2)
// Load the divisor into a SIMD register
__m128i divisorVector = _mm_set1_epi16(divisor);
for (int i = 0; i < simdLength; ++i) {
// Load 8 elements from 'arr' into a SIMD register
__m128i arrVector = _mm_loadu_si128((__m128i*)(arr + i * 8));
// Multiply each element by the reciprocal of the divisor using SIMD
__m128i resultVector = _mm_mullo_epi16(arrVector, divisorVector);
// Store the result back to 'result'
_mm_storeu_si128((__m128i*)(arr + i * 8), resultVector);
}
// Process the remaining elements
for (int i = simdLength * 8; i < length; ++i) {
arr[i] = arr[i] / divisor;
}
}
//************************* Data processing framework ********************
//main processing slot
void EventBuilder::onNewData(DataReceiver* receiver)
{
short * newcopy_sensor_data = new short int[320];
while (checkBufferOccupancies())
{
//find lowest global sync value
@ -54,7 +113,7 @@ void EventBuilder::onNewData(DataReceiver* receiver)
currentFrame[dev_nr] = data;
}
lastFrameMutex.lock();
@ -64,36 +123,46 @@ void EventBuilder::onNewData(DataReceiver* receiver)
//ToDo:
//1. Background subtraction.
frame_counter++;
/*
while (frame_counter<10000){
for (unsigned int dev_nr = 0; dev_nr < nrReceivers; dev_nr++){
for (unsigned int ch = 0; ch < channelCounts[dev_nr]; ch++)
backgroundFrame[dev_nr].sensor_data[ch]+= currentFrame[dev_nr].sensor_data[ch];
if (newDataSemaphore.available() == 1){
frame_counter++;
if (frame_counter<=32){
for (unsigned int dev_nr = 0; dev_nr < nrReceivers; dev_nr++){
if (frame_counter<=1) backgroundFrame[dev_nr].resize(channelCounts[dev_nr]);
// backgroundFrame[dev_nr].sensor_data = currentFrame[dev_nr].sensor_data;
addArrays(backgroundFrame[dev_nr].sensor_data, currentFrame[dev_nr].sensor_data, channelCounts[dev_nr]);
// std::cerr << " set bkg" << std::endl;
}
}
}
if (frame_counter==10000){
for (unsigned int dev_nr = 0; dev_nr < nrReceivers; dev_nr++){
for (unsigned int ch = 0; ch < channelCounts[dev_nr]; ch++)
backgroundFrame[dev_nr].sensor_data[ch]/= 10000 ;
else if (frame_counter==33){
for (unsigned int dev_nr = 0; dev_nr < nrReceivers; dev_nr++){
for (int i = 0; i < channelCounts[dev_nr]; ++i) {
backgroundFrame[dev_nr].sensor_data[i] /= 32; // Right-shift by 5 positions (equivalent to dividing by 32)
}
}
}
}
if (frame_counter>10000){
for (unsigned int dev_nr = 0; dev_nr < nrReceivers; dev_nr++){
for (unsigned int ch = 0; ch < channelCounts[dev_nr]; ch++)
currentFrame[dev_nr].sensor_data[ch]-=backgroundFrame[dev_nr].sensor_data[ch] ;
}
}
*/
else if (frame_counter>33){
HIT_ANALYSE_V2 hit_analyse_v2;//create the object
QString dataString;
for (unsigned int dev_nr = 0; dev_nr < nrReceivers; dev_nr++){
// subtractArrays(currentFrame[dev_nr].sensor_data, backgroundFrame[dev_nr].sensor_data, channelCounts[dev_nr], newcopy_sensor_data );
// std::cerr << currentFrame[dev_nr].sensor_data[0] << " " << backgroundFrame[dev_nr].sensor_data[0] << " " << channelCounts[dev_nr] << " " << newcopy_sensor_data[0] << std::endl;
lastFrameMutex.lock();
if (newDataSemaphore.available() == 0)
newDataSemaphore.release(1);
lastFrame = currentFrame;
lastFrameMutex.unlock();
/*
// for (unsigned int dev_nrsim = 0; dev_nrsim < 3; dev_nrsim++){
//simulate 6 planes instead of just 2
// for (unsigned int dev_nr = 0; dev_nr < nrReceivers; dev_nr++){
// dataString += hit_analyse_v2.analyseBeamData(newcopy_sensor_data, dev_nr, channelCounts[dev_nr]);
// dataString += char(nrReceivers);
//}
// if (frame_counter%1000==0) std::cerr << dataString.toStdString() << std::endl;
}
}
}
/*
//histogram stuff
if (histogramSamplesToTake)
{
@ -107,25 +176,24 @@ void EventBuilder::onNewData(DataReceiver* receiver)
emit sigHistoCompleted();
}
*/
//log data
if (loggingData) logDataToFile();
HIT_ANALYSE_V2 hit_analyse_v2;//create the object
QString dataString;
// for (unsigned int dev_nrsim = 0; dev_nrsim < 3; dev_nrsim++){
//simulate 6 planes instead of just 2
for (unsigned int dev_nr = 0; dev_nr < nrReceivers; dev_nr++){
dataString += hit_analyse_v2.analyseBeamData(currentFrame);
dataString +=',';
}
// }
QTime currentTime = QTime::currentTime();
//Calculate the time since midnight in milliseconds
int millisecondsSinceMidnight = currentTime.msecsSinceStartOfDay();
dataString += QString::number(millisecondsSinceMidnight);
receiveData(dataString.toUtf8());
// std::cerr << dataString.toStdString() << std::endl;
// Call sendData method of the UDP server
// QString dataString = QString::number(intensity) + ',' + QString::number(position) + ',' + QString::number(focus);
// }
// QTime currentTime = QTime::currentTime();
//Calculate the time since midnight in milliseconds
// int millisecondsSinceMidnight = currentTime.msecsSinceStartOfDay();
// dataString += QString::number(millisecondsSinceMidnight);
// receiveData(dataString.toUtf8());
if (newDataSemaphore.available() == 0)
newDataSemaphore.release(1);
lastFrame = currentFrame;
lastFrameMutex.unlock();
//log data
if (loggingData) logDataToFile();

View File

@ -13,6 +13,8 @@
//#include "hw.h"
#include "datareceiver.h"
#include "histogram.h"
#include <immintrin.h> // Include for Intel Intrinsics
#include <emmintrin.h> // Include for SSE2
//The event builder will constantly keep some data in the buffers to enable synchronization of the devices. So:
#define EVB_MIN_BUFFER_OCCUPANCY (RECEIVER_BUFFER_SIZE / 8) //the EVB will wait until so much data is in each device buffer
@ -73,6 +75,7 @@ protected:
QVector<DataReceiver*> receivers;
QVector<BufferData> currentFrame;
signed short * copy_sensor_data;
QVector<BufferData> backgroundFrame;
QVector<BufferData> lastFrame;
@ -99,7 +102,7 @@ protected slots:
void onStartTakingHistos(int sample_count);
void onStopTakingHistos();
private:
long unsigned int frame_counter = 0;
long long int frame_counter = 0;
double intensity = 0.0;
double position = 0.0;
double focus = 0.0;

View File

@ -1,5 +1,6 @@
#include "hit_analyse_v2.h"
#include <random>
#include <immintrin.h> // Include for Intel Intrinsics
HIT_ANALYSE_V2::HIT_ANALYSE_V2(QObject *parent) : QObject(parent)
{
@ -8,6 +9,9 @@ HIT_ANALYSE_V2::HIT_ANALYSE_V2(QObject *parent) : QObject(parent)
}
// Define your own functions for matrix operations
struct Matrix2x2 {
double data[2][2];
@ -34,146 +38,41 @@ struct Vector2 {
double data[2];
};
QString HIT_ANALYSE_V2::analyseBeamData(QVector<BufferData> dataframe){
QString HIT_ANALYSE_V2::analyseBeamData(short int * signal_list, const int dev_nr, const int vector_length)
{
double position=0.1;
double position=100;
double focus=8;
double intensity=1000.0;
QString dataString;
// Fill arr1 and arr2 with your data
const int vector_length = 300; // Replace with the actual length of your vectors
std::vector<double> signal_list(vector_length);
std::vector<double> channel_list(vector_length);
std::vector<double> channel_list;
std::vector<double> short_signal_list;
std::vector<double> short_channel_list;
// Create a random number generator with a Gaussian distribution
std::random_device rd;
std::mt19937 gen(rd());
std::normal_distribution<double> dist(0.0, 17.0); // Mean of 0 and Sigma of 17
channel_list = fixed_channel;
// Create a vector to store the generated values
std::vector<short int> result(vector_length);
// std::vector<short int> result(vector_length);
// Fill the vector with random noise values
//add a gaussian profile, focus is FWHM, position is random between 50 and 250
bool fixeddata = true;
if (!fixeddata){
position = 50 + (rand() % (int)(250 - 50 + 1));
for (int i = 0; i < vector_length; i++) {
double randomValue = dist(gen);
signal_list[i] = static_cast<short int>(std::round(randomValue));
channel_list[i] = i;
signal_list[i] += static_cast<short int>(std::round(intensity*exp(-4*log(2)*pow((channel_list[i]-position)/focus,2))));
// std::cerr << channel_list[i] << ", ";
bool fixeddata = false ;
if (fixeddata){
// signal_list = (short int)fixedsignalarray;
bool dummy = true;
}
// std::cerr <<std::endl;
}
else{
signal_list = fixed_signal[0];
channel_list = fixed_channel;
else
{
// signal_list = dataframe[dev_nr].sensor_data;
bool dummy = false;
}
// std::cerr << signal_list[0] << " " << dev_nr << std::endl;
/*
// Fill signal_list and channel_list with your data
double SumT = 0.0, SumS = 0.0, SumS2 = 0.0, SumST = 0.0, SumT2 = 0.0, SumY = 0.0, SumYS = 0.0, SumYT = 0.0;
double b_den = 0.0, b_num = 0.0, b = 0.0, p = 0.0, c = 0.0, SumYYP = 0.0, SumYYM = 0.0, MeanY = 0.0;
double S[vector_length];
double T[vector_length];
for (int k = 0; k < vector_length; k++) {
if (k == 0) {
S[k] = 0.0;
T[k] = 0.0;
} else {
S[k] = S[k - 1] + 0.5 * (signal_list[k] + signal_list[k - 1]) * (channel_list[k] - channel_list[k - 1]);
T[k] = T[k - 1] + 0.5 * (channel_list[k] * signal_list[k] + channel_list[k - 1] * signal_list[k - 1]) *
(channel_list[k] - channel_list[k - 1]);
}
SumS += S[k];
SumT += T[k];
SumY += signal_list[k];
SumS2 += S[k] * S[k];
SumST += S[k] * T[k];
SumT2 += T[k] * T[k];
SumYS += signal_list[k] * S[k];
SumYT += signal_list[k] * T[k];
MeanY += signal_list[k];
}
MeanY /= vector_length;
// Calculate M1 matrix elements
double M1_00 = SumT2;
double M1_01 = SumST;
double M1_02 = SumT;
double M1_10 = SumST;
double M1_11 = SumS2;
double M1_12 = SumS;
double M1_20 = SumT;
double M1_21 = SumS;
double M1_22 = vector_length;
// Calculate M2 vector elements
double M2_0 = SumYT;
double M2_1 = SumYS;
double M2_2 = SumY;
// Calculate the inverse of M1
double detM1 = M1_00 * (M1_11 * M1_22 - M1_12 * M1_21) -
M1_01 * (M1_10 * M1_22 - M1_12 * M1_20) +
M1_02 * (M1_10 * M1_21 - M1_11 * M1_20);
if (detM1 == 0.0) {
std::cerr << "M1 is not invertible." << std::endl;
//return 1;
}
double invM1_00 = (M1_11 * M1_22 - M1_12 * M1_21) / detM1;
double invM1_01 = (M1_02 * M1_21 - M1_01 * M1_22) / detM1;
double invM1_02 = (M1_01 * M1_12 - M1_02 * M1_11) / detM1;
double invM1_10 = (M1_12 * M1_20 - M1_10 * M1_22) / detM1;
double invM1_11 = (M1_00 * M1_22 - M1_02 * M1_20) / detM1;
double invM1_12 = (M1_02 * M1_10 - M1_00 * M1_12) / detM1;
double invM1_20 = (M1_10 * M1_21 - M1_11 * M1_20) / detM1;
double invM1_21 = (M1_01 * M1_20 - M1_00 * M1_21) / detM1;
double invM1_22 = (M1_00 * M1_11 - M1_01 * M1_10) / detM1;
// Calculate ABC vector
double ABC_0 = invM1_00 * M2_0 + invM1_01 * M2_1 + invM1_02 * M2_2;
double ABC_1 = invM1_10 * M2_0 + invM1_11 * M2_1 + invM1_12 * M2_2;
double ABC_2 = invM1_20 * M2_0 + invM1_21 * M2_1 + invM1_22 * M2_2;
// Calculate b, p, and c
p = -ABC_0 / 2.0;
c = -ABC_1 / ABC_0;
for (int k = 0; k < vector_length; k++) {
double exp_term = exp(-p * (channel_list[k] - c) * (channel_list[k] - c));
b_num += exp_term * signal_list[k];
b_den += exp_term;
}
b = b_num / b_den;
for (int k = 0; k < vector_length; k++) {
double y_pred = b * exp(-p * (channel_list[k] - c) * (channel_list[k] - c));
SumYYM += (signal_list[k] - MeanY) * (signal_list[k] - MeanY);
SumYYP += (y_pred - MeanY) * (y_pred - MeanY);
}
double R_squared = SumYYP / SumYYM;
//std::cout << "R-squared = " << R_squared << endl;
position = -ABC_1/ ABC_0;
//sigma = sqrt(1.0 / (2.0 * ABC_0));
focus = 2.3548/sqrt(2*p);
intensity = b;
*/
double SumArea = 0.0, SumY2 = 0.0, SumXY2 = 0.0, SumX2Y2 = 0.0, SumX3Y2 = 0.0;
double SumY2LnY = 0.0, SumXY2LnY = 0.0, Ymax = 0.0, Pomax = 0.0;
double fac_c = 0.0, Yn = 0.0, sigma = 0.0, amp = 0.0;
@ -185,6 +84,7 @@ QString HIT_ANALYSE_V2::analyseBeamData(QVector<BufferData> dataframe){
Vector2 ABC, M2;
for (int i = 0; i < vector_length; i++) {
std::cerr<< signal_list[i] << " ";
if (signal_list[i] > Ymax) {
Ymax = signal_list[i];
Pomax = channel_list[i];
@ -193,14 +93,14 @@ QString HIT_ANALYSE_V2::analyseBeamData(QVector<BufferData> dataframe){
SumArea += signal_list[i] * (channel_list[i] - channel_list[i - 1]);
}
}
std::cerr<< std::endl;
// Estimate sigma
sigma = SumArea / Ymax / 2.5066;
// Set a +-3 sigma window
window_start = Pomax - 3 * sigma;
window_end = Pomax + 3 * sigma;
// std::cerr<< Pomax << " " << Ymax << " " << sigma << std::endl;
std::cerr<< Pomax << " " << Ymax << " " << sigma << std::endl;
for (int i = 0; i < vector_length; i++) {
@ -209,8 +109,8 @@ QString HIT_ANALYSE_V2::analyseBeamData(QVector<BufferData> dataframe){
short_channel_list.push_back(channel_list[i]);
}
}
signal_list.clear();
channel_list.clear();
//signal_list.clear();
//channel_list.clear();
// Recalculate SumArea using the sieved data
SumArea = 0.0;
for (int i = 1; i < short_signal_list.size(); i++) {

View File

@ -0,0 +1,337 @@
#include "hit_analyse_v2.h"
#include <random>
HIT_ANALYSE_V2::HIT_ANALYSE_V2(QObject *parent) : QObject(parent)
{
}
// Define your own functions for matrix operations
struct Matrix2x2 {
double data[2][2];
};
Matrix2x2 InvertMatrix2x2(const Matrix2x2& mat) {
Matrix2x2 result;
double det = mat.data[0][0] * mat.data[1][1] - mat.data[0][1] * mat.data[1][0];
if (det != 0.0) {
double invDet = 1.0 / det;
result.data[0][0] = mat.data[1][1] * invDet;
result.data[0][1] = -mat.data[0][1] * invDet;
result.data[1][0] = -mat.data[1][0] * invDet;
result.data[1][1] = mat.data[0][0] * invDet;
} else {
// Handle the case when the matrix is not invertible
// You might want to implement error handling here.
std::cerr << "Matrix not invertible! " << std::endl;
}
return result;
}
struct Vector2 {
double data[2];
};
QString HIT_ANALYSE_V2::analyseBeamData(QVector<BufferData> dataframe, const int dev_nr, const int vector_length){
double position=100;
double focus=8;
double intensity=1000.0;
QString dataString;
double * signal_list;
std::vector<double> channel_list;
std::vector<double> short_signal_list;
std::vector<double> short_channel_list;
// Create a random number generator with a Gaussian distribution
std::random_device rd;
std::mt19937 gen(rd());
std::normal_distribution<double> dist(0.0, 17.0); // Mean of 0 and Sigma of 17
// Create a vector to store the generated values
std::vector<short int> result(vector_length);
// Fill the vector with random noise values
//add a gaussian profile, focus is FWHM, position is random between 50 and 250
bool fixeddata = false;
if (!fixeddata){
position = 100;// + (rand() % (int)(250 - 50 + 1));
signal_list = (double*)(dataframe[dev_nr].sensor_data);
channel_list = fixed_channel;
for (int i = int(position) - (int)(focus); i < int(position) + (int)(focus) ; i++) {
// double randomValue = dist(gen);
// signal_list[i] = static_cast<short int>(std::round(randomValue));
// signal_list[i] = dataframe[dev_nr].sensor_data[i];
//channel_list[i] = i;
signal_list[i] += static_cast<short int>(std::round(intensity*exp(-4*log(2)*pow((channel_list[i]-position)/focus,2))));
// std::cerr << channel_list[i] << ", ";
}
// std::cerr <<std::endl;
}
else{
signal_list = fixedsignalarray;
channel_list = fixed_channel;
}
/*
// Fill signal_list and channel_list with your data
double SumT = 0.0, SumS = 0.0, SumS2 = 0.0, SumST = 0.0, SumT2 = 0.0, SumY = 0.0, SumYS = 0.0, SumYT = 0.0;
double b_den = 0.0, b_num = 0.0, b = 0.0, p = 0.0, c = 0.0, SumYYP = 0.0, SumYYM = 0.0, MeanY = 0.0;
double S[vector_length];
double T[vector_length];
for (int k = 0; k < vector_length; k++) {
if (k == 0) {
S[k] = 0.0;
T[k] = 0.0;
} else {
S[k] = S[k - 1] + 0.5 * (signal_list[k] + signal_list[k - 1]) * (channel_list[k] - channel_list[k - 1]);
T[k] = T[k - 1] + 0.5 * (channel_list[k] * signal_list[k] + channel_list[k - 1] * signal_list[k - 1]) *
(channel_list[k] - channel_list[k - 1]);
}
SumS += S[k];
SumT += T[k];
SumY += signal_list[k];
SumS2 += S[k] * S[k];
SumST += S[k] * T[k];
SumT2 += T[k] * T[k];
SumYS += signal_list[k] * S[k];
SumYT += signal_list[k] * T[k];
MeanY += signal_list[k];
}
MeanY /= vector_length;
// Calculate M1 matrix elements
double M1_00 = SumT2;
double M1_01 = SumST;
double M1_02 = SumT;
double M1_10 = SumST;
double M1_11 = SumS2;
double M1_12 = SumS;
double M1_20 = SumT;
double M1_21 = SumS;
double M1_22 = vector_length;
// Calculate M2 vector elements
double M2_0 = SumYT;
double M2_1 = SumYS;
double M2_2 = SumY;
// Calculate the inverse of M1
double detM1 = M1_00 * (M1_11 * M1_22 - M1_12 * M1_21) -
M1_01 * (M1_10 * M1_22 - M1_12 * M1_20) +
M1_02 * (M1_10 * M1_21 - M1_11 * M1_20);
if (detM1 == 0.0) {
std::cerr << "M1 is not invertible." << std::endl;
//return 1;
}
double invM1_00 = (M1_11 * M1_22 - M1_12 * M1_21) / detM1;
double invM1_01 = (M1_02 * M1_21 - M1_01 * M1_22) / detM1;
double invM1_02 = (M1_01 * M1_12 - M1_02 * M1_11) / detM1;
double invM1_10 = (M1_12 * M1_20 - M1_10 * M1_22) / detM1;
double invM1_11 = (M1_00 * M1_22 - M1_02 * M1_20) / detM1;
double invM1_12 = (M1_02 * M1_10 - M1_00 * M1_12) / detM1;
double invM1_20 = (M1_10 * M1_21 - M1_11 * M1_20) / detM1;
double invM1_21 = (M1_01 * M1_20 - M1_00 * M1_21) / detM1;
double invM1_22 = (M1_00 * M1_11 - M1_01 * M1_10) / detM1;
// Calculate ABC vector
double ABC_0 = invM1_00 * M2_0 + invM1_01 * M2_1 + invM1_02 * M2_2;
double ABC_1 = invM1_10 * M2_0 + invM1_11 * M2_1 + invM1_12 * M2_2;
double ABC_2 = invM1_20 * M2_0 + invM1_21 * M2_1 + invM1_22 * M2_2;
// Calculate b, p, and c
p = -ABC_0 / 2.0;
c = -ABC_1 / ABC_0;
for (int k = 0; k < vector_length; k++) {
double exp_term = exp(-p * (channel_list[k] - c) * (channel_list[k] - c));
b_num += exp_term * signal_list[k];
b_den += exp_term;
}
b = b_num / b_den;
for (int k = 0; k < vector_length; k++) {
double y_pred = b * exp(-p * (channel_list[k] - c) * (channel_list[k] - c));
SumYYM += (signal_list[k] - MeanY) * (signal_list[k] - MeanY);
SumYYP += (y_pred - MeanY) * (y_pred - MeanY);
}
double R_squared = SumYYP / SumYYM;
//std::cout << "R-squared = " << R_squared << endl;
position = -ABC_1/ ABC_0;
//sigma = sqrt(1.0 / (2.0 * ABC_0));
focus = 2.3548/sqrt(2*p);
intensity = b;
*/
double SumArea = 0.0, SumY2 = 0.0, SumXY2 = 0.0, SumX2Y2 = 0.0, SumX3Y2 = 0.0;
double SumY2LnY = 0.0, SumXY2LnY = 0.0, Ymax = 0.0, Pomax = 0.0;
double fac_c = 0.0, Yn = 0.0, sigma = 0.0, amp = 0.0;
double SumYYP = 0.0, SumYYM = 0.0, MeanY = 0.0, window_start = 0.0, window_end = 0.0;
// ...
Matrix2x2 M1, M1inv;
Vector2 ABC, M2;
for (int i = 0; i < vector_length; i++) {
if (signal_list[i] > Ymax) {
Ymax = signal_list[i];
Pomax = channel_list[i];
}
if (i > 0 && signal_list[i] > 34) {
SumArea += signal_list[i] * (channel_list[i] - channel_list[i - 1]);
}
}
// Estimate sigma
sigma = SumArea / Ymax / 2.5066;
// Set a +-3 sigma window
window_start = Pomax - 3 * sigma;
window_end = Pomax + 3 * sigma;
// std::cerr<< Pomax << " " << Ymax << " " << sigma << std::endl;
for (int i = 0; i < vector_length; i++) {
if (signal_list[i] > 34 && channel_list[i] > window_start && channel_list[i] < window_end) {
short_signal_list.push_back(signal_list[i]);
short_channel_list.push_back(channel_list[i]);
}
}
//signal_list.clear();
//channel_list.clear();
// Recalculate SumArea using the sieved data
SumArea = 0.0;
for (int i = 1; i < short_signal_list.size(); i++) {
SumArea += short_signal_list[i] * (short_channel_list[i] - short_channel_list[i - 1]);
}
const int shortlist_length = short_channel_list.size();
if (shortlist_length <= 3) {
intensity = -1;
focus = -1;
position = -128;
dataString += QString::number(intensity) + ',' + QString::number(position) + ',' + QString::number(focus)
+ ',' + QString::number(0);
return dataString;
}
// Re-Estimate sigma
sigma = SumArea / Ymax / 2.5066;
fac_c = -1.0 / (2.0 * sigma * sigma);
// std::cerr << sigma << std::endl;
for(int k=0; k<shortlist_length;k++){
SumY2 += short_signal_list[k]*short_signal_list[k];
SumXY2 += short_signal_list[k]*short_signal_list[k]*short_channel_list[k];
SumX2Y2 += short_signal_list[k]*short_signal_list[k]*short_channel_list[k]*short_channel_list[k];
SumX3Y2 += short_signal_list[k]*short_signal_list[k]*short_channel_list[k]*short_channel_list[k]*short_channel_list[k];
SumY2LnY += short_signal_list[k]*short_signal_list[k]*log(short_signal_list[k]);
SumXY2LnY += short_channel_list[k]*short_signal_list[k]*short_signal_list[k]*log(short_signal_list[k]);
// std::cerr<< shortlist_length << " " << short_channel_list[k] << " " << short_signal_list[k] << " " << short_signal_list[k] << " " << log(short_signal_list[k]) << std::endl;
MeanY+=short_signal_list[k];
}
MeanY/=shortlist_length;
// Use custom matrix and vector functions for calculations
M1.data[0][0] = SumY2;
M1.data[0][1] = SumXY2;
M1.data[1][0] = SumXY2;
M1.data[1][1] = SumX2Y2;
// std::cerr << M1.data[0][0] << " " << M1.data[0][1] << " " << M1.data[1][0] << " " << M1.data[1][1] << std::endl;
M2.data[0] = SumY2LnY - fac_c * SumX2Y2;
M2.data[1] = SumXY2LnY - fac_c * SumX3Y2;
// std::cerr << M2.data[0] << " " << M2.data[1] << std::endl;
M1inv = InvertMatrix2x2(M1);
ABC.data[0] = M1inv.data[0][0] * M2.data[0] + M1inv.data[0][1] * M2.data[1];
ABC.data[1] = M1inv.data[1][0] * M2.data[0] + M1inv.data[1][1] * M2.data[1];
// std::cerr << ABC.data[0] << " " << ABC.data[1] << std::endl;
//iterate to improve the fit.
int N_iter = 1;
for (int i = 0; i < N_iter; i++) {
SumY2 = 0.0;
SumXY2 = 0.0;
SumX2Y2 = 0.0;
SumX3Y2 = 0.0;
SumY2LnY = 0.0;
SumXY2LnY = 0.0;
for (int k = 0; k < shortlist_length; k++) {
Yn = exp(ABC.data[0] + ABC.data[1] * short_channel_list[k] + fac_c * short_channel_list[k] * short_channel_list[k]);
SumY2 += Yn * Yn;
SumXY2 += Yn * Yn * short_channel_list[k];
SumX2Y2 += Yn * Yn * short_channel_list[k] * short_channel_list[k];
SumX3Y2 += Yn * Yn * short_channel_list[k] * short_channel_list[k] * short_channel_list[k];
SumY2LnY += Yn * Yn * log(short_signal_list[k]);
SumXY2LnY += short_channel_list[k] * Yn * Yn * log(short_signal_list[k]);
}
M1.data[0][0] = SumY2;
M1.data[0][1] = SumXY2;
M1.data[1][0] = SumXY2;
M1.data[1][1] = SumX2Y2;
M2.data[0] = SumY2LnY - fac_c * SumX2Y2;
M2.data[1] = SumXY2LnY - fac_c * SumX3Y2;
M1inv = InvertMatrix2x2(M1);
ABC.data[0] = M1inv.data[0][0] * M2.data[0] + M1inv.data[0][1] * M2.data[1];
ABC.data[1] = M1inv.data[1][0] * M2.data[0] + M1inv.data[1][1] * M2.data[1];
}
position = -ABC.data[1]/fac_c/2;
amp = exp(ABC.data[0]-ABC.data[1]*ABC.data[1]/4/fac_c);
sigma=SumArea/amp/2.5066;
// cout << sigma << " " << mean << " " << amp << endl;
for(int k=0; k<shortlist_length;k++){
SumYYM+= (short_signal_list[k]-MeanY)*(short_signal_list[k]-MeanY);
SumYYP+= (amp*exp(-(short_channel_list[k]-position)*(short_channel_list[k]-position)/2/(sigma*sigma)) - MeanY )*(amp*exp(-(short_channel_list[k]-position)*(short_channel_list[k]-position)/2/(sigma*sigma)) - MeanY );
}
focus = 2.3548*sigma;
intensity = amp;
double R_squared = SumYYP/SumYYM;
dataString += QString::number(intensity) + ',' + QString::number(position) + ',' + QString::number(focus)
+ ',' + QString::number(R_squared);
return dataString;
}
HIT_ANALYSE_V2::~HIT_ANALYSE_V2()
{
}

View File

@ -54,6 +54,7 @@ private:
};
double fixedsignalarray[300] = {-13, -7, -12, 22, -6, 0, 22, 5, 8, 11, 25, -10, 11, 13, 32, -4, -2, -37, -21, 23, 13, 26, 11, -24, 1, -6, -6, 1, 22, 30, -21, -3, 11, -2, -11, 5, -2, 31, 24, 4, -17, 24, -24, 20, 31, -6, -1, -4, -10, -26, -12, -19, -7, -39, 1, 19, 3, -13, 37, 2, 11, -10, -14, 20, 14, -1, -13, 13, -18, -18, -15, -25, 14, 11, -32, 50, 18, -11, 26, 4, 4, -2, -10, 34, 6, 36, -9, 19, -3, 7, -10, -15, 4, 24, -3, 2, 13, -34, -28, -25, -4, -14, -11, 23, -19, -7, -6, 6, 23, 7, -21, 18, -8, 6, 21, -4, 3, -1, -11, 7, -38, -38, -12, -11, -11, 9, -11, -7, 2, -1, 19, 12, 0, -7, 15, 3, 28, -8, 1, 8, 2, -4, 4, 23, 31, -17, 8, 11, 34, 1, 7, 14, 14, 16, -1, -30, -2, 19, -20, -4, -9, 15, -6, -4, -4, 10, -27, -18, 24, 19, 20, 22, 68, 122, 234, 371, 496, 713, 840, 967, 1026, 957, 833, 674, 485, 317, 194, 98, 70, 45, 34, -15, 3, 10, 12, -19, 11, 27, -1, 2, -9, -1, -2, -15, -22, 7, 0, -20, -1, -7, 21, -4, -21, 21, -6, 23, -4, -2, -28, -17, -13, 1, 19, 20, 6, 10, -25, -4, 5, -14, -18, -4, 12, 7, -21, 7, -10, 10, 11, -21, 7, -6, -2, -3, 1, 16, 4, -23, 2, 14, 0, -5, -7, -12, -2, -8, -20, 11, 21, -5, -5, 20, -10, 3, -18, -5, 4, 6, 4, -21, -3, -26, -15, -7, -14, -10, -14, 7, -18, -2, -14, 36, -10, 11, 9, 3, -7, -51, -12, 2, 5, 9, 15, 20, -23, -6, -14, -4, 16, 4};
const std::vector<std::vector<double>> fixed_signal =
{
{-13, -7, -12, 22, -6, 0, 22, 5, 8, 11, 25, -10, 11, 13, 32, -4, -2, -37, -21, 23, 13, 26, 11, -24, 1, -6, -6, 1, 22, 30, -21, -3, 11, -2, -11, 5, -2, 31, 24, 4, -17, 24, -24, 20, 31, -6, -1, -4, -10, -26, -12, -19, -7, -39, 1, 19, 3, -13, 37, 2, 11, -10, -14, 20, 14, -1, -13, 13, -18, -18, -15, -25, 14, 11, -32, 50, 18, -11, 26, 4, 4, -2, -10, 34, 6, 36, -9, 19, -3, 7, -10, -15, 4, 24, -3, 2, 13, -34, -28, -25, -4, -14, -11, 23, -19, -7, -6, 6, 23, 7, -21, 18, -8, 6, 21, -4, 3, -1, -11, 7, -38, -38, -12, -11, -11, 9, -11, -7, 2, -1, 19, 12, 0, -7, 15, 3, 28, -8, 1, 8, 2, -4, 4, 23, 31, -17, 8, 11, 34, 1, 7, 14, 14, 16, -1, -30, -2, 19, -20, -4, -9, 15, -6, -4, -4, 10, -27, -18, 24, 19, 20, 22, 68, 122, 234, 371, 496, 713, 840, 967, 1026, 957, 833, 674, 485, 317, 194, 98, 70, 45, 34, -15, 3, 10, 12, -19, 11, 27, -1, 2, -9, -1, -2, -15, -22, 7, 0, -20, -1, -7, 21, -4, -21, 21, -6, 23, -4, -2, -28, -17, -13, 1, 19, 20, 6, 10, -25, -4, 5, -14, -18, -4, 12, 7, -21, 7, -10, 10, 11, -21, 7, -6, -2, -3, 1, 16, 4, -23, 2, 14, 0, -5, -7, -12, -2, -8, -20, 11, 21, -5, -5, 20, -10, 3, -18, -5, 4, 6, 4, -21, -3, -26, -15, -7, -14, -10, -14, 7, -18, -2, -14, 36, -10, 11, 9, 3, -7, -51, -12, 2, 5, 9, 15, 20, -23, -6, -14, -4, 16, 4}
@ -64,7 +65,7 @@ private:
const std::vector<double> fixed_channel = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299};
public slots:
QString analyseBeamData(QVector<BufferData> dataframe);
QString analyseBeamData(short int * copysensor_data, const int dev_nr, const int vector_length);
// void processPendingDatagrams();
};

View File

@ -1,5 +1,5 @@
#include "hw.h"
HW::HW(QObject *parent) : QObject(parent), eventBuilder(), networkThread(eventBuilder)
HW::HW(QObject *parent) : QObject(parent), eventBuilder()// , networkThread(eventBuilder)
{
/*eventBuilder.moveToThread(&eventBuilderThread);
@ -7,15 +7,15 @@ HW::HW(QObject *parent) : QObject(parent), eventBuilder(), networkThread(eventBu
eventBuilder.init();*/
// Create and start the network thread
networkThread.start();
// networkThread.start();
}
HW::~HW()
{
if (networkThread.isRunning()){
networkThread.stopThread();
networkThread.wait(); // Wait for the network thread to finish gracefully
}
// if (networkThread.isRunning()){
// networkThread.stopThread();
// networkThread.wait(); // Wait for the network thread to finish gracefully
// }
eventBuilder.stopLogging();
removeDevices();
@ -84,10 +84,10 @@ void HW::run()
void HW::stop()
{
// Application cleanup
if (networkThread.isRunning()){
networkThread.stopThread();
networkThread.wait(); // Wait for the network thread to finish gracefully
}
//if (networkThread.isRunning()){
// networkThread.stopThread();
// networkThread.wait(); // Wait for the network thread to finish gracefully
// }
//stop master(s)
for (int i = 0; i < devices.length(); i++)
if (devices[i]->deviceConfig.master != 0)

View File

@ -18,7 +18,7 @@ public:
QVector<Device*> devices;
EventBuilder eventBuilder;
NetworkThread networkThread;
// NetworkThread networkThread;
Device &operator [](int nr);
void addDevices(int nr_devices);

View File

@ -215,6 +215,21 @@ void MainWindow::startLogging()
}
}
void MainWindow::startAnalysing(){
if (analysing)
stopAnalysing();
analysing = 1;
}
void MainWindow::stopAnalysing()
{
analysing = 0;
}
void MainWindow::stopLogging()
{
theHW->eventBuilder.stopLogging();
@ -328,6 +343,14 @@ void MainWindow::on_pushLogging_pressed()
stopLogging();
}
void MainWindow::on_pushAnalysing_pressed()
{
if (!analysing)
startAnalysing();
else
stopAnalysing();
}
void MainWindow::on_pushDisplay_pressed()
{
if (theDisplay->isActive())

View File

@ -36,11 +36,13 @@ public:
QSettings* deviceSettings;
int running = 0;
int logging = 0;
int analysing = 0;
void run();
void stop();
void startLogging();
void stopLogging();
void startAnalysing();
void stopAnalysing();
void startDisplay();
void stopDisplay();
public slots:
@ -59,6 +61,7 @@ protected:
private slots:
void on_pushLogSettings_pressed();
void on_actionConnect_triggered();
void on_actionDisconnect_triggered();
void on_actionHost_IP_triggered();
@ -66,6 +69,8 @@ private slots:
void on_actionDevices_triggered();
void on_pushRun_pressed();
void on_pushLogging_pressed();
void on_pushAnalysing_pressed();
void on_pushDisplay_pressed();
void on_actionConnect_Keithley_triggered();
void on_actionDisconnect_Keithley_triggered();

View File

@ -93,6 +93,22 @@
<string>Quit</string>
</property>
</widget>
<widget class="QPushButton" name="pushAnalysing">
<property name="enabled">
<bool>true</bool>
</property>
<property name="geometry">
<rect>
<x>90</x>
<y>440</y>
<width>161</width>
<height>24</height>
</rect>
</property>
<property name="text">
<string>Start Analysing!</string>
</property>
</widget>
</widget>
<widget class="QMenuBar" name="menuBar">
<property name="geometry">
@ -100,7 +116,7 @@
<x>0</x>
<y>0</y>
<width>853</width>
<height>21</height>
<height>22</height>
</rect>
</property>
<widget class="QMenu" name="menuDevice">

Binary file not shown.

56
hit2023v2/udpserver.h Normal file
View File

@ -0,0 +1,56 @@
#ifndef UDPSERVER_H
#define UDPSERVER_H
#include <QObject>
#include <QVector>
#include <QThread>
#include <QUdpSocket>
class UDPServer : public QObject
{
Q_OBJECT
private:
QUdpSocket* udpSocket; // UDP socket for communication
quint16 serverPort = 12345; // Port number for the UDP server
public:
UDPServer(QObject* parent = nullptr) : QObject(parent)
{
// Initialize and configure your UDP server here
}
public slots:
void startServer()
{
// Start your UDP server here
udpSocket = new QUdpSocket(this);
// Bind the socket to a specific IP address and port
if ( udpSocket->bind(QHostAddress("10.0.7.1"), serverPort) )
{
connect(udpSocket, SIGNAL(readyRead()), this, SLOT(processPendingDatagrams()));
qDebug() << "UDP server started on port" << serverPort;
}
else
{
qWarning() << "Failed to bind UDP socket on port" << serverPort;
}
}
void stopServer()
{
// Stop your UDP server here
if (udpSocket)
{
udpSocket->close();
udpSocket->deleteLater();
}
qDebug() << "UDP server stopped";
}
// Add any other methods and signals relevant to your UDP server
};
#endif // UDPSERVER_H

View File

@ -0,0 +1,320 @@
915
917
947
971
981
964
977
980
965
969
965
975
961
967
979
959
978
978
982
976
964
962
971
976
948
957
977
970
950
981
978
962
983
960
980
958
980
978
973
949
963
969
970
982
982
978
971
974
979
976
976
980
982
968
972
961
973
976
982
983
948
981
952
969
992
990
1028
1032
1030
1033
1034
1023
1036
1024
1032
1030
1032
1026
1026
1026
1033
1033
1025
1039
1035
1041
1034
1055
1027
1036
1024
1021
1037
1028
1021
1033
1030
1047
1035
1037
1011
1049
1044
1028
1042
1032
1065
1035
1033
1033
1026
1037
1046
1039
1047
1035
1037
1023
1019
1046
1030
1031
1017
1038
1035
1036
1039
1008
990
992
1011
1050
1048
1043
1033
1051
1024
1040
1013
1015
1024
1054
1034
1046
1029
1041
1057
1053
1035
1045
1046
1047
1051
1064
1024
1037
1030
1040
1049
1049
1050
1023
1043
1053
1051
1045
1048
1056
1038
1020
1057
1033
1041
1029
1015
1043
1030
1033
1039
1047
1049
1075
1051
1040
1046
1051
1049
1038
1019
1044
1016
1040
947
960
958
1018
981
1005
984
982
998
983
993
981
981
985
986
1011
1002
982
986
988
992
988
1001
1002
998
996
993
1002
996
1001
992
996
993
979
978
974
1004
1013
1013
1005
988
982
1002
1010
988
1008
1011
1015
997
989
984
985
1020
1008
980
993
993
1012
1002
1001
1021
1001
1002
977
957
936
994
988
996
984
976
1005
1003
999
988
991
979
988
998
1002
1003
1001
1011
1011
989
998
1017
989
999
985
996
1013
996
999
993
991
1005
1004
1007
1001
1002
1013
987
983
997
1008
1011
1005
1011
983
978
999
1011
1013
999
1021
993
1007
1035
980
1012
1014
999
1007
1014
983
1014
972

View File

@ -0,0 +1,320 @@
889
855
854
864
880
904
876
867
877
888
885
903
873
899
905
889
864
905
886
867
889
903
888
867
892
902
889
886
891
906
917
874
902
914
915
923
887
888
879
902
906
901
876
881
886
899
888
926
904
901
894
897
898
900
892
882
888
895
893
886
864
887
897
868
863
880
883
898
867
878
888
879
882
903
899
893
886
879
873
889
900
891
877
883
895
892
897
889
885
887
880
881
898
884
901
881
914
900
900
886
894
902
891
889
883
884
899
902
873
885
878
886
882
898
895
900
897
898
902
898
895
901
881
891
889
887
903
890
836
827
847
854
865
853
866
860
870
874
860
876
845
856
853
847
846
858
852
855
853
858
867
869
855
848
850
862
867
873
864
862
865
844
851
867
841
874
890
868
867
855
895
888
868
870
871
867
885
862
881
882
860
869
865
863
889
870
854
863
883
892
868
837
922
931
949
950
957
957
953
935
942
950
950
961
962
956
956
954
951
982
955
974
962
962
957
954
963
964
973
962
963
969
950
955
958
957
947
964
968
953
948
959
958
963
969
969
966
971
961
972
970
972
966
968
971
956
957
949
944
929
935
973
964
942
959
947
929
921
922
953
921
948
943
947
968
957
950
941
929
937
940
936
941
960
956
952
932
928
921
944
951
946
935
941
943
962
952
946
940
931
935
952
942
931
946
928
943
944
949
958
941
956
925
937
942
957
950
946
944
964
939
933
969
945
953
951
956
942
948
948

View File

@ -0,0 +1,320 @@
292
2236
3354
3105
7221
9400
12401
13631
13691
13931
13820
14226
14262
14193
13841
12164
13073
14288
14708
14846
14607
14566
16327
16197
14976
13606
15111
15600
15104
15385
15585
15691
14442
15071
15404
14670
15226
15735
15885
15240
15421
15632
16418
16190
16396
16544
15611
16341
16292
15607
16837
16770
17584
17644
17259
16397
16245
16194
15645
15465
15829
16301
16352
15458
15709
16213
16426
14934
15597
15333
16580
15002
14353
13799
13907
14830
14998
14885
14920
14767
14467
13557
14248
14618
14087
14110
15946
16737
16667
16772
16794
16640
16436
16972
17241
16229
15695
14983
15890
16107
16291
16408
16613
14740
15041
17430
16539
15153
15607
15691
15877
16761
16481
15689
14962
15481
16829
17368
16976
16109
16325
17517
17986
17005
17225
17085
17721
17587
17660
17752
17974
18675
18316
17720
17612
17516
17415
17155
16846
14949
15134
16036
15515
14420
15595
15455
15903
15503
15831
15713
16079
15529
14932
15400
14932
14402
14036
13638
13295
11983
10865
12046
11275
10381
9449
8657
7414
8355
9042
7945
7151
7311
7157
7315
7118
7585
8448
10341
11301
10958
11201
10929
9803
8871
8421
8223
8315
7874
8251
7806
6670
6201
7470
7852
8363
8779
9532
11717
13115
11629
11103
10523
10391
10007
9355
7557
8805
8827
8506
8555
9192
9727
9243
8690
8686
8946
12062
15079
15874
15861
15842
16140
16235
16183
15863
16392
16435
15995
15766
16034
15759
15705
15344
15735
15857
15828
15255
14959
15338
15305
15537
15569
15663
15587
15485
14371
13474
13601
14865
15566
15473
14871
14575
14644
14473
14564
13554
13925
14119
13024
13263
13568
14021
13893
13724
13961
14120
14174
14798
14344
13661
13864
13873
13606
13835
13521
13510
13778
13621
13414
13537
13965
13682
13210
13867
14077
13843
13429
13986
13597
13745
14710
14062
13379
14384
13555
12435
12032
11849
12379
12928
13152
13373
13553
13792
13937
13379
13194
13383
13745
14034
14075
13900
13894
13561
13498
13373
12896
12759
13234

View File

@ -0,0 +1,320 @@
59
55
47
143
1221
4897
7637
11168
11616
11369
12995
14242
14300
15020
15670
15970
14825
15092
14423
14866
14131
14001
14161
14692
14121
14361
14495
14560
14560
14874
15295
15315
15335
15286
15077
13436
14987
14864
15092
15088
15300
15640
14271
15287
14538
14542
14180
14552
14665
13472
14836
14487
14001
14458
14442
14343
14528
14850
14372
15499
15323
15927
15899
16312
13760
13304
14078
13889
13917
13645
13786
14058
14011
13613
13661
13601
13703
13696
13843
13412
13311
13138
13396
13666
13831
13608
13748
13496
13764
13425
13614
13681
13285
13598
12987
13401
13088
12708
12927
13305
13256
13804
13891
13589
13084
12591
12189
12709
12716
12901
12823
13200
12987
13111
12949
12452
12073
12455
12980
13014
12724
12018
12189
12898
12054
12934
12521
12539
11278
11403
11340
11581
12107
11512
10728
11544
11225
11326
11323
11108
10458
10325
9554
10385
9803
7493
7532
10147
10140
10072
8807
8059
10109
10568
10439
11157
11312
11461
11417
11340
11348
11533
11505
11331
11152
11347
11915
11433
9679
10555
10725
11267
11366
11493
11161
11189
10803
10730
10840
10392
10619
10472
10304
10912
10703
10166
9948
8960
10034
9990
10197
10416
8959
8766
9190
9298
9236
8596
9092
9482
9790
9835
10088
9971
10062
10324
10341
9748
10072
10245
9441
9085
9683
9372
9169
9679
9806
8914
9044
8748
8290
8307
7325
7790
8837
9100
8261
8705
9385
9137
9316
9145
8356
8819
8496
8663
8133
7898
8784
9043
8561
8698
7944
7502
6689
7456
8129
8513
7800
8585
8504
8531
8308
8743
9198
9331
9113
8516
8569
8816
8617
9481
8963
8757
9096
9167
8956
8145
8567
8684
8800
9469
9210
9628
9948
9339
9643
9619
9925
9934
10249
10236
10815
10931
11116
10594
10234
10688
10141
10435
10545
10446
10467
10294
10355
10757
10567
10697
10606
10658
10497
10770
10869
11193
11234
11400
11468
11357
10930
10093
10511
10475
11062
10557
10463
10689
10545
10386
10344
10567

View File

@ -1,12 +1,13 @@
#include "datareceiver.h"
#include "dev_commands.h"
#include "helpers.h"
#include <iostream>
DataReceiver::DataReceiver(QObject *parent) : QObject(parent), dataBuffer(RECEIVER_BUFFER_SIZE)
{
connect(this, DataReceiver::sigInit, this, DataReceiver::onInit);
connect(this, DataReceiver::sigDeinit, this, DataReceiver::onDeinit);
connect(this, DataReceiver::sigConfigureEthSettings, this, DataReceiver::onConfigureEthSettings);
connect(this, &DataReceiver::sigInit, this, &DataReceiver::onInit);
connect(this, &DataReceiver::sigDeinit, this, &DataReceiver::onDeinit);
connect(this, &DataReceiver::sigConfigureEthSettings, this, &DataReceiver::onConfigureEthSettings);
moveToThread(&thread);
thread.start();
@ -32,13 +33,15 @@ void DataReceiver::readData()
while ((size_received_bytes = dataSocket->readDatagram(tmpBuffer, DATA_PACKET_SIZE)) > 0)
{
//look if the packet isn't too short
int expected_size_bytes = ethBunch * (DATA_PACKET_HEADER_SIZE + DATA_SYNC_HEADER_SIZE + dmaBunch*DATA_BLOCK_SIZE);
if (size_received_bytes < expected_size_bytes)
int expected_size_bytes = ethBunch * (DATA_PACKET_HEADER_SIZE + DATA_SYNC_HEADER_SIZE + dmaBunch*DATA_BLOCK_SIZE + DATA_RMS_FRAME_SIZE);
if (size_received_bytes != expected_size_bytes)
{
std::cout << "packet error. Got" << size_received_bytes << " bytes expected" << expected_size_bytes << std::endl;
continue;
}
for (int ethb = 0; ethb < ethBunch; ethb++)
{
int baseaddr = ethb * (DATA_PACKET_HEADER_SIZE + DATA_SYNC_HEADER_SIZE + dmaBunch*DATA_BLOCK_SIZE);
int baseaddr = ethb * (DATA_PACKET_HEADER_SIZE + DATA_SYNC_HEADER_SIZE + dmaBunch*DATA_BLOCK_SIZE + DATA_RMS_FRAME_SIZE);
//check the header
if (BYTES2SHORT(tmpBuffer+baseaddr+0) != 0x5555)
@ -56,6 +59,8 @@ void DataReceiver::readData()
sync.device_nr = devNr;
sync.data_ok = 1;
RMSFrame rms;
for (int dmab=0; dmab<dmaBunch; dmab++)
{
framesReceived++;
@ -63,15 +68,18 @@ void DataReceiver::readData()
if (outputEnabled)
{
BufferData data_to_push(sensorsPerBoard * DATA_SAMPLES_PER_SENSOR); //todo is this big enough
BufferData data_to_push(sensorsPerBoard * DATA_SAMPLES_PER_SENSOR);
data_to_push.sync_frame = sync;
int baseaddr3 = baseaddr2 + DATA_PACKET_HEADER_SIZE + DATA_SYNC_HEADER_SIZE;
for (int s = 0; s < (sensorsPerBoard * DATA_SAMPLES_PER_SENSOR); s++)
data_to_push.sensor_data[s] = 65535 - BYTES2SHORT(tmpBuffer + baseaddr3 + 2*s);
for (int i = 0; i < DATA_RMS_SIZE/4; i++)
data_to_push.rms_data[i] = BYTES2INT(tmpBuffer + baseaddr3 + 2 * sensorsPerBoard * DATA_SAMPLES_PER_SENSOR + 4 * i); //what is baseaddr3?
rms.mean = BYTES2SHORT(tmpBuffer+baseaddr+DATA_PACKET_HEADER_SIZE+DATA_SYNC_HEADER_SIZE+DATA_BLOCK_SIZE);
rms.sigma = BYTES2SHORT(tmpBuffer+baseaddr+DATA_PACKET_HEADER_SIZE+DATA_SYNC_HEADER_SIZE+DATA_BLOCK_SIZE + 2);
rms.max = BYTES2SHORT(tmpBuffer+baseaddr+DATA_PACKET_HEADER_SIZE+DATA_SYNC_HEADER_SIZE+DATA_BLOCK_SIZE + 4);
rms.status = BYTES2SHORT(tmpBuffer+baseaddr+DATA_PACKET_HEADER_SIZE+DATA_SYNC_HEADER_SIZE+DATA_BLOCK_SIZE + 6);
data_to_push.rms_frame = rms;
dataBuffer.push(data_to_push);
framesFromLastSig++;
@ -100,13 +108,13 @@ void DataReceiver::onInit()
if (dataSocket == NULL)
{
dataSocket = new QUdpSocket(this);
connect(dataSocket, QUdpSocket::readyRead, this, DataReceiver::readData);
connect(dataSocket, &QUdpSocket::readyRead, this, &DataReceiver::readData);
}
if (timer == NULL)
{
timer = new QTimer(this);
connect(timer, QTimer::timeout, this, onTimer);
connect(timer, &QTimer::timeout, this, &DataReceiver::onTimer);
timer->start(RECEIVER_TIMER_PERIOD_MS);
}

View File

@ -11,24 +11,18 @@
#define DATA_PACKET_HEADER_SIZE 6
#define DATA_SYNC_HEADER_SIZE 6
#define DATA_RMS_FRAME_SIZE 16 //8 unsigned short
#define DATA_BYTES_PER_SAMPLE 2
#define DATA_SAMPLES_PER_SENSOR 64
#define DATA_MAX_SENSORS_PER_BOARD 5
#define DATA_MAX_BUNCH 16 //max. product of dmaBunch * ethBunch
//new for RMS
#define DATA_RMS_MEAN 4 //bytes, 32 bits
#define DATA_RMS_STD 4
#define DATA_RMS_MAX 4
#define DATA_RMS_STATUS 4
#define DATA_RMS_SIZE (DATA_RMS_MEAN + DATA_RMS_STD + DATA_RMS_MAX + DATA_RMS_STATUS)
//end new for RMS
//#define DATA_BLOCK_SIZE (DATA_SENSORS_PER_BOARD * DATA_SAMPLES_PER_SENSOR * DATA_BYTES_PER_SAMPLE)
#define DATA_BLOCK_SIZE (sensorsPerBoard * DATA_SAMPLES_PER_SENSOR * DATA_BYTES_PER_SAMPLE + DATA_RMS_SIZE)
#define DATA_PACKET_SIZE ( DATA_MAX_BUNCH * (DATA_PACKET_HEADER_SIZE + DATA_SYNC_HEADER_SIZE + DATA_BLOCK_SIZE) )
#define DATA_BLOCK_SIZE (sensorsPerBoard * DATA_SAMPLES_PER_SENSOR * DATA_BYTES_PER_SAMPLE)
#define DATA_PACKET_SIZE ( DATA_MAX_BUNCH * (DATA_PACKET_HEADER_SIZE + DATA_SYNC_HEADER_SIZE + DATA_BLOCK_SIZE + DATA_RMS_FRAME_SIZE ) )
#define DATA_MAX_BLOCK_SIZE (DATA_MAX_SENSORS_PER_BOARD * DATA_SAMPLES_PER_SENSOR * DATA_BYTES_PER_SAMPLE + DATA_RMS_SIZE)
#define DATA_MAX_PACKET_SIZE ( DATA_MAX_BUNCH * (DATA_PACKET_HEADER_SIZE + DATA_SYNC_HEADER_SIZE + DATA_MAX_BLOCK_SIZE) )
#define DATA_MAX_BLOCK_SIZE (DATA_MAX_SENSORS_PER_BOARD * DATA_SAMPLES_PER_SENSOR * DATA_BYTES_PER_SAMPLE)
#define DATA_MAX_PACKET_SIZE ( DATA_MAX_BUNCH * (DATA_PACKET_HEADER_SIZE + DATA_SYNC_HEADER_SIZE + DATA_MAX_BLOCK_SIZE + DATA_RMS_FRAME_SIZE ) )
#define RECEIVER_BUFFER_SIZE 10000
@ -47,13 +41,21 @@ typedef struct
int data_ok;
} SyncFrame;
typedef struct{
unsigned short mean;
unsigned short sigma;
unsigned short max;
unsigned short status;
unsigned short registers[4];
} RMSFrame;
class BufferData
{
public:
SyncFrame sync_frame;
RMSFrame rms_frame;
int buffer_size;
signed short* sensor_data;
int rms_data[DATA_RMS_SIZE/4];
BufferData() : buffer_size(0), sensor_data(NULL) {}
@ -79,9 +81,9 @@ public:
BufferData(const BufferData& master) : buffer_size(0), sensor_data(NULL)
{
sync_frame = master.sync_frame;
rms_frame = master.rms_frame;
resize(master.buffer_size);
memcpy(sensor_data, master.sensor_data, buffer_size*sizeof(signed short));
memcpy(rms_data, master.rms_data, DATA_RMS_SIZE);
}
BufferData& operator=(const BufferData& master)
@ -89,9 +91,9 @@ public:
if (this == &master)
return *this; //self-assignment
sync_frame = master.sync_frame;
rms_frame = master.rms_frame;
resize(master.buffer_size);
memcpy(sensor_data, master.sensor_data, buffer_size*sizeof(signed short));
memcpy(rms_data, master.rms_data, DATA_RMS_SIZE);
return *this;
}

View File

@ -9,7 +9,7 @@ Plane=0
Position=0
Sensors=5
Master=1
MasterDelay=62
MasterDelay=61
SlaveDelay=34
[Device1]
@ -23,12 +23,12 @@ MasterDelay=7
SlaveDelay=1
[Trigger]
Period=8999
Period=9000
Tint=8491
Gain=1
Period_v2=2500
Tint_v2=336
Gain_v2=1
Gain=0
Period_v2=2499
Tint_v2=335
Gain_v2=0
[Device2]
IP=10.0.7.5

View File

@ -0,0 +1,31 @@
[Global]
NrDevices=2
HostIp=10.0.7.1
[Device0]
IP=10.0.7.17
HardwareVer=2
Plane=0
Position=0
Sensors=5
Master=1
MasterDelay=62
SlaveDelay=34
[Device1]
IP=10.0.7.18
HardwareVer=2
Plane=1
Position=0
Sensors=5
Master=0
MasterDelay=7
SlaveDelay=1
[Trigger]
Period=9000
Tint=1000
Gain=1
Period_v2=2500
Tint_v2=336
Gain_v2=1

View File

@ -22,7 +22,7 @@ DialogBeta::DialogBeta(QWidget *parent) :
DialogBeta::~DialogBeta()
{
timer.stop();
disconnect(&timer, QTimer::timeout, this, &DialogBeta::onTimer);
disconnect(&timer, &QTimer::timeout, this, &DialogBeta::onTimer);
delete ui;
}
@ -35,9 +35,9 @@ void DialogBeta::showEvent(QShowEvent * event)
ui->lineRunsDone->setText(QString("%1").arg(nrRunsDone));
//data logging possible only if global data logging is switched off
if (theHW->eventBuilder.isLogging())
ui->checkSaveRawData->setEnabled(FALSE);
ui->checkSaveRawData->setEnabled(false);
connect(&timer, QTimer::timeout, this, &DialogBeta::onTimer);
connect(&timer, &QTimer::timeout, this, &DialogBeta::onTimer);
timer.start(250);
}
}

View File

@ -80,14 +80,14 @@ void DialogLinearity::run()
//Collect sensor data
histoReady = 0;
connect(&(theHW->eventBuilder), EventBuilder::sigHistoCompleted, this, DialogLinearity::onHistogramCompleted);
connect(&(theHW->eventBuilder), &EventBuilder::sigHistoCompleted, this, &DialogLinearity::onHistogramCompleted);
theHW->eventBuilder.startTakingHistos(nacqs);
while (!histoReady)
{
QCoreApplication::processEvents();
QThread::msleep(10);
}
disconnect(&(theHW->eventBuilder), EventBuilder::sigHistoCompleted, this, DialogLinearity::onHistogramCompleted);
disconnect(&(theHW->eventBuilder), &EventBuilder::sigHistoCompleted, this, &DialogLinearity::onHistogramCompleted);
QVector<Histogram> histos = theHW->eventBuilder.getHistos();
result.mean.fill(0, nr_devices*128);

View File

@ -99,7 +99,7 @@
<item row="0" column="1">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Display</string>
<string>BPMDisplay</string>
</property>
</widget>
</item>

View File

@ -57,14 +57,14 @@ void DialogProfiler::run(int nr_loops)
//Collect sensor data
histoReady = 0;
connect(&(theHW->eventBuilder), EventBuilder::sigHistoCompleted, this, DialogProfiler::onHistogramCompleted);
connect(&(theHW->eventBuilder), &EventBuilder::sigHistoCompleted, this, &DialogProfiler::onHistogramCompleted);
theHW->eventBuilder.startTakingHistos(nacqs);
while (!histoReady)
{
QCoreApplication::processEvents();
QThread::msleep(10);
}
disconnect(&(theHW->eventBuilder), EventBuilder::sigHistoCompleted, this, DialogProfiler::onHistogramCompleted);
disconnect(&(theHW->eventBuilder), &EventBuilder::sigHistoCompleted, this, &DialogProfiler::onHistogramCompleted);
QVector<Histogram> histos = theHW->eventBuilder.getHistos();
result.mean.fill(0, nr_devices*128);

View File

@ -106,14 +106,14 @@ void DialogTiScan::run()
//Collect sensor data
histoReady = 0;
connect(&(theHW->eventBuilder), EventBuilder::sigHistoCompleted, this, DialogTiScan::onHistogramCompleted);
connect(&(theHW->eventBuilder), &EventBuilder::sigHistoCompleted, this, &DialogTiScan::onHistogramCompleted);
theHW->eventBuilder.startTakingHistos(nacqs);
while (!histoReady)
{
QCoreApplication::processEvents();
QThread::msleep(10);
}
disconnect(&(theHW->eventBuilder), EventBuilder::sigHistoCompleted, this, DialogTiScan::onHistogramCompleted);
disconnect(&(theHW->eventBuilder), &EventBuilder::sigHistoCompleted, this, &DialogTiScan::onHistogramCompleted);
QVector<Histogram> histos = theHW->eventBuilder.getHistos();
result.mean.fill(0, nr_devices*128);

View File

@ -0,0 +1,230 @@
#include "dialogtiscan.h"
#include "ui_dialogtiscan.h"
#define RUNNING 1
#define STOPPED 0
#define STOP_ISSUED -1
DialogTiScan::DialogTiScan(QWidget *parent) :
QDialog(parent),
ui(new Ui::DialogTiScan)
{
ui->setupUi(this);
runState = STOPPED;
}
DialogTiScan::~DialogTiScan()
{
delete ui;
}
void DialogTiScan::showEvent(QShowEvent * event)
{
if (!event->spontaneous())
{
if (!theKeithley->isOpen)
ui->checkUseLED->setEnabled(false);
}
QDialog::showEvent(event);
}
//************** Processing ***************
void DialogTiScan::run()
{
runState = RUNNING;
qInfo("Starting integration time scan...");
//Prepare measurement
ui->plotResultsMean->clearGraphs();
ui->plotResultsStd->clearGraphs();
results.clear();
int nr_devices = theHW->devices.length();
int use_led = ui->checkUseLED->isChecked();
double ledv = ui->doubleSpinLEDV->value();
int decimation = ui->spinPLotDecimation->value();
int nacqs = ui->spinAcquisitions->value();
int tstart = ui->spintStart->value();
int tend = ui->spinTEnd->value();
int tinc = ui->spinTIncrement->value();
int tcurrent = tstart;
//Plot data
QVector<double> xdata;
QList<QVector<double>> ymeandata;
QList<QVector<double>> ystddata;
for (int ch = 0; ch < (nr_devices*128); ch+= decimation)
{
ymeandata.append(xdata); //just add empty vectors to the list
ystddata.append(xdata); //just add empty vectors to the list
}
//The number of plotted lines is smaller than number of channels - see decimation
for (int plotnr = 0; plotnr < nr_devices*128; plotnr++)
{
ui->plotResultsMean->addGraph();
ui->plotResultsStd->addGraph();
}
double xmin = 1e+10;
double xmax = -1e+10;
double ymeanmin = 1e+10;
double ymeanmax = -1e+10;
double ystdmin = 1e+10;
double ystdmax = -1e+10;
if (use_led)
{
theKeithley->setVoltage(ledv);
theKeithley->on(1);
}
theHW->run();
//Measure!
while ((runState != STOP_ISSUED) && (tcurrent <= tend))
{
//Set LED voltage
qInfo(qPrintable(QString("Integration time: %1 ").arg(tcurrent)));
//set up integration time for all devices
theHW->stop();
for (int dev_nr = 0; dev_nr < theHW->devices.length(); dev_nr++)
{
DeviceConfig dc = theHW->devices[dev_nr]->deviceConfig;
dc.tint = tcurrent;
theHW->devices[dev_nr]->configure(dc);
}
theHW->run();
TiScanResult result;
//Collect sensor data
histoReady = 0;
connect(&(theHW->eventBuilder), EventBuilder::sigHistoCompleted, this, DialogTiScan::onHistogramCompleted);
theHW->eventBuilder.startTakingHistos(nacqs);
while (!histoReady)
{
QCoreApplication::processEvents();
QThread::msleep(10);
}
disconnect(&(theHW->eventBuilder), EventBuilder::sigHistoCompleted, this, DialogTiScan::onHistogramCompleted);
QVector<Histogram> histos = theHW->eventBuilder.getHistos();
result.mean.fill(0, nr_devices*128);
result.std.fill(0, nr_devices*128);
for (int i = 0; i < result.mean.length(); i++)
{
histos[i].MS(&(result.mean[i]), &(result.std[i]));
//result.mean[i] = histos[i].mean();
//result.std[i] = histos[i].stdev();
}
//Add information on integration time
result.tint = tcurrent;
results.append(result);
//Plot data...
xdata.append(result.tint);
if (result.tint > xmax)
xmax = result.tint;
if (result.tint < xmin)
xmin = result.tint;
for (int ch = 0, i = 0; ch < (nr_devices*128); ch+= decimation, i++)
{
ymeandata[i].append(result.mean[ch]);
if (result.mean[ch] > ymeanmax)
ymeanmax = result.mean[ch];
if (result.mean[ch] < ymeanmin)
ymeanmin = result.mean[ch];
ystddata[i].append(result.std[ch]);
if (result.std[ch] > ystdmax)
ystdmax = result.std[ch];
if (result.std[ch] < ystdmin)
ystdmin = result.std[ch];
}
ui->plotResultsMean->xAxis->setRange(xmin, xmax);
ui->plotResultsMean->yAxis->setRange(ymeanmin, ymeanmax);
ui->plotResultsStd->xAxis->setRange(xmin, xmax);
ui->plotResultsStd->yAxis->setRange(ystdmin, ystdmax);
for (int ch = 0, i = 0; ch < (nr_devices*128); ch+= decimation, i++)
{
ui->plotResultsMean->graph(i)->setData(xdata, ymeandata[i]);
ui->plotResultsStd->graph(i)->setData(xdata, ystddata[i]);
}
ui->plotResultsMean->replot();
ui->plotResultsStd->replot();
//Roll over
tcurrent += tinc;
QCoreApplication::processEvents();
}
if (use_led)
theKeithley->on(0);
theHW->stop();
qInfo("Integration time scan finished!");
runState = STOPPED;
}
//************** Slots ****************
void DialogTiScan::onHistogramCompleted()
{
histoReady = 1;
}
void DialogTiScan::on_pushRun_pressed()
{
if (runState)
{
runState = STOP_ISSUED;
}
else
{
ui->pushRun->setText("Stop");
ui->pushSave->setEnabled(false);
run();
ui->pushRun->setText("Run");
ui->pushSave->setEnabled(true);
}
}
void DialogTiScan::on_pushSave_pressed()
{
QString filename = QFileDialog::getSaveFileName(this, "Select file for saving data", "", tr("Comma separated files (*.csv)"));
QString delimiter = QString(",");
if (filename.length() == 0)
return;
QFile file(filename);
if (!file.open(QIODevice::WriteOnly | QIODevice::Text))
return;
QTextStream out(&file);
out << qSetFieldWidth(14) << qSetRealNumberPrecision(8);
for (int row = 0; row < results.length(); row++)
{
out << results[row].tint;
for (int col = 0; (col < results[row].mean.length()) && (col < results[row].std.length()); col++)
out << delimiter << results[row].mean[col] << delimiter << results[row].std[col];
out << QString("\n");
}
file.close();
}

View File

@ -3,8 +3,9 @@
#include <QMessageBox>
#include <QFileDialog>
#include <QCheckBox>
#include <iostream>
Display::Display(QWidget *parent) :
BPMDisplay::BPMDisplay(QWidget *parent) :
QDialog(parent),
ui(new Ui::display)
{
@ -27,34 +28,31 @@ Display::Display(QWidget *parent) :
// Connect the buttonClicked signal of the button group
connect(buttonGroup, SIGNAL(buttonClicked(QAbstractButton*)), this, SLOT(onButtonClicked(QAbstractButton*)));
connect(ui->pushButton_savebkg, &QPushButton::clicked, this, &Display::onSaveBackgroundClicked);
connect(ui->pushButton_loadbkg, &QPushButton::clicked, this, &Display::onLoadBackgroundClicked);
connect(ui->checkBox_subbkg, &QCheckBox::stateChanged, this, &Display::onCheckBoxStateChanged);
connect(ui->pushButton_savecalib, &QPushButton::clicked, this, &Display::onSaveCalibrationClicked);
connect(ui->pushButton_loadcalib, &QPushButton::clicked, this, &Display::onLoadCalibrationClicked);
connect(ui->checkBox_expertmode, &QCheckBox::stateChanged, this, &Display::onExpertModeStateChanged);
connect(ui->pushButton_savecalib, &QPushButton::clicked, this, &BPMDisplay::onSaveCalibrationClicked);
connect(ui->pushButton_loadcalib, &QPushButton::clicked, this, &BPMDisplay::onLoadCalibrationClicked);
connect(ui->checkBox_enablecalib, &QCheckBox::stateChanged, this, &BPMDisplay::onCalibrationCheckBoxChanged);
connect(ui->checkBox_expertmode, &QCheckBox::stateChanged, this, &BPMDisplay::onExpertModeStateChanged);
// Enable or disable the "Save Background" and "Save Calib" buttons accordingly
ui->pushButton_savebkg->setEnabled(expertModeEnabled);
ui->pushButton_savecalib->setEnabled(expertModeEnabled);
// Gray out the buttons when they are disabled
ui->pushButton_savebkg->setStyleSheet(expertModeEnabled ? "" : "background-color: gray;");
ui->pushButton_savecalib->setStyleSheet(expertModeEnabled ? "" : "background-color: gray;");
}
Display::~Display()
BPMDisplay::~BPMDisplay()
{
delete ui;
}
void Display::showEvent(QShowEvent * event)
void BPMDisplay::showEvent(QShowEvent * event)
{
if (!event->spontaneous())
{
ui->plot->addGraph();
ui->plot->addGraph();
}
QDialog::showEvent(event);
@ -62,9 +60,9 @@ void Display::showEvent(QShowEvent * event)
//***********************************************
void Display::plot(const QVector<signed short> &data)
void BPMDisplay::plot(const QVector<signed short> &data, const QVector<signed short> &rmsdata)
{
//resize data vectors and fill X values - only if needed
//resize data vectors and fill X values - only if needed
if (data.length() != nrPoints)
{
nrPoints = data.length();
@ -80,7 +78,7 @@ void Display::plot(const QVector<signed short> &data)
dataX[i] = i;
}
//fill Y values
//fill Y values
double min = 65535;
double max = 0;
for (int i = 0; i < nrPoints; i++)
@ -95,34 +93,20 @@ void Display::plot(const QVector<signed short> &data)
QString planeName = ui->lineTitle->text();
planeName.remove(QChar(' '));
if (subtractBackground && ui->checkBox_subbkg->isChecked()) {
// Check if background subtraction is enabled and the checkbox is checked
// Check if background data exists for this plane
if (backgroundDataMap.contains(planeName)) {
const QVector<signed short> &backgroundData = backgroundDataMap[planeName];
// Subtract background data from the current data
for (int i = 0; i < nrPoints; ++i) {
dataY[i] -= backgroundData[i];
}
}
}
if (applyCalibration && ui->checkBox_enablecalib->isChecked()) {
// Check if calibration is enabled and the checkbox is checked
// Check if calibration data exists
if (calibrationDataMap.contains(planeName) ){
const QVector<signed short> &calibrationData = calibrationDataMap[planeName];
const QVector<float> &calibrationData = calibrationDataMap[planeName];
// Apply calibration to the current data
for (int i = 0; i < nrPoints; ++i) {
dataY[i] = dataY[i] / calibrationData[i];
dataY[i] = int(dataY[i] * calibrationData[i]);
}
}
}
//set Y range
//set Y range
if (ui->radioButtonAutoscale->isChecked())
ui->plot->yAxis->setRange(min-0.05*(max-min),max+0.05*(max-min));
@ -131,25 +115,94 @@ void Display::plot(const QVector<signed short> &data)
else
ui->plot->yAxis->setRange(-1000,66000);
//feed plotter
//feed plotter
ui->plot->graph(0)->setData(dataX, dataY);
updateMean((rmsdata[0]));
updateRms((rmsdata[1]));
updateMax((rmsdata[2]));
updateStatus((rmsdata[3]));
//plot
//plot
ui->plot->replot();
}
void Display::plot()
void BPMDisplay::plot(const QVector<signed short> &data)
{
plot(buffer);
//resize data vectors and fill X values - only if needed
if (data.length() != nrPoints)
{
nrPoints = data.length();
dataX.clear();
dataY.clear();
dataX.resize(nrPoints);
dataY.resize(nrPoints);
ui->plot->xAxis->setRange(0,nrPoints-1);
//ui->plot->yAxis->setRange(-1000,66000);
for (int i = 0; i < nrPoints; i++)
dataX[i] = i;
}
//fill Y values
double min = 65535;
double max = 0;
for (int i = 0; i < nrPoints; i++)
{
dataY[i] = /*65535 -*/ data[i];
if (dataY[i] < min)
min = dataY[i];
if (dataY[i] > max)
max = dataY[i];
}
QString planeName = ui->lineTitle->text();
planeName.remove(QChar(' '));
if (applyCalibration && ui->checkBox_enablecalib->isChecked()) {
// Check if calibration is enabled and the checkbox is checked
// Check if calibration data exists
if (calibrationDataMap.contains(planeName) ){
const QVector<float> &calibrationData = calibrationDataMap[planeName];
// Apply calibration to the current data
for (int i = 0; i < nrPoints; ++i) {
dataY[i] = int(dataY[i] * calibrationData[i]);
}
}
}
//set Y range
if (ui->radioButtonAutoscale->isChecked())
ui->plot->yAxis->setRange(min-0.05*(max-min),max+0.05*(max-min));
else if (ui->radioButtonFixedScale ->isChecked())
ui->plot->yAxis->setRange(ui->spinBox_fixedmin->value(), ui->spinBox_fixedmax->value());
else
ui->plot->yAxis->setRange(-1000,66000);
//feed plotter
ui->plot->graph(0)->setData(dataX, dataY);
//plot
ui->plot->replot();
}
void Display::setTitle(QString title)
void BPMDisplay::plot()
{
plot(buffer, rmsbuffer);
}
void BPMDisplay::setTitle(QString title)
{
ui->lineTitle->setText(title);
}
// Slot to handle button clicks
void Display::onButtonClicked(QAbstractButton *button)
void BPMDisplay::onButtonClicked(QAbstractButton *button)
{
// Handle button clicks here
if (button == radioButtonFixedScale)
@ -170,7 +223,7 @@ void Display::onButtonClicked(QAbstractButton *button)
}
}
void Display::onSaveBackgroundClicked()
void BPMDisplay::onSaveBackgroundClicked()
{
// Check if there is data to save
if (buffer.isEmpty()) {
@ -208,7 +261,7 @@ void Display::onSaveBackgroundClicked()
}
}
void Display::onLoadBackgroundClicked()
void BPMDisplay::onLoadBackgroundClicked()
{
// Get the plane's name (you might need to adjust how you retrieve it)
QString planeName = ui->lineTitle->text();
@ -228,7 +281,7 @@ void Display::onLoadBackgroundClicked()
QVector<signed short> backgroundData;
while (!stream.atEnd()) {
QString line = stream.readLine();
signed short value = line.toShort();
unsigned short value = line.toUShort();
backgroundData.append(value);
}
@ -246,13 +299,13 @@ void Display::onLoadBackgroundClicked()
}
}
void Display::onCheckBoxStateChanged(int state)
void BPMDisplay::onCheckBoxStateChanged(int state)
{
// The state argument will be Qt::Unchecked (0) or Qt::Checked (2)
subtractBackground = (state == Qt::Checked);
}
void Display::onSaveCalibrationClicked()
void BPMDisplay::onSaveCalibrationClicked()
{
// Check if there is data to save
@ -261,6 +314,10 @@ void Display::onSaveCalibrationClicked()
return;
}
// Get the plane's name (you might need to adjust how you retrieve it)
QString planeName = ui->lineTitle->text();
@ -272,12 +329,16 @@ void Display::onSaveCalibrationClicked()
// Open the file for writing
QFile file(filename);
const QVector<signed short> &backgroundData = backgroundDataMap[planeName];
if (file.open(QIODevice::WriteOnly | QIODevice::Text)) {
QTextStream stream(&file);
// Write the data to the file
for (int i = 0; i < buffer.size(); ++i) {
stream << QString::number(buffer[i]) << "\n";
stream << QString::number(buffer[i] - backgroundData[i]) << "\n";
}
// Close the file
@ -291,7 +352,7 @@ void Display::onSaveCalibrationClicked()
}
}
void Display::onLoadCalibrationClicked()
void BPMDisplay::onLoadCalibrationClicked()
{
// Get the plane's name (you might need to adjust how you retrieve it)
QString planeName = ui->lineTitle->text();
@ -308,10 +369,10 @@ void Display::onLoadCalibrationClicked()
QTextStream stream(&file);
// Read the data from the file and store it in a vector
QVector<signed short> calibrationData;
QVector<float> calibrationData;
while (!stream.atEnd()) {
QString line = stream.readLine();
signed short value = line.toShort();
float value = line.toFloat();
calibrationData.append(value);
}
@ -319,17 +380,17 @@ void Display::onLoadCalibrationClicked()
file.close();
// Normalize the calibration data to the median value of all values greater than zero
QVector<signed short> normalizedCalibrationData = calibrationData; // Copy the data
QVector<signed short> normalizedCalibrationData2 = calibrationData; // Copy the data again
QVector<float> normalizedCalibrationData = calibrationData; // Copy the data
QVector<float> normalizedCalibrationData2 = calibrationData; // Copy the data again
// Remove values less than 50 (noise or dead channels) before determining the median for live channels
normalizedCalibrationData.erase(std::remove_if(normalizedCalibrationData.begin(), normalizedCalibrationData.end(), [](signed short value) {
normalizedCalibrationData.erase(std::remove_if(normalizedCalibrationData.begin(), normalizedCalibrationData.end(), [](unsigned short value) {
return value < 50;
}), normalizedCalibrationData.end());
std::sort(normalizedCalibrationData.begin(), normalizedCalibrationData.end()); // Sort the data
int size = normalizedCalibrationData.size();
signed short medianValue = 0;
float medianValue = 0;
if (size % 2 == 0) {
// If the size is even, take the average of the two middle values
@ -339,45 +400,68 @@ void Display::onLoadCalibrationClicked()
medianValue = normalizedCalibrationData[size / 2];
}
//use the second copy to return the scaled calibration values.
for (signed short &value : normalizedCalibrationData2) {
if (value > 50) {
value /= medianValue;
}
else
{
value = 0;
if (medianValue>100){
//use the second copy to return the scaled calibration values.
for (auto &value : normalizedCalibrationData2) {
if (value > 50) {
value = medianValue / value;
}
else
{
value = 0;
}
// std::cerr << value << " ";
}
// std::cerr << std::endl;
// Store the normalized calibration data in the map
calibrationDataMap[planeName] = normalizedCalibrationData2;
// Notify the user that the data has been loaded and normalized
qInfo() << "Calibration data loaded and normalized for" << planeName;
}
else{
qWarning() << " Warning: MedianValue of calibration data too low. Not applied. ";
}
// Store the normalized calibration data in the map
calibrationDataMap[planeName] = normalizedCalibrationData2;
// Notify the user that the data has been loaded and normalized
qInfo() << "Calibration data loaded and normalized for" << planeName;
} else {
// Failed to open the file
qWarning() << "Error: Failed to open" << filename << "for reading";
qWarning() << "Warning: Failed to open" << filename << "for reading";
}
}
void Display::onCalibrationCheckBoxChanged(int state) {
void BPMDisplay::onCalibrationCheckBoxChanged(int state) {
// Check the state and update the subtractCalibration flag accordingly
applyCalibration = (state == Qt::Checked);
}
// Slot to handle the state change of the "Expert Mode" checkbox
void Display::onExpertModeStateChanged(int state)
void BPMDisplay::onExpertModeStateChanged(int state)
{
// Check if the checkbox is checked (Expert Mode enabled)
expertModeEnabled = (state == Qt::Checked);
// Enable or disable the "Save Background" and "Save Calib" buttons accordingly
ui->pushButton_savebkg->setEnabled(expertModeEnabled);
ui->pushButton_savecalib->setEnabled(expertModeEnabled);
// Gray out the buttons when they are disabled
ui->pushButton_savebkg->setStyleSheet(expertModeEnabled ? "" : "background-color: gray;");
ui->pushButton_savecalib->setStyleSheet(expertModeEnabled ? "" : "background-color: gray;");
}
void BPMDisplay::updateMean(unsigned short value)
{
ui->lcdNumber_mean->display((value));
}
void BPMDisplay::updateRms(unsigned short value)
{
ui->lcdNumber_focus->display(value);
}
void BPMDisplay::updateMax(unsigned short value)
{
ui->lcdNumber_max->display((value));
}
void BPMDisplay::updateStatus(unsigned short value)
{
ui->lcdNumber_status->display((value));
}

View File

@ -8,25 +8,30 @@
#include <QTextStream>
#include <QFile>
#include <QCheckBox>
#include <QLCDNumber>
namespace Ui {
class display;
}
class Display : public QDialog
class BPMDisplay : public QDialog
{
Q_OBJECT
public:
explicit Display(QWidget *parent = 0);
~Display();
explicit BPMDisplay(QWidget *parent = 0);
~BPMDisplay();
void plot(const QVector<signed short> &data);
void plot();
void plot(const QVector<signed short> &data, const QVector<signed short> &rmsdata);
void setTitle(QString title);
QVector<signed short> buffer;
QVector<signed short> rmsbuffer;
public slots:
void showEvent(QShowEvent *event);
@ -38,11 +43,20 @@ public slots:
void onLoadCalibrationClicked();
void onCalibrationCheckBoxChanged(int state);
void onExpertModeStateChanged(int state);
void updateMean(unsigned short value);
void updateRms(unsigned short value);
void updateMax(unsigned short value);
void updateStatus(unsigned short value);
protected:
int nrPoints = 0;
QVector<double> dataX;
QVector<double> dataY;
QVector<signed short> dataRMS;
private:
Ui::display *ui;
QRadioButton *radioButtonFixedScale; // Pointer to the Fixed Scale radio button
@ -51,11 +65,16 @@ private:
QMap<QString, QVector<signed short>> backgroundDataMap; // Map to store background data for each plane
bool subtractBackground = false; // Flag to track if background subtraction is enabled
QMap<QString, QVector<signed short>> calibrationDataMap; // Map to store calibration data for each plane
QMap<QString, QVector<float>> calibrationDataMap; // Map to store calibration data for each plane
bool applyCalibration = false; // Flag to track if calibration should be applied
QVector<signed short> calibrationData; // Stores the loaded calibration data
QVector<float> calibrationData; // Stores the loaded calibration data
QCheckBox *checkBoxExpertMode; // Expert Mode checkbox
bool expertModeEnabled = false; // Flag to track if expert mode is enabled
QLCDNumber * lcdNumber_mean;
QLCDNumber * lcdNumber_focus;
QLCDNumber * lcdNumber_max;
QLCDNumber * lcdNumber_status;
};
#endif // DISPLAY_H

View File

@ -0,0 +1,61 @@
#ifndef DISPLAY_H
#define DISPLAY_H
#include <QDialog>
#include <QVector>
#include <QRadioButton>
#include <QButtonGroup>
#include <QTextStream>
#include <QFile>
#include <QCheckBox>
namespace Ui {
class display;
}
class Display : public QDialog
{
Q_OBJECT
public:
explicit Display(QWidget *parent = 0);
~Display();
void plot(const QVector<unsigned short> &data);
void plot();
void setTitle(QString title);
QVector<unsigned short> buffer;
public slots:
void showEvent(QShowEvent *event);
void onButtonClicked(QAbstractButton *button);
void onSaveBackgroundClicked();
void onLoadBackgroundClicked();
void onCheckBoxStateChanged(int state);
void onSaveCalibrationClicked();
void onLoadCalibrationClicked();
void onCalibrationCheckBoxChanged(int state);
void onExpertModeStateChanged(int state);
protected:
int nrPoints = 0;
QVector<double> dataX;
QVector<double> dataY;
private:
Ui::display *ui;
QRadioButton *radioButtonFixedScale; // Pointer to the Fixed Scale radio button
QRadioButton *radioButtonAutoscale; // Pointer to the Autoscale radio button
QButtonGroup *buttonGroup;
QMap<QString, QVector<unsigned short>> backgroundDataMap; // Map to store background data for each plane
bool subtractBackground = false; // Flag to track if background subtraction is enabled
QMap<QString, QVector<unsigned short>> calibrationDataMap; // Map to store calibration data for each plane
bool applyCalibration = false; // Flag to track if calibration should be applied
QVector<unsigned short> calibrationData; // Stores the loaded calibration data
QCheckBox *checkBoxExpertMode; // Expert Mode checkbox
bool expertModeEnabled = false; // Flag to track if expert mode is enabled
};
#endif // DISPLAY_H

View File

@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>609</width>
<height>418</height>
<height>463</height>
</rect>
</property>
<property name="sizePolicy">
@ -17,7 +17,7 @@
</sizepolicy>
</property>
<property name="windowTitle">
<string>Online Display</string>
<string>Online BPMDisplay</string>
</property>
<widget class="QWidget" name="verticalLayoutWidget">
<property name="geometry">
@ -160,7 +160,7 @@
<property name="geometry">
<rect>
<x>10</x>
<y>370</y>
<y>410</y>
<width>581</width>
<height>41</height>
</rect>
@ -199,28 +199,225 @@ calibration</string>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="horizontalLayoutWidget_2">
<property name="geometry">
<rect>
<x>10</x>
<y>370</y>
<width>581</width>
<height>41</height>
</rect>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_5">
<item>
<widget class="QCheckBox" name="checkBox_subbkg">
<property name="text">
<string>sub bkg</string>
<widget class="QFrame" name="frame">
<property name="frameShape">
<enum>QFrame::WinPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
<widget class="QLCDNumber" name="lcdNumber_mean">
<property name="geometry">
<rect>
<x>50</x>
<y>0</y>
<width>91</width>
<height>41</height>
</rect>
</property>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Plain</enum>
</property>
<property name="smallDecimalPoint">
<bool>true</bool>
</property>
<property name="value" stdset="0">
<double>0.000000000000000</double>
</property>
<property name="intValue" stdset="0">
<number>0</number>
</property>
</widget>
<widget class="QLabel" name="label">
<property name="geometry">
<rect>
<x>10</x>
<y>10</y>
<width>61</width>
<height>21</height>
</rect>
</property>
<property name="font">
<font>
<pointsize>12</pointsize>
</font>
</property>
<property name="text">
<string>MEAN</string>
</property>
<property name="textFormat">
<enum>Qt::RichText</enum>
</property>
<property name="scaledContents">
<bool>true</bool>
</property>
</widget>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButton_loadbkg">
<property name="text">
<string>load bkg</string>
<widget class="QFrame" name="frame_4">
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<widget class="QLabel" name="label_4">
<property name="geometry">
<rect>
<x>0</x>
<y>10</y>
<width>61</width>
<height>21</height>
</rect>
</property>
<property name="font">
<font>
<pointsize>12</pointsize>
</font>
</property>
<property name="text">
<string>Status</string>
</property>
<property name="textFormat">
<enum>Qt::RichText</enum>
</property>
<property name="scaledContents">
<bool>true</bool>
</property>
</widget>
<widget class="QLCDNumber" name="lcdNumber_status">
<property name="geometry">
<rect>
<x>50</x>
<y>0</y>
<width>91</width>
<height>41</height>
</rect>
</property>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Plain</enum>
</property>
<property name="smallDecimalPoint">
<bool>true</bool>
</property>
<property name="value" stdset="0">
<double>0.000000000000000</double>
</property>
<property name="intValue" stdset="0">
<number>0</number>
</property>
</widget>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButton_savebkg">
<property name="enabled">
<bool>false</bool>
<widget class="QFrame" name="frame_3">
<property name="frameShape">
<enum>QFrame::WinPanel</enum>
</property>
<property name="text">
<string>save bkg</string>
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
<widget class="QLCDNumber" name="lcdNumber_focus">
<property name="geometry">
<rect>
<x>60</x>
<y>0</y>
<width>71</width>
<height>41</height>
</rect>
</property>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Plain</enum>
</property>
</widget>
<widget class="QLabel" name="label_2">
<property name="geometry">
<rect>
<x>8</x>
<y>10</y>
<width>61</width>
<height>21</height>
</rect>
</property>
<property name="font">
<font>
<pointsize>12</pointsize>
</font>
</property>
<property name="text">
<string>FOCUS</string>
</property>
</widget>
</widget>
</item>
<item>
<widget class="QFrame" name="frame_2">
<property name="frameShape">
<enum>QFrame::WinPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
<widget class="QLCDNumber" name="lcdNumber_max">
<property name="geometry">
<rect>
<x>50</x>
<y>0</y>
<width>71</width>
<height>41</height>
</rect>
</property>
<property name="font">
<font>
<family>Arial</family>
<pointsize>8</pointsize>
</font>
</property>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
</widget>
<widget class="QLabel" name="label_3">
<property name="geometry">
<rect>
<x>8</x>
<y>10</y>
<width>61</width>
<height>21</height>
</rect>
</property>
<property name="font">
<font>
<pointsize>12</pointsize>
</font>
</property>
<property name="text">
<string>MAX</string>
</property>
</widget>
</widget>
</item>
</layout>

View File

@ -66,7 +66,7 @@ void DisplayServer::show()
displays.clear();
for (int plane = 0; plane < planeConfig.length(); plane++)
{
Display* newDisplay = new Display;
BPMDisplay* newDisplay = new BPMDisplay;
newDisplay->setTitle(planeConfig[plane]->name);
newDisplay->show();
displays.append(newDisplay);
@ -102,6 +102,8 @@ void DisplayServer::plot()
{
//initialize buffer
displays[plane]->buffer.resize(planeConfig[plane]->nr_sensors*64);
displays[plane]->rmsbuffer.resize(4);
//fill with data
int current_base = 0;
for (int dev_nr = 0; dev_nr < planeConfig[plane]->nr_devices; dev_nr++)
@ -114,6 +116,11 @@ void DisplayServer::plot()
for (int i = 0; i < nr_channels; i++)
displays[plane]->buffer[current_base+i] = lastFrame[dev_id].sensor_data[i];
current_base += nr_channels;
displays[plane]->rmsbuffer[0] = lastFrame[dev_id].rms_frame.mean;
displays[plane]->rmsbuffer[1] = lastFrame[dev_id].rms_frame.sigma;
displays[plane]->rmsbuffer[2] = lastFrame[dev_id].rms_frame.max;
displays[plane]->rmsbuffer[3] = lastFrame[dev_id].rms_frame.status;
}
//plot
displays[plane]->plot();

View File

@ -38,7 +38,7 @@ protected:
int active = 0;
HW* theHW;
QVector<PlaneConfig*> planeConfig;
QVector<Display*> displays;
QVector<BPMDisplay*> displays;
PlaneConfig *findPlane(int plane_nr);
};

View File

@ -1,43 +1,46 @@
#include "eventbuilder.h"
#include "udpserver.h"
#include "hit_analyse_v2.h"
EventBuilder::EventBuilder(QObject *parent) : QObject(parent)
#include <QTime>
EventBuilder::EventBuilder( QObject *parent) : QObject(parent)
{
connect(this, EventBuilder::sigInit, this, EventBuilder::onInit);
connect(this, EventBuilder::sigDeinit, this, EventBuilder::onDeinit);
connect(this, EventBuilder::sigStartLogging, this, EventBuilder::onStartLogging);
connect(this, EventBuilder::sigStopLogging, this, EventBuilder::onStopLogging);
connect(this, EventBuilder::sigStartTakingHistos, this, EventBuilder::onStartTakingHistos);
connect(this, EventBuilder::sigStopTakingHistos, this, EventBuilder::onStopTakingHistos);
connect(this, &EventBuilder::sigInit, this, &EventBuilder::onInit);
connect(this, &EventBuilder::sigDeinit, this, &EventBuilder::onDeinit);
connect(this, &EventBuilder::sigStartLogging, this, &EventBuilder::onStartLogging);
connect(this, &EventBuilder::sigStopLogging, this, &EventBuilder::onStopLogging);
connect(this, &EventBuilder::sigStartTakingHistos, this, &EventBuilder::onStartTakingHistos);
connect(this, &EventBuilder::sigStopTakingHistos, this, &EventBuilder::onStopTakingHistos);
moveToThread(&thread);
thread.start();
init();
//get the network thread
}
EventBuilder::~EventBuilder()
{
deinit();
deinit();
thread.quit();
thread.wait();
thread.quit();
thread.wait();
// networkThread.stopThread();
// networkThread.wait(); // Wait for the network thread to finish gracefully
}
//************************* Data processing framework ********************
//main processing slot
//main processing slot
void EventBuilder::onNewData(DataReceiver* receiver)
{
short * newcopy_sensor_data = new short int[320];
while (checkBufferOccupancies())
{
//find lowest global sync value
//find lowest global sync value
int lowest_id = findLowestId();
//get and validate data from buffers
//get and validate data from buffers
for (int dev_nr = 0; dev_nr < nrReceivers; dev_nr++)
{
BufferData data = receivers[dev_nr]->dataBuffer.look();
@ -49,11 +52,11 @@ void EventBuilder::onNewData(DataReceiver* receiver)
{
data.sync_frame.data_ok = 0; //wrong data, mark as bad
}
//store data for complete frame
//store data for complete frame
currentFrame[dev_nr] = data;
}
lastFrameMutex.lock();
@ -63,36 +66,46 @@ void EventBuilder::onNewData(DataReceiver* receiver)
//ToDo:
//1. Background subtraction.
frame_counter++;
if (newDataSemaphore.available() == 1){
frame_counter++;
while (frame_counter<10000){
for (unsigned int dev_nr = 0; dev_nr < nrReceivers; dev_nr++){
for (unsigned int ch = 0; ch < channelCounts[dev_nr]; ch++)
backgroundFrame[dev_nr].sensor_data[ch]+= currentFrame[dev_nr].sensor_data[ch];
if (frame_counter<=32){
for (unsigned int dev_nr = 0; dev_nr < nrReceivers; dev_nr++){
if (frame_counter<=1) backgroundFrame[dev_nr].resize(channelCounts[dev_nr]);
// backgroundFrame[dev_nr].sensor_data = currentFrame[dev_nr].sensor_data;
// addArrays(backgroundFrame[dev_nr].sensor_data, currentFrame[dev_nr].sensor_data, channelCounts[dev_nr]);
// std::cerr << " set bkg" << std::endl;
}
}
else if (frame_counter==33){
for (unsigned int dev_nr = 0; dev_nr < nrReceivers; dev_nr++){
for (int i = 0; i < channelCounts[dev_nr]; ++i) {
// backgroundFrame[dev_nr].sensor_data[i] /= 32; // Right-shift by 5 positions (equivalent to dividing by 32)
}
}
}
else if (frame_counter>33){
HIT_ANALYSE_V2 hit_analyse_v2;//create the object
QString dataString;
for (unsigned int dev_nr = 0; dev_nr < nrReceivers; dev_nr++){
// subtractArrays(currentFrame[dev_nr].sensor_data, backgroundFrame[dev_nr].sensor_data, channelCounts[dev_nr], newcopy_sensor_data );
// std::cerr << currentFrame[dev_nr].sensor_data[0] << " " << backgroundFrame[dev_nr].sensor_data[0] << " " << channelCounts[dev_nr] << " " << newcopy_sensor_data[0] << std::endl;
// for (unsigned int dev_nrsim = 0; dev_nrsim < 3; dev_nrsim++){
//simulate 6 planes instead of just 2
// for (unsigned int dev_nr = 0; dev_nr < nrReceivers; dev_nr++){
// dataString += hit_analyse_v2.analyseBeamData(newcopy_sensor_data, dev_nr, channelCounts[dev_nr]);
// dataString += char(nrReceivers);
//}
// if (frame_counter%1000==0) std::cerr << dataString.toStdString() << std::endl;
}
}
}
if (frame_counter==10000){
for (unsigned int dev_nr = 0; dev_nr < nrReceivers; dev_nr++){
for (unsigned int ch = 0; ch < channelCounts[dev_nr]; ch++)
backgroundFrame[dev_nr].sensor_data[ch]/= 10000 ;
}
}
if (frame_counter>10000){
for (unsigned int dev_nr = 0; dev_nr < nrReceivers; dev_nr++){
for (unsigned int ch = 0; ch < channelCounts[dev_nr]; ch++)
currentFrame[dev_nr].sensor_data[ch]-=backgroundFrame[dev_nr].sensor_data[ch] ;
}
}
lastFrameMutex.lock();
if (newDataSemaphore.available() == 0)
newDataSemaphore.release(1);
lastFrame = currentFrame;
lastFrameMutex.unlock();
/*
//histogram stuff
if (histogramSamplesToTake)
{
@ -105,16 +118,27 @@ void EventBuilder::onNewData(DataReceiver* receiver)
if (histogramSamplesToTake == 0)
emit sigHistoCompleted();
}
*/
// }
// QTime currentTime = QTime::currentTime();
//Calculate the time since midnight in milliseconds
// int millisecondsSinceMidnight = currentTime.msecsSinceStartOfDay();
// dataString += QString::number(millisecondsSinceMidnight);
// receiveData(dataString.toUtf8());
if (newDataSemaphore.available() == 0)
newDataSemaphore.release(1);
lastFrame = currentFrame;
lastFrameMutex.unlock();
//log data
if (loggingData) logDataToFile();
//log data
if (loggingData) logDataToFile();
//HIT_ANALYSE_V2 hit_analyse_v2;//create the object
// QString dataString = hit_analyse_v2.analyseBeamData(currentFrame);
// Call sendData method of the UDP server
QString dataString = QString::number(intensity) + ',' + QString::number(position) + ',' + QString::number(focus);
QByteArray data = dataString.toUtf8();
udpServer.sendData(data);
}
@ -146,7 +170,7 @@ int EventBuilder::findLowestId()
//for non-zero-crossing case
if (value < min1) min1 = value;
if (value > max1) max1 = value;
//for zero-crossing case
//for zero-crossing case
if (value > 256) value -= 512;
if (value < min2) min2 = value;
if (value > max2) max2 = value;
@ -172,7 +196,7 @@ void EventBuilder::logDataToFile()
* - number of channels per each board Cn: N x unsigned short
* - N times the following sequence:
* - SyncFrame S = 1 x SyncFrame (== 16 bytes)
* - Data D = Cn x signed short
* - Data D = Cn x unsigned short
*/
logFile.write((const char*)&totalBoards, sizeof(unsigned short));
@ -181,10 +205,12 @@ void EventBuilder::logDataToFile()
for (int board = 0; board < totalBoards; board++)
{
logFile.write((const char*)&(currentFrame[board].sync_frame), sizeof(SyncFrame));
logFile.write((const char*)currentFrame[board].sensor_data, currentFrame[board].buffer_size*sizeof(signed short));
logFile.write((const char*)currentFrame[board].sensor_data, currentFrame[board].buffer_size*sizeof(unsigned short));
logFile.write((const char*)&(currentFrame[board].rms_frame), sizeof(RMSFrame));
}
//write data in native binary format. All devices written as 5-sensor-wide!
//write data in native binary format. All devices written as 5-sensor-wide!
//logFile.write((const char*)currentFrame.constData(), nrReceivers*sizeof(BufferData));
}
@ -282,13 +308,13 @@ void EventBuilder::addSource(DataReceiver* source)
nrReceivers = receivers.length();
currentFrame.resize(nrReceivers);
backgroundFrame.resize(nrReceivers);
connect(source, DataReceiver::sigDataReady, this, EventBuilder::onNewData);
connect(source, &DataReceiver::sigDataReady, this, &EventBuilder::onNewData);
}
void EventBuilder::deleteSources()
{
for (int i = 0; i < receivers.length(); i++)
disconnect(receivers[i], DataReceiver::sigDataReady, this, EventBuilder::onNewData);
disconnect(receivers[i], &DataReceiver::sigDataReady, this, &EventBuilder::onNewData);
receivers.clear();
nrReceivers = receivers.length();
@ -337,8 +363,26 @@ QVector<BufferData> EventBuilder::getLastFrame()
QVector<BufferData> EventBuilder::getNewFrame()
{
//wait for new data
//wait for new data
newDataSemaphore.acquire(1);
//and return it
return getLastFrame();
}
void EventBuilder::receiveData(const QByteArray &data)
{
QMutexLocker locker(&mutex);
dataQueue.enqueue(data);
QString dataString = QString(data);
// std::cerr << dataString.toStdString() << std::endl;
dataAvailable.wakeOne();
}
QByteArray EventBuilder::getNextData()
{
QMutexLocker locker(&mutex);
if (dataQueue.isEmpty())
return QByteArray(); // Return an empty QByteArray if no data is available
return dataQueue.dequeue();
}

View File

@ -8,11 +8,13 @@
#include <QThread>
#include <QMutex>
#include <QMutexLocker>
#include "udpserver.h" // Include the UDP server header
#include <QQueue>
#include <QWaitCondition>
//#include "hw.h"
#include "datareceiver.h"
#include "histogram.h"
#include <immintrin.h> // Include for Intel Intrinsics
#include <emmintrin.h> // Include for SSE2
//The event builder will constantly keep some data in the buffers to enable synchronization of the devices. So:
#define EVB_MIN_BUFFER_OCCUPANCY (RECEIVER_BUFFER_SIZE / 8) //the EVB will wait until so much data is in each device buffer
@ -24,7 +26,7 @@ class EventBuilder : public QObject
{
Q_OBJECT
public:
explicit EventBuilder(QObject *parent = 0);
explicit EventBuilder( QObject *parent = 0);
~EventBuilder();
void addSource(DataReceiver *source);
@ -48,9 +50,18 @@ signals:
void sigStopTakingHistos();
void sigHistoCompleted(); //this is a public signal which can be used to notify user that the histo is ready
// Define a signal to notify when postdata is updated
void dataReady(const QByteArray& data); // Define a signal for data readiness
public slots:
void onNewData(DataReceiver *receiver);
// Add a public slot to receive and store data
void receiveData(const QByteArray &data);
// Add a method to get data from the queue
QByteArray getNextData();
protected:
int checkBufferOccupancies();
int findLowestId();
@ -64,6 +75,7 @@ protected:
QVector<DataReceiver*> receivers;
QVector<BufferData> currentFrame;
signed short * copy_sensor_data;
QVector<BufferData> backgroundFrame;
QVector<BufferData> lastFrame;
@ -90,10 +102,13 @@ protected slots:
void onStartTakingHistos(int sample_count);
void onStopTakingHistos();
private:
long unsigned int frame_counter = 0;
long long int frame_counter = 0;
double intensity = 0.0;
double position = 0.0;
double focus = 0.0;
QQueue<QByteArray> dataQueue;
QMutex mutex;
QWaitCondition dataAvailable;
};

View File

@ -16,19 +16,13 @@
#define SHORT2BYTES(sh,by) {by[0] = (sh>>8) & 0xFF; by[1] = sh & 0xFF;}
#define LO(x) (x & 0xFF)
#define HI(x) ((x>>8) & 0xFF)
#define BYTES2SHORT(by) \
#define BYTES2SHORT(by) ( ((unsigned short)(unsigned char)((by)[0]) << 8) | ((unsigned short)(unsigned char)((by)[1])) ) //safe way
#define BYTES2SIGNSHORT(by) ( *((signed short*)by) ) //faster
#define BYTES2SIGNEDSHORT(by) \
( \
(static_cast<short>(static_cast<unsigned char>((by)[0])) << 8) | \
(static_cast<short>(static_cast<unsigned char>((by)[1]))) \
)
#define BYTES2INT(by) \
( \
(static_cast<int>(static_cast<unsigned char>((by)[0])) << 24) | \
(static_cast<int>(static_cast<unsigned char>((by)[1])) << 16) | \
(static_cast<int>(static_cast<unsigned char>((by)[2])) << 8) | \
(static_cast<int>(static_cast<unsigned char>((by)[3]))) \
)
//convert textual representation of IP to array of numbers and/or well-formatted string
QString ip2num(QString input, unsigned char* numbers = NULL);

View File

@ -5,8 +5,14 @@
#-------------------------------------------------
QT += core gui network serialport
QMAKE_CXXFLAGS += -Wa,-mbig-obj
#CONFIG += static
unix {
QMAKE_CXXFLAGS += -W -std=c++17
}
win32 {
QMAKE_CXXFLAGS += -Wa,-mbig-obj -std=c++17
}
greaterThan(QT_MAJOR_VERSION, 5): QT += widgets printsupport
@ -37,8 +43,7 @@ SOURCES += main.cpp\
dialogtiscan.cpp \
dialogprofiler.cpp \
stepper.cpp \
dialogbeta.cpp \
udpserver.cpp
dialogbeta.cpp
HEADERS += mainwindow.h \
Q_DebugStream.h \
@ -54,6 +59,7 @@ HEADERS += mainwindow.h \
helpers.h \
cbuffer.h \
eventbuilder.h \
networkthread.h \
qcustomplot.h \
display.h \
displayserver.h \
@ -65,7 +71,6 @@ HEADERS += mainwindow.h \
dialogprofiler.h \
stepper.h \
dialogbeta.h \
udpserver.h \
hitreader.h
FORMS += mainwindow.ui \

View File

@ -1,5 +1,6 @@
#include "hit_analyse_v2.h"
#include <random>
#include <immintrin.h> // Include for Intel Intrinsics
HIT_ANALYSE_V2::HIT_ANALYSE_V2(QObject *parent) : QObject(parent)
{
@ -8,136 +9,215 @@ HIT_ANALYSE_V2::HIT_ANALYSE_V2(QObject *parent) : QObject(parent)
}
QString HIT_ANALYSE_V2::analyseBeamData(QVector<BufferData> dataframe){
double position=0.1;
// Define your own functions for matrix operations
struct Matrix2x2 {
double data[2][2];
};
Matrix2x2 InvertMatrix2x2(const Matrix2x2& mat) {
Matrix2x2 result;
double det = mat.data[0][0] * mat.data[1][1] - mat.data[0][1] * mat.data[1][0];
if (det != 0.0) {
double invDet = 1.0 / det;
result.data[0][0] = mat.data[1][1] * invDet;
result.data[0][1] = -mat.data[0][1] * invDet;
result.data[1][0] = -mat.data[1][0] * invDet;
result.data[1][1] = mat.data[0][0] * invDet;
} else {
// Handle the case when the matrix is not invertible
// You might want to implement error handling here.
std::cerr << "Matrix not invertible! " << std::endl;
}
return result;
}
struct Vector2 {
double data[2];
};
QString HIT_ANALYSE_V2::analyseBeamData(short int * signal_list, const int dev_nr, const int vector_length)
{
double position=100;
double focus=8;
double intensity=10000.0;
double intensity=1000.0;
QString dataString;
const int vector_length = 300; // Replace with the actual length of your vectors
std::vector<double> signal_list(vector_length);
std::vector<double> channel_list(vector_length);
// Fill arr1 and arr2 with your data
// Create a random number generator with a Gaussian distribution
std::random_device rd;
std::mt19937 gen(rd());
std::normal_distribution<double> dist(0.0, 17.0); // Mean of 0 and Sigma of 17
std::vector<double> channel_list;
std::vector<double> short_signal_list;
std::vector<double> short_channel_list;
channel_list = fixed_channel;
// Create a vector to store the generated values
std::vector<short int> result(vector_length);
// std::vector<short int> result(vector_length);
// Fill the vector with random values
for (int i = 0; i < vector_length; ++i) {
result[i] = static_cast<short int>(dist(gen));
signal_list.push_back(result[i]);
channel_list.push_back(i);
}
// Fill the vector with random noise values
//add a gaussian profile, focus is FWHM, position is random between 50 and 250
position = 50 + (rand() % (int)(250 - 50 + 1));
for (int i = 0; i < vector_length; ++i) {
signal_list[i] += intensity*exp(-4*log(2)*pow((channel_list[i]-position)/focus,2));
bool fixeddata = false ;
if (fixeddata){
// signal_list = (short int)fixedsignalarray;
bool dummy = true;
}
else
{
// signal_list = dataframe[dev_nr].sensor_data;
bool dummy = false;
}
// std::cerr << signal_list[0] << " " << dev_nr << std::endl;
double SumArea = 0.0, SumY2 = 0.0, SumXY2 = 0.0, SumX2Y2 = 0.0, SumX3Y2 = 0.0;
double SumY2LnY = 0.0, SumXY2LnY = 0.0, Ymax = 0.0, Pomax = 0.0;
double fac_c = 0.0, Yn = 0.0, sigma = 0.0, amp = 0.0;
double SumYYP = 0.0, SumYYM = 0.0, MeanY = 0.0, window_start = 0.0, window_end = 0.0;
// ...
Matrix2x2 M1, M1inv;
Vector2 ABC, M2;
// Fill signal_list and channel_list with your data
double SumT = 0.0, SumS = 0.0, SumS2 = 0.0, SumST = 0.0, SumT2 = 0.0, SumY = 0.0, SumYS = 0.0, SumYT = 0.0;
double b_den = 0.0, b_num = 0.0, b = 0.0, p = 0.0, c = 0.0, SumYYP = 0.0, SumYYM = 0.0, MeanY = 0.0;
double S[vector_length];
double T[vector_length];
for (int k = 0; k < vector_length; k++) {
if (k == 0) {
S[k] = 0.0;
T[k] = 0.0;
} else {
S[k] = S[k - 1] + 0.5 * (signal_list[k] + signal_list[k - 1]) * (channel_list[k] - channel_list[k - 1]);
T[k] = T[k - 1] + 0.5 * (channel_list[k] * signal_list[k] + channel_list[k - 1] * signal_list[k - 1]) *
(channel_list[k] - channel_list[k - 1]);
for (int i = 0; i < vector_length; i++) {
std::cerr<< signal_list[i] << " ";
if (signal_list[i] > Ymax) {
Ymax = signal_list[i];
Pomax = channel_list[i];
}
if (i > 0 && signal_list[i] > 34) {
SumArea += signal_list[i] * (channel_list[i] - channel_list[i - 1]);
}
SumS += S[k];
SumT += T[k];
SumY += signal_list[k];
SumS2 += S[k] * S[k];
SumST += S[k] * T[k];
SumT2 += T[k] * T[k];
SumYS += signal_list[k] * S[k];
SumYT += signal_list[k] * T[k];
MeanY += signal_list[k];
}
MeanY /= vector_length;
std::cerr<< std::endl;
// Estimate sigma
sigma = SumArea / Ymax / 2.5066;
// Calculate M1 matrix elements
double M1_00 = SumT2;
double M1_01 = SumST;
double M1_02 = SumT;
double M1_10 = SumST;
double M1_11 = SumS2;
double M1_12 = SumS;
double M1_20 = SumT;
double M1_21 = SumS;
double M1_22 = vector_length;
// Set a +-3 sigma window
window_start = Pomax - 3 * sigma;
window_end = Pomax + 3 * sigma;
std::cerr<< Pomax << " " << Ymax << " " << sigma << std::endl;
// Calculate M2 vector elements
double M2_0 = SumYT;
double M2_1 = SumYS;
double M2_2 = SumY;
// Calculate the inverse of M1
double detM1 = M1_00 * (M1_11 * M1_22 - M1_12 * M1_21) -
M1_01 * (M1_10 * M1_22 - M1_12 * M1_20) +
M1_02 * (M1_10 * M1_21 - M1_11 * M1_20);
if (detM1 == 0.0) {
std::cerr << "M1 is not invertible." << std::endl;
//return 1;
for (int i = 0; i < vector_length; i++) {
if (signal_list[i] > 34 && channel_list[i] > window_start && channel_list[i] < window_end) {
short_signal_list.push_back(signal_list[i]);
short_channel_list.push_back(channel_list[i]);
}
}
//signal_list.clear();
//channel_list.clear();
// Recalculate SumArea using the sieved data
SumArea = 0.0;
for (int i = 1; i < short_signal_list.size(); i++) {
SumArea += short_signal_list[i] * (short_channel_list[i] - short_channel_list[i - 1]);
}
double invM1_00 = (M1_11 * M1_22 - M1_12 * M1_21) / detM1;
double invM1_01 = (M1_02 * M1_21 - M1_01 * M1_22) / detM1;
double invM1_02 = (M1_01 * M1_12 - M1_02 * M1_11) / detM1;
double invM1_10 = (M1_12 * M1_20 - M1_10 * M1_22) / detM1;
double invM1_11 = (M1_00 * M1_22 - M1_02 * M1_20) / detM1;
double invM1_12 = (M1_02 * M1_10 - M1_00 * M1_12) / detM1;
double invM1_20 = (M1_10 * M1_21 - M1_11 * M1_20) / detM1;
double invM1_21 = (M1_01 * M1_20 - M1_00 * M1_21) / detM1;
double invM1_22 = (M1_00 * M1_11 - M1_01 * M1_10) / detM1;
// Calculate ABC vector
double ABC_0 = invM1_00 * M2_0 + invM1_01 * M2_1 + invM1_02 * M2_2;
double ABC_1 = invM1_10 * M2_0 + invM1_11 * M2_1 + invM1_12 * M2_2;
double ABC_2 = invM1_20 * M2_0 + invM1_21 * M2_1 + invM1_22 * M2_2;
const int shortlist_length = short_channel_list.size();
// Calculate b, p, and c
p = -ABC_0 / 2.0;
c = -ABC_1 / ABC_0;
if (shortlist_length <= 3) {
intensity = -1;
focus = -1;
position = -128;
dataString += QString::number(intensity) + ',' + QString::number(position) + ',' + QString::number(focus)
+ ',' + QString::number(0);
for (int k = 0; k < vector_length; k++) {
double exp_term = exp(-p * (channel_list[k] - c) * (channel_list[k] - c));
b_num += exp_term * signal_list[k];
b_den += exp_term;
return dataString;
}
b = b_num / b_den;
// Re-Estimate sigma
sigma = SumArea / Ymax / 2.5066;
fac_c = -1.0 / (2.0 * sigma * sigma);
// std::cerr << sigma << std::endl;
for(int k=0; k<shortlist_length;k++){
for (int k = 0; k < vector_length; k++) {
double y_pred = b * exp(-p * (channel_list[k] - c) * (channel_list[k] - c));
SumYYM += (signal_list[k] - MeanY) * (signal_list[k] - MeanY);
SumYYP += (y_pred - MeanY) * (y_pred - MeanY);
SumY2 += short_signal_list[k]*short_signal_list[k];
SumXY2 += short_signal_list[k]*short_signal_list[k]*short_channel_list[k];
SumX2Y2 += short_signal_list[k]*short_signal_list[k]*short_channel_list[k]*short_channel_list[k];
SumX3Y2 += short_signal_list[k]*short_signal_list[k]*short_channel_list[k]*short_channel_list[k]*short_channel_list[k];
SumY2LnY += short_signal_list[k]*short_signal_list[k]*log(short_signal_list[k]);
SumXY2LnY += short_channel_list[k]*short_signal_list[k]*short_signal_list[k]*log(short_signal_list[k]);
// std::cerr<< shortlist_length << " " << short_channel_list[k] << " " << short_signal_list[k] << " " << short_signal_list[k] << " " << log(short_signal_list[k]) << std::endl;
MeanY+=short_signal_list[k];
}
MeanY/=shortlist_length;
// Use custom matrix and vector functions for calculations
M1.data[0][0] = SumY2;
M1.data[0][1] = SumXY2;
M1.data[1][0] = SumXY2;
M1.data[1][1] = SumX2Y2;
// std::cerr << M1.data[0][0] << " " << M1.data[0][1] << " " << M1.data[1][0] << " " << M1.data[1][1] << std::endl;
M2.data[0] = SumY2LnY - fac_c * SumX2Y2;
M2.data[1] = SumXY2LnY - fac_c * SumX3Y2;
// std::cerr << M2.data[0] << " " << M2.data[1] << std::endl;
M1inv = InvertMatrix2x2(M1);
ABC.data[0] = M1inv.data[0][0] * M2.data[0] + M1inv.data[0][1] * M2.data[1];
ABC.data[1] = M1inv.data[1][0] * M2.data[0] + M1inv.data[1][1] * M2.data[1];
// std::cerr << ABC.data[0] << " " << ABC.data[1] << std::endl;
//iterate to improve the fit.
int N_iter = 1;
for (int i = 0; i < N_iter; i++) {
SumY2 = 0.0;
SumXY2 = 0.0;
SumX2Y2 = 0.0;
SumX3Y2 = 0.0;
SumY2LnY = 0.0;
SumXY2LnY = 0.0;
for (int k = 0; k < shortlist_length; k++) {
Yn = exp(ABC.data[0] + ABC.data[1] * short_channel_list[k] + fac_c * short_channel_list[k] * short_channel_list[k]);
SumY2 += Yn * Yn;
SumXY2 += Yn * Yn * short_channel_list[k];
SumX2Y2 += Yn * Yn * short_channel_list[k] * short_channel_list[k];
SumX3Y2 += Yn * Yn * short_channel_list[k] * short_channel_list[k] * short_channel_list[k];
SumY2LnY += Yn * Yn * log(short_signal_list[k]);
SumXY2LnY += short_channel_list[k] * Yn * Yn * log(short_signal_list[k]);
}
M1.data[0][0] = SumY2;
M1.data[0][1] = SumXY2;
M1.data[1][0] = SumXY2;
M1.data[1][1] = SumX2Y2;
M2.data[0] = SumY2LnY - fac_c * SumX2Y2;
M2.data[1] = SumXY2LnY - fac_c * SumX3Y2;
M1inv = InvertMatrix2x2(M1);
ABC.data[0] = M1inv.data[0][0] * M2.data[0] + M1inv.data[0][1] * M2.data[1];
ABC.data[1] = M1inv.data[1][0] * M2.data[0] + M1inv.data[1][1] * M2.data[1];
}
double R_squared = SumYYP / SumYYM;
//std::cout << "R-squared = " << R_squared << endl;
position = -ABC_1/ ABC_0;
//sigma = sqrt(1.0 / (2.0 * ABC_0));
focus = 2.3548/sqrt(2*p);
intensity = b;
position = -ABC.data[1]/fac_c/2;
amp = exp(ABC.data[0]-ABC.data[1]*ABC.data[1]/4/fac_c);
sigma=SumArea/amp/2.5066;
// cout << sigma << " " << mean << " " << amp << endl;
for(int k=0; k<shortlist_length;k++){
SumYYM+= (short_signal_list[k]-MeanY)*(short_signal_list[k]-MeanY);
SumYYP+= (amp*exp(-(short_channel_list[k]-position)*(short_channel_list[k]-position)/2/(sigma*sigma)) - MeanY )*(amp*exp(-(short_channel_list[k]-position)*(short_channel_list[k]-position)/2/(sigma*sigma)) - MeanY );
}
focus = 2.3548*sigma;
intensity = amp;
double R_squared = SumYYP/SumYYM;
dataString += QString::number(intensity) + ',' + QString::number(position) + ',' + QString::number(focus)
+ ',' + QString::number(R_squared);
@ -148,6 +228,8 @@ QString HIT_ANALYSE_V2::analyseBeamData(QVector<BufferData> dataframe){
}
HIT_ANALYSE_V2::~HIT_ANALYSE_V2()
{

View File

@ -0,0 +1,337 @@
#include "hit_analyse_v2.h"
#include <random>
HIT_ANALYSE_V2::HIT_ANALYSE_V2(QObject *parent) : QObject(parent)
{
}
// Define your own functions for matrix operations
struct Matrix2x2 {
double data[2][2];
};
Matrix2x2 InvertMatrix2x2(const Matrix2x2& mat) {
Matrix2x2 result;
double det = mat.data[0][0] * mat.data[1][1] - mat.data[0][1] * mat.data[1][0];
if (det != 0.0) {
double invDet = 1.0 / det;
result.data[0][0] = mat.data[1][1] * invDet;
result.data[0][1] = -mat.data[0][1] * invDet;
result.data[1][0] = -mat.data[1][0] * invDet;
result.data[1][1] = mat.data[0][0] * invDet;
} else {
// Handle the case when the matrix is not invertible
// You might want to implement error handling here.
std::cerr << "Matrix not invertible! " << std::endl;
}
return result;
}
struct Vector2 {
double data[2];
};
QString HIT_ANALYSE_V2::analyseBeamData(QVector<BufferData> dataframe, const int dev_nr, const int vector_length){
double position=100;
double focus=8;
double intensity=1000.0;
QString dataString;
double * signal_list;
std::vector<double> channel_list;
std::vector<double> short_signal_list;
std::vector<double> short_channel_list;
// Create a random number generator with a Gaussian distribution
std::random_device rd;
std::mt19937 gen(rd());
std::normal_distribution<double> dist(0.0, 17.0); // Mean of 0 and Sigma of 17
// Create a vector to store the generated values
std::vector<short int> result(vector_length);
// Fill the vector with random noise values
//add a gaussian profile, focus is FWHM, position is random between 50 and 250
bool fixeddata = false;
if (!fixeddata){
position = 100;// + (rand() % (int)(250 - 50 + 1));
signal_list = (double*)(dataframe[dev_nr].sensor_data);
channel_list = fixed_channel;
for (int i = int(position) - (int)(focus); i < int(position) + (int)(focus) ; i++) {
// double randomValue = dist(gen);
// signal_list[i] = static_cast<short int>(std::round(randomValue));
// signal_list[i] = dataframe[dev_nr].sensor_data[i];
//channel_list[i] = i;
signal_list[i] += static_cast<short int>(std::round(intensity*exp(-4*log(2)*pow((channel_list[i]-position)/focus,2))));
// std::cerr << channel_list[i] << ", ";
}
// std::cerr <<std::endl;
}
else{
signal_list = fixedsignalarray;
channel_list = fixed_channel;
}
/*
// Fill signal_list and channel_list with your data
double SumT = 0.0, SumS = 0.0, SumS2 = 0.0, SumST = 0.0, SumT2 = 0.0, SumY = 0.0, SumYS = 0.0, SumYT = 0.0;
double b_den = 0.0, b_num = 0.0, b = 0.0, p = 0.0, c = 0.0, SumYYP = 0.0, SumYYM = 0.0, MeanY = 0.0;
double S[vector_length];
double T[vector_length];
for (int k = 0; k < vector_length; k++) {
if (k == 0) {
S[k] = 0.0;
T[k] = 0.0;
} else {
S[k] = S[k - 1] + 0.5 * (signal_list[k] + signal_list[k - 1]) * (channel_list[k] - channel_list[k - 1]);
T[k] = T[k - 1] + 0.5 * (channel_list[k] * signal_list[k] + channel_list[k - 1] * signal_list[k - 1]) *
(channel_list[k] - channel_list[k - 1]);
}
SumS += S[k];
SumT += T[k];
SumY += signal_list[k];
SumS2 += S[k] * S[k];
SumST += S[k] * T[k];
SumT2 += T[k] * T[k];
SumYS += signal_list[k] * S[k];
SumYT += signal_list[k] * T[k];
MeanY += signal_list[k];
}
MeanY /= vector_length;
// Calculate M1 matrix elements
double M1_00 = SumT2;
double M1_01 = SumST;
double M1_02 = SumT;
double M1_10 = SumST;
double M1_11 = SumS2;
double M1_12 = SumS;
double M1_20 = SumT;
double M1_21 = SumS;
double M1_22 = vector_length;
// Calculate M2 vector elements
double M2_0 = SumYT;
double M2_1 = SumYS;
double M2_2 = SumY;
// Calculate the inverse of M1
double detM1 = M1_00 * (M1_11 * M1_22 - M1_12 * M1_21) -
M1_01 * (M1_10 * M1_22 - M1_12 * M1_20) +
M1_02 * (M1_10 * M1_21 - M1_11 * M1_20);
if (detM1 == 0.0) {
std::cerr << "M1 is not invertible." << std::endl;
//return 1;
}
double invM1_00 = (M1_11 * M1_22 - M1_12 * M1_21) / detM1;
double invM1_01 = (M1_02 * M1_21 - M1_01 * M1_22) / detM1;
double invM1_02 = (M1_01 * M1_12 - M1_02 * M1_11) / detM1;
double invM1_10 = (M1_12 * M1_20 - M1_10 * M1_22) / detM1;
double invM1_11 = (M1_00 * M1_22 - M1_02 * M1_20) / detM1;
double invM1_12 = (M1_02 * M1_10 - M1_00 * M1_12) / detM1;
double invM1_20 = (M1_10 * M1_21 - M1_11 * M1_20) / detM1;
double invM1_21 = (M1_01 * M1_20 - M1_00 * M1_21) / detM1;
double invM1_22 = (M1_00 * M1_11 - M1_01 * M1_10) / detM1;
// Calculate ABC vector
double ABC_0 = invM1_00 * M2_0 + invM1_01 * M2_1 + invM1_02 * M2_2;
double ABC_1 = invM1_10 * M2_0 + invM1_11 * M2_1 + invM1_12 * M2_2;
double ABC_2 = invM1_20 * M2_0 + invM1_21 * M2_1 + invM1_22 * M2_2;
// Calculate b, p, and c
p = -ABC_0 / 2.0;
c = -ABC_1 / ABC_0;
for (int k = 0; k < vector_length; k++) {
double exp_term = exp(-p * (channel_list[k] - c) * (channel_list[k] - c));
b_num += exp_term * signal_list[k];
b_den += exp_term;
}
b = b_num / b_den;
for (int k = 0; k < vector_length; k++) {
double y_pred = b * exp(-p * (channel_list[k] - c) * (channel_list[k] - c));
SumYYM += (signal_list[k] - MeanY) * (signal_list[k] - MeanY);
SumYYP += (y_pred - MeanY) * (y_pred - MeanY);
}
double R_squared = SumYYP / SumYYM;
//std::cout << "R-squared = " << R_squared << endl;
position = -ABC_1/ ABC_0;
//sigma = sqrt(1.0 / (2.0 * ABC_0));
focus = 2.3548/sqrt(2*p);
intensity = b;
*/
double SumArea = 0.0, SumY2 = 0.0, SumXY2 = 0.0, SumX2Y2 = 0.0, SumX3Y2 = 0.0;
double SumY2LnY = 0.0, SumXY2LnY = 0.0, Ymax = 0.0, Pomax = 0.0;
double fac_c = 0.0, Yn = 0.0, sigma = 0.0, amp = 0.0;
double SumYYP = 0.0, SumYYM = 0.0, MeanY = 0.0, window_start = 0.0, window_end = 0.0;
// ...
Matrix2x2 M1, M1inv;
Vector2 ABC, M2;
for (int i = 0; i < vector_length; i++) {
if (signal_list[i] > Ymax) {
Ymax = signal_list[i];
Pomax = channel_list[i];
}
if (i > 0 && signal_list[i] > 34) {
SumArea += signal_list[i] * (channel_list[i] - channel_list[i - 1]);
}
}
// Estimate sigma
sigma = SumArea / Ymax / 2.5066;
// Set a +-3 sigma window
window_start = Pomax - 3 * sigma;
window_end = Pomax + 3 * sigma;
// std::cerr<< Pomax << " " << Ymax << " " << sigma << std::endl;
for (int i = 0; i < vector_length; i++) {
if (signal_list[i] > 34 && channel_list[i] > window_start && channel_list[i] < window_end) {
short_signal_list.push_back(signal_list[i]);
short_channel_list.push_back(channel_list[i]);
}
}
//signal_list.clear();
//channel_list.clear();
// Recalculate SumArea using the sieved data
SumArea = 0.0;
for (int i = 1; i < short_signal_list.size(); i++) {
SumArea += short_signal_list[i] * (short_channel_list[i] - short_channel_list[i - 1]);
}
const int shortlist_length = short_channel_list.size();
if (shortlist_length <= 3) {
intensity = -1;
focus = -1;
position = -128;
dataString += QString::number(intensity) + ',' + QString::number(position) + ',' + QString::number(focus)
+ ',' + QString::number(0);
return dataString;
}
// Re-Estimate sigma
sigma = SumArea / Ymax / 2.5066;
fac_c = -1.0 / (2.0 * sigma * sigma);
// std::cerr << sigma << std::endl;
for(int k=0; k<shortlist_length;k++){
SumY2 += short_signal_list[k]*short_signal_list[k];
SumXY2 += short_signal_list[k]*short_signal_list[k]*short_channel_list[k];
SumX2Y2 += short_signal_list[k]*short_signal_list[k]*short_channel_list[k]*short_channel_list[k];
SumX3Y2 += short_signal_list[k]*short_signal_list[k]*short_channel_list[k]*short_channel_list[k]*short_channel_list[k];
SumY2LnY += short_signal_list[k]*short_signal_list[k]*log(short_signal_list[k]);
SumXY2LnY += short_channel_list[k]*short_signal_list[k]*short_signal_list[k]*log(short_signal_list[k]);
// std::cerr<< shortlist_length << " " << short_channel_list[k] << " " << short_signal_list[k] << " " << short_signal_list[k] << " " << log(short_signal_list[k]) << std::endl;
MeanY+=short_signal_list[k];
}
MeanY/=shortlist_length;
// Use custom matrix and vector functions for calculations
M1.data[0][0] = SumY2;
M1.data[0][1] = SumXY2;
M1.data[1][0] = SumXY2;
M1.data[1][1] = SumX2Y2;
// std::cerr << M1.data[0][0] << " " << M1.data[0][1] << " " << M1.data[1][0] << " " << M1.data[1][1] << std::endl;
M2.data[0] = SumY2LnY - fac_c * SumX2Y2;
M2.data[1] = SumXY2LnY - fac_c * SumX3Y2;
// std::cerr << M2.data[0] << " " << M2.data[1] << std::endl;
M1inv = InvertMatrix2x2(M1);
ABC.data[0] = M1inv.data[0][0] * M2.data[0] + M1inv.data[0][1] * M2.data[1];
ABC.data[1] = M1inv.data[1][0] * M2.data[0] + M1inv.data[1][1] * M2.data[1];
// std::cerr << ABC.data[0] << " " << ABC.data[1] << std::endl;
//iterate to improve the fit.
int N_iter = 1;
for (int i = 0; i < N_iter; i++) {
SumY2 = 0.0;
SumXY2 = 0.0;
SumX2Y2 = 0.0;
SumX3Y2 = 0.0;
SumY2LnY = 0.0;
SumXY2LnY = 0.0;
for (int k = 0; k < shortlist_length; k++) {
Yn = exp(ABC.data[0] + ABC.data[1] * short_channel_list[k] + fac_c * short_channel_list[k] * short_channel_list[k]);
SumY2 += Yn * Yn;
SumXY2 += Yn * Yn * short_channel_list[k];
SumX2Y2 += Yn * Yn * short_channel_list[k] * short_channel_list[k];
SumX3Y2 += Yn * Yn * short_channel_list[k] * short_channel_list[k] * short_channel_list[k];
SumY2LnY += Yn * Yn * log(short_signal_list[k]);
SumXY2LnY += short_channel_list[k] * Yn * Yn * log(short_signal_list[k]);
}
M1.data[0][0] = SumY2;
M1.data[0][1] = SumXY2;
M1.data[1][0] = SumXY2;
M1.data[1][1] = SumX2Y2;
M2.data[0] = SumY2LnY - fac_c * SumX2Y2;
M2.data[1] = SumXY2LnY - fac_c * SumX3Y2;
M1inv = InvertMatrix2x2(M1);
ABC.data[0] = M1inv.data[0][0] * M2.data[0] + M1inv.data[0][1] * M2.data[1];
ABC.data[1] = M1inv.data[1][0] * M2.data[0] + M1inv.data[1][1] * M2.data[1];
}
position = -ABC.data[1]/fac_c/2;
amp = exp(ABC.data[0]-ABC.data[1]*ABC.data[1]/4/fac_c);
sigma=SumArea/amp/2.5066;
// cout << sigma << " " << mean << " " << amp << endl;
for(int k=0; k<shortlist_length;k++){
SumYYM+= (short_signal_list[k]-MeanY)*(short_signal_list[k]-MeanY);
SumYYP+= (amp*exp(-(short_channel_list[k]-position)*(short_channel_list[k]-position)/2/(sigma*sigma)) - MeanY )*(amp*exp(-(short_channel_list[k]-position)*(short_channel_list[k]-position)/2/(sigma*sigma)) - MeanY );
}
focus = 2.3548*sigma;
intensity = amp;
double R_squared = SumYYP/SumYYM;
dataString += QString::number(intensity) + ',' + QString::number(position) + ',' + QString::number(focus)
+ ',' + QString::number(R_squared);
return dataString;
}
HIT_ANALYSE_V2::~HIT_ANALYSE_V2()
{
}

View File

@ -54,9 +54,18 @@ private:
};
double fixedsignalarray[300] = {-13, -7, -12, 22, -6, 0, 22, 5, 8, 11, 25, -10, 11, 13, 32, -4, -2, -37, -21, 23, 13, 26, 11, -24, 1, -6, -6, 1, 22, 30, -21, -3, 11, -2, -11, 5, -2, 31, 24, 4, -17, 24, -24, 20, 31, -6, -1, -4, -10, -26, -12, -19, -7, -39, 1, 19, 3, -13, 37, 2, 11, -10, -14, 20, 14, -1, -13, 13, -18, -18, -15, -25, 14, 11, -32, 50, 18, -11, 26, 4, 4, -2, -10, 34, 6, 36, -9, 19, -3, 7, -10, -15, 4, 24, -3, 2, 13, -34, -28, -25, -4, -14, -11, 23, -19, -7, -6, 6, 23, 7, -21, 18, -8, 6, 21, -4, 3, -1, -11, 7, -38, -38, -12, -11, -11, 9, -11, -7, 2, -1, 19, 12, 0, -7, 15, 3, 28, -8, 1, 8, 2, -4, 4, 23, 31, -17, 8, 11, 34, 1, 7, 14, 14, 16, -1, -30, -2, 19, -20, -4, -9, 15, -6, -4, -4, 10, -27, -18, 24, 19, 20, 22, 68, 122, 234, 371, 496, 713, 840, 967, 1026, 957, 833, 674, 485, 317, 194, 98, 70, 45, 34, -15, 3, 10, 12, -19, 11, 27, -1, 2, -9, -1, -2, -15, -22, 7, 0, -20, -1, -7, 21, -4, -21, 21, -6, 23, -4, -2, -28, -17, -13, 1, 19, 20, 6, 10, -25, -4, 5, -14, -18, -4, 12, 7, -21, 7, -10, 10, 11, -21, 7, -6, -2, -3, 1, 16, 4, -23, 2, 14, 0, -5, -7, -12, -2, -8, -20, 11, 21, -5, -5, 20, -10, 3, -18, -5, 4, 6, 4, -21, -3, -26, -15, -7, -14, -10, -14, 7, -18, -2, -14, 36, -10, 11, 9, 3, -7, -51, -12, 2, 5, 9, 15, 20, -23, -6, -14, -4, 16, 4};
const std::vector<std::vector<double>> fixed_signal =
{
{-13, -7, -12, 22, -6, 0, 22, 5, 8, 11, 25, -10, 11, 13, 32, -4, -2, -37, -21, 23, 13, 26, 11, -24, 1, -6, -6, 1, 22, 30, -21, -3, 11, -2, -11, 5, -2, 31, 24, 4, -17, 24, -24, 20, 31, -6, -1, -4, -10, -26, -12, -19, -7, -39, 1, 19, 3, -13, 37, 2, 11, -10, -14, 20, 14, -1, -13, 13, -18, -18, -15, -25, 14, 11, -32, 50, 18, -11, 26, 4, 4, -2, -10, 34, 6, 36, -9, 19, -3, 7, -10, -15, 4, 24, -3, 2, 13, -34, -28, -25, -4, -14, -11, 23, -19, -7, -6, 6, 23, 7, -21, 18, -8, 6, 21, -4, 3, -1, -11, 7, -38, -38, -12, -11, -11, 9, -11, -7, 2, -1, 19, 12, 0, -7, 15, 3, 28, -8, 1, 8, 2, -4, 4, 23, 31, -17, 8, 11, 34, 1, 7, 14, 14, 16, -1, -30, -2, 19, -20, -4, -9, 15, -6, -4, -4, 10, -27, -18, 24, 19, 20, 22, 68, 122, 234, 371, 496, 713, 840, 967, 1026, 957, 833, 674, 485, 317, 194, 98, 70, 45, 34, -15, 3, 10, 12, -19, 11, 27, -1, 2, -9, -1, -2, -15, -22, 7, 0, -20, -1, -7, 21, -4, -21, 21, -6, 23, -4, -2, -28, -17, -13, 1, 19, 20, 6, 10, -25, -4, 5, -14, -18, -4, 12, 7, -21, 7, -10, 10, 11, -21, 7, -6, -2, -3, 1, 16, 4, -23, 2, 14, 0, -5, -7, -12, -2, -8, -20, 11, 21, -5, -5, 20, -10, 3, -18, -5, 4, 6, 4, -21, -3, -26, -15, -7, -14, -10, -14, 7, -18, -2, -14, 36, -10, 11, 9, 3, -7, -51, -12, 2, 5, 9, 15, 20, -23, -6, -14, -4, 16, 4}
,{-9, -1, -32, 19, 12, -13, 7, 7, -18, -5, 19, 15, 5, -5, -27, 4, -7, 7, -16, -9, -4, -6, -2, 27, 23, 15, -16, -23, 25, 4, 26, -17, -9, -1, 14, -9, -15, -29, -40, 5, 22, 14, 23, -25, 9, -16, -26, -4, -31, -6, -27, 1, 23, 24, 26, 61, 133, 222, 301, 501, 690, 822, 972, 980, 966, 852, 685, 486, 333, 239, 107, 54, 29, 19, 9, 1, 1, 6, 9, 14, -8, -5, 11, 21, -6, -17, -7, 11, 30, -3, 6, -4, 2, 18, -18, 4, -2, 18, 16, 17, 5, -15, -14, 24, -36, -19, 7, -22, -3, -15, -11, -4, -11, 13, -5, -6, 12, 8, 21, -24, -10, -10, -7, 5, 30, -16, -18, -3, -23, 3, -20, -3, 24, 8, -15, -1, -6, -1, -8, -25, 6, 1, -16, -11, 29, -21, 13, 11, -2, -10, 12, -13, 24, -31, 21, -7, 6, -13, 3, -6, -9, 20, -3, 2, -16, -14, 10, 6, 20, 6, 21, 9, 7, -27, 13, -17, 19, 20, -13, -11, -17, -4, 11, -24, 17, -7, -4, 26, 5, 13, 13, 4, -3, -17, -32, -14, 40, 1, -23, -28, 16, 1, 16, -4, -8, -9, 4, 2, -7, 7, -16, -23, -9, 10, 24, 0, -5, -24, -4, -22, -10, -29, 0, 2, 2, 4, -45, 4, -2, 12, 21, -22, -31, -15, 16, 2, 11, 35, 0, 3, 15, -15, -17, 20, -27, 24, 24, -6, 8, -15, 8, 26, -6, -14, 10, -20, 33, 6, -5, 1, 0, 9, 3, -33, -10, -3, 0, 11, -33, 0, 33, 25, -5, 1, 0, -32, -24, 17, 10, -2, 12, -26, 13, 7, -3, 36, 28, 10, 17, -26, 29, -15, 3, 14, -8, -9, -7, -15, -4, 0}
,{14, -3, 2, 20, 3, -9, 15, -3, 26, 3, 8, -1, -5, 13, -10, -18, -9, 35, 3, 29, -12, 37, 12, -12, -9, -34, 9, -3, -19, -3, -10, -9, 3, -1, 5, 22, 10, -10, -27, 30, -19, -26, -23, -25, 16, 4, 4, 9, -23, 5, 0, -35, -5, -21, 0, 22, 18, -42, -4, 16, 17, 41, -15, -12, 13, -5, 35, 5, -4, 19, -12, 4, 4, -2, 2, -12, -23, 5, -2, 4, 7, 5, -10, 41, -20, -2, 4, 5, -34, -19, -6, 6, -3, -12, 39, 38, 72, 104, 194, 347, 484, 666, 808, 946, 1018, 978, 838, 690, 511, 317, 211, 112, 51, 22, 0, -14, 21, -2, 12, -24, 1, -6, 18, 5, -12, 6, -3, -9, -6, -29, -31, -6, -15, -2, -22, 14, -33, 1, 3, -7, -13, 14, 21, -11, -17, -1, -9, -12, 7, 5, -2, -2, -4, -2, -12, -33, 2, 5, -2, -8, 10, 26, 2, -28, 3, -20, 10, -8, 22, 8, -25, 3, -18, -18, 19, 15, -8, 8, 24, -13, 0, -5, -15, 1, -24, -2, 3, -28, 8, 5, -5, 0, 12, 10, -5, 12, 0, -10, -5, -7, -23, -32, -3, 9, 17, -14, -12, -3, -35, -12, -5, 8, 15, -10, 13, 4, 9, 23, -21, -31, 32, 6, -3, -7, 10, -5, 25, -32, 16, -22, 18, 0, 1, -16, -13, -10, -13, 2, -20, -2, 15, 7, 17, -17, 0, 8, 43, -23, -34, -7, 45, 8, 16, 26, -7, -7, -5, 4, -20, -8, -21, 13, 4, -23, 9, 29, 1, 13, -3, -23, 3, 20, 23, 29, -7, -8, 37, -4, -23, 1, -14, -11, 9, -4, -13, -20, -20, 16, -12, 23, 31, 5, 0, 27, 2, 5, 30, -12, -10, 3}
,{-9, -15, -6, 24, -10, -12, 12, -9, -13, 1, -15, -2, -2, 0, 26, -19, -22, 7, 0, 26, 28, -13, -8, -24, 20, -1, -18, -1, -23, -21, -7, -10, 25, 29, 16, 23, -36, 9, 7, -28, -7, 1, 41, -1, -2, 14, -3, 26, -26, 20, -4, 22, 8, 50, 8, 0, -22, -8, 45, 1, -22, -24, -12, 6, 8, 26, 21, 22, -5, 1, -1, -10, -4, 22, 20, 40, -9, 11, -32, 9, -12, -3, -8, 13, 3, -4, -6, 2, 18, 6, 1, -16, 0, 33, 16, -18, -7, 27, 10, -3, 11, -10, -16, -3, 24, 1, -14, -4, 12, -11, -4, 22, 22, -21, -4, 24, 3, 12, 13, 28, -3, 27, 11, -6, 19, 8, -22, -1, 5, 0, 27, 2, -2, -12, -8, 6, 6, 9, 10, -8, 4, 40, 27, 38, 111, 200, 323, 492, 667, 834, 944, 990, 945, 861, 683, 466, 337, 205, 108, 53, 22, 0, 27, 9, -3, 37, 11, -8, -15, -16, 4, 23, 25, -14, -7, -7, -18, -7, 21, 6, 19, -12, 2, -13, -9, -8, -3, -7, -20, -27, 13, 4, -11, 16, 3, -24, 4, -23, 17, 17, -18, -25, 4, 5, -21, -10, -13, 43, 4, -1, -3, -1, -4, -4, 25, 47, 18, 21, 29, 4, -22, 16, -17, -37, -1, 12, -9, -7, 5, -4, 23, 21, -14, -17, 19, 11, 22, 39, -6, 3, 19, -25, 4, 1, -15, -8, 20, 13, -31, 5, 28, 10, 27, 9, -11, 2, 0, -20, -18, -9, 14, 9, 24, -16, -10, 29, 16, 13, 13, -22, 16, 18, 22, 20, 27, -20, 23, 6, 0, 14, -6, -6, -8, 15, -11, 23, -11, 23, -16, 16, -2, 10, 4, -22, -33, -17, -4, 4, 4, -8}
};
const std::vector<double> fixed_channel = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299};
public slots:
QString analyseBeamData(QVector<BufferData> dataframe);
QString analyseBeamData(short int * copysensor_data, const int dev_nr, const int vector_length);
// void processPendingDatagrams();
};

View File

@ -1,16 +1,21 @@
#include "hw.h"
HW::HW(QObject *parent) : QObject(parent)
HW::HW(QObject *parent) : QObject(parent), eventBuilder()// , networkThread(eventBuilder)
{
/*eventBuilder.moveToThread(&eventBuilderThread);
eventBuilderThread.start();
eventBuilder.init();*/
// Create and start the network thread
// networkThread.start();
}
HW::~HW()
{
// if (networkThread.isRunning()){
// networkThread.stopThread();
// networkThread.wait(); // Wait for the network thread to finish gracefully
// }
eventBuilder.stopLogging();
removeDevices();
@ -64,7 +69,7 @@ void HW::disconnectDevices()
void HW::run()
{
//No need to start EVB. It's running all the time.
// Start the UDP server when an instance of HW is created
//run slave(s)
for (int i = 0; i < devices.length(); i++)
if (devices[i]->deviceConfig.master == 0)
@ -78,6 +83,11 @@ void HW::run()
void HW::stop()
{
// Application cleanup
//if (networkThread.isRunning()){
// networkThread.stopThread();
// networkThread.wait(); // Wait for the network thread to finish gracefully
// }
//stop master(s)
for (int i = 0; i < devices.length(); i++)
if (devices[i]->deviceConfig.master != 0)

View File

@ -6,17 +6,19 @@
#include <QThread>
#include "device.h"
#include "eventbuilder.h"
#include "networkthread.h"
class HW : public QObject
{
Q_OBJECT
public:
public:
explicit HW(QObject *parent = 0);
~HW();
QVector<Device*> devices;
EventBuilder eventBuilder;
// NetworkThread networkThread;
Device &operator [](int nr);
void addDevices(int nr_devices);
@ -33,9 +35,12 @@ signals:
public slots:
protected:
private:
};
#endif // HW_H

View File

@ -64,11 +64,11 @@ keithley_thr::keithley_thr()
keithleyWorker *worker = new keithleyWorker;
//worker->theKeithley = &theKeithley;
worker->moveToThread(&workerThread);
worker->timer.moveToThread(&workerThread);
worker->theKeithley.serialPort.moveToThread(&workerThread);
worker->moveToThread(&udpThread);
worker->timer.moveToThread(&udpThread);
worker->theKeithley.serialPort.moveToThread(&udpThread);
//controller -> worker
QObject::connect(&workerThread, &QThread::finished, worker, &QObject::deleteLater);
QObject::connect(&udpThread, &QThread::finished, worker, &QObject::deleteLater);
QObject::connect(this, &keithley_thr::sig_connect, worker, &keithleyWorker::connect);
QObject::connect(this, &keithley_thr::sig_disconnect, worker, &keithleyWorker::disconnect);
QObject::connect(this, &keithley_thr::sig_on, worker, &keithleyWorker::on);
@ -78,13 +78,13 @@ keithley_thr::keithley_thr()
//worker -> controller
QObject::connect(worker, &keithleyWorker::sig_currentReadout, this, &keithley_thr::on_currentReadout);
QObject::connect(worker, &keithleyWorker::sig_isOpen, this, &keithley_thr::on_isOpen);
workerThread.start();
udpThread.start();
}
keithley_thr::~keithley_thr()
{
workerThread.quit();
workerThread.wait();
udpThread.quit();
udpThread.wait();
}
@ -92,7 +92,7 @@ keithley_thr::~keithley_thr()
//************************** slots for communication with worker thread ******************
//called on each current readout
keithley_thr::on_currentReadout(const double value)
void keithley_thr::on_currentReadout(const double value)
{
lastCurrentReadout = value;
emit esig_newCurrentReadout(lastCurrentReadout);

View File

@ -58,14 +58,14 @@ public:
double getCurrent();
void ps_flush();
QThread workerThread;
QThread udpThread;
double lastCurrentReadout;
QString portName;
int recognizeSpillState(double current);
public slots:
on_currentReadout(const double value);
void on_currentReadout(const double value);
int on_isOpen(const int state, const QString givenPortName);
signals:
void sig_connect();

View File

@ -1,16 +1,10 @@
#include "mainwindow.h"
#include <QApplication>
#include "udpserver.h" // Include udpserver header
// Define the global UdpServer object
UdpServer udpServer; // This allocates memory for udpServer
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
// Create the UdpServer object on the heap and store a pointer to it
udpServer.startServer();
// Apply the stylesheet to each display
qDebug() << "App path : " << qApp->applicationDirPath();

View File

@ -29,8 +29,13 @@ MainWindow::MainWindow(QWidget *parent) :
theKeithley = new keithley_thr;
theStepper = new Stepper;
connect(&timer, QTimer::timeout, this, on_timer);
connect(theKeithley, keithley_thr::esig_newCurrentReadout, this, MainWindow::on_newCurrentReadout);
// connect(&timer, QTimer::timeout, this, on_timer);
connect(&timer, &QTimer::timeout, this, &MainWindow::on_timer);
// connect(theKeithley, keithley_thr::esig_newCurrentReadout, this, MainWindow::on_newCurrentReadout);
connect(theKeithley, &keithley_thr::esig_newCurrentReadout, this, &MainWindow::on_newCurrentReadout);
}
@ -41,6 +46,7 @@ MainWindow::~MainWindow()
delete theHW;
delete theDisplay;
delete theKeithley;
}
//***************** Initialization ******************
@ -209,6 +215,21 @@ void MainWindow::startLogging()
}
}
void MainWindow::startAnalysing(){
if (analysing)
stopAnalysing();
analysing = 1;
}
void MainWindow::stopAnalysing()
{
analysing = 0;
}
void MainWindow::stopLogging()
{
theHW->eventBuilder.stopLogging();
@ -322,6 +343,14 @@ void MainWindow::on_pushLogging_pressed()
stopLogging();
}
void MainWindow::on_pushAnalysing_pressed()
{
if (!analysing)
startAnalysing();
else
stopAnalysing();
}
void MainWindow::on_pushDisplay_pressed()
{
if (theDisplay->isActive())
@ -479,3 +508,14 @@ void MainWindow::on_actionDisconnect_Stepper_triggered()
qInfo("Stepper controller disconnected.");
}
void MainWindow::on_pushButton_exit_clicked()
{
if(running) stop();
theHW->stop();
theHW->disconnectDevices();
QApplication::exit(); //close the application;
}

View File

@ -36,11 +36,13 @@ public:
QSettings* deviceSettings;
int running = 0;
int logging = 0;
int analysing = 0;
void run();
void stop();
void startLogging();
void stopLogging();
void startAnalysing();
void stopAnalysing();
void startDisplay();
void stopDisplay();
public slots:
@ -59,34 +61,26 @@ protected:
private slots:
void on_pushLogSettings_pressed();
void on_actionConnect_triggered();
void on_actionDisconnect_triggered();
void on_actionHost_IP_triggered();
void on_actionTrigger_config_triggered();
void on_actionDevices_triggered();
void on_pushRun_pressed();
void on_pushLogging_pressed();
void on_pushAnalysing_pressed();
void on_pushDisplay_pressed();
void on_actionConnect_Keithley_triggered();
void on_actionDisconnect_Keithley_triggered();
void on_actionLinearity_test_triggered();
void on_actionIntegration_time_scan_triggered();
void on_actionProfile_viewer_triggered();
void on_actionConnect_Stepper_triggered();
void on_actionDisconnect_Stepper_triggered();
void on_actionBeta_Scanner_triggered();
void on_pushButton_exit_clicked();
private:
Ui::MainWindow *ui;

View File

@ -80,6 +80,35 @@
</item>
</layout>
</widget>
<widget class="QPushButton" name="pushButton_exit">
<property name="geometry">
<rect>
<x>760</x>
<y>510</y>
<width>80</width>
<height>24</height>
</rect>
</property>
<property name="text">
<string>Quit</string>
</property>
</widget>
<widget class="QPushButton" name="pushAnalysing">
<property name="enabled">
<bool>true</bool>
</property>
<property name="geometry">
<rect>
<x>90</x>
<y>440</y>
<width>161</width>
<height>24</height>
</rect>
</property>
<property name="text">
<string>Start Analysing!</string>
</property>
</widget>
</widget>
<widget class="QMenuBar" name="menuBar">
<property name="geometry">
@ -87,7 +116,7 @@
<x>0</x>
<y>0</y>
<width>853</width>
<height>21</height>
<height>22</height>
</rect>
</property>
<widget class="QMenu" name="menuDevice">

View File

@ -0,0 +1,198 @@
#ifndef NETWORKTHREAD_H
#define NETWORKTHREAD_H
#include <QThread>
#include <QUdpSocket>
#include "iostream"
#include <QTime>
#include <QThread>
#include <QUdpSocket>
#include <QMutex>
#include <QWaitCondition>
#include "eventbuilder.h"
class NetworkThread : public QThread
{
Q_OBJECT
private:
quint16 serverPort = 1901; // Port number for the UDP server
double intensity = 0.0, position = 0.0, focus = 0.0;
QMutex mutex; // Mutex for data synchronization
QWaitCondition dataReady; // Condition variable to signal data readiness
EventBuilder &eventBuilder;
public:
NetworkThread(EventBuilder &builder, QObject *parent = nullptr) : QThread(parent), eventBuilder(builder), stopped(false) {}
void run() override
{
QUdpSocket udpSocket;
//udpSocket.bind(QHostAddress::Any, 12345); // Set your desired port
// Bind the socket to a specific IP address and port
if ( udpSocket.bind(QHostAddress("127.0.0.1"), serverPort) )
{
// connect(udpSocket, SIGNAL(readyRead()), this, SLOT(processPendingDatagrams()));
qInfo() << "UDP server started on port" << serverPort;
}
else
{
stopped = true;
qWarning() << "Failed to bind UDP socket on port" << serverPort;
}
while (!stopped)
{
// Your data serialization and broadcasting logic here
QByteArray data = eventBuilder.getNextData(); // Get data from the EventBuilder
if (!data.isEmpty())
{
QString dataString = QString(data);
udpSocket.writeDatagram(data.data(), data.size(), QHostAddress::Broadcast, serverPort);
// std::cerr << dataString.toStdString() << std::endl;
}
else
{
// std::cerr << "data is empty" << std::endl;
}
// QByteArray data = serializeYourData();
// QTime currentTime = QTime::currentTime();
// Calculate the time since midnight in milliseconds
// int millisecondsSinceMidnight = currentTime.msecsSinceStartOfDay();
// QByteArray data; // Create a QByteArray for your data
// Populate data with your custom data
// data.append(QByteArray::number(millisecondsSinceMidnight));
// udpSocket.writeDatagram(data.data(),data.size(), QHostAddress::Broadcast, serverPort); // Broadcast to all reachable devices
// emit dataReady(data); // Emit the signal when data is ready
// std::cerr << " running" << std::endl;
// QThread::msleep(1); // Sleep for microseconds usleep / millisecond msleep //!!!!! on windows the minimum is about 15ms from OS reasons. ~ 30 microseconds between loops without thread sleep.
}
}
void stopThread()
{
stopped = true;
emit terminationRequested();
}
// Add this public slot to receive data from the main thread
public slots:
signals:
void terminationRequested();
private:
bool stopped;
QByteArray serializeYourData()
{
// Implement your data serialization here
}
};
/*
#include <QThread>
#include <QUdpSocket>
#include <QMutex>
#include <QWaitCondition>
#include <QTime>
class NetworkThread : public QThread
{
Q_OBJECT
private:
quint16 serverPort = 1901; // Port number for the UDP server
double intensity = 0.0, position = 0.0, focus = 0.0;
QMutex mutex; // Mutex for data synchronization
QWaitCondition dataReady; // Condition variable to signal data readiness
public:
NetworkThread(QObject *parent = nullptr) : QThread(parent), stopped(false) {}
void run() override
{
QUdpSocket udpSocket;
if (udpSocket.bind(QHostAddress("10.0.7.1"), serverPort))
{
qInfo() << "UDP server started on port" << serverPort;
}
else
{
stopped = true;
qWarning() << "Failed to bind UDP socket on port" << serverPort;
}
while (!stopped)
{
// Wait for data to be ready
mutex.lock();
dataReady.wait(&mutex);
// Data is now ready, unlock the mutex
QTime currentTime = QTime::currentTime();
int millisecondsSinceMidnight = currentTime.msecsSinceStartOfDay();
QByteArray data;
data.append(QByteArray::number(millisecondsSinceMidnight));
// Append the updated parameters to the data
data.append(",");
data.append(QByteArray::number(intensity));
data.append(",");
data.append(QByteArray::number(position));
data.append(",");
data.append(QByteArray::number(focus));
udpSocket.writeDatagram(data.data(), data.size(), QHostAddress::Broadcast, serverPort);
mutex.unlock();
}
}
void stopThread()
{
stopped = true;
emit terminationRequested();
}
public slots:
// This slot is called from another thread to update the parameters
void updateParameters(double newIntensity, double newPosition, double newFocus)
{
// Lock the mutex before updating the parameters
mutex.lock();
// Update the parameters
intensity = newIntensity;
position = newPosition;
focus = newFocus;
// Signal that data is ready to be sent
dataReady.wakeAll();
// Unlock the mutex
mutex.unlock();
}
signals:
void terminationRequested();
private:
bool stopped;
};
*/
#endif // NETWORKTHREAD_H

Binary file not shown.

Binary file not shown.

View File

@ -1,37 +0,0 @@
#include "udpserver.h"
UdpServer::UdpServer(QObject *parent) : QObject(parent)
{
// Configure the timer for data updates
// connect(&timer, &QTimer::timeout, this, &UdpServer::sendData);
// timer.setInterval(1); // 1 milliseconds (1 kHz)
startServer();
}
void UdpServer::startServer()
{
// Bind the UDP socket to a specific port (replace with your desired port)
// udpSocket.bind(QHostAddress::Any, 12345); // Replace 12345 with your desired port
udpSocket.bind(QHostAddress("10.0.7.1"), 12345); // Use the desired host address and port
// udpSocket.bind(QHostAddress::LocalHost, 12345); // Use "localhost" (127.0.0.1) and port 12345
// Start the timer for data updates
// timer.start();
}
void UdpServer::stopServer()
{
// Stop the timer and close the UDP socket
// timer.stop();
udpSocket.close();
}
void UdpServer::sendData(QByteArray data)
{
// Prepare the data to be sent
// QString dataString = QString::number(intensity) + ',' + QString::number(position) + ',' + QString::number(focus);
// QByteArray data = dataString.toUtf8();
// Send the data to all connected clients (broadcast to all on the same network)
udpSocket.writeDatagram(data, QHostAddress::Broadcast, 12345); // Replace 12345 with your desired port
}

View File

@ -2,30 +2,55 @@
#define UDPSERVER_H
#include <QObject>
#include <QVector>
#include <QThread>
#include <QUdpSocket>
#include <QTimer> // Add this line to include QTimer
class UdpServer : public QObject
class UDPServer : public QObject
{
Q_OBJECT
private:
QUdpSocket* udpSocket; // UDP socket for communication
quint16 serverPort = 12345; // Port number for the UDP server
public:
explicit UdpServer(QObject *parent = nullptr);
UDPServer(QObject* parent = nullptr) : QObject(parent)
{
// Initialize and configure your UDP server here
}
public slots:
void startServer();
void stopServer();
void sendData(QByteArray data); // New slot to send data with custom values
void startServer()
{
// Start your UDP server here
udpSocket = new QUdpSocket(this);
private:
QUdpSocket udpSocket;
QTimer timer;
// Bind the socket to a specific IP address and port
if ( udpSocket->bind(QHostAddress("10.0.7.1"), serverPort) )
{
connect(udpSocket, SIGNAL(readyRead()), this, SLOT(processPendingDatagrams()));
qDebug() << "UDP server started on port" << serverPort;
}
else
{
qWarning() << "Failed to bind UDP socket on port" << serverPort;
}
}
void stopServer()
{
// Stop your UDP server here
if (udpSocket)
{
udpSocket->close();
udpSocket->deleteLater();
}
qDebug() << "UDP server stopped";
}
// Add any other methods and signals relevant to your UDP server
};
// Declare the global UdpServer object as an external variable
extern UdpServer udpServer;
#endif // UDPSERVER_H

View File

@ -0,0 +1,57 @@
// udpclient.cpp
#include "udpclient.h"
#include <iostream>
UdpClient::UdpClient(QObject *parent) : QObject(parent)
{
// Create a QHostAddress for the server's IP address
QHostAddress serverAddress("10.0.7.1");
// Bind the UDP socket to a specific port for receiving data (replace with your desired port)
udpSocket.bind(QHostAddress("10.0.7.1"), 12345); // Replace 12345 with your desired port
// Connect the UDP socket's readyRead signal to the receiveData slot
connect(&udpSocket, &QUdpSocket::readyRead, this, &UdpClient::receiveData);
// Set the server's address and port for sending data
udpSocket.connectToHost(QHostAddress("10.0.7.1"), 12345); // Replace 12345 with the server's port
}
void UdpClient::startClient()
{
// Start any client functionality here
// This method can be used to initialize the client if needed.
qDebug() << "UDP Client is listening for data...";
}
void UdpClient::receiveData()
{
// Process pending datagrams
processPendingDatagrams();
}
void UdpClient::processPendingDatagrams()
{
while (udpSocket.hasPendingDatagrams()) {
QByteArray datagram;
datagram.resize(udpSocket.pendingDatagramSize());
QHostAddress sender;
quint16 senderPort;
udpSocket.readDatagram(datagram.data(), datagram.size(), &sender, &senderPort);
// Parse and display the received data
QString receivedData = QString::fromUtf8(datagram);
// QStringList dataList = receivedData.split(',');
std::cout << "Received Data: " << receivedData.toStdString() << std::endl;
/* if (dataList.size() == 3) {
double intensity = dataList[0].toDouble();
double position = dataList[1].toDouble();
double focus = dataList[2].toDouble();
qDebug() << "Received data - Intensity:" << intensity << "Position:" << position << "Focus:" << focus;
}*/
}
}