diff --git a/python/slsdet/detector.py b/python/slsdet/detector.py index 061e70193..7887d582f 100755 --- a/python/slsdet/detector.py +++ b/python/slsdet/detector.py @@ -8,6 +8,8 @@ speedLevel = slsDetectorDefs.speedLevel dacIndex = slsDetectorDefs.dacIndex detectorType = slsDetectorDefs.detectorType +defs = slsDetectorDefs + from .utils import element_if_equal, all_equal, get_set_bits, list_to_bitmask from .utils import Geometry, to_geo, element, reduce_time, is_iterable from _slsdet import xy @@ -1787,10 +1789,25 @@ class Detector(CppDetectorApi): """ - <<<-----------------------Eiger specific----------------------->>> + <<>> """ + @property + def datastream(self): + """ + datastream [left|right] [0, 1] + [Eiger] Enables or disables data streaming from left or/and right side of detector. 1 (enabled) by default. + """ + result = {} + for port in [defs.LEFT, defs.RIGHT]: + result[port] = element_if_equal(self.getDataStream(port)) + return result + + @datastream.setter + def datastream(self, value): + ut.set_using_dict(self.setDataStream, *value) + @property @element def quad(self): diff --git a/python/src/detector.cpp b/python/src/detector.cpp index c29c8cabf..a5d909f9d 100644 --- a/python/src/detector.cpp +++ b/python/src/detector.cpp @@ -401,7 +401,9 @@ void init_det(py::module &m) { .def("startDetector", (void (Detector::*)()) & Detector::startDetector) .def("startDetectorReadout", (void (Detector::*)()) & Detector::startDetectorReadout) - .def("stopDetector", (void (Detector::*)()) & Detector::stopDetector) + .def("stopDetector", + (void (Detector::*)(sls::Positions)) & Detector::stopDetector, + py::arg() = Positions{}) .def("getDetectorStatus", (Result(Detector::*)(sls::Positions) const) & Detector::getDetectorStatus, @@ -430,7 +432,7 @@ void init_det(py::module &m) { .def("sendSoftwareTrigger", (void (Detector::*)(const bool, sls::Positions)) & Detector::sendSoftwareTrigger, - py::arg(), py::arg() = Positions{}) + py::arg() = false, py::arg() = Positions{}) .def("getScan", (Result(Detector::*)(sls::Positions) const) & Detector::getScan, @@ -911,6 +913,16 @@ void init_det(py::module &m) { py::arg() = Positions{}) .def("setQuad", (void (Detector::*)(const bool)) & Detector::setQuad, py::arg()) + .def("getDataStream", + (Result(Detector::*)(const defs::portPosition, + sls::Positions) const) & + Detector::getDataStream, + py::arg(), py::arg() = Positions{}) + .def("setDataStream", + (void (Detector::*)(const defs::portPosition, const bool, + sls::Positions)) & + Detector::setDataStream, + py::arg(), py::arg(), py::arg() = Positions{}) .def("getThresholdTemperature", (Result(Detector::*)(sls::Positions) const) & Detector::getThresholdTemperature, diff --git a/python/src/enums.cpp b/python/src/enums.cpp index 961f615be..fb39c208a 100644 --- a/python/src/enums.cpp +++ b/python/src/enums.cpp @@ -281,4 +281,11 @@ void init_enums(py::module &m) { .value("M3_C225ACsh", slsDetectorDefs::M3_GainCaps::M3_C225ACsh) .value("M3_C15pre", slsDetectorDefs::M3_GainCaps::M3_C15pre) .export_values(); + + py::enum_(Defs, "portPosition") + .value("LEFT", slsDetectorDefs::portPosition::LEFT) + .value("RIGHT", slsDetectorDefs::portPosition::RIGHT) + .value("TOP", slsDetectorDefs::portPosition::TOP) + .value("BOTTOM", slsDetectorDefs::portPosition::BOTTOM) + .export_values(); } diff --git a/slsDetectorServers/eigerDetectorServer/Beb.c b/slsDetectorServers/eigerDetectorServer/Beb.c index 7d7fb71f2..d25469ccb 100644 --- a/slsDetectorServers/eigerDetectorServer/Beb.c +++ b/slsDetectorServers/eigerDetectorServer/Beb.c @@ -43,6 +43,8 @@ int Beb_deactivated_transmission_flowcontrol_10g = 0; int Beb_deactivated_transmission_delay_frame = 0; int Beb_deactivated_transmission_delay_left = 0; int Beb_deactivated_transmission_delay_right = 0; +int Beb_deactivated_left_datastream = 1; +int Beb_deactivated_right_datastream = 1; void BebInfo_BebInfo(struct BebInfo *bebInfo, unsigned int beb_num) { bebInfo->beb_number = beb_num; @@ -449,6 +451,74 @@ int Beb_GetActivate(int *retval) { return 1; } +int Beb_SetDataStream(enum portPosition port, int enable) { + if (!Beb_activated) { + if (port == LEFT) { + Beb_deactivated_left_datastream = enable; + } else { + Beb_deactivated_right_datastream = enable; + } + return 1; + } + if (enable < 0) { + LOG(logERROR, ("Invalid enable value\n")); + return 0; + } + u_int32_t *csp0base = 0; + int fd = Beb_open(&csp0base, XPAR_PLB_GPIO_SYS_BASEADDR); + if (fd < 0) { + LOG(logERROR, ("Activate FAIL, could not open fd\n")); + return 0; + } else { + u_int32_t reg = XPAR_GPIO_P15_STREAMING_REG; + u_int32_t mask = (port == LEFT ? XPAR_GPIO_LFT_STRM_DSBL_MSK + : XPAR_GPIO_RGHT_STRM_DSBL_MSK); + + u_int32_t value = Beb_Read32(csp0base, reg); + // disabling in firmware + if (!enable) + value |= mask; + else + value &= ~mask; + u_int32_t retval = Beb_Write32(csp0base, reg, value); + if (retval != value) { + LOG(logERROR, + ("Could not %s %s fpga datastream. Wrote 0x%x, read 0x%x\n", + (enable ? "enable" : "disable"), + (port == LEFT ? "left" : "right"), value, retval)); + Beb_close(fd, csp0base); + } + } + Beb_close(fd, csp0base); + return 1; +} + +int Beb_GetDataStream(enum portPosition port, int *retval) { + if (!Beb_activated) { + if (port == LEFT) { + return Beb_deactivated_left_datastream; + } else { + return Beb_deactivated_right_datastream; + } + } + u_int32_t *csp0base = 0; + int fd = Beb_open(&csp0base, XPAR_PLB_GPIO_SYS_BASEADDR); + if (fd < 0) { + LOG(logERROR, ("Activate FAIL, could not open fd\n")); + return 0; + } else { + u_int32_t reg = XPAR_GPIO_P15_STREAMING_REG; + u_int32_t mask = (port == LEFT ? XPAR_GPIO_LFT_STRM_DSBL_MSK + : XPAR_GPIO_RGHT_STRM_DSBL_MSK); + + u_int32_t value = Beb_Read32(csp0base, reg); + // disabling in firmware + *retval = (value & mask) ? 0 : 1; + } + Beb_close(fd, csp0base); + return 1; +} + int Beb_Set32bitOverflow(int val) { if (!Beb_activated) return val; diff --git a/slsDetectorServers/eigerDetectorServer/Beb.h b/slsDetectorServers/eigerDetectorServer/Beb.h index 44eb42ad1..3c328cb1d 100644 --- a/slsDetectorServers/eigerDetectorServer/Beb.h +++ b/slsDetectorServers/eigerDetectorServer/Beb.h @@ -41,6 +41,8 @@ int Beb_SetTop(enum TOPINDEX ind); int Beb_SetMaster(enum MASTERINDEX ind); int Beb_SetActivate(int enable); int Beb_GetActivate(int *retval); +int Beb_SetDataStream(enum portPosition port, int enable); +int Beb_GetDataStream(enum portPosition port, int *retval); int Beb_Set32bitOverflow(int val); int Beb_GetTenGigaFlowControl(); diff --git a/slsDetectorServers/eigerDetectorServer/FebControl.c b/slsDetectorServers/eigerDetectorServer/FebControl.c index 176e73560..7ddd6823e 100644 --- a/slsDetectorServers/eigerDetectorServer/FebControl.c +++ b/slsDetectorServers/eigerDetectorServer/FebControl.c @@ -23,26 +23,26 @@ int Feb_Control_activated = 1; int Feb_Control_hv_fd = -1; unsigned int Feb_Control_idelay[4]; // ll,lr,rl,ll int Feb_Control_counter_bit = 1; -unsigned int Feb_Control_staticBits; -unsigned int Feb_Control_acquireNReadoutMode; -unsigned int Feb_Control_triggerMode; -unsigned int Feb_Control_externalEnableMode; -unsigned int Feb_Control_subFrameMode; -unsigned int Feb_Control_softwareTrigger; +unsigned int Feb_Control_staticBits = 0; +unsigned int Feb_Control_acquireNReadoutMode = 0; +unsigned int Feb_Control_triggerMode = 0; +unsigned int Feb_Control_externalEnableMode = 0; +unsigned int Feb_Control_subFrameMode = 0; +unsigned int Feb_Control_quadMode = 0; -unsigned int Feb_Control_nimages; -double Feb_Control_exposure_time_in_sec; -int64_t Feb_Control_subframe_exposure_time_in_10nsec; -int64_t Feb_Control_subframe_period_in_10nsec; -double Feb_Control_exposure_period_in_sec; +unsigned int Feb_Control_nimages = 0; +double Feb_Control_exposure_time_in_sec = 0; +int64_t Feb_Control_subframe_exposure_time_in_10nsec = 0; +int64_t Feb_Control_subframe_period_in_10nsec = 0; +double Feb_Control_exposure_period_in_sec = 0; -unsigned int Feb_Control_trimbit_size; -unsigned int *Feb_Control_last_downloaded_trimbits; +unsigned int Feb_Control_trimbit_size = 0; +unsigned int *Feb_Control_last_downloaded_trimbits = 0; int64_t Feb_Control_RateTable_Tau_in_nsec = -1; int64_t Feb_Control_RateTable_Period_in_nsec = -1; -unsigned int Feb_Control_rate_correction_table[1024]; -double Feb_Control_rate_meas[16384]; +unsigned int Feb_Control_rate_correction_table[1024] = {}; +double Feb_Control_rate_meas[16384] = {}; double ratemax = -1; // setup @@ -1518,10 +1518,31 @@ int Feb_Control_SetMaster(enum MASTERINDEX ind) { int Feb_Control_SetQuad(int val) { LOG(logINFO, ("Setting Quad to %d in Feb\n", val)); + Feb_Control_quadMode = val; // only setting on the right feb if quad return Feb_Control_SetTop(val == 0 ? TOP_HARDWARE : OW_BOTTOM, 0, 1); } +int Feb_Control_SetChipSignalsToTrimQuad(int enable) { + if (Feb_Control_quadMode) { + LOG(logINFO, ("%s chip signals to trim quad\n", + enable ? "Enabling" : "Disabling")); + unsigned int regval = 0; + if (!Feb_Control_ReadRegister(DAQ_REG_HRDWRE, ®val)) { + LOG(logERROR, ("Could not set chip signals to trim quad\n")); + return 0; + } + if (enable) { + regval |= (DAQ_REG_HRDWRE_PROGRAM_MSK | DAQ_REG_HRDWRE_M8_MSK); + } else { + regval &= ~(DAQ_REG_HRDWRE_PROGRAM_MSK | DAQ_REG_HRDWRE_M8_MSK); + } + + return Feb_Control_WriteRegister(DAQ_REG_HRDWRE, regval); + } + return 1; +} + int Feb_Control_SetReadNLines(int value) { LOG(logINFO, ("Setting Read N Lines to %d\n", value)); if (!Feb_Interface_WriteRegister(Feb_Control_AddressToAll(), diff --git a/slsDetectorServers/eigerDetectorServer/FebControl.h b/slsDetectorServers/eigerDetectorServer/FebControl.h index 856b5b015..3209a5505 100644 --- a/slsDetectorServers/eigerDetectorServer/FebControl.h +++ b/slsDetectorServers/eigerDetectorServer/FebControl.h @@ -87,6 +87,7 @@ int Feb_Control_SetTop(enum TOPINDEX ind, int left, int right); void Feb_Control_SetMasterVariable(int val); int Feb_Control_SetMaster(enum MASTERINDEX ind); int Feb_Control_SetQuad(int val); +int Feb_Control_SetChipSignalsToTrimQuad(int enable); int Feb_Control_SetReadNLines(int value); int Feb_Control_GetReadNLines(); int Feb_Control_WriteRegister(uint32_t offset, uint32_t data); diff --git a/slsDetectorServers/eigerDetectorServer/FebRegisterDefs.h b/slsDetectorServers/eigerDetectorServer/FebRegisterDefs.h index 1bc79c331..da4728be6 100644 --- a/slsDetectorServers/eigerDetectorServer/FebRegisterDefs.h +++ b/slsDetectorServers/eigerDetectorServer/FebRegisterDefs.h @@ -27,6 +27,11 @@ #define DAQ_REG_HRDWRE_OW_MASTER_MSK (0x00000001 << DAQ_REG_HRDWRE_OW_MASTER_OFST) #define DAQ_REG_HRDWRE_MASTER_OFST (4) #define DAQ_REG_HRDWRE_MASTER_MSK (0x00000001 << DAQ_REG_HRDWRE_MASTER_OFST) +#define DAQ_REG_HRDWRE_PROGRAM_OFST (30) +#define DAQ_REG_HRDWRE_PROGRAM_MSK (0x00000001 << DAQ_REG_HRDWRE_PROGRAM_OFST) +#define DAQ_REG_HRDWRE_M8_OFST (31) +#define DAQ_REG_HRDWRE_M8_MSK (0x00000001 << DAQ_REG_HRDWRE_M8_OFST) + #define DAQ_REG_RO_OFFSET 20 #define DAQ_REG_STATUS (DAQ_REG_RO_OFFSET + 0) // also pg and fifo status register diff --git a/slsDetectorServers/eigerDetectorServer/bin/eigerDetectorServer_developer b/slsDetectorServers/eigerDetectorServer/bin/eigerDetectorServer_developer index a3c4a2803..75320fb9b 100755 Binary files a/slsDetectorServers/eigerDetectorServer/bin/eigerDetectorServer_developer and b/slsDetectorServers/eigerDetectorServer/bin/eigerDetectorServer_developer differ diff --git a/slsDetectorServers/eigerDetectorServer/slsDetectorFunctionList.c b/slsDetectorServers/eigerDetectorServer/slsDetectorFunctionList.c index 5ac882454..73b337ada 100644 --- a/slsDetectorServers/eigerDetectorServer/slsDetectorFunctionList.c +++ b/slsDetectorServers/eigerDetectorServer/slsDetectorFunctionList.c @@ -90,6 +90,8 @@ int eiger_virtual_test_mode = 0; int eiger_virtual_quad_mode = 0; int eiger_virtual_read_nlines = 256; int eiger_virtual_interrupt_subframe = 0; +int eiger_virtual_left_datastream = 1; +int eiger_virtual_right_datastream = 1; #endif int isInitCheckDone() { return initCheckDone; } @@ -1135,15 +1137,33 @@ int setModule(sls_detector_module myMod, char *mess) { // set trimbits sharedMemory_lockLocalLink(); + + // if quad, set M8 and PROGRAM manually + if (!Feb_Control_SetChipSignalsToTrimQuad(1)) { + return FAIL; + } + if (!Feb_Control_SetTrimbits(tt, top)) { sprintf(mess, "Could not set module. Could not set trimbits\n"); LOG(logERROR, (mess)); setSettings(UNDEFINED); LOG(logERROR, ("Settings has been changed to undefined (random " "trim file)\n")); + + // if quad, reset M8 and PROGRAM manually + if (!Feb_Control_SetChipSignalsToTrimQuad(0)) { + return FAIL; + } + sharedMemory_unlockLocalLink(); return FAIL; } + + // if quad, reset M8 and PROGRAM manually + if (!Feb_Control_SetChipSignalsToTrimQuad(0)) { + return FAIL; + } + sharedMemory_unlockLocalLink(); } #endif @@ -2049,6 +2069,40 @@ int getActivate(int *retval) { return OK; } +int setDataStream(enum portPosition port, int enable) { + if (enable < 0) { + LOG(logERROR, ("Invalid setDataStream enable argument: %d\n", enable)); + return FAIL; + } +#ifdef VIRTUAL + if (port == LEFT) { + eiger_virtual_left_datastream = enable; + } else { + eiger_virtual_right_datastream = enable; + } +#else + if (!Beb_SetDataStream(port, enable)) { + return FAIL; + } +#endif + return OK; +} + +int getDataStream(enum portPosition port, int *retval) { +#ifdef VIRTUAL + if (port == LEFT) { + *retval = eiger_virtual_left_datastream; + } else { + *retval = eiger_virtual_right_datastream; + } +#else + if (!Beb_GetDataStream(port, retval)) { + return FAIL; + } +#endif + return OK; +} + int getTenGigaFlowControl() { #ifdef VIRTUAL return eiger_virtual_transmission_flowcontrol_10g; @@ -2196,6 +2250,19 @@ void *start_timer(void *arg) { return NULL; } + int skipData = 0; + if (!eiger_virtual_activate || + (!eiger_virtual_left_datastream && !eiger_virtual_right_datastream)) { + skipData = 1; + LOG(logWARNING, ("Not sending Left and Right datastream\n")); + } + if (!eiger_virtual_left_datastream) { + LOG(logWARNING, ("Not sending Left datastream\n")); + } + if (!eiger_virtual_right_datastream) { + LOG(logWARNING, ("Not sending Right datastream\n")); + } + int64_t periodNs = eiger_virtual_period; int numFrames = nimages_per_request; int64_t expUs = eiger_virtual_exptime / 1000; @@ -2257,7 +2324,7 @@ void *start_timer(void *arg) { } // Send data - { + if (!skipData) { uint64_t frameNr = 0; getNextFrameNumber(&frameNr); // loop over number of frames @@ -2342,10 +2409,14 @@ void *start_timer(void *arg) { } } } - usleep(eiger_virtual_transmission_delay_left); - sendUDPPacket(0, packetData, packetsize); - usleep(eiger_virtual_transmission_delay_right); - sendUDPPacket(1, packetData2, packetsize); + if (eiger_virtual_left_datastream) { + usleep(eiger_virtual_transmission_delay_left); + sendUDPPacket(0, packetData, packetsize); + } + if (eiger_virtual_right_datastream) { + usleep(eiger_virtual_transmission_delay_right); + sendUDPPacket(1, packetData2, packetsize); + } } LOG(logINFO, ("Sent frame: %d[%lld]\n", iframes, (long long unsigned int)(frameNr + iframes))); diff --git a/slsDetectorServers/eigerDetectorServer/xparameters.h b/slsDetectorServers/eigerDetectorServer/xparameters.h index 67a826283..d293257d2 100644 --- a/slsDetectorServers/eigerDetectorServer/xparameters.h +++ b/slsDetectorServers/eigerDetectorServer/xparameters.h @@ -35,7 +35,7 @@ XPAR_PLB_LL_FIFO_AURORA_DUAL_CTRL_FEB_LEFT_BASEADDR /* Definitions for peripheral PLB_BRAM_10G */ #define XPAR_PLB_BRAM_10G_MEM0_BASEADDR 0xD4100000 -#define XPAR_PLB_BRAM_10G_MEM0_HIGHADDR 0xD410FFFF +#define XPAR_PLB_BRAM_10G_MEM0_HIGHADDR /* Definitions for peripheral PLB_BRAM_TEMAC */ #define XPAR_PLB_BRAM_TEMAC_MEM0_BASEADDR 0xD4000000 @@ -45,6 +45,18 @@ XPAR_PLB_LL_FIFO_AURORA_DUAL_CTRL_FEB_LEFT_BASEADDR #define XPAR_PLB_GPIO_SYS_BASEADDR 0xD1000000 #define XPAR_PLB_GPIO_SYS_HIGHADDR 0xD100FFFF +// data streaming register +// clang-format off +#define XPAR_GPIO_P15_STREAMING_REG 0x01e0 +#define XPAR_GPIO_FRAME_PKT_ENBL_OFST (0) +#define XPAR_GPIO_FRAME_PKT_ENBL_MSK (0x00000001 << XPAR_GPIO_FRAME_PKT_ENBL_OFST) +#define XPAR_GPIO_RGHT_STRM_DSBL_OFST (1) +#define XPAR_GPIO_RGHT_STRM_DSBL_MSK (0x00000001 << XPAR_GPIO_RGHT_STRM_DSBL_OFST) +#define XPAR_GPIO_LFT_STRM_DSBL_OFST (2) +#define XPAR_GPIO_LFT_STRM_DSBL_MSK (0x00000001 << XPAR_GPIO_LFT_STRM_DSBL_OFST) + +// clang-format on + /** Command Generator */ #define XPAR_CMD_GENERATOR 0xC5000000 diff --git a/slsDetectorServers/slsDetectorServer/include/slsDetectorFunctionList.h b/slsDetectorServers/slsDetectorServer/include/slsDetectorFunctionList.h index 87e7b7256..e5bf46a84 100644 --- a/slsDetectorServers/slsDetectorServer/include/slsDetectorFunctionList.h +++ b/slsDetectorServers/slsDetectorServer/include/slsDetectorFunctionList.h @@ -474,6 +474,8 @@ int getAllTrimbits(); int getBebFPGATemp(); int setActivate(int enable); int getActivate(int *retval); +int getDataStream(enum portPosition port, int *retval); +int setDataStream(enum portPosition port, int enable); // gotthard specific - adc phase #elif GOTTHARDD diff --git a/slsDetectorServers/slsDetectorServer/include/slsDetectorServer_funcs.h b/slsDetectorServers/slsDetectorServer/include/slsDetectorServer_funcs.h index ffa18b91f..395378476 100644 --- a/slsDetectorServers/slsDetectorServer/include/slsDetectorServer_funcs.h +++ b/slsDetectorServers/slsDetectorServer/include/slsDetectorServer_funcs.h @@ -246,4 +246,6 @@ int get_all_threshold_energy(int); int get_master(int); int get_csr(); int set_gain_caps(int); -int get_gain_caps(int); \ No newline at end of file +int get_gain_caps(int); +int get_datastream(int); +int set_datastream(int); diff --git a/slsDetectorServers/slsDetectorServer/src/slsDetectorServer_funcs.c b/slsDetectorServers/slsDetectorServer/src/slsDetectorServer_funcs.c index e97b600ab..f745e5d65 100644 --- a/slsDetectorServers/slsDetectorServer/src/slsDetectorServer_funcs.c +++ b/slsDetectorServers/slsDetectorServer/src/slsDetectorServer_funcs.c @@ -373,6 +373,8 @@ void function_table() { flist[F_GET_CSR] = &get_csr; flist[F_SET_GAIN_CAPS] = &set_gain_caps; flist[F_GET_GAIN_CAPS] = &get_gain_caps; + flist[F_GET_DATASTREAM] = &get_datastream; + flist[F_SET_DATASTREAM] = &set_datastream; // check if (NUM_DET_FUNCTIONS >= RECEIVER_ENUM_START) { @@ -3038,13 +3040,13 @@ int set_pattern_loop_addresses(int file_des) { else { // set if (startAddr >= 0 && stopAddr >= 0) { - ret = validate_setPatternLoopAddresses(mess, loopLevel, startAddr, - stopAddr); + ret = validate_setPatternLoopAddresses(mess, loopLevel, + startAddr, stopAddr); } // get if (ret == OK) { - ret = validate_getPatternLoopAddresses(mess, loopLevel, &retvals[0], - &retvals[1]); + ret = validate_getPatternLoopAddresses( + mess, loopLevel, &retvals[0], &retvals[1]); } } } @@ -7053,6 +7055,28 @@ int get_receiver_parameters(int file_des) { if (n < 0) return printSocketReadError(); + // data stream left +#ifdef EIGERD + i32 = 0; + getDataStream(LEFT, &i32); +#else + i32 = 0; +#endif + n += sendData(file_des, &i32, sizeof(i32), INT32); + if (n < 0) + return printSocketReadError(); + + // data stream right +#ifdef EIGERD + i32 = 0; + getDataStream(RIGHT, &i32); +#else + i32 = 0; +#endif + n += sendData(file_des, &i32, sizeof(i32), INT32); + if (n < 0) + return printSocketReadError(); + // quad #ifdef EIGERD i32 = getQuad(); @@ -8223,3 +8247,91 @@ int get_gain_caps(int file_des) { #endif return Server_SendResult(file_des, INT32, &retval, sizeof(retval)); } + +int get_datastream(int file_des) { + ret = OK; + memset(mess, 0, sizeof(mess)); + enum portPosition arg = LEFT; + int retval = -1; + + if (receiveData(file_des, &arg, sizeof(arg), INT32) < 0) + return printSocketReadError(); + LOG(logDEBUG1, ("Getting data stream enable [port:%d]\n", arg)); + +#ifndef EIGERD + functionNotImplemented(); +#else + // get only + if (arg != LEFT && arg != RIGHT) { + ret = FAIL; + sprintf( + mess, + "Could not get data stream enable. Invalid port position %d. Only left and right allowed\n", + arg); + LOG(logERROR, (mess)); + } else { + ret = getDataStream(arg, &retval); + LOG(logDEBUG1, ("datastream (%s) retval: %u\n", + (arg == LEFT? "left" : "right"), retval)); + if (ret == FAIL) { + sprintf(mess, "Could not get %s data stream enable.\n", + (arg == LEFT ? "left" : "right")); + LOG(logERROR, (mess)); + } + } +#endif + return Server_SendResult(file_des, INT32, &retval, sizeof(retval)); +} + +int set_datastream(int file_des) { + ret = OK; + memset(mess, 0, sizeof(mess)); + int args[2] = {-1, -1}; + + if (receiveData(file_des, args, sizeof(args), INT32) < 0) + return printSocketReadError(); + LOG(logDEBUG1, ("Setting data stream enable [left:%d, enable:%d]\n", + args[0], args[1])); + +#ifndef EIGERD + functionNotImplemented(); +#else + // only set + if (Server_VerifyLock() == OK) { + enum portPosition port = args[0]; + int enable = args[1]; + char msg[256]; + memset(msg, 0, sizeof(msg)); + sprintf(msg, "%s %s fpga datastream", (enable ? "enable" : "disable"), + (port == LEFT ? "left" : "right")); + if (port != LEFT && port != RIGHT) { + ret = FAIL; + sprintf(mess, + "Could not %s. Invalid port position %d. Only left and right allowed\n", + msg, port); + LOG(logERROR, (mess)); + } else if (enable != 0 && enable != 1) { + ret = FAIL; + sprintf(mess, "Could not %s. Invalid enable %d. \n", msg, enable); + LOG(logERROR, (mess)); + } else { + ret = setDataStream(port, enable); + if (ret == FAIL) { + sprintf(mess, "Could not %s\n", msg); + LOG(logERROR, (mess)); + } else { + int retval = -1; + ret = getDataStream(port, &retval); + LOG(logDEBUG1, ("%s retval: %u\n", msg, retval)); + if (ret == FAIL) { + sprintf(mess, "Could not get %s data stream enable.\n", + (port == LEFT ? "left" : "right")); + LOG(logERROR, (mess)); + } + validate(&ret, mess, enable, retval, msg, DEC); + } + } + } +#endif + return Server_SendResult(file_des, INT32, NULL, 0); +} \ No newline at end of file diff --git a/slsDetectorSoftware/include/sls/Detector.h b/slsDetectorSoftware/include/sls/Detector.h index 32b16d192..4e3d60d97 100644 --- a/slsDetectorSoftware/include/sls/Detector.h +++ b/slsDetectorSoftware/include/sls/Detector.h @@ -1060,6 +1060,17 @@ class Detector { /** [Eiger] Sets detector size to a quad. 0 (disabled) is default. (Specific * hardware required). */ void setQuad(const bool enable); + + /** [Eiger] */ + Result getDataStream(const defs::portPosition port, + Positions pos = {}) const; + + /** [Eiger] enable or disable data streaming from left or right of detector. + * Default: enabled + */ + void setDataStream(const defs::portPosition port, const bool enable, + Positions pos = {}); + ///@{ /** @name Jungfrau Specific */ diff --git a/slsDetectorSoftware/src/CmdProxy.cpp b/slsDetectorSoftware/src/CmdProxy.cpp index bd7fdce80..a14a4a58a 100644 --- a/slsDetectorSoftware/src/CmdProxy.cpp +++ b/slsDetectorSoftware/src/CmdProxy.cpp @@ -1590,6 +1590,34 @@ std::string CmdProxy::Quad(int action) { return os.str(); } +std::string CmdProxy::DataStream(int action) { + std::ostringstream os; + os << cmd << ' '; + if (action == defs::HELP_ACTION) { + os << "[left|right] [0, 1]\n\t[Eiger] Enables or disables data " + "streaming from left or/and right side of detector. 1 (enabled) " + "by default." + << '\n'; + } else if (action == defs::GET_ACTION) { + if (args.size() != 1) { + WrongNumberOfParameters(1); + } + auto t = det->getDataStream(StringTo(args[0]), + std::vector{det_id}); + os << OutString(t) << '\n'; + } else if (action == defs::PUT_ACTION) { + if (args.size() != 2) { + WrongNumberOfParameters(2); + } + det->setDataStream(StringTo(args[0]), + StringTo(args[1]), std::vector{det_id}); + os << args << '\n'; + } else { + throw sls::RuntimeError("Unknown action"); + } + return os.str(); +} + /* Jungfrau Specific */ std::string CmdProxy::TemperatureEvent(int action) { diff --git a/slsDetectorSoftware/src/CmdProxy.h b/slsDetectorSoftware/src/CmdProxy.h index f0d3e41ff..60529ff18 100644 --- a/slsDetectorSoftware/src/CmdProxy.h +++ b/slsDetectorSoftware/src/CmdProxy.h @@ -915,6 +915,7 @@ class CmdProxy { {"pulsenmove", &CmdProxy::PulsePixelAndMove}, {"pulsechip", &CmdProxy::PulseChip}, {"quad", &CmdProxy::Quad}, + {"datastream", &CmdProxy::DataStream}, /* Jungfrau Specific */ {"temp_threshold", &CmdProxy::temp_threshold}, @@ -1110,6 +1111,7 @@ class CmdProxy { std::string PulsePixelAndMove(int action); std::string PulseChip(int action); std::string Quad(int action); + std::string DataStream(int action); /* Jungfrau Specific */ std::string TemperatureEvent(int action); /* Gotthard Specific */ diff --git a/slsDetectorSoftware/src/Detector.cpp b/slsDetectorSoftware/src/Detector.cpp index 1d0bd7489..67c9d84c3 100644 --- a/slsDetectorSoftware/src/Detector.cpp +++ b/slsDetectorSoftware/src/Detector.cpp @@ -1369,6 +1369,16 @@ void Detector::setQuad(const bool enable) { pimpl->Parallel(&Module::setQuad, {}, enable); } +Result Detector::getDataStream(const defs::portPosition port, + Positions pos) const { + return pimpl->Parallel(&Module::getDataStream, pos, port); +} + +void Detector::setDataStream(const defs::portPosition port, const bool enable, + Positions pos) { + pimpl->Parallel(&Module::setDataStream, pos, port, enable); +} + // Jungfrau Specific Result Detector::getThresholdTemperature(Positions pos) const { diff --git a/slsDetectorSoftware/src/Module.cpp b/slsDetectorSoftware/src/Module.cpp index f2ebb2d02..21145f6ea 100644 --- a/slsDetectorSoftware/src/Module.cpp +++ b/slsDetectorSoftware/src/Module.cpp @@ -1509,6 +1509,18 @@ void Module::setQuad(const bool enable) { } } +bool Module::getDataStream(const portPosition port) const { + return sendToDetector(F_GET_DATASTREAM, static_cast(port)); +} + +void Module::setDataStream(const portPosition port, const bool enable) { + int args[]{static_cast(port), static_cast(enable)}; + sendToDetector(F_SET_DATASTREAM, args, nullptr); + if (shm()->useReceiverFlag) { + sendToReceiver(F_RECEIVER_SET_DATASTREAM, args, nullptr); + } +} + // Jungfrau Specific int Module::getThresholdTemperature() const { diff --git a/slsDetectorSoftware/src/Module.h b/slsDetectorSoftware/src/Module.h index 6462ffac2..b1baf5af5 100644 --- a/slsDetectorSoftware/src/Module.h +++ b/slsDetectorSoftware/src/Module.h @@ -343,6 +343,8 @@ class Module : public virtual slsDetectorDefs { void pulseChip(int n_pulses = 0); bool getQuad() const; void setQuad(const bool enable); + bool getDataStream(const portPosition port) const; + void setDataStream(const portPosition port, const bool enable); /************************************************** * * diff --git a/slsDetectorSoftware/tests/test-CmdProxy-eiger.cpp b/slsDetectorSoftware/tests/test-CmdProxy-eiger.cpp index 0249b6460..d47c0a75b 100644 --- a/slsDetectorSoftware/tests/test-CmdProxy-eiger.cpp +++ b/slsDetectorSoftware/tests/test-CmdProxy-eiger.cpp @@ -649,3 +649,43 @@ TEST_CASE("quad", "[.cmd]") { REQUIRE_THROWS(proxy.Call("quad", {}, -1, GET)); } } + +TEST_CASE("datastream", "[.cmd]") { + Detector det; + CmdProxy proxy(&det); + auto det_type = det.getDetectorType().squash(); + if (det_type == defs::EIGER) { + auto prev_val_left = det.getDataStream(defs::LEFT); + auto prev_val_right = det.getDataStream(defs::RIGHT); + // no "left" or "right" + REQUIRE_THROWS(proxy.Call("datastream", {"1"}, -1, PUT)); + { + std::ostringstream oss; + proxy.Call("datastream", {"left", "0"}, -1, PUT, oss); + REQUIRE(oss.str() == "datastream left 0\n"); + } + { + std::ostringstream oss; + proxy.Call("datastream", {"right", "0"}, -1, PUT, oss); + REQUIRE(oss.str() == "datastream right 0\n"); + } + { + std::ostringstream oss; + proxy.Call("datastream", {"left", "1"}, -1, PUT, oss); + REQUIRE(oss.str() == "datastream left 1\n"); + } + { + std::ostringstream oss; + proxy.Call("datastream", {"right", "1"}, -1, PUT, oss); + REQUIRE(oss.str() == "datastream right 1\n"); + } + for (int i = 0; i != det.size(); ++i) { + det.setDataStream(defs::LEFT, prev_val_left[i], {i}); + det.setDataStream(defs::RIGHT, prev_val_right[i], {i}); + } + } else { + REQUIRE_THROWS(proxy.Call("datastream", {}, -1, GET)); + REQUIRE_THROWS(proxy.Call("datastream", {"1"}, -1, PUT)); + REQUIRE_THROWS(proxy.Call("datastream", {"left", "1"}, -1, PUT)); + } +} \ No newline at end of file diff --git a/slsReceiverSoftware/CMakeLists.txt b/slsReceiverSoftware/CMakeLists.txt index ad2a958c5..8ed871ab5 100755 --- a/slsReceiverSoftware/CMakeLists.txt +++ b/slsReceiverSoftware/CMakeLists.txt @@ -3,7 +3,8 @@ set(SOURCES src/ClientInterface.cpp src/Receiver.cpp src/File.cpp - src/BinaryFile.cpp + src/BinaryDataFile.cpp + src/BinaryMasterFile.cpp src/ThreadObject.cpp src/Listener.cpp src/DataProcessor.cpp @@ -22,7 +23,9 @@ if (SLS_USE_HDF5) -DHDF5C ${HDF5_DEFINITIONS} ) list (APPEND SOURCES - src/HDF5File.cpp + src/HDF5DataFile.cpp + src/HDF5MasterFile.cpp + src/HDF5VirtualFile.cpp ) endif (SLS_USE_HDF5) diff --git a/slsReceiverSoftware/src/BinaryDataFile.cpp b/slsReceiverSoftware/src/BinaryDataFile.cpp new file mode 100644 index 000000000..731adae3d --- /dev/null +++ b/slsReceiverSoftware/src/BinaryDataFile.cpp @@ -0,0 +1,108 @@ +#include "BinaryDataFile.h" + +BinaryDataFile::BinaryDataFile(const int index) : File(BINARY), index_(index) {} + +BinaryDataFile::~BinaryDataFile() { CloseFile(); } + +void BinaryDataFile::CloseFile() { + if (fd_) { + fclose(fd_); + } + fd_ = nullptr; +} + +void BinaryDataFile::CreateFirstBinaryDataFile( + const std::string filePath, const std::string fileNamePrefix, + const uint64_t fileIndex, const bool overWriteEnable, const bool silentMode, + const int modulePos, const int numUnitsPerReadout, + const uint32_t udpPortNumber, const uint32_t maxFramesPerFile) { + + subFileIndex_ = 0; + numFramesInFile_ = 0; + + filePath_ = filePath; + fileNamePrefix_ = fileNamePrefix; + fileIndex_ = fileIndex; + overWriteEnable_ = overWriteEnable; + silentMode_ = silentMode; + detIndex_ = modulePos; + numUnitsPerReadout_ = numUnitsPerReadout; + udpPortNumber_ = udpPortNumber; + maxFramesPerFile_ = maxFramesPerFile; + + CreateFile(); +} + +void BinaryDataFile::CreateFile() { + numFramesInFile_ = 0; + + std::ostringstream os; + os << filePath_ << "/" << fileNamePrefix_ << "_d" + << (detIndex_ * numUnitsPerReadout_ + index_) << "_f" << subFileIndex_ + << '_' << fileIndex_ << ".raw"; + fileName_ = os.str(); + + if (!overWriteEnable_) { + if (nullptr == (fd_ = fopen((const char *)fileName_.c_str(), "wx"))) { + fd_ = nullptr; + throw sls::RuntimeError("Could not create/overwrite file " + + fileName_); + } + } else if (nullptr == (fd_ = fopen((const char *)fileName_.c_str(), "w"))) { + fd_ = nullptr; + throw sls::RuntimeError("Could not create file " + fileName_); + } + // setting to no file buffering + setvbuf(fd_, nullptr, _IONBF, 0); + + if (!silentMode_) { + LOG(logINFO) << "[" << udpPortNumber_ + << "]: Binary File created: " << fileName_; + } +} + +void BinaryDataFile::WriteToFile(char *buffer, const int buffersize, + const uint64_t currentFrameNumber, + const uint32_t numPacketsCaught) { + // check if maxframesperfile = 0 for infinite + if (maxFramesPerFile_ && (numFramesInFile_ >= maxFramesPerFile_)) { + CloseFile(); + ++subFileIndex_; + CreateFile(); + } + numFramesInFile_++; + + // write to file + int ret = 0; + + // contiguous bitset + if (sizeof(sls_bitset) == sizeof(bitset_storage)) { + ret = fwrite(buffer, 1, buffersize, fd_); + } + + // not contiguous bitset + else { + // write detector header + ret = fwrite(buffer, 1, sizeof(sls_detector_header), fd_); + + // get contiguous representation of bit mask + bitset_storage storage; + memset(storage, 0, sizeof(bitset_storage)); + sls_bitset bits = *(sls_bitset *)(buffer + sizeof(sls_detector_header)); + for (int i = 0; i < MAX_NUM_PACKETS; ++i) + storage[i >> 3] |= (bits[i] << (i & 7)); + // write bitmask + ret += fwrite((char *)storage, 1, sizeof(bitset_storage), fd_); + + // write data + ret += fwrite(buffer + sizeof(sls_detector_header), 1, + buffersize - sizeof(sls_receiver_header), fd_); + } + + // if write error + if (ret != buffersize) { + throw sls::RuntimeError(std::to_string(index_) + + " : Write to file failed for image number " + + std::to_string(currentFrameNumber)); + } +} \ No newline at end of file diff --git a/slsReceiverSoftware/src/BinaryDataFile.h b/slsReceiverSoftware/src/BinaryDataFile.h new file mode 100644 index 000000000..a76a5003b --- /dev/null +++ b/slsReceiverSoftware/src/BinaryDataFile.h @@ -0,0 +1,43 @@ +#pragma once + +#include "File.h" + +class BinaryDataFile : private virtual slsDetectorDefs, public File { + + public: + BinaryDataFile(const int index); + ~BinaryDataFile(); + + void CloseFile() override; + void CreateFirstBinaryDataFile(const std::string filePath, + const std::string fileNamePrefix, + const uint64_t fileIndex, + const bool overWriteEnable, + const bool silentMode, const int modulePos, + const int numUnitsPerReadout, + const uint32_t udpPortNumber, + const uint32_t maxFramesPerFile) override; + + void WriteToFile(char *buffer, const int buffersize, + const uint64_t currentFrameNumber, + const uint32_t numPacketsCaught) override; + + private: + void CreateFile(); + + uint32_t index_; + FILE *fd_{nullptr}; + std::string fileName_; + uint32_t numFramesInFile_{0}; + uint32_t subFileIndex_{0}; + + std::string filePath_; + std::string fileNamePrefix_; + uint64_t fileIndex_{0}; + bool overWriteEnable_{false}; + bool silentMode_{false}; + int detIndex_{0}; + int numUnitsPerReadout_{0}; + uint32_t udpPortNumber_{0}; + uint32_t maxFramesPerFile_{0}; +}; \ No newline at end of file diff --git a/slsReceiverSoftware/src/BinaryFile.cpp b/slsReceiverSoftware/src/BinaryFile.cpp deleted file mode 100644 index 6ed3946e9..000000000 --- a/slsReceiverSoftware/src/BinaryFile.cpp +++ /dev/null @@ -1,175 +0,0 @@ -/************************************************ - * @file BinaryFile.cpp - * @short sets/gets properties for the binary file, - * creates/closes the file and writes data to it - ***********************************************/ - -#include "BinaryFile.h" -#include "Fifo.h" -#include "MasterAttributes.h" -#include "receiver_defs.h" - -#include -#include -#include - -FILE *BinaryFile::masterfd = nullptr; - -BinaryFile::BinaryFile(int ind, uint32_t *maxf, int *nd, std::string *fname, - std::string *fpath, uint64_t *findex, bool *owenable, - int *dindex, int *nunits, uint64_t *nf, uint32_t *dr, - uint32_t *portno, bool *smode) - : File(ind, BINARY, maxf, nd, fname, fpath, findex, owenable, dindex, - nunits, nf, dr, portno, smode) { -#ifdef VERBOSE - PrintMembers(); -#endif -} - -BinaryFile::~BinaryFile() { CloseAllFiles(); } - -void BinaryFile::PrintMembers(TLogLevel level) { - File::PrintMembers(level); - LOG(logINFO) << "Max Frames Per File: " << *maxFramesPerFile; - LOG(logINFO) << "Number of Frames in File: " << numFramesInFile; -} - -void BinaryFile::CreateFile() { - numFramesInFile = 0; - numActualPacketsInFile = 0; - - std::ostringstream os; - os << *filePath << "/" << *fileNamePrefix << "_d" - << (*detIndex * (*numUnitsPerDetector) + index) << "_f" << subFileIndex - << '_' << *fileIndex << ".raw"; - currentFileName = os.str(); - - if (!(*overWriteEnable)) { - if (nullptr == - (filefd = fopen((const char *)currentFileName.c_str(), "wx"))) { - filefd = nullptr; - throw sls::RuntimeError("Could not create/overwrite file " + - currentFileName); - } - } else if (nullptr == - (filefd = fopen((const char *)currentFileName.c_str(), "w"))) { - filefd = nullptr; - throw sls::RuntimeError("Could not create file " + currentFileName); - } - // setting to no file buffering - setvbuf(filefd, nullptr, _IONBF, 0); - - if (!(*silentMode)) { - LOG(logINFO) << "[" << *udpPortNumber - << "]: Binary File created: " << currentFileName; - } -} - -void BinaryFile::CloseCurrentFile() { - if (filefd) - fclose(filefd); - filefd = nullptr; -} - -void BinaryFile::CloseAllFiles() { - CloseCurrentFile(); - if (master) { - if (masterfd) - fclose(masterfd); - masterfd = nullptr; - } -} - -int BinaryFile::WriteData(char *buf, int bsize) { - if (!filefd) - return 0; - return fwrite(buf, 1, bsize, filefd); -} - -void BinaryFile::WriteToFile(char *buffer, int buffersize, - uint64_t currentFrameNumber, - uint32_t numPacketsCaught) { - // check if maxframesperfile = 0 for infinite - if ((*maxFramesPerFile) && (numFramesInFile >= (*maxFramesPerFile))) { - CloseCurrentFile(); - ++subFileIndex; - CreateFile(); - } - numFramesInFile++; - numActualPacketsInFile += numPacketsCaught; - - // write to file - int ret = 0; - - // contiguous bitset - if (sizeof(sls_bitset) == sizeof(bitset_storage)) { - ret = WriteData(buffer, buffersize); - } - - // not contiguous bitset - else { - // write detector header - ret = WriteData(buffer, sizeof(sls_detector_header)); - - // get contiguous representation of bit mask - bitset_storage storage; - memset(storage, 0, sizeof(bitset_storage)); - sls_bitset bits = *(sls_bitset *)(buffer + sizeof(sls_detector_header)); - for (int i = 0; i < MAX_NUM_PACKETS; ++i) - storage[i >> 3] |= (bits[i] << (i & 7)); - // write bitmask - ret += WriteData((char *)storage, sizeof(bitset_storage)); - - // write data - ret += WriteData(buffer + sizeof(sls_detector_header), - buffersize - sizeof(sls_receiver_header)); - } - - // if write error - if (ret != buffersize) { - throw sls::RuntimeError(std::to_string(index) + - " : Write to file failed for image number " + - std::to_string(currentFrameNumber)); - } -} - -void BinaryFile::CreateMasterFile(bool masterFileWriteEnable, - MasterAttributes *attr) { - // beginning of every acquisition - numFramesInFile = 0; - numActualPacketsInFile = 0; - - if (masterFileWriteEnable && master) { - - std::ostringstream os; - os << *filePath << "/" << *fileNamePrefix << "_master" - << "_" << *fileIndex << ".raw"; - masterFileName = os.str(); - if (!(*silentMode)) { - LOG(logINFO) << "Master File: " << masterFileName; - } - - // create master file - if (!(*overWriteEnable)) { - if (nullptr == (masterfd = fopen( - (const char *)masterFileName.c_str(), "wx"))) { - masterfd = nullptr; - throw sls::RuntimeError("Could not create binary master file " - "(without overwrite enable) " + - masterFileName); - } - } else if (nullptr == - (masterfd = - fopen((const char *)masterFileName.c_str(), "w"))) { - masterfd = nullptr; - throw sls::RuntimeError("Could not create binary master file " - "(with overwrite enable) " + - masterFileName); - } - - attr->WriteMasterBinaryAttributes(masterfd); - if (masterfd) - fclose(masterfd); - masterfd = nullptr; - } -} diff --git a/slsReceiverSoftware/src/BinaryFile.h b/slsReceiverSoftware/src/BinaryFile.h deleted file mode 100644 index d429bd705..000000000 --- a/slsReceiverSoftware/src/BinaryFile.h +++ /dev/null @@ -1,58 +0,0 @@ -#pragma once -/************************************************ - * @file BinaryFile.h - * @short sets/gets properties for the binary file, - * creates/closes the file and writes data to it - ***********************************************/ -/** - *@short sets/gets properties for the binary file, creates/closes the file and - *writes data to it - */ - -#include "File.h" - -#include - -class BinaryFile : private virtual slsDetectorDefs, public File { - - public: - /** - * Constructor - * creates the File Writer - * @param ind self index - * @param maxf pointer to max frames per file - * @param nd pointer to number of detectors in each dimension - * @param fname pointer to file name prefix - * @param fpath pointer to file path - * @param findex pointer to file index - * @param owenable pointer to over write enable - * @param dindex pointer to detector index - * @param nunits pointer to number of theads/ units per detector - * @param nf pointer to number of images in acquisition - * @param dr pointer to dynamic range - * @param portno pointer to udp port number for logging - * @param smode pointer to silent mode - */ - BinaryFile(int ind, uint32_t *maxf, int *nd, std::string *fname, - std::string *fpath, uint64_t *findex, bool *owenable, - int *dindex, int *nunits, uint64_t *nf, uint32_t *dr, - uint32_t *portno, bool *smode); - ~BinaryFile(); - - void PrintMembers(TLogLevel level = logDEBUG1) override; - void CreateFile() override; - void CreateMasterFile(bool masterFileWriteEnable, - MasterAttributes *attr) override; - void CloseCurrentFile() override; - void CloseAllFiles() override; - void WriteToFile(char *buffer, int buffersize, uint64_t currentFrameNumber, - uint32_t numPacketsCaught) override; - - private: - int WriteData(char *buf, int bsize); - - FILE *filefd = nullptr; - static FILE *masterfd; - uint32_t numFramesInFile = 0; - uint64_t numActualPacketsInFile = 0; -}; \ No newline at end of file diff --git a/slsReceiverSoftware/src/BinaryMasterFile.cpp b/slsReceiverSoftware/src/BinaryMasterFile.cpp new file mode 100644 index 000000000..3b11b803a --- /dev/null +++ b/slsReceiverSoftware/src/BinaryMasterFile.cpp @@ -0,0 +1,44 @@ +#include "BinaryMasterFile.h" +#include "MasterAttributes.h" + +BinaryMasterFile::BinaryMasterFile() : File(BINARY) {} + +BinaryMasterFile::~BinaryMasterFile() { CloseFile(); } + +void BinaryMasterFile::CloseFile() { + if (fd_) { + fclose(fd_); + } + fd_ = nullptr; +} + +void BinaryMasterFile::CreateMasterFile(const std::string filePath, + const std::string fileNamePrefix, + const uint64_t fileIndex, + const bool overWriteEnable, + const bool silentMode, + MasterAttributes *attr) { + // create file name + std::ostringstream os; + os << filePath << "/" << fileNamePrefix << "_master" + << "_" << fileIndex << ".raw"; + fileName_ = os.str(); + + // create file + if (!overWriteEnable) { + if (nullptr == (fd_ = fopen((const char *)fileName_.c_str(), "wx"))) { + fd_ = nullptr; + throw sls::RuntimeError("Could not create binary master file " + + fileName_); + } + } else if (nullptr == (fd_ = fopen((const char *)fileName_.c_str(), "w"))) { + fd_ = nullptr; + throw sls::RuntimeError( + "Could not create/overwrite binary master file " + fileName_); + } + if (!silentMode) { + LOG(logINFO) << "Master File: " << fileName_; + } + attr->WriteMasterBinaryAttributes(fd_); + CloseFile(); +} diff --git a/slsReceiverSoftware/src/BinaryMasterFile.h b/slsReceiverSoftware/src/BinaryMasterFile.h new file mode 100644 index 000000000..ae5405828 --- /dev/null +++ b/slsReceiverSoftware/src/BinaryMasterFile.h @@ -0,0 +1,22 @@ +#pragma once + +#include "File.h" +#include "MasterAttributes.h" + +class BinaryMasterFile : private virtual slsDetectorDefs, public File { + + public: + BinaryMasterFile(); + ~BinaryMasterFile(); + + void CloseFile() override; + void CreateMasterFile(const std::string filePath, + const std::string fileNamePrefix, + const uint64_t fileIndex, const bool overWriteEnable, + const bool silentMode, + MasterAttributes *attr) override; + + private: + FILE *fd_{nullptr}; + std::string fileName_; +}; \ No newline at end of file diff --git a/slsReceiverSoftware/src/ClientInterface.cpp b/slsReceiverSoftware/src/ClientInterface.cpp index 8f644000e..d882ba1d8 100644 --- a/slsReceiverSoftware/src/ClientInterface.cpp +++ b/slsReceiverSoftware/src/ClientInterface.cpp @@ -209,6 +209,8 @@ int ClientInterface::functionTable(){ flist[F_GET_RECEIVER_STREAMING_HWM] = &ClientInterface::get_streaming_hwm; flist[F_SET_RECEIVER_STREAMING_HWM] = &ClientInterface::set_streaming_hwm; flist[F_RECEIVER_SET_ALL_THRESHOLD] = &ClientInterface::set_all_threshold; + flist[F_RECEIVER_SET_DATASTREAM] = &ClientInterface::set_detector_datastream; + for (int i = NUM_DET_FUNCTIONS + 1; i < NUM_REC_FUNCTIONS ; i++) { LOG(logDEBUG1) << "function fnum: " << i << " (" << @@ -401,6 +403,8 @@ int ClientInterface::setup_receiver(Interface &socket) { impl()->setSubPeriod(std::chrono::nanoseconds(arg.subExpTimeNs) + std::chrono::nanoseconds(arg.subDeadTimeNs)); impl()->setActivate(static_cast(arg.activate)); + impl()->setDetectorDataStream(LEFT, arg.dataStreamLeft); + impl()->setDetectorDataStream(RIGHT, arg.dataStreamRight); try { impl()->setQuad(arg.quad == 0 ? false : true); } catch (const RuntimeError &e) { @@ -1695,3 +1699,25 @@ int ClientInterface::set_all_threshold(Interface &socket) { impl()->setThresholdEnergy(eVs); return socket.Send(OK); } + +int ClientInterface::set_detector_datastream(Interface &socket) { + int args[2]{-1, -1}; + socket.Receive(args); + portPosition port = static_cast(args[0]); + switch (port) { + case LEFT: + case RIGHT: + break; + default: + throw RuntimeError("Invalid port type"); + } + bool enable = static_cast(args[1]); + LOG(logDEBUG1) << "Setting datastream (" << sls::ToString(port) << ") to " + << sls::ToString(enable); + if (myDetectorType != EIGER) + functionNotImplemented(); + verifyIdle(socket); + impl()->setDetectorDataStream(port, enable); + return socket.Send(OK); +} + diff --git a/slsReceiverSoftware/src/ClientInterface.h b/slsReceiverSoftware/src/ClientInterface.h index fa3d3b683..64ed796c0 100644 --- a/slsReceiverSoftware/src/ClientInterface.h +++ b/slsReceiverSoftware/src/ClientInterface.h @@ -162,6 +162,8 @@ class ClientInterface : private virtual slsDetectorDefs { int get_streaming_hwm(sls::ServerInterface &socket); int set_streaming_hwm(sls::ServerInterface &socket); int set_all_threshold(sls::ServerInterface &socket); + int set_detector_datastream(sls::ServerInterface &socket); + Implementation *impl() { if (receiver != nullptr) { diff --git a/slsReceiverSoftware/src/DataProcessor.cpp b/slsReceiverSoftware/src/DataProcessor.cpp index 173bdffbf..a506e02fb 100644 --- a/slsReceiverSoftware/src/DataProcessor.cpp +++ b/slsReceiverSoftware/src/DataProcessor.cpp @@ -6,12 +6,15 @@ ***********************************************/ #include "DataProcessor.h" -#include "BinaryFile.h" +#include "BinaryDataFile.h" +#include "BinaryMasterFile.h" #include "Fifo.h" #include "GeneralData.h" #include "MasterAttributes.h" #ifdef HDF5C -#include "HDF5File.h" +#include "HDF5DataFile.h" +#include "HDF5MasterFile.h" +#include "HDF5VirtualFile.h" #endif #include "DataStreamer.h" #include "sls/sls_detector_exceptions.h" @@ -20,158 +23,234 @@ #include #include -const std::string DataProcessor::TypeName = "DataProcessor"; +const std::string DataProcessor::typeName_ = "DataProcessor"; -DataProcessor::DataProcessor(int ind, detectorType dtype, Fifo *f, - fileFormat *ftype, bool fwenable, bool *mfwenable, - bool *dsEnable, uint32_t *freq, uint32_t *timer, - uint32_t *sfnum, bool *fp, bool *act, - bool *depaden, bool *sm, std::vector *cdl, - int *cdo, int *cad) - : ThreadObject(ind, TypeName), fifo(f), myDetectorType(dtype), - dataStreamEnable(dsEnable), fileFormatType(ftype), - fileWriteEnable(fwenable), masterFileWriteEnable(mfwenable), - streamingFrequency(freq), streamingTimerInMs(timer), - streamingStartFnum(sfnum), activated(act), - deactivatedPaddingEnable(depaden), silentMode(sm), framePadding(fp), - ctbDbitList(cdl), ctbDbitOffset(cdo), ctbAnalogDataBytes(cad), - firstStreamerFrame(false) { - LOG(logDEBUG) << "DataProcessor " << ind << " created"; - memset((void *)&timerBegin, 0, sizeof(timespec)); +DataProcessor::DataProcessor(int index, detectorType detectorType, Fifo *fifo, + bool *activated, bool *deactivatedPaddingEnable, + bool *dataStreamEnable, + uint32_t *streamingFrequency, + uint32_t *streamingTimerInMs, + uint32_t *streamingStartFnum, bool *framePadding, + std::vector *ctbDbitList, int *ctbDbitOffset, + int *ctbAnalogDataBytes, std::mutex *hdf5Lib) + : ThreadObject(index, typeName_), fifo_(fifo), detectorType_(detectorType), + dataStreamEnable_(dataStreamEnable), activated_(activated), + deactivatedPaddingEnable_(deactivatedPaddingEnable), + streamingFrequency_(streamingFrequency), + streamingTimerInMs_(streamingTimerInMs), + streamingStartFnum_(streamingStartFnum), framePadding_(framePadding), + ctbDbitList_(ctbDbitList), ctbDbitOffset_(ctbDbitOffset), + ctbAnalogDataBytes_(ctbAnalogDataBytes), firstStreamerFrame_(false), + hdf5Lib_(hdf5Lib) { + + LOG(logDEBUG) << "DataProcessor " << index << " created"; + + memset((void *)&timerbegin_, 0, sizeof(timespec)); } -DataProcessor::~DataProcessor() { delete file; } +DataProcessor::~DataProcessor() { DeleteFiles(); } /** getters */ -bool DataProcessor::GetStartedFlag() { return startedFlag; } +bool DataProcessor::GetStartedFlag() { return startedFlag_; } -uint64_t DataProcessor::GetNumFramesCaught() { return numFramesCaught; } +uint64_t DataProcessor::GetNumFramesCaught() { return numFramesCaught_; } -uint64_t DataProcessor::GetCurrentFrameIndex() { return currentFrameIndex; } +uint64_t DataProcessor::GetCurrentFrameIndex() { return currentFrameIndex_; } uint64_t DataProcessor::GetProcessedIndex() { - return currentFrameIndex - firstIndex; + return currentFrameIndex_ - firstIndex_; } -void DataProcessor::SetFifo(Fifo *f) { fifo = f; } +void DataProcessor::SetFifo(Fifo *fifo) { fifo_ = fifo; } void DataProcessor::ResetParametersforNewAcquisition() { StopRunning(); - startedFlag = false; - numFramesCaught = 0; - firstIndex = 0; - currentFrameIndex = 0; - firstStreamerFrame = true; + startedFlag_ = false; + numFramesCaught_ = 0; + firstIndex_ = 0; + currentFrameIndex_ = 0; + firstStreamerFrame_ = true; } void DataProcessor::RecordFirstIndex(uint64_t fnum) { // listen to this fnum, later +1 - currentFrameIndex = fnum; + currentFrameIndex_ = fnum; - startedFlag = true; - firstIndex = fnum; + startedFlag_ = true; + firstIndex_ = fnum; - LOG(logDEBUG1) << index << " First Index:" << firstIndex; + LOG(logDEBUG1) << index << " First Index:" << firstIndex_; } -void DataProcessor::SetGeneralData(GeneralData *g) { - generalData = g; - if (file != nullptr) { - if (file->GetFileType() == HDF5) { - file->SetNumberofPixels(generalData->nPixelsX, - generalData->nPixelsY); - } - } -} - -void DataProcessor::SetFileFormat(const fileFormat f) { - if ((file != nullptr) && file->GetFileType() != f) { - // remember the pointer values before they are destroyed - int nd[MAX_DIMENSIONS]; - nd[0] = 0; - nd[1] = 0; - uint32_t *maxf = nullptr; - std::string *fname = nullptr; - std::string *fpath = nullptr; - uint64_t *findex = nullptr; - bool *owenable = nullptr; - int *dindex = nullptr; - int *nunits = nullptr; - uint64_t *nf = nullptr; - uint32_t *dr = nullptr; - uint32_t *port = nullptr; - file->GetMemberPointerValues(nd, maxf, fname, fpath, findex, owenable, - dindex, nunits, nf, dr, port); - // create file writer with same pointers - SetupFileWriter(fileWriteEnable, nd, maxf, fname, fpath, findex, - owenable, dindex, nunits, nf, dr, port); - } -} - -void DataProcessor::SetupFileWriter(bool fwe, int *nd, uint32_t *maxf, - std::string *fname, std::string *fpath, - uint64_t *findex, bool *owenable, - int *dindex, int *nunits, uint64_t *nf, - uint32_t *dr, uint32_t *portno, - GeneralData *g) { - fileWriteEnable = fwe; - if (g != nullptr) - generalData = g; - - if (file != nullptr) { - delete file; - file = nullptr; - } - - if (fileWriteEnable) { - switch (*fileFormatType) { -#ifdef HDF5C - case HDF5: - file = new HDF5File(index, maxf, nd, fname, fpath, findex, owenable, - dindex, nunits, nf, dr, portno, - generalData->nPixelsX, generalData->nPixelsY, - silentMode); - break; -#endif - default: - file = - new BinaryFile(index, maxf, nd, fname, fpath, findex, owenable, - dindex, nunits, nf, dr, portno, silentMode); - break; - } - } -} - -// only the first file -void DataProcessor::CreateNewFile(MasterAttributes *attr) { - if (file == nullptr) { - throw sls::RuntimeError("file object not contstructed"); - } - file->CloseAllFiles(); - file->resetSubFileIndex(); - file->CreateMasterFile(*masterFileWriteEnable, attr); - file->CreateFile(); +void DataProcessor::SetGeneralData(GeneralData *generalData) { + generalData_ = generalData; } void DataProcessor::CloseFiles() { - if (file != nullptr) - file->CloseAllFiles(); + if (dataFile_) + dataFile_->CloseFile(); + if (masterFile_) + masterFile_->CloseFile(); +#ifdef HDF5C + if (virtualFile_) + virtualFile_->CloseFile(); +#endif } -void DataProcessor::EndofAcquisition(bool anyPacketsCaught, uint64_t numf) { - if ((file != nullptr) && file->GetFileType() == HDF5) { - try { - file->EndofAcquisition(anyPacketsCaught, numf); - } catch (const sls::RuntimeError &e) { - ; // ignore for now //TODO: send error to client via stop receiver +void DataProcessor::DeleteFiles() { + CloseFiles(); + if (dataFile_) { + delete dataFile_; + dataFile_ = nullptr; + } + if (masterFile_) { + delete masterFile_; + masterFile_ = nullptr; + } +#ifdef HDF5C + if (virtualFile_) { + delete virtualFile_; + virtualFile_ = nullptr; + } +#endif +} +void DataProcessor::SetupFileWriter(const bool filewriteEnable, + const bool masterFilewriteEnable, + const fileFormat fileFormatType, + const int modulePos) { + DeleteFiles(); + if (filewriteEnable) { + switch (fileFormatType) { +#ifdef HDF5C + case HDF5: + dataFile_ = new HDF5DataFile(index, hdf5Lib_); + if (modulePos == 0 && index == 0) { + if (masterFilewriteEnable) { + masterFile_ = new HDF5MasterFile(hdf5Lib_); + } + } + break; +#endif + case BINARY: + dataFile_ = new BinaryDataFile(index); + if (modulePos == 0 && index == 0 && masterFilewriteEnable) { + masterFile_ = new BinaryMasterFile(); + } + break; + default: + throw sls::RuntimeError( + "Unknown file format (compile with hdf5 flags"); } } } +void DataProcessor::CreateFirstFiles( + MasterAttributes *attr, const std::string filePath, + const std::string fileNamePrefix, const uint64_t fileIndex, + const bool overWriteEnable, const bool silentMode, const int modulePos, + const int numUnitsPerReadout, const uint32_t udpPortNumber, + const uint32_t maxFramesPerFile, const uint64_t numImages, + const uint32_t dynamicRange, const bool detectorDataStream) { + if (dataFile_ == nullptr) { + throw sls::RuntimeError("file object not contstructed"); + } + CloseFiles(); + + // master file write enabled + if (masterFile_) { + masterFile_->CreateMasterFile(filePath, fileNamePrefix, fileIndex, + overWriteEnable, silentMode, attr); + } + + // deactivated with padding enabled, dont write file + if (!*activated_ && !*deactivatedPaddingEnable_) { + return; + } + + // deactivated port, dont write file + if (!detectorDataStream) { + return; + } + + switch (dataFile_->GetFileFormat()) { +#ifdef HDF5C + case HDF5: + dataFile_->CreateFirstHDF5DataFile( + filePath, fileNamePrefix, fileIndex, overWriteEnable, silentMode, + modulePos, numUnitsPerReadout, udpPortNumber, maxFramesPerFile, + numImages, generalData_->nPixelsX, generalData_->nPixelsY, + dynamicRange); + break; +#endif + case BINARY: + dataFile_->CreateFirstBinaryDataFile( + filePath, fileNamePrefix, fileIndex, overWriteEnable, silentMode, + modulePos, numUnitsPerReadout, udpPortNumber, maxFramesPerFile); + break; + default: + throw sls::RuntimeError("Unknown file format (compile with hdf5 flags"); + } +} + +#ifdef HDF5C +uint32_t DataProcessor::GetFilesInAcquisition() const { + if (dataFile_ == nullptr) { + throw sls::RuntimeError("No data file object created to get number of " + "files in acquiistion"); + } + return dataFile_->GetFilesInAcquisition(); +} + +void DataProcessor::CreateVirtualFile( + const std::string filePath, const std::string fileNamePrefix, + const uint64_t fileIndex, const bool overWriteEnable, const bool silentMode, + const int modulePos, const int numUnitsPerReadout, + const uint32_t maxFramesPerFile, const uint64_t numImages, + const uint32_t dynamicRange, const int numModX, const int numModY) { + + if (virtualFile_) { + delete virtualFile_; + } + virtualFile_ = new HDF5VirtualFile(hdf5Lib_); + + uint64_t numImagesProcessed = GetProcessedIndex() + 1; + // maxframesperfile = 0 for infinite files + uint32_t framesPerFile = + ((maxFramesPerFile == 0) ? numImagesProcessed + 1 : maxFramesPerFile); + + // TODO: assumption 1: create virtual file even if no data in other + // files (they exist anyway) assumption2: virtual file max frame index + // is from R0 P0 (difference from others when missing frames or for a + // stop acquisition) + virtualFile_->CreateVirtualFile( + filePath, fileNamePrefix, fileIndex, overWriteEnable, silentMode, + modulePos, numUnitsPerReadout, framesPerFile, numImages, + generalData_->nPixelsX, generalData_->nPixelsY, dynamicRange, + numImagesProcessed, numModX, numModY, dataFile_->GetPDataType(), + dataFile_->GetParameterNames(), dataFile_->GetParameterDataTypes()); +} + +void DataProcessor::LinkDataInMasterFile(const bool silentMode) { + std::string fname, datasetName; + if (virtualFile_) { + auto res = virtualFile_->GetFileAndDatasetName(); + fname = res[0]; + datasetName = res[1]; + } else { + auto res = dataFile_->GetFileAndDatasetName(); + fname = res[0]; + datasetName = res[1]; + } + // link in master + masterFile_->LinkDataFile(fname, datasetName, + dataFile_->GetParameterNames(), silentMode); +} +#endif + void DataProcessor::ThreadExecution() { char *buffer = nullptr; - fifo->PopAddress(buffer); + fifo_->PopAddress(buffer); LOG(logDEBUG5) << "DataProcessor " << index << ", " "pop 0x" @@ -189,21 +268,21 @@ void DataProcessor::ThreadExecution() { try { fnum = ProcessAnImage(buffer); } catch (const std::exception &e) { - fifo->FreeAddress(buffer); + fifo_->FreeAddress(buffer); return; } // stream (if time/freq to stream) or free - if (*dataStreamEnable && SendToStreamer()) { + if (*dataStreamEnable_ && SendToStreamer()) { // if first frame to stream, add frame index to fifo header (might // not be the first) - if (firstStreamerFrame) { - firstStreamerFrame = false; + if (firstStreamerFrame_) { + firstStreamerFrame_ = false; (*((uint32_t *)(buffer + FIFO_DATASIZE_NUMBYTES))) = - (uint32_t)(fnum - firstIndex); + (uint32_t)(fnum - firstIndex_); } - fifo->PushAddressToStream(buffer); + fifo_->PushAddressToStream(buffer); } else { - fifo->FreeAddress(buffer); + fifo_->FreeAddress(buffer); } } @@ -211,13 +290,12 @@ void DataProcessor::StopProcessing(char *buf) { LOG(logDEBUG1) << "DataProcessing " << index << ": Dummy"; // stream or free - if (*dataStreamEnable) - fifo->PushAddressToStream(buf); + if (*dataStreamEnable_) + fifo_->PushAddressToStream(buf); else - fifo->FreeAddress(buf); + fifo_->FreeAddress(buf); - if (file != nullptr) - file->CloseCurrentFile(); + CloseFiles(); StopRunning(); LOG(logDEBUG1) << index << ": Processing Completed"; } @@ -227,37 +305,37 @@ uint64_t DataProcessor::ProcessAnImage(char *buf) { auto *rheader = (sls_receiver_header *)(buf + FIFO_HEADER_NUMBYTES); sls_detector_header header = rheader->detHeader; uint64_t fnum = header.frameNumber; - currentFrameIndex = fnum; + currentFrameIndex_ = fnum; uint32_t nump = header.packetNumber; - if (nump == generalData->packetsPerFrame) { - numFramesCaught++; + if (nump == generalData_->packetsPerFrame) { + numFramesCaught_++; } LOG(logDEBUG1) << "DataProcessing " << index << ": fnum:" << fnum; - if (!startedFlag) { + if (!startedFlag_) { RecordFirstIndex(fnum); - if (*dataStreamEnable) { + if (*dataStreamEnable_) { // restart timer - clock_gettime(CLOCK_REALTIME, &timerBegin); - timerBegin.tv_sec -= (*streamingTimerInMs) / 1000; - timerBegin.tv_nsec -= ((*streamingTimerInMs) % 1000) * 1000000; + clock_gettime(CLOCK_REALTIME, &timerbegin_); + timerbegin_.tv_sec -= (*streamingTimerInMs_) / 1000; + timerbegin_.tv_nsec -= ((*streamingTimerInMs_) % 1000) * 1000000; // to send first image - currentFreqCount = *streamingFrequency - *streamingStartFnum; + currentFreqCount_ = *streamingFrequency_ - *streamingStartFnum_; } } // frame padding - if (*activated && *framePadding && nump < generalData->packetsPerFrame) + if (*activated_ && *framePadding_ && nump < generalData_->packetsPerFrame) PadMissingPackets(buf); // deactivated and padding enabled - else if (!(*activated) && *deactivatedPaddingEnable) + else if (!*activated_ && *deactivatedPaddingEnable_) PadMissingPackets(buf); // rearrange ctb digital bits (if ctbDbitlist is not empty) - if (!(*ctbDbitList).empty()) { + if (!(*ctbDbitList_).empty()) { RearrangeDbitData(buf); } @@ -285,14 +363,14 @@ uint64_t DataProcessor::ProcessAnImage(char *buf) { } // write to file - if (file != nullptr) { + if (dataFile_) { try { - file->WriteToFile( + dataFile_->WriteToFile( buf + FIFO_HEADER_NUMBYTES, sizeof(sls_receiver_header) + (uint32_t)(*((uint32_t *)buf)), //+ size of data (resizable // from previous call back - fnum - firstIndex, nump); + fnum - firstIndex_, nump); } catch (const sls::RuntimeError &e) { ; // ignore write exception for now (TODO: send error message // via stopReceiver tcp) @@ -303,7 +381,7 @@ uint64_t DataProcessor::ProcessAnImage(char *buf) { bool DataProcessor::SendToStreamer() { // skip - if ((*streamingFrequency) == 0u) { + if ((*streamingFrequency_) == 0u) { if (!CheckTimer()) return false; } else { @@ -318,38 +396,29 @@ bool DataProcessor::CheckTimer() { clock_gettime(CLOCK_REALTIME, &end); LOG(logDEBUG1) << index << " Timer elapsed time:" - << ((end.tv_sec - timerBegin.tv_sec) + - (end.tv_nsec - timerBegin.tv_nsec) / 1000000000.0) + << ((end.tv_sec - timerbegin_.tv_sec) + + (end.tv_nsec - timerbegin_.tv_nsec) / 1000000000.0) << " seconds"; // still less than streaming timer, keep waiting - if (((end.tv_sec - timerBegin.tv_sec) + - (end.tv_nsec - timerBegin.tv_nsec) / 1000000000.0) < - ((double)*streamingTimerInMs / 1000.00)) + if (((end.tv_sec - timerbegin_.tv_sec) + + (end.tv_nsec - timerbegin_.tv_nsec) / 1000000000.0) < + ((double)*streamingTimerInMs_ / 1000.00)) return false; // restart timer - clock_gettime(CLOCK_REALTIME, &timerBegin); + clock_gettime(CLOCK_REALTIME, &timerbegin_); return true; } bool DataProcessor::CheckCount() { - if (currentFreqCount == *streamingFrequency) { - currentFreqCount = 1; + if (currentFreqCount_ == *streamingFrequency_) { + currentFreqCount_ = 1; return true; } - currentFreqCount++; + currentFreqCount_++; return false; } -void DataProcessor::SetPixelDimension() { - if (file != nullptr) { - if (file->GetFileType() == HDF5) { - file->SetNumberofPixels(generalData->nPixelsX, - generalData->nPixelsY); - } - } -} - void DataProcessor::registerCallBackRawDataReady(void (*func)(char *, char *, uint32_t, void *), void *arg) { @@ -366,18 +435,18 @@ void DataProcessor::registerCallBackRawDataModifyReady( void DataProcessor::PadMissingPackets(char *buf) { LOG(logDEBUG) << index << ": Padding Missing Packets"; - uint32_t pperFrame = generalData->packetsPerFrame; + uint32_t pperFrame = generalData_->packetsPerFrame; auto *header = (sls_receiver_header *)(buf + FIFO_HEADER_NUMBYTES); uint32_t nmissing = pperFrame - header->detHeader.packetNumber; sls_bitset pmask = header->packetsMask; - uint32_t dsize = generalData->dataSize; - if (myDetectorType == GOTTHARD2 && index != 0) { - dsize = generalData->vetoDataSize; + uint32_t dsize = generalData_->dataSize; + if (detectorType_ == GOTTHARD2 && index != 0) { + dsize = generalData_->vetoDataSize; } - uint32_t fifohsize = generalData->fifoBufferHeaderSize; + uint32_t fifohsize = generalData_->fifoBufferHeaderSize; uint32_t corrected_dsize = - dsize - ((pperFrame * dsize) - generalData->imageSize); + dsize - ((pperFrame * dsize) - generalData_->imageSize); LOG(logDEBUG1) << "bitmask: " << pmask.to_string(); for (unsigned int pnum = 0; pnum < pperFrame; ++pnum) { @@ -394,7 +463,7 @@ void DataProcessor::PadMissingPackets(char *buf) { << std::endl; // missing packet - switch (myDetectorType) { + switch (detectorType_) { // for gotthard, 1st packet: 4 bytes fnum, CACA + CACA, 639*2 bytes // data // 2nd packet: 4 bytes fnum, previous 1*2 bytes data + @@ -425,7 +494,7 @@ void DataProcessor::RearrangeDbitData(char *buf) { // TODO! (Erik) Refactor and add tests int totalSize = (int)(*((uint32_t *)buf)); int ctbDigitalDataBytes = - totalSize - (*ctbAnalogDataBytes) - (*ctbDbitOffset); + totalSize - (*ctbAnalogDataBytes_) - (*ctbDbitOffset_); // no digital data if (ctbDigitalDataBytes == 0) { @@ -436,19 +505,19 @@ void DataProcessor::RearrangeDbitData(char *buf) { const int numSamples = (ctbDigitalDataBytes / sizeof(uint64_t)); const int digOffset = FIFO_HEADER_NUMBYTES + sizeof(sls_receiver_header) + - (*ctbAnalogDataBytes); + (*ctbAnalogDataBytes_); // ceil as numResult8Bits could be decimal const int numResult8Bits = - ceil((double)(numSamples * (*ctbDbitList).size()) / 8.00); + ceil((double)(numSamples * (*ctbDbitList_).size()) / 8.00); std::vector result(numResult8Bits); uint8_t *dest = &result[0]; - auto *source = (uint64_t *)(buf + digOffset + (*ctbDbitOffset)); + auto *source = (uint64_t *)(buf + digOffset + (*ctbDbitOffset_)); // loop through digital bit enable vector int bitoffset = 0; - for (auto bi : (*ctbDbitList)) { + for (auto bi : (*ctbDbitList_)) { // where numbits * numsamples is not a multiple of 8 if (bitoffset != 0) { bitoffset = 0; diff --git a/slsReceiverSoftware/src/DataProcessor.h b/slsReceiverSoftware/src/DataProcessor.h index 98c7a19b6..c05af8784 100644 --- a/slsReceiverSoftware/src/DataProcessor.h +++ b/slsReceiverSoftware/src/DataProcessor.h @@ -19,141 +19,63 @@ class DataStreamer; struct MasterAttributes; #include +#include #include class DataProcessor : private virtual slsDetectorDefs, public ThreadObject { public: - /** - * Constructor - * Calls Base Class CreateThread(), sets ErrorMask if error and increments - * NumberofDataProcessors - * @param ind self index - * @param dtype detector type - * @param f address of Fifo pointer - * @param ftype pointer to file format type - * @param fwenable file writer enable - * @param mfwenable pointer to master file write enable - * @param dsEnable pointer to data stream enable - * @param dr pointer to dynamic range - * @param freq pointer to streaming frequency - * @param timer pointer to timer if streaming frequency is random - * @param sfnum pointer to streaming starting fnum - * @param fp pointer to frame padding enable - * @param act pointer to activated - * @param depaden pointer to deactivated padding enable - * @param sm pointer to silent mode - * @param qe pointer to quad Enable - * @param cdl pointer to vector or ctb digital bits enable - * @param cdo pointer to digital bits offset - * @param cad pointer to ctb analog databytes - */ - DataProcessor(int ind, detectorType dtype, Fifo *f, fileFormat *ftype, - bool fwenable, bool *mfwenable, bool *dsEnable, - uint32_t *freq, uint32_t *timer, uint32_t *sfnum, bool *fp, - bool *act, bool *depaden, bool *sm, std::vector *cdl, - int *cdo, int *cad); + DataProcessor(int index, detectorType detectorType, Fifo *fifo, + bool *activated, bool *deactivatedPaddingEnable, + bool *dataStreamEnable, uint32_t *streamingFrequency, + uint32_t *streamingTimerInMs, uint32_t *streamingStartFnum, + bool *framePadding, std::vector *ctbDbitList, + int *ctbDbitOffset, int *ctbAnalogDataBytes, + std::mutex *hdf5Lib); - /** - * Destructor - * Calls Base Class DestroyThread() and decrements NumberofDataProcessors - */ ~DataProcessor() override; - //*** getters *** - - /** - * Get acquisition started flag - * @return acquisition started flag - */ bool GetStartedFlag(); - - /** - * Get Frames Complete Caught - * @return number of frames - */ uint64_t GetNumFramesCaught(); - - /** - * Gets Actual Current Frame Index (that has not been subtracted from - * firstIndex) thats been processed - * @return -1 if no frames have been caught, else current frame index - */ + /** (-1 if no frames have been caught */ uint64_t GetCurrentFrameIndex(); - - /** - * Get Current Frame Index thats been processed - * @return -1 if no frames have been caught, else current frame index - */ + /** (-1 if no frames have been caught) */ uint64_t GetProcessedIndex(); - /** - * Set Fifo pointer to the one given - * @param f address of Fifo pointer - */ void SetFifo(Fifo *f); - - /** - * Reset parameters for new acquisition - */ void ResetParametersforNewAcquisition(); + void SetGeneralData(GeneralData *generalData); - /** - * Set GeneralData pointer to the one given - * @param g address of GeneralData (Detector Data) pointer - */ - void SetGeneralData(GeneralData *g); - - /** - * Set File Format - * @param fs file format - */ - void SetFileFormat(const fileFormat fs); - - /** - * Set up file writer object and call backs - * @param fwe file write enable - * @param nd pointer to number of detectors in each dimension - * @param maxf pointer to max frames per file - * @param fname pointer to file name prefix - * @param fpath pointer to file path - * @param findex pointer to file index - * @param owenable pointer to over write enable - * @param dindex pointer to detector index - * @param nunits pointer to number of threads/ units per detector - * @param nf pointer to number of images in acquisition - * @param dr pointer to dynamic range - * @param portno pointer to udp port number - * @param g address of GeneralData (Detector Data) pointer - */ - void SetupFileWriter(bool fwe, int *nd, uint32_t *maxf, std::string *fname, - std::string *fpath, uint64_t *findex, bool *owenable, - int *dindex, int *nunits, uint64_t *nf, uint32_t *dr, - uint32_t *portno, GeneralData *g = nullptr); - - /** - * Create New File - * @param attr master file attributes - */ - void CreateNewFile(MasterAttributes *attr); - - /** - * Closes files - */ void CloseFiles(); + void DeleteFiles(); + void SetupFileWriter(const bool filewriteEnable, + const bool masterFilewriteEnable, + const fileFormat fileFormatType, const int modulePos); - /** - * End of Acquisition - * @param anyPacketsCaught true if any packets are caught, else false - * @param numf number of images caught - */ - void EndofAcquisition(bool anyPacketsCaught, uint64_t numf); - - /** - * Update pixel dimensions in file writer - */ - void SetPixelDimension(); - + void CreateFirstFiles(MasterAttributes *attr, const std::string filePath, + const std::string fileNamePrefix, + const uint64_t fileIndex, const bool overWriteEnable, + const bool silentMode, const int modulePos, + const int numUnitsPerReadout, + const uint32_t udpPortNumber, + const uint32_t maxFramesPerFile, + const uint64_t numImages, + const uint32_t dynamicRange, + const bool detectorDataStream + ); +#ifdef HDF5C + uint32_t GetFilesInAcquisition() const; + void CreateVirtualFile(const std::string filePath, + const std::string fileNamePrefix, + const uint64_t fileIndex, const bool overWriteEnable, + const bool silentMode, const int modulePos, + const int numUnitsPerReadout, + const uint32_t maxFramesPerFile, + const uint64_t numImages, + const uint32_t dynamicRange, const int numModX, + const int numModY); + void LinkDataInMasterFile(const bool silentMode); +#endif /** * Call back for raw data * args to raw data ready callback are @@ -179,10 +101,6 @@ class DataProcessor : private virtual slsDetectorDefs, public ThreadObject { void *arg); private: - /** - * Record First Index - * @param fnum frame index to record - */ void RecordFirstIndex(uint64_t fnum); /** @@ -195,14 +113,12 @@ class DataProcessor : private virtual slsDetectorDefs, public ThreadObject { /** * Frees dummy buffer, * reset running mask by calling StopRunning() - * @param buf address of pointer */ void StopProcessing(char *buf); /** * Process an image popped from fifo, * write to file if fw enabled & update parameters - * @param buf address of pointer * @returns frame number */ uint64_t ProcessAnImage(char *buf); @@ -228,10 +144,6 @@ class DataProcessor : private virtual slsDetectorDefs, public ThreadObject { */ bool CheckCount(); - /** - * Pad Missing Packets from the bit mask - * @param buf buffer - */ void PadMissingPackets(char *buf); /** @@ -240,87 +152,43 @@ class DataProcessor : private virtual slsDetectorDefs, public ThreadObject { */ void RearrangeDbitData(char *buf); - /** type of thread */ - static const std::string TypeName; + static const std::string typeName_; - /** GeneralData (Detector Data) object */ - const GeneralData *generalData{nullptr}; - - /** Fifo structure */ - Fifo *fifo; - - // individual members - /** Detector Type */ - detectorType myDetectorType; - - /** File writer implemented as binary or hdf5 File */ - File *file{nullptr}; - - /** Data Stream Enable */ - bool *dataStreamEnable; - - /** File Format Type */ - fileFormat *fileFormatType; - - /** File Write Enable */ - bool fileWriteEnable; - - /** Master File Write Enable */ - bool *masterFileWriteEnable; - - /** Pointer to Streaming frequency, if 0, sending random images with a timer - */ - uint32_t *streamingFrequency; - - /** Pointer to the timer if Streaming frequency is random */ - uint32_t *streamingTimerInMs; - - /** Pointer to streaming starting fnum */ - uint32_t *streamingStartFnum; - - /** Current frequency count */ - uint32_t currentFreqCount{0}; - - /** timer beginning stamp for random streaming */ - struct timespec timerBegin; - - /** Activated/Deactivated */ - bool *activated; - - /** Deactivated padding enable */ - bool *deactivatedPaddingEnable; - - /** Silent Mode */ - bool *silentMode; - - /** frame padding */ - bool *framePadding; - - /** ctb digital bits enable list */ - std::vector *ctbDbitList; - - /** ctb digital bits offset */ - int *ctbDbitOffset; - - /** ctb analog databytes */ - int *ctbAnalogDataBytes; - - // acquisition start - /** Aquisition Started flag */ - std::atomic startedFlag{false}; - - /** Frame Number of First Frame */ - std::atomic firstIndex{0}; + const GeneralData *generalData_{nullptr}; + Fifo *fifo_; + detectorType detectorType_; + bool *dataStreamEnable_; + bool *activated_; + bool *deactivatedPaddingEnable_; + /** if 0, sending random images with a timer */ + uint32_t *streamingFrequency_; + uint32_t *streamingTimerInMs_; + uint32_t *streamingStartFnum_; + uint32_t currentFreqCount_{0}; + struct timespec timerbegin_; + bool *framePadding_; + std::vector *ctbDbitList_; + int *ctbDbitOffset_; + int *ctbAnalogDataBytes_; + std::atomic startedFlag_{false}; + std::atomic firstIndex_{0}; // for statistics /** Number of complete frames caught */ - uint64_t numFramesCaught{0}; + uint64_t numFramesCaught_{0}; /** Frame Number of latest processed frame number */ - std::atomic currentFrameIndex{0}; + std::atomic currentFrameIndex_{0}; /** first streamer frame to add frame index in fifo header */ - bool firstStreamerFrame{false}; + bool firstStreamerFrame_{false}; + + File *dataFile_{nullptr}; + File *masterFile_{nullptr}; + std::mutex *hdf5Lib_; +#ifdef HDF5C + File *virtualFile_{nullptr}; +#endif // call back /** diff --git a/slsReceiverSoftware/src/DataStreamer.cpp b/slsReceiverSoftware/src/DataStreamer.cpp index 7192e4918..86b41112f 100644 --- a/slsReceiverSoftware/src/DataStreamer.cpp +++ b/slsReceiverSoftware/src/DataStreamer.cpp @@ -15,11 +15,11 @@ const std::string DataStreamer::TypeName = "DataStreamer"; DataStreamer::DataStreamer(int ind, Fifo *f, uint32_t *dr, ROI *r, uint64_t *fi, - int fd, int *nd, bool *qe, uint64_t *tot) + int fd, int *nm, bool *qe, uint64_t *tot) : ThreadObject(ind, TypeName), fifo(f), dynamicRange(dr), roi(r), fileIndex(fi), flippedDataX(fd), quadEnable(qe), totalNumFrames(tot) { - numDet[0] = nd[0]; - numDet[1] = nd[1]; + numMods[0] = nm[0]; + numMods[1] = nm[1]; LOG(logDEBUG) << "DataStreamer " << ind << " created"; } @@ -60,9 +60,9 @@ void DataStreamer::RecordFirstIndex(uint64_t fnum, char *buf) { void DataStreamer::SetGeneralData(GeneralData *g) { generalData = g; } -void DataStreamer::SetNumberofDetectors(int *nd) { - numDet[0] = nd[0]; - numDet[1] = nd[1]; +void DataStreamer::SetNumberofModules(int *nm) { + numMods[0] = nm[0]; + numMods[1] = nm[1]; } void DataStreamer::SetFlippedDataX(int fd) { flippedDataX = fd; } @@ -217,8 +217,8 @@ int DataStreamer::SendHeader(sls_receiver_header *rheader, uint32_t size, zHeader.dynamicRange = *dynamicRange; zHeader.fileIndex = *fileIndex; - zHeader.ndetx = numDet[0]; - zHeader.ndety = numDet[1]; + zHeader.ndetx = numMods[0]; + zHeader.ndety = numMods[1]; zHeader.npixelsx = nx; zHeader.npixelsy = ny; zHeader.imageSize = size; diff --git a/slsReceiverSoftware/src/DataStreamer.h b/slsReceiverSoftware/src/DataStreamer.h index 4fcf543ca..45d4c0839 100644 --- a/slsReceiverSoftware/src/DataStreamer.h +++ b/slsReceiverSoftware/src/DataStreamer.h @@ -31,12 +31,12 @@ class DataStreamer : private virtual slsDetectorDefs, public ThreadObject { * @param r roi * @param fi pointer to file index * @param fd flipped data enable for x dimension - * @param nd pointer to number of detectors in each dimension + * @param nm pointer to number of modules in each dimension * @param qe pointer to quad Enable * @param tot pointer to total number of frames */ DataStreamer(int ind, Fifo *f, uint32_t *dr, ROI *r, uint64_t *fi, int fd, - int *nd, bool *qe, uint64_t *tot); + int *nm, bool *qe, uint64_t *tot); /** * Destructor @@ -63,9 +63,9 @@ class DataStreamer : private virtual slsDetectorDefs, public ThreadObject { /** * Set number of detectors - * @param nd number of detectors in both dimensions + * @param nm number of modules in both dimensions */ - void SetNumberofDetectors(int *nd); + void SetNumberofModules(int *nm); /** * Set Flipped data enable across x dimension @@ -193,8 +193,8 @@ class DataStreamer : private virtual slsDetectorDefs, public ThreadObject { /** Complete buffer used for roi, eg. shortGotthard */ char *completeBuffer{nullptr}; - /** Number of Detectors in X and Y dimension */ - int numDet[2]; + /** Number of Modules in X and Y dimension */ + int numMods[2]; /** Quad Enable */ bool *quadEnable; diff --git a/slsReceiverSoftware/src/File.cpp b/slsReceiverSoftware/src/File.cpp index 047461b75..caa5ea93a 100644 --- a/slsReceiverSoftware/src/File.cpp +++ b/slsReceiverSoftware/src/File.cpp @@ -1,71 +1,9 @@ -/************************************************ - * @file File.cpp - * @short sets/gets properties for the file, - * creates/closes the file and writes data to it - ***********************************************/ - #include "File.h" #include -File::File(int ind, slsDetectorDefs::fileFormat type, uint32_t *maxf, int *nd, - std::string *fname, std::string *fpath, uint64_t *findex, - bool *owenable, int *dindex, int *nunits, uint64_t *nf, uint32_t *dr, - uint32_t *portno, bool *smode) - : index(ind), formatType(type), maxFramesPerFile(maxf), numDetX(nd[0]), - numDetY(nd[1]), fileNamePrefix(fname), filePath(fpath), fileIndex(findex), - overWriteEnable(owenable), detIndex(dindex), numUnitsPerDetector(nunits), - numImages(nf), dynamicRange(dr), udpPortNumber(portno), silentMode(smode) - -{ - master = ((index == 0) && (*detIndex == 0)) ? true : false; -} +File::File(const slsDetectorDefs::fileFormat format) : format_(format) {} File::~File() {} -slsDetectorDefs::fileFormat File::GetFileType() { return formatType; } - -std::string File::GetCurrentFileName() { return currentFileName; } - -void File::resetSubFileIndex() { subFileIndex = 0u; } - -void File::PrintMembers(TLogLevel level) { - LOG(level) << "\nGeneral Writer Variables:" << std::endl - << "Index: " << index << std::endl - << "Max Frames Per File: " << *maxFramesPerFile << std::endl - << "Number of Detectors in x dir: " << numDetX << std::endl - << "Number of Detectors in y dir: " << numDetY << std::endl - << "File Name Prefix: " << fileNamePrefix << std::endl - << "File Path: " << filePath << std::endl - << "File Index: " << *fileIndex << std::endl - << "Over Write Enable: " << *overWriteEnable << std::endl - - << "Detector Index: " << *detIndex << std::endl - << "Number of Units Per Detector: " << *numUnitsPerDetector - << std::endl - << "Number of Images in Acquisition: " << *numImages << std::endl - << "Dynamic Range: " << *dynamicRange << std::endl - << "UDP Port number: " << *udpPortNumber << std::endl - << "Master File Name: " << masterFileName << std::endl - << "Current File Name: " << currentFileName << std::endl - << "Silent Mode: " << *silentMode; -} - -void File::GetMemberPointerValues(int *nd, uint32_t *&maxf, std::string *&fname, - std::string *&fpath, uint64_t *&findex, - bool *&owenable, int *&dindex, int *&nunits, - uint64_t *&nf, uint32_t *&dr, - uint32_t *&portno) { - nd[0] = numDetX; - nd[1] = numDetY; - maxf = maxFramesPerFile; - fname = fileNamePrefix; - fpath = filePath; - findex = fileIndex; - owenable = overWriteEnable; - dindex = detIndex; - nunits = numUnitsPerDetector; - nf = numImages; - dr = dynamicRange; - portno = udpPortNumber; -} +slsDetectorDefs::fileFormat File::GetFileFormat() const { return format_; } diff --git a/slsReceiverSoftware/src/File.h b/slsReceiverSoftware/src/File.h index 6077bcb76..70fbd6449 100644 --- a/slsReceiverSoftware/src/File.h +++ b/slsReceiverSoftware/src/File.h @@ -1,134 +1,123 @@ #pragma once -/************************************************ - * @file File.h - * @short sets/gets properties for the file, - * creates/closes the file and writes data to it - ***********************************************/ -/** - *@short sets/gets properties for the file, creates/closes the file and writes - *data to it - */ -#include "receiver_defs.h" #include "sls/logger.h" #include "sls/sls_detector_defs.h" -#include - struct MasterAttributes; +#ifdef HDF5C +#include "H5Cpp.h" +#ifndef H5_NO_NAMESPACE +using namespace H5; +#endif +#endif + +#include + class File : private virtual slsDetectorDefs { public: - /** - * Constructor - * creates the File Writer - * @param ind self index - * @param type file format type - * @param maxf pointer to max frames per file - * @param nd pointer to number of detectors in each dimension - * @param fname pointer to file name prefix - * @param fpath pointer to file path - * @param findex pointer to file index - * @param owenable pointer to over write enable - * @param dindex pointer to detector index - * @param nunits pointer to number of theads/ units per detector - * @param nf pointer to number of images in acquisition - * @param dr pointer to dynamic range - * @param portno pointer to udp port number for logging - * @param smode pointer to silent mode - */ - File(int ind, slsDetectorDefs::fileFormat type, uint32_t *maxf, int *nd, - std::string *fname, std::string *fpath, uint64_t *findex, - bool *owenable, int *dindex, int *nunits, uint64_t *nf, uint32_t *dr, - uint32_t *portno, bool *smode); - + File(const slsDetectorDefs::fileFormat format); virtual ~File(); - fileFormat GetFileType(); - std::string GetCurrentFileName(); - void resetSubFileIndex(); - virtual void PrintMembers(TLogLevel level = logDEBUG1); - /** - * Get Member Pointer Values before the object is destroyed - * @param nd pointer to number of detectors in each dimension - * @param maxf pointer to max frames per file - * @param fname pointer to file name prefix - * @param fpath pointer to file path - * @param findex pointer to file index - * @param owenable pointer to over write enable - * @param dindex pointer to detector index - * @param nunits pointer to number of theads/ units per detector - * @param nf pointer to number of images in acquisition - * @param dr pointer to dynamic range - * @param portno pointer to dynamic range - */ - void GetMemberPointerValues(int *nd, uint32_t *&maxf, std::string *&fname, - std::string *&fpath, uint64_t *&findex, - bool *&owenable, int *&dindex, int *&nunits, - uint64_t *&nf, uint32_t *&dr, - uint32_t *&portno); + fileFormat GetFileFormat() const; + virtual void CloseFile() = 0; - virtual void CreateFile() = 0; - virtual void CloseCurrentFile() = 0; - virtual void CloseAllFiles() = 0; +#ifdef HDF5C + virtual std::array GetFileAndDatasetName() const { + LOG(logERROR) + << "This is a generic function GetFilesInAcquisition that " + "should be overloaded by a derived class"; + return std::array{}; + } - /** - * Write data to file - * @param buffer buffer to write from - * @param buffersize size of buffer - * @param fnum current image number - * @param nump number of packets caught - */ - virtual void WriteToFile(char *buffer, int buffersize, uint64_t fnum, - uint32_t nump) = 0; + virtual uint32_t GetFilesInAcquisition() const { + LOG(logERROR) + << "This is a generic function GetFilesInAcquisition that " + "should be overloaded by a derived class"; + return 0; + }; - /** - * Create master file - * @param mfwenable master file write enable - * @param attr master file attributes - */ - virtual void CreateMasterFile(bool mfwenable, MasterAttributes *attr) = 0; + virtual DataType GetPDataType() const { + LOG(logERROR) << "This is a generic function GetPDataType that " + "should be overloaded by a derived class"; + return PredType::STD_U16LE; + } - // HDf5 specific - /** - * Set Number of pixels - * @param nx number of pixels in x direction - * @param ny number of pixels in y direction - */ - virtual void SetNumberofPixels(uint32_t nx, uint32_t ny) { - LOG(logERROR) << "This is a generic function SetNumberofPixels that " + virtual std::vector GetParameterNames() const { + LOG(logERROR) + << "This is a generic function GetFilesInAcquisition that " + "should be overloaded by a derived class"; + return std::vector{}; + }; + + virtual std::vector GetParameterDataTypes() const { + LOG(logERROR) + << "This is a generic function GetFilesInAcquisition that " + "should be overloaded by a derived class"; + return std::vector{}; + }; + + virtual void CreateVirtualFile( + const std::string filePath, const std::string fileNamePrefix, + const uint64_t fileIndex, const bool overWriteEnable, + const bool silentMode, const int modulePos, + const int numUnitsPerReadout, const uint32_t maxFramesPerFile, + const uint64_t numImages, const uint32_t nPixelsX, + const uint32_t nPixelsY, const uint32_t dynamicRange, + const uint64_t numImagesCaught, const int numModX, const int numModY, + const DataType dataType, const std::vector parameterNames, + const std::vector parameterDataTypes) { + LOG(logERROR) << "This is a generic function CreateVirtualFile that " "should be overloaded by a derived class"; } - /** - * End of Acquisition - * @param anyPacketsCaught true if any packets are caught, else false - * @param numf number of images caught - */ - virtual void EndofAcquisition(bool anyPacketsCaught, uint64_t numf) { - LOG(logERROR) << "This is a generic function EndofAcquisition that " + virtual void CreateFirstHDF5DataFile( + const std::string filePath, const std::string fileNamePrefix, + const uint64_t fileIndex, const bool overWriteEnable, + const bool silentMode, const int modulePos, + const int numUnitsPerReadout, const uint32_t udpPortNumber, + const uint32_t maxFramesPerFile, const uint64_t numImages, + const uint32_t nPixelsX, const uint32_t nPixelsY, + const uint32_t dynamicRange) { + LOG(logERROR) << "This is a generic function CreateFirstDataFile that " "should be overloaded by a derived class"; - } + }; + + virtual void LinkDataFile(std::string dataFilename, std::string dataSetname, + const std::vector parameterNames, + const bool silentMode) { + LOG(logERROR) << "This is a generic function LinkDataFile that " + "should be overloaded by a derived class"; + }; +#endif + virtual void CreateFirstBinaryDataFile( + const std::string filePath, const std::string fileNamePrefix, + const uint64_t fileIndex, const bool overWriteEnable, + const bool silentMode, const int modulePos, + const int numUnitsPerReadout, const uint32_t udpPortNumber, + const uint32_t maxFramesPerFile) { + LOG(logERROR) << "This is a generic function CreateFirstDataFile that " + "should be overloaded by a derived class"; + }; + + virtual void CreateMasterFile(const std::string filePath, + const std::string fileNamePrefix, + const uint64_t fileIndex, + const bool overWriteEnable, + const bool silentMode, + MasterAttributes *attr) { + LOG(logERROR) << "This is a generic function CreateMasterFile that " + "should be overloaded by a derived class"; + }; + + virtual void WriteToFile(char *buffer, const int buffersize, + const uint64_t currentFrameNumber, + const uint32_t numPacketsCaught) { + LOG(logERROR) << "This is a generic function WriteToFile that " + "should be overloaded by a derived class"; + }; protected: - bool master; - int index; - slsDetectorDefs::fileFormat formatType; - uint32_t *maxFramesPerFile; - std::string masterFileName; - std::string currentFileName; - int numDetX; - int numDetY; - std::string *fileNamePrefix; - std::string *filePath; - uint64_t *fileIndex; - uint64_t subFileIndex{0}; - bool *overWriteEnable; - int *detIndex; - int *numUnitsPerDetector; - uint64_t *numImages; - uint32_t *dynamicRange; - uint32_t *udpPortNumber; - bool *silentMode; + slsDetectorDefs::fileFormat format_; }; diff --git a/slsReceiverSoftware/src/HDF5DataFile.cpp b/slsReceiverSoftware/src/HDF5DataFile.cpp new file mode 100644 index 000000000..270924fc1 --- /dev/null +++ b/slsReceiverSoftware/src/HDF5DataFile.cpp @@ -0,0 +1,393 @@ +#include "HDF5DataFile.h" +#include "receiver_defs.h" + +#include + +HDF5DataFile::HDF5DataFile(int index, std::mutex *hdf5Lib) + : File(HDF5), index_(index), hdf5Lib_(hdf5Lib) { + + parameterNames_ = std::vector{ + "frame number", + "exp length or sub exposure time", + "packets caught", + "bunch id", + "timestamp", + "mod id", + "row", + "column", + "reserved", + "debug", + "round robin number", + "detector type", + "detector header version", + "packets caught bit mask", + }; + StrType strdatatype(PredType::C_S1, sizeof(bitset_storage)); + parameterDataTypes_ = std::vector{ + PredType::STD_U64LE, PredType::STD_U32LE, PredType::STD_U32LE, + PredType::STD_U64LE, PredType::STD_U64LE, PredType::STD_U16LE, + PredType::STD_U16LE, PredType::STD_U16LE, PredType::STD_U16LE, + PredType::STD_U32LE, PredType::STD_U16LE, PredType::STD_U8LE, + PredType::STD_U8LE, strdatatype}; +} + +HDF5DataFile::~HDF5DataFile() { CloseFile(); } + +std::array HDF5DataFile::GetFileAndDatasetName() const { + return std::array{fileName_, dataSetName_}; +} + +uint32_t HDF5DataFile::GetFilesInAcquisition() const { + return numFilesInAcquisition_; +} + +DataType HDF5DataFile::GetPDataType() const { return dataType_; } + +std::vector HDF5DataFile::GetParameterNames() const { + return parameterNames_; +} +std::vector HDF5DataFile::GetParameterDataTypes() const { + return parameterDataTypes_; +} + +void HDF5DataFile::CloseFile() { + std::lock_guard lock(*hdf5Lib_); + try { + Exception::dontPrint(); // to handle errors + if (fd_) { + fd_->close(); + delete fd_; + fd_ = nullptr; + } + } catch (const Exception &error) { + LOG(logERROR) << "Could not close data HDF5 handles of index " + << index_; + error.printErrorStack(); + } + if (dataSpace_) { + delete dataSpace_; + dataSpace_ = nullptr; + } + if (dataSet_) { + delete dataSet_; + dataSet_ = nullptr; + } + if (dataSpacePara_) { + delete dataSpacePara_; + dataSpacePara_ = nullptr; + } + for (auto it : dataSetPara_) + delete it; + dataSetPara_.clear(); +} + +void HDF5DataFile::CreateFirstHDF5DataFile( + const std::string filePath, const std::string fileNamePrefix, + const uint64_t fileIndex, const bool overWriteEnable, const bool silentMode, + const int modulePos, const int numUnitsPerReadout, + const uint32_t udpPortNumber, const uint32_t maxFramesPerFile, + const uint64_t numImages, const uint32_t nPixelsX, const uint32_t nPixelsY, + const uint32_t dynamicRange) { + + subFileIndex_ = 0; + numFramesInFile_ = 0; + extNumImages_ = numImages; + numFilesInAcquisition_ = 0; + + maxFramesPerFile_ = maxFramesPerFile; + numImages_ = numImages; + nPixelsX_ = nPixelsX; + nPixelsY_ = nPixelsY; + dynamicRange_ = dynamicRange; + + filePath_ = filePath; + fileNamePrefix_ = fileNamePrefix; + fileIndex_ = fileIndex; + overWriteEnable_ = overWriteEnable; + silentMode_ = silentMode; + detIndex_ = modulePos; + numUnitsPerReadout_ = numUnitsPerReadout; + udpPortNumber_ = udpPortNumber; + + switch (dynamicRange_) { + case 16: + dataType_ = PredType::STD_U16LE; + break; + case 32: + dataType_ = PredType::STD_U32LE; + break; + default: + dataType_ = PredType::STD_U8LE; + break; + } + + CreateFile(); +} + +void HDF5DataFile::CreateFile() { + + numFilesInAcquisition_++; + + std::ostringstream os; + os << filePath_ << "/" << fileNamePrefix_ << "_d" + << (detIndex_ * numUnitsPerReadout_ + index_) << "_f" << subFileIndex_ + << '_' << fileIndex_ << ".h5"; + fileName_ = os.str(); + + std::lock_guard lock(*hdf5Lib_); + + uint64_t framestosave = + ((maxFramesPerFile_ == 0) ? numImages_ : // infinite images + (((extNumImages_ - subFileIndex_) > maxFramesPerFile_) + ? // save up to maximum at a time + maxFramesPerFile_ + : (extNumImages_ - subFileIndex_))); + + uint64_t nDimx = framestosave; + uint32_t nDimy = nPixelsY_; + uint32_t nDimz = ((dynamicRange_ == 4) ? (nPixelsX_ / 2) : nPixelsX_); + + try { + Exception::dontPrint(); // to handle errors + + // file + FileAccPropList fapl; + fapl.setFcloseDegree(H5F_CLOSE_STRONG); + fd_ = nullptr; + if (!overWriteEnable_) + fd_ = new H5File(fileName_.c_str(), H5F_ACC_EXCL, + FileCreatPropList::DEFAULT, fapl); + else + fd_ = new H5File(fileName_.c_str(), H5F_ACC_TRUNC, + FileCreatPropList::DEFAULT, fapl); + + // attributes - version + double dValue = HDF5_WRITER_VERSION; + DataSpace dataspace_attr = DataSpace(H5S_SCALAR); + Attribute attribute = fd_->createAttribute( + "version", PredType::NATIVE_DOUBLE, dataspace_attr); + attribute.write(PredType::NATIVE_DOUBLE, &dValue); + + // dataspace + hsize_t srcdims[3] = {nDimx, nDimy, nDimz}; + hsize_t srcdimsmax[3] = {H5S_UNLIMITED, nDimy, nDimz}; + dataSpace_ = nullptr; + dataSpace_ = new DataSpace(3, srcdims, srcdimsmax); + + // dataset name + std::ostringstream osfn; + osfn << "/data"; + if (numImages_ > 1) + osfn << "_f" << std::setfill('0') << std::setw(12) << subFileIndex_; + dataSetName_ = osfn.str(); + + // dataset + // fill value + DSetCreatPropList plist; + int fill_value = -1; + plist.setFillValue(dataType_, &fill_value); + // always create chunked dataset as unlimited is only + // supported with chunked layout + hsize_t chunk_dims[3] = {MAX_CHUNKED_IMAGES, nDimy, nDimz}; + plist.setChunk(3, chunk_dims); + dataSet_ = nullptr; + dataSet_ = new DataSet(fd_->createDataSet( + dataSetName_.c_str(), dataType_, *dataSpace_, plist)); + + // create parameter datasets + hsize_t dims[1] = {nDimx}; + hsize_t dimsmax[1] = {H5S_UNLIMITED}; + dataSpacePara_ = nullptr; + dataSpacePara_ = new DataSpace(1, dims, dimsmax); + + // always create chunked dataset as unlimited is only + // supported with chunked layout + DSetCreatPropList paralist; + hsize_t chunkpara_dims[3] = {MAX_CHUNKED_IMAGES}; + paralist.setChunk(1, chunkpara_dims); + + for (unsigned int i = 0; i < parameterNames_.size(); ++i) { + DataSet *ds = new DataSet(fd_->createDataSet( + parameterNames_[i].c_str(), parameterDataTypes_[i], + *dataSpacePara_, paralist)); + dataSetPara_.push_back(ds); + } + } catch (const Exception &error) { + error.printErrorStack(); + CloseFile(); + throw sls::RuntimeError("Could not create HDF5 handles in object " + + index_); + } + if (!silentMode_) { + LOG(logINFO) << "[" << udpPortNumber_ + << "]: HDF5 File created: " << fileName_; + } +} + +void HDF5DataFile::WriteToFile(char *buffer, const int buffersize, + const uint64_t currentFrameNumber, + const uint32_t numPacketsCaught) { + + // check if maxframesperfile = 0 for infinite + if (maxFramesPerFile_ && (numFramesInFile_ >= maxFramesPerFile_)) { + CloseFile(); + ++subFileIndex_; + CreateFile(); + } + numFramesInFile_++; + + // extend dataset (when receiver start followed by many status starts + // (jungfrau))) + if (currentFrameNumber >= extNumImages_) { + ExtendDataset(); + } + + WriteDataFile(currentFrameNumber, buffer + sizeof(sls_receiver_header)); + WriteParameterDatasets(currentFrameNumber, (sls_receiver_header *)(buffer)); +} + +void HDF5DataFile::WriteDataFile(const uint64_t currentFrameNumber, + char *buffer) { + std::lock_guard lock(*hdf5Lib_); + + uint64_t nDimx = + ((maxFramesPerFile_ == 0) ? currentFrameNumber + : currentFrameNumber % maxFramesPerFile_); + uint32_t nDimy = nPixelsY_; + uint32_t nDimz = ((dynamicRange_ == 4) ? (nPixelsX_ / 2) : nPixelsX_); + + hsize_t count[3] = {1, nDimy, nDimz}; + hsize_t start[3] = {nDimx, 0, 0}; + hsize_t dims2[2] = {nDimy, nDimz}; + try { + Exception::dontPrint(); // to handle errors + + dataSpace_->selectHyperslab(H5S_SELECT_SET, count, start); + DataSpace memspace(2, dims2); + dataSet_->write(buffer, dataType_, memspace, *dataSpace_); + memspace.close(); + } catch (const Exception &error) { + LOG(logERROR) << "Could not write to file in object " << index_; + error.printErrorStack(); + throw sls::RuntimeError("Could not write to file in object " + + std::to_string(index_)); + } +} + +void HDF5DataFile::WriteParameterDatasets(const uint64_t currentFrameNumber, + sls_receiver_header *rheader) { + std::lock_guard lock(*hdf5Lib_); + + uint64_t fnum = + ((maxFramesPerFile_ == 0) ? currentFrameNumber + : currentFrameNumber % maxFramesPerFile_); + + sls_detector_header header = rheader->detHeader; + hsize_t count[1] = {1}; + hsize_t start[1] = {fnum}; + int i = 0; + try { + Exception::dontPrint(); // to handle errors + dataSpacePara_->selectHyperslab(H5S_SELECT_SET, count, start); + DataSpace memspace(H5S_SCALAR); + dataSetPara_[0]->write(&header.frameNumber, parameterDataTypes_[0], + memspace, *dataSpacePara_); + i = 1; + dataSetPara_[1]->write(&header.expLength, parameterDataTypes_[1], + memspace, *dataSpacePara_); + i = 2; + dataSetPara_[2]->write(&header.packetNumber, parameterDataTypes_[2], + memspace, *dataSpacePara_); + i = 3; + dataSetPara_[3]->write(&header.bunchId, parameterDataTypes_[3], + memspace, *dataSpacePara_); + i = 4; + dataSetPara_[4]->write(&header.timestamp, parameterDataTypes_[4], + memspace, *dataSpacePara_); + i = 5; + dataSetPara_[5]->write(&header.modId, parameterDataTypes_[5], memspace, + *dataSpacePara_); + i = 6; + dataSetPara_[6]->write(&header.row, parameterDataTypes_[6], memspace, + *dataSpacePara_); + i = 7; + dataSetPara_[7]->write(&header.column, parameterDataTypes_[7], memspace, + *dataSpacePara_); + i = 8; + dataSetPara_[8]->write(&header.reserved, parameterDataTypes_[8], + memspace, *dataSpacePara_); + i = 9; + dataSetPara_[9]->write(&header.debug, parameterDataTypes_[9], memspace, + *dataSpacePara_); + i = 10; + dataSetPara_[10]->write(&header.roundRNumber, parameterDataTypes_[10], + memspace, *dataSpacePara_); + i = 11; + dataSetPara_[11]->write(&header.detType, parameterDataTypes_[11], + memspace, *dataSpacePara_); + i = 12; + dataSetPara_[12]->write(&header.version, parameterDataTypes_[12], + memspace, *dataSpacePara_); + i = 13; + + // contiguous bitset + if (sizeof(sls_bitset) == sizeof(bitset_storage)) { + dataSetPara_[13]->write((char *)&(rheader->packetsMask), + parameterDataTypes_[13], memspace, + *dataSpacePara_); + } + + // not contiguous bitset + else { + // get contiguous representation of bit mask + bitset_storage storage; + memset(storage, 0, sizeof(bitset_storage)); + sls_bitset bits = rheader->packetsMask; + for (int i = 0; i < MAX_NUM_PACKETS; ++i) + storage[i >> 3] |= (bits[i] << (i & 7)); + // write bitmask + dataSetPara_[13]->write((char *)storage, parameterDataTypes_[13], + memspace, *dataSpacePara_); + } + i = 14; + } catch (const Exception &error) { + error.printErrorStack(); + throw sls::RuntimeError( + "Could not write parameters (index:" + std::to_string(i) + + ") to file in object " + std::to_string(index_)); + } +} + +void HDF5DataFile::ExtendDataset() { + std::lock_guard lock(*hdf5Lib_); + + try { + Exception::dontPrint(); // to handle errors + + hsize_t dims[3]; + dataSpace_->getSimpleExtentDims(dims); + dims[0] += numImages_; + + dataSet_->extend(dims); + delete dataSpace_; + dataSpace_ = nullptr; + dataSpace_ = new DataSpace(dataSet_->getSpace()); + + hsize_t dims_para[1] = {dims[0]}; + for (unsigned int i = 0; i < dataSetPara_.size(); ++i) + dataSetPara_[i]->extend(dims_para); + delete dataSpacePara_; + dataSpacePara_ = nullptr; + dataSpacePara_ = new DataSpace(dataSetPara_[0]->getSpace()); + + } catch (const Exception &error) { + error.printErrorStack(); + throw sls::RuntimeError("Could not extend dataset in object " + + std::to_string(index_)); + } + if (!silentMode_) { + LOG(logINFO) << index_ << " Extending HDF5 dataset by " << extNumImages_ + << ", Total x Dimension: " << (extNumImages_ + numImages_); + } + extNumImages_ += numImages_; +} \ No newline at end of file diff --git a/slsReceiverSoftware/src/HDF5DataFile.h b/slsReceiverSoftware/src/HDF5DataFile.h new file mode 100644 index 000000000..fdc68e148 --- /dev/null +++ b/slsReceiverSoftware/src/HDF5DataFile.h @@ -0,0 +1,73 @@ +#pragma once + +#include "File.h" + +#include + +class HDF5DataFile : private virtual slsDetectorDefs, public File { + + public: + HDF5DataFile(const int index, std::mutex *hdf5Lib); + ~HDF5DataFile(); + + std::array GetFileAndDatasetName() const override; + uint32_t GetFilesInAcquisition() const override; + DataType GetPDataType() const override; + std::vector GetParameterNames() const override; + std::vector GetParameterDataTypes() const override; + + void CloseFile() override; + + void CreateFirstHDF5DataFile( + const std::string filePath, const std::string fileNamePrefix, + const uint64_t fileIndex, const bool overWriteEnable, + const bool silentMode, const int modulePos, + const int numUnitsPerReadout, const uint32_t udpPortNumber, + const uint32_t maxFramesPerFile, const uint64_t numImages, + const uint32_t nPixelsX, const uint32_t nPixelsY, + const uint32_t dynamicRange) override; + + void WriteToFile(char *buffer, const int buffersize, + const uint64_t currentFrameNumber, + const uint32_t numPacketsCaught) override; + + private: + void CreateFile(); + void WriteDataFile(const uint64_t currentFrameNumber, char *buffer); + void WriteParameterDatasets(const uint64_t currentFrameNumber, + sls_receiver_header *rheader); + void ExtendDataset(); + + int index_; + std::mutex *hdf5Lib_; + H5File *fd_{nullptr}; + std::string fileName_; + std::string dataSetName_; + DataSpace *dataSpace_{nullptr}; + DataSet *dataSet_{nullptr}; + DataType dataType_{PredType::STD_U16LE}; + + DataSpace *dataSpacePara_{nullptr}; + std::vector dataSetPara_{nullptr}; + std::vector parameterNames_; + std::vector parameterDataTypes_; + + uint32_t subFileIndex_{0}; + uint32_t numFramesInFile_{0}; + uint32_t numFilesInAcquisition_{0}; + uint32_t maxFramesPerFile_{0}; + uint64_t numImages_{0}; + uint64_t extNumImages_{0}; + uint32_t nPixelsX_{0}; + uint32_t nPixelsY_{0}; + uint32_t dynamicRange_{0}; + + std::string filePath_; + std::string fileNamePrefix_; + uint64_t fileIndex_{0}; + bool overWriteEnable_{false}; + bool silentMode_{false}; + int detIndex_{0}; + int numUnitsPerReadout_{0}; + uint32_t udpPortNumber_{0}; +}; \ No newline at end of file diff --git a/slsReceiverSoftware/src/HDF5File.cpp b/slsReceiverSoftware/src/HDF5File.cpp deleted file mode 100644 index 24157ee8a..000000000 --- a/slsReceiverSoftware/src/HDF5File.cpp +++ /dev/null @@ -1,838 +0,0 @@ -/************************************************ - * @file HDF5File.cpp - * @short sets/gets properties for the HDF5 file, - * creates/closes the file and writes data to it - ***********************************************/ -#include "HDF5File.h" -#include "Fifo.h" -#include "MasterAttributes.h" -#include "receiver_defs.h" - -#include -#include -#include //basename -#include - -std::mutex HDF5File::hdf5Lib; - -HDF5File::HDF5File(int ind, uint32_t *maxf, int *nd, std::string *fname, - std::string *fpath, uint64_t *findex, bool *owenable, - int *dindex, int *nunits, uint64_t *nf, uint32_t *dr, - uint32_t *portno, uint32_t nx, uint32_t ny, bool *smode) - : - - File(ind, HDF5, maxf, nd, fname, fpath, findex, owenable, dindex, nunits, - nf, dr, portno, smode), - masterfd(nullptr), virtualfd(0), filefd(nullptr), dataspace(nullptr), - dataset(nullptr), datatype(PredType::STD_U16LE), nPixelsX(nx), - nPixelsY(ny), numFramesInFile(0), numActualPacketsInFile(0), - numFilesinAcquisition(0), dataspace_para(nullptr), extNumImages(0) { - PrintMembers(); - dataset_para.clear(); - parameterNames.clear(); - parameterDataTypes.clear(); - - parameterNames = std::vector{ - "frame number", - "exp length or sub exposure time", - "packets caught", - "bunch id", - "timestamp", - "mod id", - "row", - "column", - "reserved", - "debug", - "round robin number", - "detector type", - "detector header version", - "packets caught bit mask", - }; - StrType strdatatype(PredType::C_S1, sizeof(bitset_storage)); - parameterDataTypes = std::vector{ - PredType::STD_U64LE, PredType::STD_U32LE, PredType::STD_U32LE, - PredType::STD_U64LE, PredType::STD_U64LE, PredType::STD_U16LE, - PredType::STD_U16LE, PredType::STD_U16LE, PredType::STD_U16LE, - PredType::STD_U32LE, PredType::STD_U16LE, PredType::STD_U8LE, - PredType::STD_U8LE, strdatatype}; -} - -HDF5File::~HDF5File() { CloseAllFiles(); } - -void HDF5File::SetNumberofPixels(uint32_t nx, uint32_t ny) { - nPixelsX = nx; - nPixelsY = ny; -} - -void HDF5File::CreateFile() { - numFilesinAcquisition++; - numFramesInFile = 0; - numActualPacketsInFile = 0; - - // first time - if (subFileIndex == 0u) { - switch (*dynamicRange) { - case 16: - datatype = PredType::STD_U16LE; - break; - case 32: - datatype = PredType::STD_U32LE; - break; - default: - datatype = PredType::STD_U8LE; - break; - } - } - CreateDataFile(); -} - -void HDF5File::CloseCurrentFile() { - CloseFile(filefd, false); - for (unsigned int i = 0; i < dataset_para.size(); ++i) - delete dataset_para[i]; - dataset_para.clear(); - if (dataspace_para) { - delete dataspace_para; - dataspace_para = nullptr; - } - if (dataset) { - delete dataset; - dataset = nullptr; - } - if (dataspace) { - delete dataspace; - dataspace = nullptr; - } -} - -void HDF5File::CloseAllFiles() { - numFilesinAcquisition = 0; - { - CloseFile(filefd, false); - if (master) { - CloseFile(masterfd, true); - // close virtual file - // c code due to only c implementation of H5Pset_virtual available - if (virtualfd != 0) { - if (H5Fclose(virtualfd) < 0) { - LOG(logERROR) << "Could not close virtual HDF5 handles"; - } - virtualfd = 0; - } - } - } - for (unsigned int i = 0; i < dataset_para.size(); ++i) - delete dataset_para[i]; - dataset_para.clear(); - delete dataspace_para; - delete dataset; - delete dataspace; -} - -void HDF5File::WriteToFile(char *buffer, int bufferSize, - uint64_t currentFrameNumber, - uint32_t numPacketsCaught) { - - // check if maxframesperfile = 0 for infinite - if ((*maxFramesPerFile) && (numFramesInFile >= (*maxFramesPerFile))) { - CloseCurrentFile(); - ++subFileIndex; - CreateFile(); - } - numFramesInFile++; - numActualPacketsInFile += numPacketsCaught; - - // extend dataset (when receiver start followed by many status starts - // (jungfrau))) - if (currentFrameNumber >= extNumImages) { - ExtendDataset(); - } - - WriteDataFile(currentFrameNumber, buffer + sizeof(sls_receiver_header)); - WriteParameterDatasets(currentFrameNumber, (sls_receiver_header *)(buffer)); -} - -void HDF5File::CreateMasterFile(bool masterFileWriteEnable, - MasterAttributes *attr) { - - // beginning of every acquisition - numFramesInFile = 0; - numActualPacketsInFile = 0; - extNumImages = *numImages; - - if (masterFileWriteEnable && master) { - virtualfd = 0; - CreateMasterDataFile(attr); - } -} - -void HDF5File::EndofAcquisition(bool anyPacketsCaught, - uint64_t numImagesCaught) { - // not created before - if (!virtualfd && anyPacketsCaught) { - // called only by the one maser receiver - if (master && masterfd != nullptr) { - // only one file and one sub image (link current file in master) - if (((numFilesinAcquisition == 1) && (numDetY * numDetX) == 1)) { - // dataset name - std::ostringstream oss; - oss << "/data"; - if ((*numImages > 1)) { - oss << "_f" << std::setfill('0') << std::setw(12) << 0; - } - std::string dsetname = oss.str(); - - LinkVirtualInMaster(currentFileName, dsetname); - } - // create virutal file - else { - CreateVirtualDataFile( - // infinite images in 1 file, then maxfrperfile = - // numImagesCaught - ((*maxFramesPerFile == 0) ? numImagesCaught + 1 - : *maxFramesPerFile), - numImagesCaught + 1); - } - } - } - numFilesinAcquisition = 0; -} - -void HDF5File::CloseFile(H5File *&fd, bool masterFile) { - std::lock_guard lock(HDF5File::hdf5Lib); - try { - Exception::dontPrint(); // to handle errors - if (fd) { - fd->close(); - delete fd; - fd = nullptr; - } - } catch (const Exception &error) { - LOG(logERROR) << "Could not close " << (masterFile ? "master" : "data") - << " HDF5 handles of index " << index; - error.printErrorStack(); - } -} - -void HDF5File::WriteDataFile(uint64_t currentFrameNumber, char *buffer) { - std::lock_guard lock(HDF5File::hdf5Lib); - - uint64_t nDimx = - ((*maxFramesPerFile == 0) ? currentFrameNumber - : currentFrameNumber % (*maxFramesPerFile)); - uint32_t nDimy = nPixelsY; - uint32_t nDimz = ((*dynamicRange == 4) ? (nPixelsX / 2) : nPixelsX); - - hsize_t count[3] = {1, nDimy, nDimz}; - hsize_t start[3] = {nDimx, 0, 0}; - hsize_t dims2[2] = {nDimy, nDimz}; - try { - Exception::dontPrint(); // to handle errors - - dataspace->selectHyperslab(H5S_SELECT_SET, count, start); - DataSpace memspace(2, dims2); - dataset->write(buffer, datatype, memspace, *dataspace); - memspace.close(); - } catch (const Exception &error) { - LOG(logERROR) << "Could not write to file in object " << index; - error.printErrorStack(); - throw sls::RuntimeError("Could not write to file in object " + - std::to_string(index)); - } -} - -void HDF5File::WriteParameterDatasets(uint64_t currentFrameNumber, - sls_receiver_header *rheader) { - std::lock_guard lock(HDF5File::hdf5Lib); - - uint64_t fnum = - ((*maxFramesPerFile == 0) ? currentFrameNumber - : currentFrameNumber % (*maxFramesPerFile)); - - sls_detector_header header = rheader->detHeader; - hsize_t count[1] = {1}; - hsize_t start[1] = {fnum}; - int i = 0; - try { - Exception::dontPrint(); // to handle errors - dataspace_para->selectHyperslab(H5S_SELECT_SET, count, start); - DataSpace memspace(H5S_SCALAR); - dataset_para[0]->write(&header.frameNumber, parameterDataTypes[0], - memspace, *dataspace_para); - i = 1; - dataset_para[1]->write(&header.expLength, parameterDataTypes[1], - memspace, *dataspace_para); - i = 2; - dataset_para[2]->write(&header.packetNumber, parameterDataTypes[2], - memspace, *dataspace_para); - i = 3; - dataset_para[3]->write(&header.bunchId, parameterDataTypes[3], memspace, - *dataspace_para); - i = 4; - dataset_para[4]->write(&header.timestamp, parameterDataTypes[4], - memspace, *dataspace_para); - i = 5; - dataset_para[5]->write(&header.modId, parameterDataTypes[5], memspace, - *dataspace_para); - i = 6; - dataset_para[6]->write(&header.row, parameterDataTypes[6], memspace, - *dataspace_para); - i = 7; - dataset_para[7]->write(&header.column, parameterDataTypes[7], memspace, - *dataspace_para); - i = 8; - dataset_para[8]->write(&header.reserved, parameterDataTypes[8], - memspace, *dataspace_para); - i = 9; - dataset_para[9]->write(&header.debug, parameterDataTypes[9], memspace, - *dataspace_para); - i = 10; - dataset_para[10]->write(&header.roundRNumber, parameterDataTypes[10], - memspace, *dataspace_para); - i = 11; - dataset_para[11]->write(&header.detType, parameterDataTypes[11], - memspace, *dataspace_para); - i = 12; - dataset_para[12]->write(&header.version, parameterDataTypes[12], - memspace, *dataspace_para); - i = 13; - - // contiguous bitset - if (sizeof(sls_bitset) == sizeof(bitset_storage)) { - dataset_para[13]->write((char *)&(rheader->packetsMask), - parameterDataTypes[13], memspace, - *dataspace_para); - } - - // not contiguous bitset - else { - // get contiguous representation of bit mask - bitset_storage storage; - memset(storage, 0, sizeof(bitset_storage)); - sls_bitset bits = rheader->packetsMask; - for (int i = 0; i < MAX_NUM_PACKETS; ++i) - storage[i >> 3] |= (bits[i] << (i & 7)); - // write bitmask - dataset_para[13]->write((char *)storage, parameterDataTypes[13], - memspace, *dataspace_para); - } - i = 14; - } catch (const Exception &error) { - error.printErrorStack(); - throw sls::RuntimeError( - "Could not write parameters (index:" + std::to_string(i) + - ") to file in object " + std::to_string(index)); - } -} - -void HDF5File::ExtendDataset() { - std::lock_guard lock(HDF5File::hdf5Lib); - - try { - Exception::dontPrint(); // to handle errors - - hsize_t dims[3]; - dataspace->getSimpleExtentDims(dims); - dims[0] += *numImages; - - dataset->extend(dims); - delete dataspace; - dataspace = nullptr; - dataspace = new DataSpace(dataset->getSpace()); - - hsize_t dims_para[1] = {dims[0]}; - for (unsigned int i = 0; i < dataset_para.size(); ++i) - dataset_para[i]->extend(dims_para); - delete dataspace_para; - dataspace_para = nullptr; - dataspace_para = new DataSpace(dataset_para[0]->getSpace()); - - } catch (const Exception &error) { - error.printErrorStack(); - throw sls::RuntimeError("Could not extend dataset in object " + - std::to_string(index)); - } - if (!(*silentMode)) { - LOG(logINFO) << index << " Extending HDF5 dataset by " << extNumImages - << ", Total x Dimension: " << (extNumImages + *numImages); - } - extNumImages += *numImages; -} - -void HDF5File::CreateDataFile() { - - std::ostringstream os; - os << *filePath << "/" << *fileNamePrefix << "_d" - << (*detIndex * (*numUnitsPerDetector) + index) << "_f" << subFileIndex - << '_' << *fileIndex << ".h5"; - currentFileName = os.str(); - - std::lock_guard lock(HDF5File::hdf5Lib); - - uint64_t framestosave = - ((*maxFramesPerFile == 0) ? *numImages : // infinite images - (((extNumImages - subFileIndex) > (*maxFramesPerFile)) - ? // save up to maximum at a time - (*maxFramesPerFile) - : (extNumImages - subFileIndex))); - - uint64_t nDimx = framestosave; - uint32_t nDimy = nPixelsY; - uint32_t nDimz = ((*dynamicRange == 4) ? (nPixelsX / 2) : nPixelsX); - - try { - Exception::dontPrint(); // to handle errors - - // file - FileAccPropList fapl; - fapl.setFcloseDegree(H5F_CLOSE_STRONG); - filefd = nullptr; - if (!(*overWriteEnable)) - filefd = new H5File(currentFileName.c_str(), H5F_ACC_EXCL, - FileCreatPropList::DEFAULT, fapl); - else - filefd = new H5File(currentFileName.c_str(), H5F_ACC_TRUNC, - FileCreatPropList::DEFAULT, fapl); - - // attributes - version - double dValue = HDF5_WRITER_VERSION; - DataSpace dataspace_attr = DataSpace(H5S_SCALAR); - Attribute attribute = filefd->createAttribute( - "version", PredType::NATIVE_DOUBLE, dataspace_attr); - attribute.write(PredType::NATIVE_DOUBLE, &dValue); - - // dataspace - hsize_t srcdims[3] = {nDimx, nDimy, nDimz}; - hsize_t srcdimsmax[3] = {H5S_UNLIMITED, nDimy, nDimz}; - dataspace = nullptr; - dataspace = new DataSpace(3, srcdims, srcdimsmax); - - // dataset name - std::ostringstream osfn; - osfn << "/data"; - if (*numImages > 1) - osfn << "_f" << std::setfill('0') << std::setw(12) << subFileIndex; - std::string dsetname = osfn.str(); - - // dataset - // fill value - DSetCreatPropList plist; - int fill_value = -1; - plist.setFillValue(datatype, &fill_value); - // always create chunked dataset as unlimited is only - // supported with chunked layout - hsize_t chunk_dims[3] = {MAX_CHUNKED_IMAGES, nDimy, nDimz}; - plist.setChunk(3, chunk_dims); - dataset = nullptr; - dataset = new DataSet(filefd->createDataSet(dsetname.c_str(), datatype, - *dataspace, plist)); - - // create parameter datasets - hsize_t dims[1] = {nDimx}; - hsize_t dimsmax[1] = {H5S_UNLIMITED}; - dataspace_para = nullptr; - dataspace_para = new DataSpace(1, dims, dimsmax); - - // always create chunked dataset as unlimited is only - // supported with chunked layout - DSetCreatPropList paralist; - hsize_t chunkpara_dims[3] = {MAX_CHUNKED_IMAGES}; - paralist.setChunk(1, chunkpara_dims); - - for (unsigned int i = 0; i < parameterNames.size(); ++i) { - DataSet *ds = new DataSet(filefd->createDataSet( - parameterNames[i].c_str(), parameterDataTypes[i], - *dataspace_para, paralist)); - dataset_para.push_back(ds); - } - } catch (const Exception &error) { - error.printErrorStack(); - if (filefd) { - filefd->close(); - } - throw sls::RuntimeError("Could not create HDF5 handles in object " + - index); - } - if (!(*silentMode)) { - LOG(logINFO) << *udpPortNumber - << ": HDF5 File created: " << currentFileName; - } -} - -void HDF5File::CreateMasterDataFile(MasterAttributes *attr) { - - std::ostringstream os; - os << *filePath << "/" << *fileNamePrefix << "_master" - << "_" << *fileIndex << ".h5"; - masterFileName = os.str(); - - if (!(*silentMode)) { - LOG(logINFO) << "Master File: " << masterFileName; - } - - std::lock_guard lock(HDF5File::hdf5Lib); - - try { - Exception::dontPrint(); // to handle errors - - FileAccPropList flist; - flist.setFcloseDegree(H5F_CLOSE_STRONG); - masterfd = nullptr; - if (!(*overWriteEnable)) - masterfd = new H5File(masterFileName.c_str(), H5F_ACC_EXCL, - FileCreatPropList::DEFAULT, flist); - else - masterfd = new H5File(masterFileName.c_str(), H5F_ACC_TRUNC, - FileCreatPropList::DEFAULT, flist); - - // Create a group in the file - Group group1(masterfd->createGroup("entry")); - Group group2(group1.createGroup("data")); - Group group3(group1.createGroup("instrument")); - Group group4(group3.createGroup("beam")); - Group group5(group3.createGroup("detector")); - Group group6(group1.createGroup("sample")); - - attr->WriteMasterHDF5Attributes(masterfd, &group5); - masterfd->close(); - - } catch (const Exception &error) { - error.printErrorStack(); - if (masterfd) { - masterfd->close(); - } - throw sls::RuntimeError("Could not create master HDF5 handles"); - } -} - -void HDF5File::CreateVirtualDataFile(uint32_t maxFramesPerFile, uint64_t numf) { - - std::ostringstream osfn; - osfn << *filePath << "/" << *fileNamePrefix; - osfn << "_virtual"; - osfn << "_" << *fileIndex; - osfn << ".h5"; - std::string vname = osfn.str(); - - if (!(*silentMode)) { - LOG(logINFO) << "Virtual File: " << vname; - } - - int numDetz = numDetX; - uint32_t nDimy = nPixelsY; - uint32_t nDimz = ((*dynamicRange == 4) ? (nPixelsX / 2) : nPixelsX); - - std::lock_guard lock(HDF5File::hdf5Lib); - - try { - // file - hid_t dfal = H5Pcreate(H5P_FILE_ACCESS); - if (dfal < 0) - throw sls::RuntimeError( - "Could not create file access property for virtual file " + - vname); - if (H5Pset_fclose_degree(dfal, H5F_CLOSE_STRONG) < 0) - throw sls::RuntimeError( - "Could not set strong file close degree for virtual file " + - vname); - virtualfd = H5Fcreate(vname.c_str(), H5F_ACC_TRUNC, H5P_DEFAULT, dfal); - if (virtualfd < 0) - throw sls::RuntimeError("Could not create virtual file " + vname); - - // attributes - version - hid_t dataspace_attr = H5Screate(H5S_SCALAR); - if (dataspace_attr < 0) - throw sls::RuntimeError( - "Could not create dataspace for attribute in virtual file " + - vname); - hid_t attrid = H5Acreate2(virtualfd, "version", H5T_NATIVE_DOUBLE, - dataspace_attr, H5P_DEFAULT, H5P_DEFAULT); - if (attrid < 0) - throw sls::RuntimeError( - "Could not create attribute in virtual file " + vname); - double attr_data = HDF5_WRITER_VERSION; - if (H5Awrite(attrid, H5T_NATIVE_DOUBLE, &attr_data) < 0) - throw sls::RuntimeError( - "Could not write attribute in virtual file " + vname); - if (H5Aclose(attrid) < 0) - throw sls::RuntimeError( - "Could not close attribute in virtual file " + vname); - - // virtual dataspace - hsize_t vdsdims[3] = {numf, numDetY * nDimy, numDetz * nDimz}; - hid_t vdsDataspace = H5Screate_simple(3, vdsdims, nullptr); - if (vdsDataspace < 0) - throw sls::RuntimeError( - "Could not create virtual dataspace in virtual file " + vname); - hsize_t vdsdims_para[2] = {numf, (unsigned int)numDetY * numDetz}; - hid_t vdsDataspace_para = H5Screate_simple(2, vdsdims_para, nullptr); - if (vdsDataspace_para < 0) - throw sls::RuntimeError("Could not create virtual dataspace " - "(parameters) in virtual file " + - vname); - - // fill values - hid_t dcpl = H5Pcreate(H5P_DATASET_CREATE); - if (dcpl < 0) - throw sls::RuntimeError( - "Could not create file creation properties in virtual file " + - vname); - int fill_value = -1; - if (H5Pset_fill_value(dcpl, GetDataTypeinC(datatype), &fill_value) < 0) - throw sls::RuntimeError( - "Could not create fill value in virtual file " + vname); - std::vector dcpl_para(parameterNames.size()); - for (unsigned int i = 0; i < parameterNames.size(); ++i) { - dcpl_para[i] = H5Pcreate(H5P_DATASET_CREATE); - if (dcpl_para[i] < 0) - throw sls::RuntimeError( - "Could not create file creation properties (parameters) in " - "virtual file " + - vname); - if (H5Pset_fill_value(dcpl_para[i], - GetDataTypeinC(parameterDataTypes[i]), - &fill_value) < 0) - throw sls::RuntimeError("Could not create fill value " - "(parameters) in virtual file " + - vname); - } - - // hyperslab - int numMajorHyperslab = numf / maxFramesPerFile; - if (numf % maxFramesPerFile) - numMajorHyperslab++; - uint64_t framesSaved = 0; - for (int j = 0; j < numMajorHyperslab; j++) { - - uint64_t nDimx = ((numf - framesSaved) > maxFramesPerFile) - ? maxFramesPerFile - : (numf - framesSaved); - hsize_t offset[3] = {framesSaved, 0, 0}; - hsize_t count[3] = {nDimx, nDimy, nDimz}; - hsize_t offset_para[2] = {framesSaved, 0}; - hsize_t count_para[2] = {nDimx, 1}; - - for (int i = 0; i < numDetY * numDetz; ++i) { - - // setect hyperslabs - if (H5Sselect_hyperslab(vdsDataspace, H5S_SELECT_SET, offset, - nullptr, count, nullptr) < 0) { - throw sls::RuntimeError("Could not select hyperslab"); - } - if (H5Sselect_hyperslab(vdsDataspace_para, H5S_SELECT_SET, - offset_para, nullptr, count_para, - nullptr) < 0) { - throw sls::RuntimeError( - "Could not select hyperslab for parameters"); - } - - // source file name - std::ostringstream os; - os << *filePath << "/" << *fileNamePrefix << "_d" - << (*detIndex * (*numUnitsPerDetector) + i) << "_f" << j - << '_' << *fileIndex << ".h5"; - std::string srcFileName = os.str(); - - LOG(logDEBUG1) << srcFileName; - // find relative path - std::string relative_srcFileName = srcFileName; - { - size_t i = srcFileName.rfind('/', srcFileName.length()); - if (i != std::string::npos) - relative_srcFileName = (srcFileName.substr( - i + 1, srcFileName.length() - i)); - } - - // source dataset name - std::ostringstream osfn; - osfn << "/data"; - if (*numImages > 1) - osfn << "_f" << std::setfill('0') << std::setw(12) << j; - std::string srcDatasetName = osfn.str(); - - // source dataspace - hsize_t srcdims[3] = {nDimx, nDimy, nDimz}; - hsize_t srcdimsmax[3] = {H5S_UNLIMITED, nDimy, nDimz}; - hid_t srcDataspace = H5Screate_simple(3, srcdims, srcdimsmax); - if (srcDataspace < 0) - throw sls::RuntimeError( - "Could not create source dataspace in virtual file " + - vname); - hsize_t srcdims_para[1] = {nDimx}; - hsize_t srcdimsmax_para[1] = {H5S_UNLIMITED}; - hid_t srcDataspace_para = - H5Screate_simple(1, srcdims_para, srcdimsmax_para); - if (srcDataspace_para < 0) - throw sls::RuntimeError("Could not create source dataspace " - "(parameters) in virtual file " + - vname); - - // mapping - if (H5Pset_virtual(dcpl, vdsDataspace, - relative_srcFileName.c_str(), - srcDatasetName.c_str(), srcDataspace) < 0) { - throw sls::RuntimeError( - "Could not set mapping for paramter 1"); - } - - for (unsigned int k = 0; k < parameterNames.size(); ++k) { - if (H5Pset_virtual(dcpl_para[k], vdsDataspace_para, - relative_srcFileName.c_str(), - parameterNames[k].c_str(), - srcDataspace_para) < 0) { - throw sls::RuntimeError( - "Could not set mapping for paramter " + - std::to_string(k)); - } - } - - // H5Sclose(srcDataspace); - // H5Sclose(srcDataspace_para); - offset[2] += nDimz; - if (offset[2] >= (numDetz * nDimz)) { - offset[2] = 0; - offset[1] += nDimy; - } - offset_para[1]++; - } - framesSaved += nDimx; - } - - // dataset - std::string virtualDatasetName = "data"; - hid_t vdsdataset = H5Dcreate2(virtualfd, virtualDatasetName.c_str(), - GetDataTypeinC(datatype), vdsDataspace, - H5P_DEFAULT, dcpl, H5P_DEFAULT); - if (vdsdataset < 0) - throw sls::RuntimeError( - "Could not create virutal dataset in virtual file " + vname); - - // virtual parameter dataset - for (unsigned int i = 0; i < parameterNames.size(); ++i) { - hid_t vdsdataset_para = H5Dcreate2( - virtualfd, parameterNames[i].c_str(), - GetDataTypeinC(parameterDataTypes[i]), vdsDataspace_para, - H5P_DEFAULT, dcpl_para[i], H5P_DEFAULT); - if (vdsdataset_para < 0) - throw sls::RuntimeError("Could not create virutal dataset " - "(parameters) in virtual file " + - vname); - } - - // close - H5Fclose(virtualfd); - virtualfd = 0; - - // link - LinkVirtualInMaster(vname, virtualDatasetName); - } catch (const sls::RuntimeError &e) { - if (virtualfd > 0) - H5Fclose(virtualfd); - virtualfd = 0; - } -} - -void HDF5File::LinkVirtualInMaster(std::string fname, std::string dsetname) { - - if (fname == currentFileName) { - std::lock_guard lock(HDF5File::hdf5Lib); - } - - char linkname[100]; - hid_t vfd = 0; - - try { - hid_t dfal = H5Pcreate(H5P_FILE_ACCESS); - if (dfal < 0) - throw sls::RuntimeError( - "Could not create file access property for link"); - if (H5Pset_fclose_degree(dfal, H5F_CLOSE_STRONG) < 0) - throw sls::RuntimeError( - "Could not set strong file close degree for link"); - - // open master file - hid_t mfd = H5Fopen(masterFileName.c_str(), H5F_ACC_RDWR, dfal); - if (mfd < 0) - throw sls::RuntimeError("Could not open master file"); - - // open virtual file - vfd = H5Fopen(fname.c_str(), H5F_ACC_RDWR, dfal); - if (vfd < 0) { - H5Fclose(mfd); - mfd = 0; - throw sls::RuntimeError("Could not open virtual file"); - } - - // find relative path - std::string relative_virtualfname = fname; - { - size_t i = fname.rfind('/', fname.length()); - if (i != std::string::npos) - relative_virtualfname = - (fname.substr(i + 1, fname.length() - i)); - } - - //**data dataset** - hid_t vdset = H5Dopen2(vfd, dsetname.c_str(), H5P_DEFAULT); - if (vdset < 0) { - H5Fclose(mfd); - throw sls::RuntimeError("Could not open virtual data dataset"); - } - sprintf(linkname, "/entry/data/%s", dsetname.c_str()); - if (H5Lcreate_external(relative_virtualfname.c_str(), dsetname.c_str(), - mfd, linkname, H5P_DEFAULT, H5P_DEFAULT) < 0) { - H5Fclose(mfd); - mfd = 0; - throw sls::RuntimeError("Could not create link to data dataset"); - } - H5Dclose(vdset); - - //**paramter datasets** - for (unsigned int i = 0; i < parameterNames.size(); ++i) { - hid_t vdset_para = H5Dopen2( - vfd, (std::string(parameterNames[i])).c_str(), H5P_DEFAULT); - if (vdset_para < 0) { - H5Fclose(mfd); - mfd = 0; - throw sls::RuntimeError( - "Could not open virtual parameter dataset to create link"); - } - sprintf(linkname, "/entry/data/%s", - (std::string(parameterNames[i])).c_str()); - - if (H5Lcreate_external(relative_virtualfname.c_str(), - parameterNames[i].c_str(), mfd, linkname, - H5P_DEFAULT, H5P_DEFAULT) < 0) { - H5Fclose(mfd); - mfd = 0; - throw sls::RuntimeError( - "Could not create link to virtual parameter dataset"); - } - } - - H5Fclose(mfd); - mfd = 0; - H5Fclose(vfd); - vfd = 0; - } catch (...) { - if (vfd > 0) - H5Fclose(vfd); - vfd = 0; - } -} - -hid_t HDF5File::GetDataTypeinC(DataType dtype) { - if (dtype == PredType::STD_U8LE) - return H5T_STD_U8LE; - else if (dtype == PredType::STD_U16LE) - return H5T_STD_U16LE; - else if (dtype == PredType::STD_U32LE) - return H5T_STD_U32LE; - else if (dtype == PredType::STD_U64LE) - return H5T_STD_U64LE; - else { - hid_t s = H5Tcopy(H5T_C_S1); - H5Tset_size(s, MAX_NUM_PACKETS); - return s; - } -} \ No newline at end of file diff --git a/slsReceiverSoftware/src/HDF5File.h b/slsReceiverSoftware/src/HDF5File.h deleted file mode 100644 index 110f50810..000000000 --- a/slsReceiverSoftware/src/HDF5File.h +++ /dev/null @@ -1,92 +0,0 @@ -#pragma once -/************************************************ - * @file HDF5File.h - * @short sets/gets properties for the HDF5 file, - * creates/closes the file and writes data to it - ***********************************************/ -/** - *@short sets/gets properties for the HDF5 file, creates/closes the file and - *writes data to it - */ - -#include "File.h" - -#include "H5Cpp.h" -#ifndef H5_NO_NAMESPACE -using namespace H5; -#endif -#include - -class HDF5File : private virtual slsDetectorDefs, public File { - - public: - /** - * Constructor - * creates the File Writer - * @param ind self index - * @param maxf pointer to max frames per file - * @param nd pointer to number of detectors in each dimension - * @param fname pointer to file name prefix - * @param fpath pointer to file path - * @param findex pointer to file index - * @param owenable pointer to over write enable - * @param dindex pointer to detector index - * @param nunits pointer to number of theads/ units per detector - * @param nf pointer to number of images in acquisition - * @param dr pointer to dynamic range - * @param portno pointer to udp port number for logging - * @param nx number of pixels in x direction - * @param ny number of pixels in y direction - * @param smode pointer to silent mode - */ - HDF5File(int ind, uint32_t *maxf, int *nd, std::string *fname, - std::string *fpath, uint64_t *findex, bool *owenable, int *dindex, - int *nunits, uint64_t *nf, uint32_t *dr, uint32_t *portno, - uint32_t nx, uint32_t ny, bool *smode); - ~HDF5File(); - void SetNumberofPixels(uint32_t nx, uint32_t ny); - void CreateFile(); - void CloseCurrentFile(); - void CloseAllFiles(); - void WriteToFile(char *buffer, int bufferSize, uint64_t currentFrameNumber, - uint32_t numPacketsCaught); - void CreateMasterFile(bool masterFileWriteEnable, - MasterAttributes *attr) override; - void EndofAcquisition(bool anyPacketsCaught, uint64_t numImagesCaught); - - private: - void CloseFile(H5File *&fd, bool masterFile); - void WriteDataFile(uint64_t currentFrameNumber, char *buffer); - void WriteParameterDatasets(uint64_t currentFrameNumber, - sls_receiver_header *rheader); - void ExtendDataset(); - void CreateDataFile(); - void CreateMasterDataFile(MasterAttributes *attr); - void CreateVirtualDataFile(uint32_t maxFramesPerFile, uint64_t numf); - void LinkVirtualInMaster(std::string fname, std::string dsetname); - hid_t GetDataTypeinC(DataType dtype); - - static std::mutex hdf5Lib; - - H5File *masterfd; - /** Virtual File handle ( only file name because - code in C as H5Pset_virtual doesnt exist yet in C++) */ - hid_t virtualfd; - H5File *filefd; - DataSpace *dataspace; - DataSet *dataset; - DataType datatype; - - uint32_t nPixelsX; - uint32_t nPixelsY; - uint32_t numFramesInFile; - uint64_t numActualPacketsInFile; - int numFilesinAcquisition; - - std::vector parameterNames; - std::vector parameterDataTypes; - DataSpace *dataspace_para; - std::vector dataset_para; - - uint64_t extNumImages; -}; diff --git a/slsReceiverSoftware/src/HDF5MasterFile.cpp b/slsReceiverSoftware/src/HDF5MasterFile.cpp new file mode 100644 index 000000000..27eaeb245 --- /dev/null +++ b/slsReceiverSoftware/src/HDF5MasterFile.cpp @@ -0,0 +1,132 @@ +#include "HDF5MasterFile.h" +#include "MasterAttributes.h" + +HDF5MasterFile::HDF5MasterFile(std::mutex *hdf5Lib) + : File(HDF5), hdf5Lib_(hdf5Lib) {} + +HDF5MasterFile::~HDF5MasterFile() { CloseFile(); } + +void HDF5MasterFile::CloseFile() { + std::lock_guard lock(*hdf5Lib_); + try { + Exception::dontPrint(); // to handle errors + if (fd_) { + fd_->close(); + delete fd_; + fd_ = nullptr; + } + } catch (const Exception &error) { + LOG(logERROR) << "Could not close master HDF5 handles"; + error.printErrorStack(); + } +} + +void HDF5MasterFile::LinkDataFile(std::string dataFilename, + std::string dataSetname, + const std::vector parameterNames, + const bool silentMode) { + + std::lock_guard lock(*hdf5Lib_); + try { + Exception::dontPrint(); // to handle errors + + FileAccPropList flist; + flist.setFcloseDegree(H5F_CLOSE_STRONG); + + // open master file + H5File masterfd(fileName_.c_str(), H5F_ACC_RDWR, + FileCreatPropList::DEFAULT, flist); + + // open data file + H5File fd(dataFilename.c_str(), H5F_ACC_RDONLY, + FileCreatPropList::DEFAULT, flist); + + // create link for data dataset + DataSet dset = fd.openDataSet(dataSetname.c_str()); + std::string linkname = std::string("/entry/data/") + dataSetname; + if (H5Lcreate_external(dataFilename.c_str(), dataSetname.c_str(), + masterfd.getLocId(), linkname.c_str(), + H5P_DEFAULT, H5P_DEFAULT) < 0) { + throw sls::RuntimeError( + "Could not create link to data dataset in master"); + } + + // create link for parameter datasets + for (unsigned int i = 0; i < parameterNames.size(); ++i) { + DataSet pDset = fd.openDataSet(parameterNames[i].c_str()); + linkname = std::string("/entry/data/") + parameterNames[i]; + if (H5Lcreate_external(dataFilename.c_str(), + parameterNames[i].c_str(), + masterfd.getLocId(), linkname.c_str(), + H5P_DEFAULT, H5P_DEFAULT) < 0) { + throw sls::RuntimeError( + "Could not create link to parameter dataset in master"); + } + } + fd.close(); + masterfd.close(); + } catch (const Exception &error) { + error.printErrorStack(); + CloseFile(); + throw sls::RuntimeError("Could not link in master hdf5 file"); + } + if (!silentMode) { + LOG(logINFO) << "Linked in Master File: " << dataFilename; + } +} + +void HDF5MasterFile::CreateMasterFile(const std::string filePath, + const std::string fileNamePrefix, + const uint64_t fileIndex, + const bool overWriteEnable, + const bool silentMode, + MasterAttributes *attr) { + + std::ostringstream os; + os << filePath << "/" << fileNamePrefix << "_master" + << "_" << fileIndex << ".h5"; + fileName_ = os.str(); + + std::lock_guard lock(*hdf5Lib_); + + try { + Exception::dontPrint(); // to handle errors + + FileAccPropList flist; + flist.setFcloseDegree(H5F_CLOSE_STRONG); + fd_ = nullptr; + if (!(overWriteEnable)) + fd_ = new H5File(fileName_.c_str(), H5F_ACC_EXCL, + FileCreatPropList::DEFAULT, flist); + else + fd_ = new H5File(fileName_.c_str(), H5F_ACC_TRUNC, + FileCreatPropList::DEFAULT, flist); + + // attributes - version + double dValue = HDF5_WRITER_VERSION; + DataSpace dataspace_attr = DataSpace(H5S_SCALAR); + Attribute attribute = fd_->createAttribute( + "version", PredType::NATIVE_DOUBLE, dataspace_attr); + attribute.write(PredType::NATIVE_DOUBLE, &dValue); + + // Create a group in the file + Group group1(fd_->createGroup("entry")); + Group group2(group1.createGroup("data")); + Group group3(group1.createGroup("instrument")); + Group group4(group3.createGroup("beam")); + Group group5(group3.createGroup("detector")); + Group group6(group1.createGroup("sample")); + + attr->WriteMasterHDF5Attributes(fd_, &group5); + fd_->close(); + + } catch (const Exception &error) { + error.printErrorStack(); + CloseFile(); + throw sls::RuntimeError( + "Could not create/overwrite master HDF5 handles"); + } + if (!silentMode) { + LOG(logINFO) << "Master File: " << fileName_; + } +} \ No newline at end of file diff --git a/slsReceiverSoftware/src/HDF5MasterFile.h b/slsReceiverSoftware/src/HDF5MasterFile.h new file mode 100644 index 000000000..344e1ec6f --- /dev/null +++ b/slsReceiverSoftware/src/HDF5MasterFile.h @@ -0,0 +1,27 @@ +#pragma once + +#include "File.h" + +#include + +class HDF5MasterFile : private virtual slsDetectorDefs, public File { + + public: + HDF5MasterFile(std::mutex *hdf5Lib); + ~HDF5MasterFile(); + + void CloseFile() override; + void LinkDataFile(std::string dataFilename, std::string dataSetname, + const std::vector parameterNames, + const bool silentMode) override; + void CreateMasterFile(const std::string filePath, + const std::string fileNamePrefix, + const uint64_t fileIndex, const bool overWriteEnable, + const bool silentMode, + MasterAttributes *attr) override; + + private: + std::mutex *hdf5Lib_; + H5File *fd_{nullptr}; + std::string fileName_; +}; \ No newline at end of file diff --git a/slsReceiverSoftware/src/HDF5VirtualFile.cpp b/slsReceiverSoftware/src/HDF5VirtualFile.cpp new file mode 100644 index 000000000..9a988e275 --- /dev/null +++ b/slsReceiverSoftware/src/HDF5VirtualFile.cpp @@ -0,0 +1,197 @@ +#include "HDF5VirtualFile.h" +#include "receiver_defs.h" + +#include + +HDF5VirtualFile::HDF5VirtualFile(std::mutex *hdf5Lib) + : File(HDF5), hdf5Lib_(hdf5Lib) {} + +HDF5VirtualFile::~HDF5VirtualFile() { CloseFile(); } + +std::array HDF5VirtualFile::GetFileAndDatasetName() const { + return std::array{fileName_, dataSetName_}; +} + +void HDF5VirtualFile::CloseFile() { + std::lock_guard lock(*hdf5Lib_); + try { + Exception::dontPrint(); // to handle errors + if (fd_) { + fd_->close(); + delete fd_; + fd_ = nullptr; + } + } catch (const Exception &error) { + LOG(logERROR) << "Could not close virtual HDF5 handles of index"; + error.printErrorStack(); + } +} + +void HDF5VirtualFile::CreateVirtualFile( + const std::string filePath, const std::string fileNamePrefix, + const uint64_t fileIndex, const bool overWriteEnable, const bool silentMode, + const int modulePos, const int numUnitsPerReadout, + const uint32_t maxFramesPerFile, const uint64_t numImages, + const uint32_t nPixelsX, const uint32_t nPixelsY, + const uint32_t dynamicRange, const uint64_t numImagesCaught, + const int numModX, const int numModY, const DataType dataType, + const std::vector parameterNames, + const std::vector parameterDataTypes) { + // virtual file name + std::ostringstream osfn; + osfn << filePath << "/" << fileNamePrefix << "_virtual" + << "_" << fileIndex << ".h5"; + fileName_ = osfn.str(); + + unsigned int paraSize = parameterNames.size(); + uint64_t numModZ = numModX; + uint32_t nDimy = nPixelsY; + uint32_t nDimz = ((dynamicRange == 4) ? (nPixelsX / 2) : nPixelsX); + + std::lock_guard lock(*hdf5Lib_); + + try { + Exception::dontPrint(); // to handle errors + + // file + FileAccPropList fapl; + fapl.setFcloseDegree(H5F_CLOSE_STRONG); + fd_ = nullptr; + if (!overWriteEnable) + fd_ = new H5File(fileName_.c_str(), H5F_ACC_EXCL, + FileCreatPropList::DEFAULT, fapl); + else + fd_ = new H5File(fileName_.c_str(), H5F_ACC_TRUNC, + FileCreatPropList::DEFAULT, fapl); + + // attributes - version + double dValue = HDF5_WRITER_VERSION; + DataSpace dataspace_attr = DataSpace(H5S_SCALAR); + Attribute attribute = fd_->createAttribute( + "version", PredType::NATIVE_DOUBLE, dataspace_attr); + attribute.write(PredType::NATIVE_DOUBLE, &dValue); + + // virtual data dataspace + hsize_t vdsDims[3] = {numImagesCaught, numModY * nDimy, + numModZ * nDimz}; + DataSpace vdsDataSpace(3, vdsDims, nullptr); + + // virtual parameter dataspace + hsize_t vdsDimsPara[2] = {numImagesCaught, + (unsigned int)numModY * numModZ}; + DataSpace vdsDataSpacePara(2, vdsDimsPara, nullptr); + + // property list (fill value and datatype) + int fill_value = -1; + DSetCreatPropList plist; + plist.setFillValue(dataType, &fill_value); + + // property list for parameters (datatype) + std::vector plistPara(paraSize); + + // hyperslab + int numMajorHyperslab = numImagesCaught / maxFramesPerFile; + if (numImagesCaught % maxFramesPerFile) + ++numMajorHyperslab; + uint64_t framesSaved = 0; + // loop through files + for (int hyperSlab = 0; hyperSlab < numMajorHyperslab; ++hyperSlab) { + + uint64_t nDimx = + ((numImagesCaught - framesSaved) > maxFramesPerFile) + ? maxFramesPerFile + : (numImagesCaught - framesSaved); + hsize_t start[3] = {framesSaved, 0, 0}; + hsize_t count[3] = {nDimx, nDimy, nDimz}; + hsize_t startPara[2] = {framesSaved, 0}; + hsize_t countPara[2] = {nDimx, 1}; + // loop through readouts + for (unsigned int i = 0; i < numModY * numModZ; ++i) { + + // setect data hyperslabs + vdsDataSpace.selectHyperslab(H5S_SELECT_SET, count, start); + + // select parameter hyperslabs + vdsDataSpacePara.selectHyperslab(H5S_SELECT_SET, countPara, + startPara); + + // source file name + std::ostringstream os; + os << filePath << "/" << fileNamePrefix << "_d" + << (modulePos * numUnitsPerReadout + i) << "_f" << hyperSlab + << '_' << fileIndex << ".h5"; + std::string srcFileName = os.str(); + LOG(logDEBUG1) << srcFileName; + + // find relative path + std::string relative_srcFileName = srcFileName; + { + size_t p = srcFileName.rfind('/', srcFileName.length()); + if (p != std::string::npos) + relative_srcFileName = (srcFileName.substr( + p + 1, srcFileName.length() - p)); + } + + // source dataset name + std::ostringstream osfn; + osfn << "/data"; + if (numImages > 1) + osfn << "_f" << std::setfill('0') << std::setw(12) + << hyperSlab; + std::string srcDatasetName = osfn.str(); + + // source data dataspace + hsize_t srcDims[3] = {nDimx, nDimy, nDimz}; + hsize_t srcDimsMax[3] = {H5S_UNLIMITED, nDimy, nDimz}; + DataSpace srcDataSpace(3, srcDims, srcDimsMax); + + // source parameter dataspace + hsize_t srcDimsPara[1] = {nDimx}; + hsize_t srcDimsMaxPara[1] = {H5S_UNLIMITED}; + DataSpace srcDataSpacePara(1, srcDimsPara, srcDimsMaxPara); + + // mapping of data property list + plist.setVirtual(vdsDataSpace, relative_srcFileName.c_str(), + srcDatasetName.c_str(), srcDataSpace); + + // mapping of parameter property list + for (unsigned int p = 0; p < paraSize; ++p) { + plistPara[p].setVirtual( + vdsDataSpacePara, relative_srcFileName.c_str(), + parameterNames[p].c_str(), srcDataSpacePara); + } + + // H5Sclose(srcDataspace); + // H5Sclose(srcDataspace_para); + start[2] += nDimz; + if (start[2] >= (numModZ * nDimz)) { + start[2] = 0; + start[1] += nDimy; + } + startPara[1]++; + } + framesSaved += nDimx; + } + // data dataset + dataSetName_ = "data"; + DataSet vdsDataSet(fd_->createDataSet(dataSetName_.c_str(), dataType, + vdsDataSpace, plist)); + + // parameter dataset + for (unsigned int p = 0; p < paraSize; ++p) { + DataSet vdsDataSetPara(fd_->createDataSet( + parameterNames[p].c_str(), parameterDataTypes[p], + vdsDataSpacePara, plistPara[p])); + } + + fd_->close(); + } catch (const Exception &error) { + error.printErrorStack(); + CloseFile(); + throw sls::RuntimeError( + "Could not create/overwrite virtual HDF5 handles"); + } + if (!silentMode) { + LOG(logINFO) << "Virtual File: " << fileName_; + } +} \ No newline at end of file diff --git a/slsReceiverSoftware/src/HDF5VirtualFile.h b/slsReceiverSoftware/src/HDF5VirtualFile.h new file mode 100644 index 000000000..1ab64094e --- /dev/null +++ b/slsReceiverSoftware/src/HDF5VirtualFile.h @@ -0,0 +1,31 @@ +#pragma once + +#include "File.h" + +#include + +class HDF5VirtualFile : private virtual slsDetectorDefs, public File { + + public: + HDF5VirtualFile(std::mutex *hdf5Lib); + ~HDF5VirtualFile(); + + std::array GetFileAndDatasetName() const override; + void CloseFile() override; + void CreateVirtualFile( + const std::string filePath, const std::string fileNamePrefix, + const uint64_t fileIndex, const bool overWriteEnable, + const bool silentMode, const int modulePos, + const int numUnitsPerReadout, const uint32_t maxFramesPerFile, + const uint64_t numImages, const uint32_t nPixelsX, + const uint32_t nPixelsY, const uint32_t dynamicRange, + const uint64_t numImagesCaught, const int numModX, const int numModY, + const DataType dataType, const std::vector parameterNames, + const std::vector parameterDataTypes) override; + + private: + std::mutex *hdf5Lib_; + H5File *fd_{nullptr}; + std::string fileName_; + std::string dataSetName_; +}; \ No newline at end of file diff --git a/slsReceiverSoftware/src/Implementation.cpp b/slsReceiverSoftware/src/Implementation.cpp index 8c956eadd..1a8bdbefc 100644 --- a/slsReceiverSoftware/src/Implementation.cpp +++ b/slsReceiverSoftware/src/Implementation.cpp @@ -65,7 +65,7 @@ void Implementation::SetupFifoStructure() { for (int i = 0; i < numThreads; ++i) { uint32_t datasize = generalData->imageSize; // veto data size - if (myDetectorType == GOTTHARD2 && i != 0) { + if (detType == GOTTHARD2 && i != 0) { datasize = generalData->vetoImageSize; } @@ -105,8 +105,8 @@ void Implementation::SetupFifoStructure() { * ************************************************/ void Implementation::setDetectorType(const detectorType d) { - myDetectorType = d; - switch (myDetectorType) { + detType = d; + switch (detType) { case GOTTHARD: case EIGER: case JUNGFRAU: @@ -125,7 +125,7 @@ void Implementation::setDetectorType(const detectorType d) { generalData = nullptr; // set detector specific variables - switch (myDetectorType) { + switch (detType) { case GOTTHARD: generalData = new GotthardData(); break; @@ -164,16 +164,15 @@ void Implementation::setDetectorType(const detectorType d) { try { auto fifo_ptr = fifo[i].get(); listener.push_back(sls::make_unique( - i, myDetectorType, fifo_ptr, &status, &udpPortNum[i], ð[i], + i, detType, fifo_ptr, &status, &udpPortNum[i], ð[i], &numberOfTotalFrames, &udpSocketBufferSize, &actualUDPSocketBufferSize, &framesPerFile, &frameDiscardMode, - &activated, &deactivatedPaddingEnable, &silentMode)); + &activated, &detectorDataStream[i], &deactivatedPaddingEnable, &silentMode)); dataProcessor.push_back(sls::make_unique( - i, myDetectorType, fifo_ptr, &fileFormatType, fileWriteEnable, - &masterFileWriteEnable, &dataStreamEnable, &streamingFrequency, - &streamingTimerInMs, &streamingStartFnum, &framePadding, - &activated, &deactivatedPaddingEnable, &silentMode, - &ctbDbitList, &ctbDbitOffset, &ctbAnalogDataBytes)); + i, detType, fifo_ptr, &activated, &deactivatedPaddingEnable, + &dataStreamEnable, &streamingFrequency, &streamingTimerInMs, + &streamingStartFnum, &framePadding, &ctbDbitList, + &ctbDbitOffset, &ctbAnalogDataBytes, &hdf5Lib)); } catch (...) { listener.clear(); dataProcessor.clear(); @@ -193,32 +192,32 @@ void Implementation::setDetectorType(const detectorType d) { LOG(logDEBUG) << " Detector type set to " << sls::ToString(d); } -int *Implementation::getDetectorSize() const { return (int *)numDet; } +int *Implementation::getDetectorSize() const { return (int *)numMods; } void Implementation::setDetectorSize(const int *size) { std::string log_message = "Detector Size (ports): ("; for (int i = 0; i < MAX_DIMENSIONS; ++i) { // x dir (colums) each udp port - if (myDetectorType == EIGER && i == X) - numDet[i] = size[i] * 2; + if (detType == EIGER && i == X) + numMods[i] = size[i] * 2; // y dir (rows) each udp port else if (numUDPInterfaces == 2 && i == Y) - numDet[i] = size[i] * 2; + numMods[i] = size[i] * 2; else - numDet[i] = size[i]; - log_message += std::to_string(numDet[i]); + numMods[i] = size[i]; + log_message += std::to_string(numMods[i]); if (i < MAX_DIMENSIONS - 1) log_message += ", "; } log_message += ")"; - int nd[2] = {numDet[0], numDet[1]}; + int nm[2] = {numMods[0], numMods[1]}; if (quadEnable) { - nd[0] = 1; - nd[1] = 2; + nm[0] = 1; + nm[1] = 2; } for (const auto &it : dataStreamer) { - it->SetNumberofDetectors(nd); + it->SetNumberofModules(nm); } LOG(logINFO) << log_message; @@ -232,20 +231,17 @@ void Implementation::setModulePositionId(const int id) { // update zmq port streamingPort = - DEFAULT_ZMQ_RX_PORTNO + (modulePos * (myDetectorType == EIGER ? 2 : 1)); + DEFAULT_ZMQ_RX_PORTNO + (modulePos * (detType == EIGER ? 2 : 1)); - for (unsigned int i = 0; i < dataProcessor.size(); ++i) { - dataProcessor[i]->SetupFileWriter( - fileWriteEnable, (int *)numDet, &framesPerFile, &fileName, - &filePath, &fileIndex, &overwriteEnable, &modulePos, &numThreads, - &numberOfTotalFrames, &dynamicRange, &udpPortNum[i], generalData); - } - assert(numDet[1] != 0); + for (const auto &it : dataProcessor) + it->SetupFileWriter(fileWriteEnable, masterFileWriteEnable, + fileFormatType, modulePos); + assert(numMods[1] != 0); for (unsigned int i = 0; i < listener.size(); ++i) { uint16_t row = 0, col = 0; row = - (modulePos % numDet[1]) * ((numUDPInterfaces == 2) ? 2 : 1); // row - col = (modulePos / numDet[1]) * ((myDetectorType == EIGER) ? 2 : 1) + + (modulePos % numMods[1]) * ((numUDPInterfaces == 2) ? 2 : 1); // row + col = (modulePos / numMods[1]) * ((detType == EIGER) ? 2 : 1) + i; // col for horiz. udp ports listener[i]->SetHardCodedPosition(row, col); } @@ -332,20 +328,24 @@ slsDetectorDefs::fileFormat Implementation::getFileFormat() const { } void Implementation::setFileFormat(const fileFormat f) { - switch (f) { + if (f != fileFormatType) { + switch (f) { #ifdef HDF5C - case HDF5: - fileFormatType = HDF5; - break; + case HDF5: + fileFormatType = HDF5; + break; #endif - default: - fileFormatType = BINARY; - break; + case BINARY: + fileFormatType = BINARY; + break; + default: + throw sls::RuntimeError("Unknown file format"); + } + for (const auto &it : dataProcessor) + it->SetupFileWriter(fileWriteEnable, masterFileWriteEnable, + fileFormatType, modulePos); } - for (const auto &it : dataProcessor) - it->SetFileFormat(f); - LOG(logINFO) << "File Format: " << sls::ToString(fileFormatType); } @@ -378,13 +378,9 @@ bool Implementation::getFileWriteEnable() const { return fileWriteEnable; } void Implementation::setFileWriteEnable(const bool b) { if (fileWriteEnable != b) { fileWriteEnable = b; - for (unsigned int i = 0; i < dataProcessor.size(); ++i) { - dataProcessor[i]->SetupFileWriter( - fileWriteEnable, (int *)numDet, &framesPerFile, &fileName, - &filePath, &fileIndex, &overwriteEnable, &modulePos, - &numThreads, &numberOfTotalFrames, &dynamicRange, - &udpPortNum[i], generalData); - } + for (const auto &it : dataProcessor) + it->SetupFileWriter(fileWriteEnable, masterFileWriteEnable, + fileFormatType, modulePos); } LOG(logINFO) << "File Write Enable: " << (fileWriteEnable ? "enabled" : "disabled"); @@ -395,7 +391,12 @@ bool Implementation::getMasterFileWriteEnable() const { } void Implementation::setMasterFileWriteEnable(const bool b) { - masterFileWriteEnable = b; + if (masterFileWriteEnable != b) { + masterFileWriteEnable = b; + for (const auto &it : dataProcessor) + it->SetupFileWriter(fileWriteEnable, masterFileWriteEnable, + fileFormatType, modulePos); + } LOG(logINFO) << "Master File Write Enable: " << (masterFileWriteEnable ? "enabled" : "disabled"); } @@ -554,19 +555,22 @@ void Implementation::stopReceiver() { std::this_thread::sleep_for(std::chrono::milliseconds(5)); } - // create virtual file +#ifdef HDF5C if (fileWriteEnable && fileFormatType == HDF5) { - uint64_t maxIndexCaught = 0; - bool anycaught = false; - for (const auto &it : dataProcessor) { - maxIndexCaught = std::max(maxIndexCaught, it->GetProcessedIndex()); - if (it->GetStartedFlag()) - anycaught = true; + if (modulePos == 0) { + // more than 1 file, create virtual file + if (dataProcessor[0]->GetFilesInAcquisition() > 1 || + (numMods[X] * numMods[Y]) > 1) { + dataProcessor[0]->CreateVirtualFile( + filePath, fileName, fileIndex, overwriteEnable, silentMode, + modulePos, numThreads, framesPerFile, numberOfTotalFrames, + dynamicRange, numMods[X], numMods[Y]); + } + // link file in master + dataProcessor[0]->LinkDataInMasterFile(silentMode); } - // to create virtual file & set files/acquisition to 0 (only hdf5 at the - // moment) - dataProcessor[0]->EndofAcquisition(anycaught, maxIndexCaught); } +#endif // wait for the processes (dataStreamer) to be done running = true; @@ -606,6 +610,12 @@ void Implementation::stopReceiver() { if (!activated) { LOG(logINFORED) << "Deactivated Receiver"; } + if (!detectorDataStream[0]) { + LOG(logINFORED) << "Deactivated Left Port"; + } + if (!detectorDataStream[1]) { + LOG(logINFORED) << "Deactivated Right Port"; + } // callback if (acquisitionFinishedCallBack) { try { @@ -671,20 +681,6 @@ void Implementation::shutDownUDPSockets() { it->ShutDownUDPSocket(); } -void Implementation::closeFiles() { - uint64_t maxIndexCaught = 0; - bool anycaught = false; - for (const auto &it : dataProcessor) { - it->CloseFiles(); - maxIndexCaught = std::max(maxIndexCaught, it->GetProcessedIndex()); - if (it->GetStartedFlag()) - anycaught = true; - } - // to create virtual file & set files/acquisition to 0 (only hdf5 at the - // moment) - dataProcessor[0]->EndofAcquisition(anycaught, maxIndexCaught); -} - void Implementation::restreamStop() { for (const auto &it : dataStreamer) it->RestreamStop(); @@ -719,90 +715,100 @@ void Implementation::CreateUDPSockets() { } void Implementation::SetupWriter() { + // master file std::unique_ptr masterAttributes; - switch (myDetectorType) { - case GOTTHARD: - masterAttributes = sls::make_unique(); - break; - case JUNGFRAU: - masterAttributes = sls::make_unique(); - break; - case EIGER: - masterAttributes = sls::make_unique(); - break; - case MYTHEN3: - masterAttributes = sls::make_unique(); - break; - case GOTTHARD2: - masterAttributes = sls::make_unique(); - break; - case MOENCH: - masterAttributes = sls::make_unique(); - break; - case CHIPTESTBOARD: - masterAttributes = sls::make_unique(); - break; - default: - throw sls::RuntimeError( - "Unknown detector type to set up master file attributes"); + if (masterFileWriteEnable && modulePos == 0) { + switch (detType) { + case GOTTHARD: + masterAttributes = sls::make_unique(); + break; + case JUNGFRAU: + masterAttributes = sls::make_unique(); + break; + case EIGER: + masterAttributes = sls::make_unique(); + break; + case MYTHEN3: + masterAttributes = sls::make_unique(); + break; + case GOTTHARD2: + masterAttributes = sls::make_unique(); + break; + case MOENCH: + masterAttributes = sls::make_unique(); + break; + case CHIPTESTBOARD: + masterAttributes = sls::make_unique(); + break; + default: + throw sls::RuntimeError( + "Unknown detector type to set up master file attributes"); + } + masterAttributes->detType = detType; + masterAttributes->timingMode = timingMode; + masterAttributes->imageSize = generalData->imageSize; + masterAttributes->nPixels = + xy(generalData->nPixelsX, generalData->nPixelsY); + masterAttributes->maxFramesPerFile = framesPerFile; + masterAttributes->frameDiscardMode = frameDiscardMode; + masterAttributes->framePadding = framePadding; + masterAttributes->scanParams = scanParams; + masterAttributes->totalFrames = numberOfTotalFrames; + masterAttributes->exptime = acquisitionTime; + masterAttributes->period = acquisitionPeriod; + masterAttributes->burstMode = burstMode; + masterAttributes->numUDPInterfaces = numUDPInterfaces; + masterAttributes->dynamicRange = dynamicRange; + masterAttributes->tenGiga = tengigaEnable; + masterAttributes->thresholdEnergyeV = thresholdEnergyeV; + masterAttributes->thresholdAllEnergyeV = thresholdAllEnergyeV; + masterAttributes->subExptime = subExpTime; + masterAttributes->subPeriod = subPeriod; + masterAttributes->quad = quadEnable; + masterAttributes->numLinesReadout = numLinesReadout; + masterAttributes->ratecorr = rateCorrections; + masterAttributes->adcmask = + tengigaEnable ? adcEnableMaskTenGiga : adcEnableMaskOneGiga; + masterAttributes->analog = + (readoutType == ANALOG_ONLY || readoutType == ANALOG_AND_DIGITAL) + ? 1 + : 0; + masterAttributes->analogSamples = numberOfAnalogSamples; + masterAttributes->digital = + (readoutType == DIGITAL_ONLY || readoutType == ANALOG_AND_DIGITAL) + ? 1 + : 0; + masterAttributes->digitalSamples = numberOfDigitalSamples; + masterAttributes->dbitoffset = ctbDbitOffset; + masterAttributes->dbitlist = 0; + for (auto &i : ctbDbitList) { + masterAttributes->dbitlist |= (1 << i); + } + masterAttributes->roi = roi; + masterAttributes->counterMask = counterMask; + masterAttributes->exptime1 = acquisitionTime1; + masterAttributes->exptime2 = acquisitionTime2; + masterAttributes->exptime3 = acquisitionTime3; + masterAttributes->gateDelay1 = gateDelay1; + masterAttributes->gateDelay2 = gateDelay2; + masterAttributes->gateDelay3 = gateDelay3; + masterAttributes->gates = numberOfGates; + masterAttributes->additionalJsonHeader = additionalJsonHeader; } - masterAttributes->detType = myDetectorType; - masterAttributes->timingMode = timingMode; - masterAttributes->imageSize = generalData->imageSize; - masterAttributes->nPixels = - xy(generalData->nPixelsX, generalData->nPixelsY); - masterAttributes->maxFramesPerFile = framesPerFile; - masterAttributes->frameDiscardMode = frameDiscardMode; - masterAttributes->framePadding = framePadding; - masterAttributes->scanParams = scanParams; - masterAttributes->totalFrames = numberOfTotalFrames; - masterAttributes->exptime = acquisitionTime; - masterAttributes->period = acquisitionPeriod; - masterAttributes->burstMode = burstMode; - masterAttributes->numUDPInterfaces = numUDPInterfaces; - masterAttributes->dynamicRange = dynamicRange; - masterAttributes->tenGiga = tengigaEnable; - masterAttributes->thresholdEnergyeV = thresholdEnergyeV; - masterAttributes->thresholdAllEnergyeV = thresholdAllEnergyeV; - masterAttributes->subExptime = subExpTime; - masterAttributes->subPeriod = subPeriod; - masterAttributes->quad = quadEnable; - masterAttributes->numLinesReadout = numLinesReadout; - masterAttributes->ratecorr = rateCorrections; - masterAttributes->adcmask = - tengigaEnable ? adcEnableMaskTenGiga : adcEnableMaskOneGiga; - masterAttributes->analog = - (readoutType == ANALOG_ONLY || readoutType == ANALOG_AND_DIGITAL) ? 1 - : 0; - masterAttributes->analogSamples = numberOfAnalogSamples; - masterAttributes->digital = - (readoutType == DIGITAL_ONLY || readoutType == ANALOG_AND_DIGITAL) ? 1 - : 0; - masterAttributes->digitalSamples = numberOfDigitalSamples; - masterAttributes->dbitoffset = ctbDbitOffset; - masterAttributes->dbitlist = 0; - for (auto &i : ctbDbitList) { - masterAttributes->dbitlist |= (1 << i); - } - masterAttributes->roi = roi; - masterAttributes->counterMask = counterMask; - masterAttributes->exptime1 = acquisitionTime1; - masterAttributes->exptime2 = acquisitionTime2; - masterAttributes->exptime3 = acquisitionTime3; - masterAttributes->gateDelay1 = gateDelay1; - masterAttributes->gateDelay2 = gateDelay2; - masterAttributes->gateDelay3 = gateDelay3; - masterAttributes->gates = numberOfGates; - masterAttributes->additionalJsonHeader = additionalJsonHeader; try { for (unsigned int i = 0; i < dataProcessor.size(); ++i) { - dataProcessor[i]->CreateNewFile(masterAttributes.get()); + dataProcessor[i]->CreateFirstFiles( + masterAttributes.get(), filePath, fileName, fileIndex, + overwriteEnable, silentMode, modulePos, numThreads, + udpPortNum[i], framesPerFile, numberOfTotalFrames, + dynamicRange, detectorDataStream[i]); } } catch (const sls::RuntimeError &e) { shutDownUDPSockets(); - closeFiles(); - throw sls::RuntimeError("Could not create file."); + for (const auto &it : dataProcessor) + it->CloseFiles(); + throw sls::RuntimeError("Could not create first data file."); } } @@ -840,7 +846,7 @@ void Implementation::setNumberofUDPInterfaces(const int n) { // reduce number of detectors in y dir (rows) if it had 2 interfaces // before if (numUDPInterfaces == 2) - numDet[Y] /= 2; + numMods[Y] /= 2; numUDPInterfaces = n; @@ -864,20 +870,18 @@ void Implementation::setNumberofUDPInterfaces(const int n) { try { auto fifo_ptr = fifo[i].get(); listener.push_back(sls::make_unique( - i, myDetectorType, fifo_ptr, &status, &udpPortNum[i], - ð[i], &numberOfTotalFrames, &udpSocketBufferSize, + i, detType, fifo_ptr, &status, &udpPortNum[i], ð[i], + &numberOfTotalFrames, &udpSocketBufferSize, &actualUDPSocketBufferSize, &framesPerFile, - &frameDiscardMode, &activated, &deactivatedPaddingEnable, + &frameDiscardMode, &activated, &detectorDataStream[i], &deactivatedPaddingEnable, &silentMode)); listener[i]->SetGeneralData(generalData); dataProcessor.push_back(sls::make_unique( - i, myDetectorType, fifo_ptr, &fileFormatType, - fileWriteEnable, &masterFileWriteEnable, &dataStreamEnable, - &streamingFrequency, &streamingTimerInMs, - &streamingStartFnum, &framePadding, &activated, - &deactivatedPaddingEnable, &silentMode, &ctbDbitList, - &ctbDbitOffset, &ctbAnalogDataBytes)); + i, detType, fifo_ptr, &activated, &deactivatedPaddingEnable, + &dataStreamEnable, &streamingFrequency, &streamingTimerInMs, + &streamingStartFnum, &framePadding, &ctbDbitList, + &ctbDbitOffset, &ctbAnalogDataBytes, &hdf5Lib)); dataProcessor[i]->SetGeneralData(generalData); } catch (...) { listener.clear(); @@ -890,15 +894,15 @@ void Implementation::setNumberofUDPInterfaces(const int n) { if (dataStreamEnable) { try { int fd = flippedDataX; - int nd[2] = {numDet[0], numDet[1]}; + int nm[2] = {numMods[0], numMods[1]}; if (quadEnable) { fd = i; - nd[0] = 1; - nd[1] = 2; + nm[0] = 1; + nm[1] = 2; } dataStreamer.push_back(sls::make_unique( i, fifo[i].get(), &dynamicRange, &roi, &fileIndex, fd, - (int *)nd, &quadEnable, &numberOfTotalFrames)); + (int *)nm, &quadEnable, &numberOfTotalFrames)); dataStreamer[i]->SetGeneralData(generalData); dataStreamer[i]->CreateZmqSockets( &numThreads, streamingPort, streamingSrcIP, @@ -921,7 +925,7 @@ void Implementation::setNumberofUDPInterfaces(const int n) { SetThreadPriorities(); // update (from 1 to 2 interface) & also for printout - setDetectorSize(numDet); + setDetectorSize(numMods); // update row and column in dataprocessor setModulePositionId(modulePos); @@ -981,7 +985,7 @@ void Implementation::setUDPSocketBufferSize(const int s) { // testing default setup at startup, argument is 0 to use default values int size = (s == 0) ? udpSocketBufferSize : s; size_t listSize = listener.size(); - if (myDetectorType == JUNGFRAU && (int)listSize != numUDPInterfaces) { + if (detType == JUNGFRAU && (int)listSize != numUDPInterfaces) { throw sls::RuntimeError( "Number of Interfaces " + std::to_string(numUDPInterfaces) + " do not match listener size " + std::to_string(listSize)); @@ -1019,15 +1023,15 @@ void Implementation::setDataStreamEnable(const bool enable) { for (int i = 0; i < numThreads; ++i) { try { int fd = flippedDataX; - int nd[2] = {numDet[0], numDet[1]}; + int nm[2] = {numMods[0], numMods[1]}; if (quadEnable) { fd = i; - nd[0] = 1; - nd[1] = 2; + nm[0] = 1; + nm[1] = 2; } dataStreamer.push_back(sls::make_unique( i, fifo[i].get(), &dynamicRange, &roi, &fileIndex, fd, - (int *)nd, &quadEnable, &numberOfTotalFrames)); + (int *)nm, &quadEnable, &numberOfTotalFrames)); dataStreamer[i]->SetGeneralData(generalData); dataStreamer[i]->CreateZmqSockets( &numThreads, streamingPort, streamingSrcIP, @@ -1166,7 +1170,7 @@ void Implementation::updateTotalNumberOfFrames() { int64_t repeats = numberOfTriggers; int64_t numFrames = numberOfFrames; // gotthard2 - if (myDetectorType == GOTTHARD2) { + if (detType == GOTTHARD2) { // auto if (timingMode == AUTO_TIMING) { // burst mode, repeats = #bursts @@ -1340,8 +1344,6 @@ void Implementation::setNumberofAnalogSamples(const uint32_t i) { numberOfAnalogSamples, numberOfDigitalSamples, tengigaEnable, readoutType); - for (const auto &it : dataProcessor) - it->SetPixelDimension(); SetupFifoStructure(); } LOG(logINFO) << "Number of Analog Samples: " << numberOfAnalogSamples; @@ -1361,8 +1363,6 @@ void Implementation::setNumberofDigitalSamples(const uint32_t i) { numberOfAnalogSamples, numberOfDigitalSamples, tengigaEnable, readoutType); - for (const auto &it : dataProcessor) - it->SetPixelDimension(); SetupFifoStructure(); } LOG(logINFO) << "Number of Digital Samples: " << numberOfDigitalSamples; @@ -1382,9 +1382,6 @@ void Implementation::setCounterMask(const uint32_t i) { counterMask = i; generalData->SetNumberofCounters(ncounters, dynamicRange, tengigaEnable); - // to update npixelsx, npixelsy in file writer - for (const auto &it : dataProcessor) - it->SetPixelDimension(); SetupFifoStructure(); } LOG(logINFO) << "Counter mask: " << sls::ToStringHex(counterMask); @@ -1398,18 +1395,15 @@ void Implementation::setDynamicRange(const uint32_t i) { if (dynamicRange != i) { dynamicRange = i; - if (myDetectorType == EIGER || myDetectorType == MYTHEN3) { + if (detType == EIGER || detType == MYTHEN3) { - if (myDetectorType == EIGER) { + if (detType == EIGER) { generalData->SetDynamicRange(i, tengigaEnable); } else { int ncounters = __builtin_popcount(counterMask); generalData->SetNumberofCounters(ncounters, i, tengigaEnable); } - // to update npixelsx, npixelsy in file writer - for (const auto &it : dataProcessor) - it->SetPixelDimension(); fifoDepth = generalData->defaultFifoDepth; SetupFifoStructure(); } @@ -1427,8 +1421,6 @@ void Implementation::setROI(slsDetectorDefs::ROI arg) { // only for gotthard generalData->SetROI(arg); framesPerFile = generalData->maxFramesPerFile; - for (const auto &it : dataProcessor) - it->SetPixelDimension(); SetupFifoStructure(); } @@ -1443,7 +1435,7 @@ void Implementation::setTenGigaEnable(const bool b) { tengigaEnable = b; int ncounters = __builtin_popcount(counterMask); // side effects - switch (myDetectorType) { + switch (detType) { case EIGER: generalData->SetTenGigaEnable(b, dynamicRange); break; @@ -1492,13 +1484,13 @@ void Implementation::setQuad(const bool b) { if (!quadEnable) { for (const auto &it : dataStreamer) { - it->SetNumberofDetectors(numDet); + it->SetNumberofModules(numMods); it->SetFlippedDataX(flippedDataX); } } else { int size[2] = {1, 2}; for (const auto &it : dataStreamer) { - it->SetNumberofDetectors(size); + it->SetNumberofModules(size); } if (dataStreamer.size() == 2) { dataStreamer[0]->SetFlippedDataX(0); @@ -1511,10 +1503,22 @@ void Implementation::setQuad(const bool b) { bool Implementation::getActivate() const { return activated; } -bool Implementation::setActivate(bool enable) { +void Implementation::setActivate(bool enable) { activated = enable; LOG(logINFO) << "Activation: " << (activated ? "enabled" : "disabled"); - return activated; +} + +bool Implementation::getDetectorDataStream(const portPosition port) const { + int index = (port == LEFT ? 0 : 1); + return detectorDataStream[index]; +} + +void Implementation::setDetectorDataStream(const portPosition port, + const bool enable) { + int index = (port == LEFT ? 0 : 1); + detectorDataStream[index] = enable; + LOG(logINFO) << "Detector datastream (" << sls::ToString(port) + << " Port): " << sls::ToString(detectorDataStream[index]); } bool Implementation::getDeactivatedPadding() const { @@ -1563,8 +1567,6 @@ void Implementation::setReadoutMode(const readoutMode f) { tengigaEnable ? adcEnableMaskTenGiga : adcEnableMaskOneGiga, numberOfAnalogSamples, numberOfDigitalSamples, tengigaEnable, readoutType); - for (const auto &it : dataProcessor) - it->SetPixelDimension(); SetupFifoStructure(); } LOG(logINFO) << "Readout Mode: " << sls::ToString(f); @@ -1583,8 +1585,6 @@ void Implementation::setADCEnableMask(uint32_t mask) { numberOfAnalogSamples, numberOfDigitalSamples, tengigaEnable, readoutType); - for (const auto &it : dataProcessor) - it->SetPixelDimension(); SetupFifoStructure(); } LOG(logINFO) << "ADC Enable Mask for 1Gb mode: 0x" << std::hex @@ -1605,8 +1605,6 @@ void Implementation::setTenGigaADCEnableMask(uint32_t mask) { numberOfAnalogSamples, numberOfDigitalSamples, tengigaEnable, readoutType); - for (const auto &it : dataProcessor) - it->SetPixelDimension(); SetupFifoStructure(); } LOG(logINFO) << "ADC Enable Mask for 10Gb mode: 0x" << std::hex diff --git a/slsReceiverSoftware/src/Implementation.h b/slsReceiverSoftware/src/Implementation.h index 1a82e1c03..5a1650705 100644 --- a/slsReceiverSoftware/src/Implementation.h +++ b/slsReceiverSoftware/src/Implementation.h @@ -15,6 +15,7 @@ class slsDetectorDefs; #include #include #include +#include #include using ns = std::chrono::nanoseconds; @@ -87,7 +88,6 @@ class Implementation : private virtual slsDetectorDefs { void stopReceiver(); void startReadout(); void shutDownUDPSockets(); - void closeFiles(); void restreamStop(); /************************************************** @@ -210,7 +210,11 @@ class Implementation : private virtual slsDetectorDefs { bool getActivate() const; /** [Eiger] If deactivated, receiver will create dummy data if deactivated * padding is enabled (as it will receive nothing from detector) */ - bool setActivate(const bool enable); + void setActivate(const bool enable); + bool getDetectorDataStream(const portPosition port) const; + /** [Eiger] If datastream is disabled, receiver will create dummy data if deactivated + * padding for that port is enabled (as it will receive nothing from detector) */ + void setDetectorDataStream(const portPosition port, const bool enable); bool getDeactivatedPadding() const; /* [Eiger] */ void setDeactivatedPadding(const bool enable); @@ -274,8 +278,8 @@ class Implementation : private virtual slsDetectorDefs { // config parameters int numThreads{1}; - detectorType myDetectorType{GENERIC}; - int numDet[MAX_DIMENSIONS] = {0, 0}; + detectorType detType{GENERIC}; + int numMods[MAX_DIMENSIONS] = {0, 0}; int modulePos{0}; std::string detHostname; bool silentMode{false}; @@ -346,10 +350,11 @@ class Implementation : private virtual slsDetectorDefs { int flippedDataX{0}; bool quadEnable{false}; bool activated{true}; + std::array detectorDataStream = {{true, true}}; bool deactivatedPaddingEnable{true}; int numLinesReadout{MAX_EIGER_ROWS_PER_READOUT}; int thresholdEnergyeV{-1}; - std::array thresholdAllEnergyeV={{-1, -1, -1}}; + std::array thresholdAllEnergyeV = {{-1, -1, -1}}; std::vector rateCorrections; readoutMode readoutType{ANALOG_ONLY}; uint32_t adcEnableMaskOneGiga{BIT32_MASK}; @@ -375,4 +380,6 @@ class Implementation : private virtual slsDetectorDefs { std::vector> dataProcessor; std::vector> dataStreamer; std::vector> fifo; + + std::mutex hdf5Lib; }; diff --git a/slsReceiverSoftware/src/Listener.cpp b/slsReceiverSoftware/src/Listener.cpp index f1b1bcee1..9b0aaed55 100644 --- a/slsReceiverSoftware/src/Listener.cpp +++ b/slsReceiverSoftware/src/Listener.cpp @@ -22,11 +22,11 @@ const std::string Listener::TypeName = "Listener"; Listener::Listener(int ind, detectorType dtype, Fifo *f, std::atomic *s, uint32_t *portno, std::string *e, uint64_t *nf, int *us, int *as, uint32_t *fpf, - frameDiscardPolicy *fdp, bool *act, bool *depaden, bool *sm) + frameDiscardPolicy *fdp, bool *act, bool* detds, bool *depaden, bool *sm) : ThreadObject(ind, TypeName), fifo(f), myDetectorType(dtype), status(s), udpPortNumber(portno), eth(e), numImages(nf), udpSocketBufferSize(us), actualUDPSocketBufferSize(as), framesPerFile(fpf), frameDiscardMode(fdp), - activated(act), deactivatedPaddingEnable(depaden), silentMode(sm) { + activated(act), detectorDataStream(detds), deactivatedPaddingEnable(depaden), silentMode(sm) { LOG(logDEBUG) << "Listener " << ind << " created"; } @@ -94,7 +94,7 @@ void Listener::RecordFirstIndex(uint64_t fnum) { void Listener::SetGeneralData(GeneralData *g) { generalData = g; } void Listener::CreateUDPSockets() { - if (!(*activated)) { + if (!(*activated) || !(*detectorDataStream)) { return; } @@ -144,7 +144,7 @@ void Listener::CreateDummySocketForUDPSocketBufferSize(int s) { LOG(logINFO) << "Testing UDP Socket Buffer size " << s << " with test port " << *udpPortNumber; - if (!(*activated)) { + if (!(*activated) || !(*detectorDataStream)) { *actualUDPSocketBufferSize = (s * 2); return; } @@ -201,7 +201,7 @@ void Listener::ThreadExecution() { << std::hex << (void *)(buffer) << std::dec << ":" << buffer; // udpsocket doesnt exist - if (*activated && !udpSocketAlive && !carryOverFlag) { + if (*activated && *detectorDataStream && !udpSocketAlive && !carryOverFlag) { // LOG(logERROR) << "Listening_Thread " << index << ": UDP Socket not // created or shut down earlier"; (*((uint32_t *)buffer)) = 0; @@ -210,7 +210,7 @@ void Listener::ThreadExecution() { } // get data - if ((*status != TRANSMITTING && (!(*activated) || udpSocketAlive)) || + if ((*status != TRANSMITTING && (!(*activated) || !(*detectorDataStream) || udpSocketAlive)) || carryOverFlag) { rc = ListenToAnImage(buffer); } @@ -293,6 +293,10 @@ uint32_t Listener::ListenToAnImage(char *buf) { memset(buf, 0, fifohsize); new_header = (sls_receiver_header *)(buf + FIFO_HEADER_NUMBYTES); + // deactivated port (eiger) + if (!(*detectorDataStream)) { + return 0; + } // deactivated (eiger) if (!(*activated)) { // no padding diff --git a/slsReceiverSoftware/src/Listener.h b/slsReceiverSoftware/src/Listener.h index 5f6bdc46e..eff5800dc 100644 --- a/slsReceiverSoftware/src/Listener.h +++ b/slsReceiverSoftware/src/Listener.h @@ -37,12 +37,13 @@ class Listener : private virtual slsDetectorDefs, public ThreadObject { * @param fpf pointer to frames per file * @param fdp frame discard policy * @param act pointer to activated + * @param detds pointer to detector data stream * @param depaden pointer to deactivated padding enable * @param sm pointer to silent mode */ Listener(int ind, detectorType dtype, Fifo *f, std::atomic *s, uint32_t *portno, std::string *e, uint64_t *nf, int *us, int *as, - uint32_t *fpf, frameDiscardPolicy *fdp, bool *act, bool *depaden, + uint32_t *fpf, frameDiscardPolicy *fdp, bool *act, bool* detds, bool *depaden, bool *sm); /** @@ -187,6 +188,9 @@ class Listener : private virtual slsDetectorDefs, public ThreadObject { /** Activated/Deactivated */ bool *activated; + /** detector data stream */ + bool* detectorDataStream; + /** Deactivated padding enable */ bool *deactivatedPaddingEnable; diff --git a/slsReceiverSoftware/src/MasterAttributes.h b/slsReceiverSoftware/src/MasterAttributes.h index 2444f2318..14ecb1849 100644 --- a/slsReceiverSoftware/src/MasterAttributes.h +++ b/slsReceiverSoftware/src/MasterAttributes.h @@ -1,5 +1,6 @@ #pragma once +#include "receiver_defs.h" #include "sls/ToString.h" #include "sls/logger.h" #include "sls/sls_detector_defs.h" @@ -14,10 +15,6 @@ using namespace H5; #include using ns = std::chrono::nanoseconds; -// versions -#define HDF5_WRITER_VERSION (6.2) // 1 decimal places -#define BINARY_WRITER_VERSION (6.2) // 1 decimal places - struct MasterAttributes { slsDetectorDefs::detectorType detType{slsDetectorDefs::GENERIC}; slsDetectorDefs::timingMode timingMode{slsDetectorDefs::AUTO_TIMING}; @@ -36,7 +33,7 @@ struct MasterAttributes { uint32_t dynamicRange{0}; uint32_t tenGiga{0}; int thresholdEnergyeV{0}; - std::array thresholdAllEnergyeV={{0, 0, 0}}; + std::array thresholdAllEnergyeV = {{0, 0, 0}}; ns subExptime{0}; ns subPeriod{0}; uint32_t quad{0}; @@ -130,6 +127,8 @@ struct MasterAttributes { }; void WriteHDF5Attributes(H5File *fd, Group *group) { + char c[1024]; + memset(c, 0, sizeof(c)); // clang-format off // version { @@ -145,24 +144,27 @@ struct MasterAttributes { StrType strdatatype(PredType::C_S1, 256); DataSpace dataspace = DataSpace(H5S_SCALAR); DataSet dataset = - group->createDataSet("Timestamp", strdatatype, dataspace); - dataset.write(std::string(ctime(&t)), strdatatype); + group->createDataSet("Timestamp", strdatatype, dataspace); + sls::strcpy_safe(c, std::string(ctime(&t))); + dataset.write(c, strdatatype); } // detector type { DataSpace dataspace = DataSpace(H5S_SCALAR); StrType strdatatype(PredType::C_S1, 256); DataSet dataset = - group->createDataSet("Detector Type", strdatatype, dataspace); - dataset.write(sls::ToString(detType), strdatatype); + group->createDataSet("Detector Type", strdatatype, dataspace); + sls::strcpy_safe(c, sls::ToString(detType)); + dataset.write(c, strdatatype); } // timing mode { DataSpace dataspace = DataSpace(H5S_SCALAR); StrType strdatatype(PredType::C_S1, 256); DataSet dataset = - group->createDataSet("Timing Mode", strdatatype, dataspace); - dataset.write(sls::ToString(timingMode), strdatatype); + group->createDataSet("Timing Mode", strdatatype, dataspace); + sls::strcpy_safe(c, sls::ToString(timingMode)); + dataset.write(c, strdatatype); } // Image Size { @@ -173,8 +175,9 @@ struct MasterAttributes { DataSpace dataspaceAttr = DataSpace(H5S_SCALAR); StrType strdatatype(PredType::C_S1, 256); Attribute attribute = - dataset.createAttribute("Unit", strdatatype, dataspaceAttr); - attribute.write(strdatatype, std::string("bytes")); + dataset.createAttribute("Unit", strdatatype, dataspaceAttr); + sls::strcpy_safe(c, "bytes"); + attribute.write(strdatatype, c); } //TODO: make this into an array? // x @@ -203,8 +206,9 @@ struct MasterAttributes { DataSpace dataspace = DataSpace(H5S_SCALAR); StrType strdatatype(PredType::C_S1, 256); DataSet dataset = - group->createDataSet("Frame Discard Policy", strdatatype, dataspace); - dataset.write(sls::ToString(frameDiscardMode), strdatatype); + group->createDataSet("Frame Discard Policy", strdatatype, dataspace); + sls::strcpy_safe(c, sls::ToString(frameDiscardMode)); + dataset.write(c, strdatatype); } // Frame Padding { @@ -218,8 +222,9 @@ struct MasterAttributes { DataSpace dataspace = DataSpace(H5S_SCALAR); StrType strdatatype(PredType::C_S1, 256); DataSet dataset = - group->createDataSet("Scan Parameters", strdatatype, dataspace); - dataset.write(sls::ToString(scanParams), strdatatype); + group->createDataSet("Scan Parameters", strdatatype, dataspace); + sls::strcpy_safe(c, sls::ToString(scanParams)); + dataset.write(c, strdatatype); } // Total Frames { @@ -234,8 +239,9 @@ struct MasterAttributes { StrType strdatatype(PredType::C_S1, json.length()); DataSpace dataspace = DataSpace(H5S_SCALAR); DataSet dataset = - group->createDataSet("Additional JSON Header", strdatatype, dataspace); - dataset.write(sls::ToString(additionalJsonHeader), strdatatype); + group->createDataSet("Additional JSON Header", strdatatype, dataspace); + sls::strcpy_safe(c, sls::ToString(additionalJsonHeader)); + dataset.write(c, strdatatype); } }; @@ -243,16 +249,22 @@ struct MasterAttributes { DataSpace dataspace = DataSpace(H5S_SCALAR); StrType strdatatype(PredType::C_S1, 256); DataSet dataset = - group->createDataSet("Exposure Time", strdatatype, dataspace); - dataset.write(sls::ToString(exptime), strdatatype); + group->createDataSet("Exposure Time", strdatatype, dataspace); + char c[1024]; + memset(c, 0, sizeof(c)); + sls::strcpy_safe(c, sls::ToString(exptime)); + dataset.write(c, strdatatype); }; void WriteHDF5Period(H5File *fd, Group *group) { DataSpace dataspace = DataSpace(H5S_SCALAR); StrType strdatatype(PredType::C_S1, 256); DataSet dataset = - group->createDataSet("Acquisition Period", strdatatype, dataspace); - dataset.write(sls::ToString(period), strdatatype); + group->createDataSet("Acquisition Period", strdatatype, dataspace); + char c[1024]; + memset(c, 0, sizeof(c)); + sls::strcpy_safe(c, sls::ToString(period)); + dataset.write(c, strdatatype); }; void WriteHDF5DynamicRange(H5File *fd, Group *group) { @@ -263,8 +275,9 @@ struct MasterAttributes { DataSpace dataspaceAttr = DataSpace(H5S_SCALAR); StrType strdatatype(PredType::C_S1, 256); Attribute attribute = - dataset.createAttribute("Unit", strdatatype, dataspaceAttr); - attribute.write(strdatatype, std::string("bits")); + dataset.createAttribute("Unit", strdatatype, dataspaceAttr); + char c[1024] = "bits"; + attribute.write( strdatatype, c); }; void WriteHDF5TenGiga(H5File *fd, Group *group) { @@ -374,6 +387,8 @@ class EigerMasterAttributes : public MasterAttributes { MasterAttributes::WriteHDF5TenGiga(fd, group); MasterAttributes::WriteHDF5Exptime(fd, group); MasterAttributes::WriteHDF5Period(fd, group); + char c[1024]; + memset(c, 0, sizeof(c)); // threshold { DataSpace dataspace = DataSpace(H5S_SCALAR); @@ -383,8 +398,9 @@ class EigerMasterAttributes : public MasterAttributes { DataSpace dataspaceAttr = DataSpace(H5S_SCALAR); StrType strdatatype(PredType::C_S1, 256); Attribute attribute = - dataset.createAttribute("Unit", strdatatype, dataspaceAttr); - attribute.write(strdatatype, std::string("eV")); + dataset.createAttribute("Unit", strdatatype, dataspaceAttr); + sls::strcpy_safe(c, "eV"); + attribute.write(strdatatype, c); } // SubExptime { @@ -392,21 +408,23 @@ class EigerMasterAttributes : public MasterAttributes { StrType strdatatype(PredType::C_S1, 256); DataSet dataset = group->createDataSet("Sub Exposure Time", strdatatype, dataspace); - dataset.write(sls::ToString(subExptime), strdatatype); + sls::strcpy_safe(c, sls::ToString(subExptime)); + dataset.write(c, strdatatype); } // SubPeriod { DataSpace dataspace = DataSpace(H5S_SCALAR); StrType strdatatype(PredType::C_S1, 256); DataSet dataset = - group->createDataSet("Sub Period", strdatatype, dataspace); - dataset.write(sls::ToString(subPeriod), strdatatype); + group->createDataSet("Sub Period", strdatatype, dataspace); + sls::strcpy_safe(c, sls::ToString(subPeriod)); + dataset.write(c, strdatatype); } // Quad { DataSpace dataspace = DataSpace(H5S_SCALAR); DataSet dataset = - group->createDataSet("Quad", PredType::NATIVE_INT, dataspace); + group->createDataSet("Quad", PredType::NATIVE_INT, dataspace); dataset.write(&quad, PredType::NATIVE_INT); } // numLinesReadout @@ -422,7 +440,8 @@ class EigerMasterAttributes : public MasterAttributes { StrType strdatatype(PredType::C_S1, 1024); DataSet dataset = group->createDataSet("Rate Corrections", strdatatype, dataspace); - dataset.write(sls::ToString(ratecorr), strdatatype); + sls::strcpy_safe(c, sls::ToString(ratecorr)); + dataset.write(c, strdatatype); } }; #endif @@ -465,6 +484,8 @@ class Mythen3MasterAttributes : public MasterAttributes { MasterAttributes::WriteHDF5DynamicRange(fd, group); MasterAttributes::WriteHDF5TenGiga(fd, group); MasterAttributes::WriteHDF5Period(fd, group); + char c[1024]; + memset(c, 0, sizeof(c)); // Counter Mask { DataSpace dataspace = DataSpace(H5S_SCALAR); @@ -478,7 +499,8 @@ class Mythen3MasterAttributes : public MasterAttributes { StrType strdatatype(PredType::C_S1, 256); DataSet dataset = group->createDataSet("Exposure Time1", strdatatype, dataspace); - dataset.write(sls::ToString(exptime1), strdatatype); + sls::strcpy_safe(c, sls::ToString(exptime1)); + dataset.write(c, strdatatype); } // Exptime2 { @@ -486,7 +508,8 @@ class Mythen3MasterAttributes : public MasterAttributes { StrType strdatatype(PredType::C_S1, 256); DataSet dataset = group->createDataSet("Exposure Time2", strdatatype, dataspace); - dataset.write(sls::ToString(exptime2), strdatatype); + sls::strcpy_safe(c, sls::ToString(exptime2)); + dataset.write(c, strdatatype); } // Exptime3 { @@ -494,7 +517,8 @@ class Mythen3MasterAttributes : public MasterAttributes { StrType strdatatype(PredType::C_S1, 256); DataSet dataset = group->createDataSet("Exposure Time3", strdatatype, dataspace); - dataset.write(sls::ToString(exptime3), strdatatype); + sls::strcpy_safe(c, sls::ToString(exptime3)); + dataset.write(c, strdatatype); } // GateDelay1 { @@ -502,7 +526,8 @@ class Mythen3MasterAttributes : public MasterAttributes { StrType strdatatype(PredType::C_S1, 256); DataSet dataset = group->createDataSet("Gate Delay1", strdatatype, dataspace); - dataset.write(sls::ToString(gateDelay1), strdatatype); + sls::strcpy_safe(c, sls::ToString(gateDelay1)); + dataset.write(c, strdatatype); } // GateDelay2 { @@ -510,7 +535,8 @@ class Mythen3MasterAttributes : public MasterAttributes { StrType strdatatype(PredType::C_S1, 256); DataSet dataset = group->createDataSet("Gate Delay2", strdatatype, dataspace); - dataset.write(sls::ToString(gateDelay2), strdatatype); + sls::strcpy_safe(c, sls::ToString(gateDelay2)); + dataset.write(c, strdatatype); } // GateDelay3 { @@ -518,7 +544,8 @@ class Mythen3MasterAttributes : public MasterAttributes { StrType strdatatype(PredType::C_S1, 256); DataSet dataset = group->createDataSet("Gate Delay3", strdatatype, dataspace); - dataset.write(sls::ToString(gateDelay3), strdatatype); + sls::strcpy_safe(c, sls::ToString(gateDelay3)); + dataset.write(c, strdatatype); } // Gates { @@ -533,7 +560,8 @@ class Mythen3MasterAttributes : public MasterAttributes { StrType strdatatype(PredType::C_S1, 1024); DataSet dataset = group->createDataSet("Threshold Energies", strdatatype, dataspace); - dataset.write(sls::ToString(thresholdAllEnergyeV), strdatatype); + sls::strcpy_safe(c, sls::ToString(thresholdAllEnergyeV)); + dataset.write(c, strdatatype); } }; #endif @@ -565,7 +593,10 @@ class Gotthard2MasterAttributes : public MasterAttributes { StrType strdatatype(PredType::C_S1, 256); DataSet dataset = group->createDataSet("Burst Mode", strdatatype, dataspace); - dataset.write(sls::ToString(burstMode), strdatatype); + char c[1024]; + memset(c, 0, sizeof(c)); + sls::strcpy_safe(c, sls::ToString(burstMode)); + dataset.write(c, strdatatype); } }; #endif diff --git a/slsReceiverSoftware/src/receiver_defs.h b/slsReceiverSoftware/src/receiver_defs.h index 26fd25160..fa46fbef8 100755 --- a/slsReceiverSoftware/src/receiver_defs.h +++ b/slsReceiverSoftware/src/receiver_defs.h @@ -13,6 +13,11 @@ #define MAX_SOCKET_INPUT_PACKET_QUEUE (250000) // files + +// versions +#define HDF5_WRITER_VERSION (6.2) // 1 decimal places +#define BINARY_WRITER_VERSION (6.2) // 1 decimal places + #define MAX_FRAMES_PER_FILE 20000 #define SHORT_MAX_FRAMES_PER_FILE 100000 #define MOENCH_MAX_FRAMES_PER_FILE 100000 diff --git a/slsSupportLib/include/sls/ToString.h b/slsSupportLib/include/sls/ToString.h index cd301ff53..1b275cda6 100644 --- a/slsSupportLib/include/sls/ToString.h +++ b/slsSupportLib/include/sls/ToString.h @@ -37,6 +37,7 @@ std::string ToString(const std::vector &vec); std::string ToString(const defs::burstMode s); std::string ToString(const defs::timingSourceType s); std::string ToString(const defs::M3_GainCaps s); +std::string ToString(const defs::portPosition s); std::string ToString(const slsDetectorDefs::xy &coord); std::ostream &operator<<(std::ostream &os, const slsDetectorDefs::xy &coord); @@ -299,6 +300,7 @@ template <> defs::dacIndex StringTo(const std::string &s); template <> defs::burstMode StringTo(const std::string &s); template <> defs::timingSourceType StringTo(const std::string &s); template <> defs::M3_GainCaps StringTo(const std::string &s); +template <> defs::portPosition StringTo(const std::string &s); template <> uint32_t StringTo(const std::string &s); template <> uint64_t StringTo(const std::string &s); diff --git a/slsSupportLib/include/sls/sls_detector_defs.h b/slsSupportLib/include/sls/sls_detector_defs.h index 28a6403a9..81fe98fea 100644 --- a/slsSupportLib/include/sls/sls_detector_defs.h +++ b/slsSupportLib/include/sls/sls_detector_defs.h @@ -401,6 +401,8 @@ typedef struct { M3_C15pre = 1 << 14, }; + enum portPosition { LEFT, RIGHT, TOP, BOTTOM }; + #ifdef __cplusplus /** scan structure */ @@ -459,6 +461,8 @@ typedef struct { int64_t subExpTimeNs{0}; int64_t subDeadTimeNs{0}; int activate{0}; + int dataStreamLeft{0}; + int dataStreamRight{0}; int quad{0}; int numLinesReadout{0}; int thresholdEnergyeV[3]{0, 0, 0}; diff --git a/slsSupportLib/include/sls/sls_detector_funcs.h b/slsSupportLib/include/sls/sls_detector_funcs.h index bfc3eecdb..e0f46f96a 100755 --- a/slsSupportLib/include/sls/sls_detector_funcs.h +++ b/slsSupportLib/include/sls/sls_detector_funcs.h @@ -224,6 +224,8 @@ enum detFuncs { F_GET_CSR, F_SET_GAIN_CAPS, F_GET_GAIN_CAPS, + F_GET_DATASTREAM, + F_SET_DATASTREAM, NUM_DET_FUNCTIONS, RECEIVER_ENUM_START = 256, /**< detector function should not exceed this @@ -328,6 +330,7 @@ enum detFuncs { F_GET_RECEIVER_STREAMING_HWM, F_SET_RECEIVER_STREAMING_HWM, F_RECEIVER_SET_ALL_THRESHOLD, + F_RECEIVER_SET_DATASTREAM, NUM_REC_FUNCTIONS }; @@ -551,6 +554,8 @@ const char* getFunctionNameFromEnum(enum detFuncs func) { case F_LOAD_DEFAULT_PATTERN: return "F_LOAD_DEFAULT_PATTERN"; case F_GET_ALL_THRESHOLD_ENERGY: return "F_GET_ALL_THRESHOLD_ENERGY"; case F_GET_MASTER: return "F_GET_MASTER"; + case F_GET_DATASTREAM: return "F_GET_DATASTREAM"; + case F_SET_DATASTREAM: return "F_SET_DATASTREAM"; case NUM_DET_FUNCTIONS: return "NUM_DET_FUNCTIONS"; case RECEIVER_ENUM_START: return "RECEIVER_ENUM_START"; @@ -654,7 +659,7 @@ const char* getFunctionNameFromEnum(enum detFuncs func) { case F_GET_RECEIVER_STREAMING_HWM: return "F_GET_RECEIVER_STREAMING_HWM"; case F_SET_RECEIVER_STREAMING_HWM: return "F_SET_RECEIVER_STREAMING_HWM"; case F_RECEIVER_SET_ALL_THRESHOLD: return "F_RECEIVER_SET_ALL_THRESHOLD"; - + case F_RECEIVER_SET_DATASTREAM: return "F_RECEIVER_SET_DATASTREAM"; case NUM_REC_FUNCTIONS: return "NUM_REC_FUNCTIONS"; default: return "Unknown Function"; diff --git a/slsSupportLib/include/sls/versionAPI.h b/slsSupportLib/include/sls/versionAPI.h index 0ce7960be..aaf426002 100644 --- a/slsSupportLib/include/sls/versionAPI.h +++ b/slsSupportLib/include/sls/versionAPI.h @@ -10,4 +10,4 @@ #define APIMYTHEN3 0x210621 #define APIMOENCH 0x210621 -#define APIEIGER 0x210701 +#define APIEIGER 0x210721 diff --git a/slsSupportLib/src/ToString.cpp b/slsSupportLib/src/ToString.cpp index 3d5b92de5..211f31f2d 100644 --- a/slsSupportLib/src/ToString.cpp +++ b/slsSupportLib/src/ToString.cpp @@ -52,6 +52,8 @@ std::string ToString(const slsDetectorDefs::rxParameters &r) { << "subDeadTime:" << ToString(std::chrono::nanoseconds(r.subDeadTimeNs)) << std::endl << "activate:" << r.activate << std::endl + << "leftDataStream:" << r.dataStreamLeft << std::endl + << "rightDataStream:" << r.dataStreamRight << std::endl << "quad:" << r.quad << std::endl << "numLinesReadout:" << r.numLinesReadout << std::endl << "thresholdEnergyeV:" << ToString(r.thresholdEnergyeV) << std::endl @@ -519,6 +521,40 @@ std::string ToString(const defs::timingSourceType s) { } } +std::string ToString(defs::M3_GainCaps s) { + std::ostringstream os; + if (s & defs::M3_C10pre) + os << "C10pre, "; + if (s & defs::M3_C15sh) + os << "C15sh, "; + if (s & defs::M3_C30sh) + os << "C30sh, "; + if (s & defs::M3_C50sh) + os << "C50sh, "; + if (s & defs::M3_C225ACsh) + os << "C225ACsh, "; + if (s & defs::M3_C15pre) + os << "C15pre, "; + auto rs = os.str(); + rs.erase(rs.end() - 2); + return rs; +} + +std::string ToString(const defs::portPosition s) { + switch (s) { + case defs::LEFT: + return std::string("left"); + case defs::RIGHT: + return std::string("right"); + case defs::TOP: + return std::string("top"); + case defs::BOTTOM: + return std::string("bottom"); + default: + return std::string("Unknown"); + } +} + const std::string &ToString(const std::string &s) { return s; } template <> defs::detectorType StringTo(const std::string &s) { @@ -859,7 +895,7 @@ template <> defs::timingSourceType StringTo(const std::string &s) { throw sls::RuntimeError("Unknown timing source type " + s); } -template <> defs::M3_GainCaps StringTo(const std::string &s){ +template <> defs::M3_GainCaps StringTo(const std::string &s) { if (s == "C10pre") return defs::M3_C10pre; if (s == "C15sh") @@ -873,28 +909,18 @@ template <> defs::M3_GainCaps StringTo(const std::string &s){ if (s == "C15pre") return defs::M3_C15pre; throw sls::RuntimeError("Unknown gain cap " + s); - } - -std::string ToString(defs::M3_GainCaps s){ - std::ostringstream os; - if (s & defs::M3_C10pre) - os << "C10pre, "; - if (s & defs::M3_C15sh) - os << "C15sh, "; - if (s & defs::M3_C30sh) - os << "C30sh, "; - if (s & defs::M3_C50sh) - os << "C50sh, "; - if (s & defs::M3_C225ACsh) - os << "C225ACsh, "; - if (s & defs::M3_C15pre) - os << "C15pre, "; - auto rs = os.str(); - rs.erase(rs.end()-2); - return rs; - +template <> defs::portPosition StringTo(const std::string &s) { + if (s == "left") + return defs::LEFT; + if (s == "right") + return defs::RIGHT; + if (s == "top") + return defs::TOP; + if (s == "bottom") + return defs::BOTTOM; + throw sls::RuntimeError("Unknown port position " + s); } template <> uint32_t StringTo(const std::string &s) {