diff --git a/hit2023v2/bkg/background_Plane0.txt b/hit2023v2/bkg/background_Plane0.txt new file mode 100644 index 0000000..f2fb184 --- /dev/null +++ b/hit2023v2/bkg/background_Plane0.txt @@ -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 diff --git a/hit2023v2/bkg/background_Plane1.txt b/hit2023v2/bkg/background_Plane1.txt new file mode 100644 index 0000000..d4e96f3 --- /dev/null +++ b/hit2023v2/bkg/background_Plane1.txt @@ -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 diff --git a/hit2023v2/calib/calibration_Plane0.txt b/hit2023v2/calib/calibration_Plane0.txt new file mode 100644 index 0000000..0a0ead7 --- /dev/null +++ b/hit2023v2/calib/calibration_Plane0.txt @@ -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 diff --git a/hit2023v2/calib/calibration_Plane1.txt b/hit2023v2/calib/calibration_Plane1.txt new file mode 100644 index 0000000..49c4507 --- /dev/null +++ b/hit2023v2/calib/calibration_Plane1.txt @@ -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 diff --git a/hit2023v2/device_config.ini b/hit2023v2/device_config.ini index 47a626a..97921a9 100644 --- a/hit2023v2/device_config.ini +++ b/hit2023v2/device_config.ini @@ -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 diff --git a/hit2023v2/device_config.ini.old b/hit2023v2/device_config.ini.old new file mode 100644 index 0000000..49ba9b3 --- /dev/null +++ b/hit2023v2/device_config.ini.old @@ -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 diff --git a/hit2023v2/dialogtiscan.cpp~RF5aa2696.TMP b/hit2023v2/dialogtiscan.cpp~RF5aa2696.TMP new file mode 100644 index 0000000..5c0277a --- /dev/null +++ b/hit2023v2/dialogtiscan.cpp~RF5aa2696.TMP @@ -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 xdata; + QList> ymeandata; + QList> 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 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(); +} diff --git a/hit2023v2/display.cpp b/hit2023v2/display.cpp index fc38aa5..a18ca1a 100644 --- a/hit2023v2/display.cpp +++ b/hit2023v2/display.cpp @@ -3,6 +3,7 @@ #include #include #include +#include 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 &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 &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 &data) // Check if calibration is enabled and the checkbox is checked // Check if calibration data exists if (calibrationDataMap.contains(planeName) ){ - const QVector &calibrationData = calibrationDataMap[planeName]; - + const QVector &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 &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 &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 calibrationData; + QVector 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 normalizedCalibrationData = calibrationData; // Copy the data - QVector normalizedCalibrationData2 = calibrationData; // Copy the data again + QVector normalizedCalibrationData = calibrationData; // Copy the data + QVector 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"; } } diff --git a/hit2023v2/display.h b/hit2023v2/display.h index c34f4a2..f807a4a 100644 --- a/hit2023v2/display.h +++ b/hit2023v2/display.h @@ -51,9 +51,9 @@ private: QMap> backgroundDataMap; // Map to store background data for each plane bool subtractBackground = false; // Flag to track if background subtraction is enabled - QMap> calibrationDataMap; // Map to store calibration data for each plane + QMap> calibrationDataMap; // Map to store calibration data for each plane bool applyCalibration = false; // Flag to track if calibration should be applied - QVector calibrationData; // Stores the loaded calibration data + QVector calibrationData; // Stores the loaded calibration data QCheckBox *checkBoxExpertMode; // Expert Mode checkbox bool expertModeEnabled = false; // Flag to track if expert mode is enabled }; diff --git a/hit2023v2/display.h~RF57c8986.TMP b/hit2023v2/display.h~RF57c8986.TMP new file mode 100644 index 0000000..68548f8 --- /dev/null +++ b/hit2023v2/display.h~RF57c8986.TMP @@ -0,0 +1,61 @@ +#ifndef DISPLAY_H +#define DISPLAY_H + +#include +#include +#include +#include +#include +#include +#include + +namespace Ui { +class display; +} + +class Display : public QDialog +{ + Q_OBJECT + +public: + explicit Display(QWidget *parent = 0); + ~Display(); + + + void plot(const QVector &data); + void plot(); + void setTitle(QString title); + + QVector 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 dataX; + QVector 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> backgroundDataMap; // Map to store background data for each plane + bool subtractBackground = false; // Flag to track if background subtraction is enabled + + QMap> calibrationDataMap; // Map to store calibration data for each plane + bool applyCalibration = false; // Flag to track if calibration should be applied + QVector 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 diff --git a/hit2023v2/eventbuilder.cpp b/hit2023v2/eventbuilder.cpp index 1232799..b006913 100644 --- a/hit2023v2/eventbuilder.cpp +++ b/hit2023v2/eventbuilder.cpp @@ -18,27 +18,86 @@ EventBuilder::EventBuilder( QObject *parent) : QObject(parent) EventBuilder::~EventBuilder() { - deinit(); + deinit(); - thread.quit(); - thread.wait(); - // networkThread.stopThread(); - // networkThread.wait(); // Wait for the network thread to finish gracefully + thread.quit(); + thread.wait(); + // networkThread.stopThread(); + // networkThread.wait(); // Wait for the network thread to finish gracefully +} + + +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 +//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(); @@ -50,11 +109,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(); @@ -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,22 +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_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(); @@ -156,7 +227,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; @@ -194,7 +265,7 @@ void EventBuilder::logDataToFile() logFile.write((const char*)currentFrame[board].sensor_data, currentFrame[board].buffer_size*sizeof(unsigned short)); } - //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)); } @@ -347,7 +418,7 @@ QVector EventBuilder::getLastFrame() QVector EventBuilder::getNewFrame() { - //wait for new data + //wait for new data newDataSemaphore.acquire(1); //and return it return getLastFrame(); @@ -358,7 +429,7 @@ void EventBuilder::receiveData(const QByteArray &data) QMutexLocker locker(&mutex); dataQueue.enqueue(data); QString dataString = QString(data); - // std::cerr << dataString.toStdString() << std::endl; + // std::cerr << dataString.toStdString() << std::endl; dataAvailable.wakeOne(); } diff --git a/hit2023v2/eventbuilder.h b/hit2023v2/eventbuilder.h index a5467ab..5aa9a4e 100644 --- a/hit2023v2/eventbuilder.h +++ b/hit2023v2/eventbuilder.h @@ -13,6 +13,8 @@ //#include "hw.h" #include "datareceiver.h" #include "histogram.h" +#include // Include for Intel Intrinsics +#include // 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 receivers; QVector currentFrame; + signed short * copy_sensor_data; QVector backgroundFrame; QVector 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; diff --git a/hit2023v2/hit2023v2.pro b/hit2023v2/hit2023v2.pro index 1722868..8be04e0 100644 --- a/hit2023v2/hit2023v2.pro +++ b/hit2023v2/hit2023v2.pro @@ -5,7 +5,7 @@ #------------------------------------------------- QT += core gui network serialport - +#CONFIG += static unix { QMAKE_CXXFLAGS += -W -std=c++17 } diff --git a/hit2023v2/hit_analyse_v2.cpp b/hit2023v2/hit_analyse_v2.cpp index d223d82..e2d7ae0 100644 --- a/hit2023v2/hit_analyse_v2.cpp +++ b/hit2023v2/hit_analyse_v2.cpp @@ -1,5 +1,6 @@ #include "hit_analyse_v2.h" #include +#include // 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 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 signal_list(vector_length); - std::vector channel_list(vector_length); + std::vector channel_list; std::vector short_signal_list; std::vector short_channel_list; - // Create a random number generator with a Gaussian distribution - std::random_device rd; - std::mt19937 gen(rd()); - std::normal_distribution 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 result(vector_length); + // std::vector 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(std::round(randomValue)); - channel_list[i] = i; - signal_list[i] += static_cast(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 < Ymax) { Ymax = signal_list[i]; Pomax = channel_list[i]; @@ -193,14 +93,14 @@ QString HIT_ANALYSE_V2::analyseBeamData(QVector 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 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++) { diff --git a/hit2023v2/hit_analyse_v2.cpp~RF264e94.TMP b/hit2023v2/hit_analyse_v2.cpp~RF264e94.TMP new file mode 100644 index 0000000..9fdc251 --- /dev/null +++ b/hit2023v2/hit_analyse_v2.cpp~RF264e94.TMP @@ -0,0 +1,337 @@ +#include "hit_analyse_v2.h" +#include + +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 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 channel_list; + std::vector short_signal_list; + std::vector short_channel_list; + + // Create a random number generator with a Gaussian distribution + std::random_device rd; + std::mt19937 gen(rd()); + std::normal_distribution dist(0.0, 17.0); // Mean of 0 and Sigma of 17 + + // Create a vector to store the generated values + std::vector 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(std::round(randomValue)); + // signal_list[i] = dataframe[dev_nr].sensor_data[i]; + //channel_list[i] = i; + signal_list[i] += static_cast(std::round(intensity*exp(-4*log(2)*pow((channel_list[i]-position)/focus,2)))); + + // std::cerr << channel_list[i] << ", "; + } + + // std::cerr < 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> 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 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 dataframe); + QString analyseBeamData(short int * copysensor_data, const int dev_nr, const int vector_length); // void processPendingDatagrams(); }; diff --git a/hit2023v2/hw.cpp b/hit2023v2/hw.cpp index 944f31c..3973502 100644 --- a/hit2023v2/hw.cpp +++ b/hit2023v2/hw.cpp @@ -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) diff --git a/hit2023v2/hw.h b/hit2023v2/hw.h index 9454a8e..0657bd2 100644 --- a/hit2023v2/hw.h +++ b/hit2023v2/hw.h @@ -18,7 +18,7 @@ public: QVector devices; EventBuilder eventBuilder; - NetworkThread networkThread; + // NetworkThread networkThread; Device &operator [](int nr); void addDevices(int nr_devices); diff --git a/hit2023v2/mainwindow.cpp b/hit2023v2/mainwindow.cpp index 9e07b1e..50fc109 100644 --- a/hit2023v2/mainwindow.cpp +++ b/hit2023v2/mainwindow.cpp @@ -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()) diff --git a/hit2023v2/mainwindow.h b/hit2023v2/mainwindow.h index b78cb06..ef10721 100644 --- a/hit2023v2/mainwindow.h +++ b/hit2023v2/mainwindow.h @@ -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(); diff --git a/hit2023v2/mainwindow.ui b/hit2023v2/mainwindow.ui index 4c20f10..146e59c 100644 --- a/hit2023v2/mainwindow.ui +++ b/hit2023v2/mainwindow.ui @@ -93,6 +93,22 @@ Quit + + + true + + + + 90 + 440 + 161 + 24 + + + + Start Analysing! + + @@ -100,7 +116,7 @@ 0 0 853 - 21 + 22 diff --git a/hit2023v2/release/hit2023v2.exe b/hit2023v2/release/hit2023v2.exe index 568b126..8de5af6 100644 Binary files a/hit2023v2/release/hit2023v2.exe and b/hit2023v2/release/hit2023v2.exe differ diff --git a/hit2023v2/udpserver.h b/hit2023v2/udpserver.h new file mode 100644 index 0000000..d3f6aa9 --- /dev/null +++ b/hit2023v2/udpserver.h @@ -0,0 +1,56 @@ +#ifndef UDPSERVER_H +#define UDPSERVER_H + +#include +#include +#include +#include + +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 diff --git a/hit2023v2_RMS/bkg/background_Plane0.txt b/hit2023v2_RMS/bkg/background_Plane0.txt new file mode 100644 index 0000000..f2fb184 --- /dev/null +++ b/hit2023v2_RMS/bkg/background_Plane0.txt @@ -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 diff --git a/hit2023v2_RMS/bkg/background_Plane1.txt b/hit2023v2_RMS/bkg/background_Plane1.txt new file mode 100644 index 0000000..d4e96f3 --- /dev/null +++ b/hit2023v2_RMS/bkg/background_Plane1.txt @@ -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 diff --git a/hit2023v2_RMS/calib/calibration_Plane0.txt b/hit2023v2_RMS/calib/calibration_Plane0.txt new file mode 100644 index 0000000..0a0ead7 --- /dev/null +++ b/hit2023v2_RMS/calib/calibration_Plane0.txt @@ -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 diff --git a/hit2023v2_RMS/calib/calibration_Plane1.txt b/hit2023v2_RMS/calib/calibration_Plane1.txt new file mode 100644 index 0000000..49c4507 --- /dev/null +++ b/hit2023v2_RMS/calib/calibration_Plane1.txt @@ -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 diff --git a/hit2023v2_RMS/datareceiver.cpp b/hit2023v2_RMS/datareceiver.cpp index 253e905..e89876d 100644 --- a/hit2023v2_RMS/datareceiver.cpp +++ b/hit2023v2_RMS/datareceiver.cpp @@ -1,12 +1,13 @@ #include "datareceiver.h" #include "dev_commands.h" #include "helpers.h" +#include 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; dmabstart(RECEIVER_TIMER_PERIOD_MS); } diff --git a/hit2023v2_RMS/datareceiver.h b/hit2023v2_RMS/datareceiver.h index c77a2b1..b5c2ee7 100644 --- a/hit2023v2_RMS/datareceiver.h +++ b/hit2023v2_RMS/datareceiver.h @@ -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; } diff --git a/hit2023v2_RMS/device_config.ini b/hit2023v2_RMS/device_config.ini index 47a626a..b079857 100644 --- a/hit2023v2_RMS/device_config.ini +++ b/hit2023v2_RMS/device_config.ini @@ -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 diff --git a/hit2023v2_RMS/device_config.ini.old b/hit2023v2_RMS/device_config.ini.old new file mode 100644 index 0000000..49ba9b3 --- /dev/null +++ b/hit2023v2_RMS/device_config.ini.old @@ -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 diff --git a/hit2023v2_RMS/dialogbeta.cpp b/hit2023v2_RMS/dialogbeta.cpp index 6391aa7..480503d 100644 --- a/hit2023v2_RMS/dialogbeta.cpp +++ b/hit2023v2_RMS/dialogbeta.cpp @@ -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); } } diff --git a/hit2023v2_RMS/dialoglinearity.cpp b/hit2023v2_RMS/dialoglinearity.cpp index e6ea70d..78af262 100644 --- a/hit2023v2_RMS/dialoglinearity.cpp +++ b/hit2023v2_RMS/dialoglinearity.cpp @@ -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 histos = theHW->eventBuilder.getHistos(); result.mean.fill(0, nr_devices*128); diff --git a/hit2023v2_RMS/dialoglogsettings.ui b/hit2023v2_RMS/dialoglogsettings.ui index 568c05f..29a09fc 100644 --- a/hit2023v2_RMS/dialoglogsettings.ui +++ b/hit2023v2_RMS/dialoglogsettings.ui @@ -99,7 +99,7 @@ - Display + BPMDisplay diff --git a/hit2023v2_RMS/dialogprofiler.cpp b/hit2023v2_RMS/dialogprofiler.cpp index 310ccd9..93a4d3d 100644 --- a/hit2023v2_RMS/dialogprofiler.cpp +++ b/hit2023v2_RMS/dialogprofiler.cpp @@ -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 histos = theHW->eventBuilder.getHistos(); result.mean.fill(0, nr_devices*128); diff --git a/hit2023v2_RMS/dialogtiscan.cpp b/hit2023v2_RMS/dialogtiscan.cpp index 5c0277a..81c47bd 100644 --- a/hit2023v2_RMS/dialogtiscan.cpp +++ b/hit2023v2_RMS/dialogtiscan.cpp @@ -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 histos = theHW->eventBuilder.getHistos(); result.mean.fill(0, nr_devices*128); diff --git a/hit2023v2_RMS/dialogtiscan.cpp~RF5aa2696.TMP b/hit2023v2_RMS/dialogtiscan.cpp~RF5aa2696.TMP new file mode 100644 index 0000000..5c0277a --- /dev/null +++ b/hit2023v2_RMS/dialogtiscan.cpp~RF5aa2696.TMP @@ -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 xdata; + QList> ymeandata; + QList> 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 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(); +} diff --git a/hit2023v2_RMS/display.cpp b/hit2023v2_RMS/display.cpp index 63f1494..a077365 100644 --- a/hit2023v2_RMS/display.cpp +++ b/hit2023v2_RMS/display.cpp @@ -3,8 +3,9 @@ #include #include #include +#include -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 &data) +void BPMDisplay::plot(const QVector &data, const QVector &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 &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 &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 &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 &calibrationData = calibrationDataMap[planeName]; - + const QVector &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 &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 &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 &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 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 &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 calibrationData; + QVector 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 normalizedCalibrationData = calibrationData; // Copy the data - QVector normalizedCalibrationData2 = calibrationData; // Copy the data again + QVector normalizedCalibrationData = calibrationData; // Copy the data + QVector 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)); +} diff --git a/hit2023v2_RMS/display.h b/hit2023v2_RMS/display.h index 6c999aa..923f1f4 100644 --- a/hit2023v2_RMS/display.h +++ b/hit2023v2_RMS/display.h @@ -8,25 +8,30 @@ #include #include #include +#include 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 &data); void plot(); + void plot(const QVector &data, const QVector &rmsdata); + void setTitle(QString title); QVector buffer; + QVector 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 dataX; QVector dataY; + QVector dataRMS; + + private: Ui::display *ui; QRadioButton *radioButtonFixedScale; // Pointer to the Fixed Scale radio button @@ -51,11 +65,16 @@ private: QMap> backgroundDataMap; // Map to store background data for each plane bool subtractBackground = false; // Flag to track if background subtraction is enabled - QMap> calibrationDataMap; // Map to store calibration data for each plane + QMap> calibrationDataMap; // Map to store calibration data for each plane bool applyCalibration = false; // Flag to track if calibration should be applied - QVector calibrationData; // Stores the loaded calibration data + QVector 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 diff --git a/hit2023v2_RMS/display.h~RF57c8986.TMP b/hit2023v2_RMS/display.h~RF57c8986.TMP new file mode 100644 index 0000000..68548f8 --- /dev/null +++ b/hit2023v2_RMS/display.h~RF57c8986.TMP @@ -0,0 +1,61 @@ +#ifndef DISPLAY_H +#define DISPLAY_H + +#include +#include +#include +#include +#include +#include +#include + +namespace Ui { +class display; +} + +class Display : public QDialog +{ + Q_OBJECT + +public: + explicit Display(QWidget *parent = 0); + ~Display(); + + + void plot(const QVector &data); + void plot(); + void setTitle(QString title); + + QVector 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 dataX; + QVector 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> backgroundDataMap; // Map to store background data for each plane + bool subtractBackground = false; // Flag to track if background subtraction is enabled + + QMap> calibrationDataMap; // Map to store calibration data for each plane + bool applyCalibration = false; // Flag to track if calibration should be applied + QVector 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 diff --git a/hit2023v2_RMS/display.ui b/hit2023v2_RMS/display.ui index b0e7302..bb11732 100644 --- a/hit2023v2_RMS/display.ui +++ b/hit2023v2_RMS/display.ui @@ -7,7 +7,7 @@ 0 0 609 - 418 + 463 @@ -17,7 +17,7 @@ - Online Display + Online BPMDisplay @@ -160,7 +160,7 @@ 10 - 370 + 410 581 41 @@ -199,28 +199,225 @@ calibration + + + + + + 10 + 370 + 581 + 41 + + + - - - sub bkg + + + QFrame::WinPanel + + QFrame::Sunken + + + + + 50 + 0 + 91 + 41 + + + + QFrame::NoFrame + + + QFrame::Plain + + + true + + + 0.000000000000000 + + + 0 + + + + + + 10 + 10 + 61 + 21 + + + + + 12 + + + + MEAN + + + Qt::RichText + + + true + + - - - load bkg + + + QFrame::StyledPanel + + QFrame::Raised + + + + + 0 + 10 + 61 + 21 + + + + + 12 + + + + Status + + + Qt::RichText + + + true + + + + + + 50 + 0 + 91 + 41 + + + + QFrame::NoFrame + + + QFrame::Plain + + + true + + + 0.000000000000000 + + + 0 + + - - - false + + + QFrame::WinPanel - - save bkg + + QFrame::Sunken + + + + 60 + 0 + 71 + 41 + + + + QFrame::NoFrame + + + QFrame::Plain + + + + + + 8 + 10 + 61 + 21 + + + + + 12 + + + + FOCUS + + + + + + + + QFrame::WinPanel + + + QFrame::Sunken + + + + + 50 + 0 + 71 + 41 + + + + + Arial + 8 + + + + QFrame::NoFrame + + + + + + 8 + 10 + 61 + 21 + + + + + 12 + + + + MAX + + diff --git a/hit2023v2_RMS/displayserver.cpp b/hit2023v2_RMS/displayserver.cpp index 7948b17..bc97189 100644 --- a/hit2023v2_RMS/displayserver.cpp +++ b/hit2023v2_RMS/displayserver.cpp @@ -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(); diff --git a/hit2023v2_RMS/displayserver.h b/hit2023v2_RMS/displayserver.h index 41091b1..68d7a98 100644 --- a/hit2023v2_RMS/displayserver.h +++ b/hit2023v2_RMS/displayserver.h @@ -38,7 +38,7 @@ protected: int active = 0; HW* theHW; QVector planeConfig; - QVector displays; + QVector displays; PlaneConfig *findPlane(int plane_nr); }; diff --git a/hit2023v2_RMS/eventbuilder.cpp b/hit2023v2_RMS/eventbuilder.cpp index c154706..d819224 100644 --- a/hit2023v2_RMS/eventbuilder.cpp +++ b/hit2023v2_RMS/eventbuilder.cpp @@ -1,43 +1,46 @@ #include "eventbuilder.h" -#include "udpserver.h" #include "hit_analyse_v2.h" - -EventBuilder::EventBuilder(QObject *parent) : QObject(parent) +#include +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 EventBuilder::getLastFrame() QVector 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(); +} diff --git a/hit2023v2_RMS/eventbuilder.h b/hit2023v2_RMS/eventbuilder.h index 17b378d..5aa9a4e 100644 --- a/hit2023v2_RMS/eventbuilder.h +++ b/hit2023v2_RMS/eventbuilder.h @@ -8,11 +8,13 @@ #include #include #include -#include "udpserver.h" // Include the UDP server header - +#include +#include //#include "hw.h" #include "datareceiver.h" #include "histogram.h" +#include // Include for Intel Intrinsics +#include // 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 receivers; QVector currentFrame; + signed short * copy_sensor_data; QVector backgroundFrame; QVector 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 dataQueue; + QMutex mutex; + QWaitCondition dataAvailable; }; diff --git a/hit2023v2_RMS/helpers.h b/hit2023v2_RMS/helpers.h index 96a2cc9..b346dd1 100644 --- a/hit2023v2_RMS/helpers.h +++ b/hit2023v2_RMS/helpers.h @@ -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(static_cast((by)[0])) << 8) | \ (static_cast(static_cast((by)[1]))) \ ) -#define BYTES2INT(by) \ - ( \ - (static_cast(static_cast((by)[0])) << 24) | \ - (static_cast(static_cast((by)[1])) << 16) | \ - (static_cast(static_cast((by)[2])) << 8) | \ - (static_cast(static_cast((by)[3]))) \ - ) - //convert textual representation of IP to array of numbers and/or well-formatted string QString ip2num(QString input, unsigned char* numbers = NULL); diff --git a/hit2023v2_RMS/hit2023v2_RMS.pro b/hit2023v2_RMS/hit2023v2_RMS.pro index d2c4a5c..8be04e0 100644 --- a/hit2023v2_RMS/hit2023v2_RMS.pro +++ b/hit2023v2_RMS/hit2023v2_RMS.pro @@ -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 \ diff --git a/hit2023v2_RMS/hit_analyse_v2.cpp b/hit2023v2_RMS/hit_analyse_v2.cpp index 6a096f4..e2d7ae0 100644 --- a/hit2023v2_RMS/hit_analyse_v2.cpp +++ b/hit2023v2_RMS/hit_analyse_v2.cpp @@ -1,5 +1,6 @@ #include "hit_analyse_v2.h" #include +#include // 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 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 signal_list(vector_length); - std::vector 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 dist(0.0, 17.0); // Mean of 0 and Sigma of 17 + std::vector channel_list; + std::vector short_signal_list; + std::vector short_channel_list; + + channel_list = fixed_channel; // Create a vector to store the generated values - std::vector result(vector_length); + // std::vector result(vector_length); - // Fill the vector with random values - for (int i = 0; i < vector_length; ++i) { - result[i] = static_cast(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 dataframe){ } + + HIT_ANALYSE_V2::~HIT_ANALYSE_V2() { diff --git a/hit2023v2_RMS/hit_analyse_v2.cpp~RF264e94.TMP b/hit2023v2_RMS/hit_analyse_v2.cpp~RF264e94.TMP new file mode 100644 index 0000000..9fdc251 --- /dev/null +++ b/hit2023v2_RMS/hit_analyse_v2.cpp~RF264e94.TMP @@ -0,0 +1,337 @@ +#include "hit_analyse_v2.h" +#include + +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 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 channel_list; + std::vector short_signal_list; + std::vector short_channel_list; + + // Create a random number generator with a Gaussian distribution + std::random_device rd; + std::mt19937 gen(rd()); + std::normal_distribution dist(0.0, 17.0); // Mean of 0 and Sigma of 17 + + // Create a vector to store the generated values + std::vector 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(std::round(randomValue)); + // signal_list[i] = dataframe[dev_nr].sensor_data[i]; + //channel_list[i] = i; + signal_list[i] += static_cast(std::round(intensity*exp(-4*log(2)*pow((channel_list[i]-position)/focus,2)))); + + // std::cerr << channel_list[i] << ", "; + } + + // std::cerr < 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> 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 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 dataframe); + QString analyseBeamData(short int * copysensor_data, const int dev_nr, const int vector_length); // void processPendingDatagrams(); }; diff --git a/hit2023v2_RMS/hw.cpp b/hit2023v2_RMS/hw.cpp index 2ed6bb0..3973502 100644 --- a/hit2023v2_RMS/hw.cpp +++ b/hit2023v2_RMS/hw.cpp @@ -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) diff --git a/hit2023v2_RMS/hw.h b/hit2023v2_RMS/hw.h index 3d5f1e8..0657bd2 100644 --- a/hit2023v2_RMS/hw.h +++ b/hit2023v2_RMS/hw.h @@ -6,17 +6,19 @@ #include #include "device.h" #include "eventbuilder.h" - +#include "networkthread.h" class HW : public QObject { Q_OBJECT +public: + public: explicit HW(QObject *parent = 0); ~HW(); QVector 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 diff --git a/hit2023v2_RMS/keithley_thr.cpp b/hit2023v2_RMS/keithley_thr.cpp index 306c19b..c2931df 100644 --- a/hit2023v2_RMS/keithley_thr.cpp +++ b/hit2023v2_RMS/keithley_thr.cpp @@ -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); diff --git a/hit2023v2_RMS/keithley_thr.h b/hit2023v2_RMS/keithley_thr.h index 2cac354..fe30173 100644 --- a/hit2023v2_RMS/keithley_thr.h +++ b/hit2023v2_RMS/keithley_thr.h @@ -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(); diff --git a/hit2023v2_RMS/main.cpp b/hit2023v2_RMS/main.cpp index 9db49a4..66c046b 100644 --- a/hit2023v2_RMS/main.cpp +++ b/hit2023v2_RMS/main.cpp @@ -1,16 +1,10 @@ #include "mainwindow.h" #include -#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(); diff --git a/hit2023v2_RMS/mainwindow.cpp b/hit2023v2_RMS/mainwindow.cpp index a5a34c1..50fc109 100644 --- a/hit2023v2_RMS/mainwindow.cpp +++ b/hit2023v2_RMS/mainwindow.cpp @@ -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; +} + diff --git a/hit2023v2_RMS/mainwindow.h b/hit2023v2_RMS/mainwindow.h index a3902d9..ef10721 100644 --- a/hit2023v2_RMS/mainwindow.h +++ b/hit2023v2_RMS/mainwindow.h @@ -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; diff --git a/hit2023v2_RMS/mainwindow.ui b/hit2023v2_RMS/mainwindow.ui index 3d36b83..146e59c 100644 --- a/hit2023v2_RMS/mainwindow.ui +++ b/hit2023v2_RMS/mainwindow.ui @@ -80,6 +80,35 @@ + + + + 760 + 510 + 80 + 24 + + + + Quit + + + + + true + + + + 90 + 440 + 161 + 24 + + + + Start Analysing! + + @@ -87,7 +116,7 @@ 0 0 853 - 21 + 22 diff --git a/hit2023v2_RMS/networkthread.h b/hit2023v2_RMS/networkthread.h new file mode 100644 index 0000000..e5e5dfa --- /dev/null +++ b/hit2023v2_RMS/networkthread.h @@ -0,0 +1,198 @@ +#ifndef NETWORKTHREAD_H +#define NETWORKTHREAD_H + + +#include +#include +#include "iostream" +#include +#include +#include +#include +#include +#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 +#include +#include +#include +#include + +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 diff --git a/hit2023v2_RMS/release/hit2023v2.exe b/hit2023v2_RMS/release/hit2023v2.exe index 68d2eed..780a7fe 100644 Binary files a/hit2023v2_RMS/release/hit2023v2.exe and b/hit2023v2_RMS/release/hit2023v2.exe differ diff --git a/hit2023v2_RMS/release/hit2023v2.exe.debug b/hit2023v2_RMS/release/hit2023v2.exe.debug new file mode 100644 index 0000000..0181876 Binary files /dev/null and b/hit2023v2_RMS/release/hit2023v2.exe.debug differ diff --git a/hit2023v2_RMS/udpserver.cpp b/hit2023v2_RMS/udpserver.cpp deleted file mode 100644 index bea789d..0000000 --- a/hit2023v2_RMS/udpserver.cpp +++ /dev/null @@ -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 -} diff --git a/hit2023v2_RMS/udpserver.h b/hit2023v2_RMS/udpserver.h index 16e05c0..d3f6aa9 100644 --- a/hit2023v2_RMS/udpserver.h +++ b/hit2023v2_RMS/udpserver.h @@ -2,30 +2,55 @@ #define UDPSERVER_H #include +#include +#include #include -#include // 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 diff --git a/hit2023v2_client/udpclient.cpp~RF7c15a.TMP b/hit2023v2_client/udpclient.cpp~RF7c15a.TMP new file mode 100644 index 0000000..014b0be --- /dev/null +++ b/hit2023v2_client/udpclient.cpp~RF7c15a.TMP @@ -0,0 +1,57 @@ +// udpclient.cpp + +#include "udpclient.h" +#include +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; + }*/ + } +}