moved non public headers

This commit is contained in:
Erik Frojdh
2020-02-03 14:38:24 +01:00
parent 6cc13f9dc1
commit 254e8f85d8
20 changed files with 12 additions and 5 deletions

View File

@ -0,0 +1,108 @@
#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 "BinaryFileStatic.h"
#include <string>
class BinaryFile : private virtual slsDetectorDefs, public File, public BinaryFileStatic {
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);
/**
* Destructor
*/
~BinaryFile();
/**
* Print all member values
*/
void PrintMembers(TLogLevel level = logDEBUG1) override;
/**
* Create file
*/
void CreateFile() override;
/**
* Create master file
* @param mfwenable master file write enable
* @param attr master file attributes
*/
void CreateMasterFile(bool mfwenable, masterAttributes& attr) override;
/**
* Close Current File
*/
void CloseCurrentFile() override;
/**
* Close all Files
*/
void CloseAllFiles() override;
/**
* 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
*/
void WriteToFile(char* buffer, int buffersize, uint64_t fnum, uint32_t nump) override;
private:
/**
* Get Type
* @return type
*/
fileFormat GetFileType() override;
/** File Descriptor */
FILE* filefd;
/** Master File Descriptor */
static FILE* masterfd;
/** Number of frames in file */
uint32_t numFramesInFile;
/** Number of actual packets caught in file */
uint64_t numActualPacketsInFile;
};

View File

@ -0,0 +1,217 @@
#pragma once
/************************************************
* @file BinaryFileStatic.h
* @short creating, closing, writing and reading
* from binary files
***********************************************/
/**
*@short creating, closing, writing and reading from binary files
*/
#include "ansi.h"
#include "logger.h"
#include <string>
#include <iomanip>
#include <string.h>
#define MAX_MASTER_FILE_LENGTH 2000
class BinaryFileStatic {
public:
/** Constructor */
BinaryFileStatic(){};
/** Destructor */
virtual ~BinaryFileStatic(){};
/**
* Create File Name in format fpath/fnameprefix_fx_dy_z.raw,
* where x is fnum, y is (dindex * numunits + unitindex) and z is findex
* @param fpath file path
* @param fnameprefix file name prefix
* @param findex file index
* @param subfindex sub file index
* @param dindex readout index
* @param numunits number of units per readout. eg. eiger has 2 udp units per readout
* @param unitindex unit index
* @returns complete file name created
*/
static std::string CreateFileName(std::string fpath, std::string fprefix,
uint64_t findex, uint64_t subfindex,
int dindex, int numunits = 1,
int unitindex = 0) {
std::ostringstream os;
os << fpath << "/" << fprefix << "_d"
<< (dindex * numunits + unitindex) << "_f" << subfindex << '_'
<< findex << ".raw";
return os.str();
}
/**
* Create file names for master file
* @param fpath file path
* @param fnameprefix file name prefix
* @param findex file index
* @returns master file name
*/
static std::string CreateMasterFileName(std::string fpath, std::string fnameprefix,
uint64_t findex) {
std::ostringstream os;
os << fpath << "/" << fnameprefix << "_master"
<< "_" << findex << ".raw";
return os.str();
}
/**
* Close File
* @param fd file pointer
*/
static void CloseDataFile(FILE*& fd)
{
if (fd)
fclose(fd);
fd = 0;
}
/**
* Write data to file
* @param fd file pointer
* @param buf buffer to write from
* @param bsize size of buffer
* @returns number of elements written
*/
static int WriteDataFile(FILE* fd, char* buf, int bsize)
{
if (!fd)
return 0;
return fwrite(buf, 1, bsize, fd);
}
/**
* Create master files
* @param fd pointer to file handle
* @param fname master file name
* @param owenable overwrite enable
* @param attr master file attributes
*/
static void CreateMasterDataFile(FILE*& fd, std::string fname, bool owenable,
masterAttributes& attr)
{
if(!owenable){
if (NULL == (fd = fopen((const char *) fname.c_str(), "wx"))){
fd = 0;
throw sls::RuntimeError("Could not create binary master file "
"(without overwrite enable) " + fname);
}
}else if (NULL == (fd = fopen((const char *) fname.c_str(), "w"))){
fd = 0;
throw sls::RuntimeError("Could not create binary master file "
"(with overwrite enable) " + fname);
}
time_t t = time(0);
char message[MAX_MASTER_FILE_LENGTH];
sprintf(message,
"Version : %.1f\n"
"Detector Type : %d\n"
"Dynamic Range : %d\n"
"Ten Giga : %d\n"
"Image Size : %d bytes\n"
"nPixelsX : %d pixels\n"
"nPixelsY : %d pixels\n"
"Max Frames Per File : %u\n"
"Total Frames : %lld\n"
"Exptime (ns) : %lld\n"
"SubExptime (ns) : %lld\n"
"SubPeriod(ns) : %lld\n"
"Period (ns) : %lld\n"
"Gap Pixels Enable : %d\n"
"Quad Enable : %d\n"
"Analog Flag : %d\n"
"Digital Flag : %d\n"
"ADC Mask : %d\n"
"Dbit Offset : %d\n"
"Dbit Bitset : %lld\n"
"Roi (xmin, xmax) : %d %d\n"
"Timestamp : %s\n\n"
"#Frame Header\n"
"Frame Number : 8 bytes\n"
"SubFrame Number/ExpLength : 4 bytes\n"
"Packet Number : 4 bytes\n"
"Bunch ID : 8 bytes\n"
"Timestamp : 8 bytes\n"
"Module Id : 2 bytes\n"
"Row : 2 bytes\n"
"Column : 2 bytes\n"
"Reserved : 2 bytes\n"
"Debug : 4 bytes\n"
"Round Robin Number : 2 bytes\n"
"Detector Type : 1 byte\n"
"Header Version : 1 byte\n"
"Packets Caught Mask : 64 bytes\n"
,
attr.version,
attr.detectorType,
attr.dynamicRange,
attr.tenGiga,
attr.imageSize,
attr.nPixelsX,
attr.nPixelsY,
attr.maxFramesPerFile,
(long long int)attr.totalFrames,
(long long int)attr.exptimeNs,
(long long int)attr.subExptimeNs,
(long long int)attr.subPeriodNs,
(long long int)attr.periodNs,
attr.gapPixelsEnable,
attr.quadEnable,
attr.analogFlag,
attr.digitalFlag,
attr.adcmask,
attr.dbitoffset,
(long long int)attr.dbitlist,
attr.roiXmin,
attr.roiXmax,
ctime(&t));
if (strlen(message) > MAX_MASTER_FILE_LENGTH) {
throw sls::RuntimeError("Master File Size " + std::to_string(strlen(message)) +
" is greater than max str size " + std::to_string(MAX_MASTER_FILE_LENGTH));
}
if (fwrite((void*)message, 1, strlen(message), fd) != strlen(message)) {
throw sls::RuntimeError("Master binary file incorrect number of bytes written to file");
}
BinaryFileStatic::CloseDataFile(fd);
}
/**
* Create File
* @param fd file pointer
* @param owenable overwrite enable
* @param fname complete file name
* @returns 0 for success and 1 for fail
*/
static void CreateDataFile(FILE*& fd, bool owenable, std::string fname)
{
if(!owenable){
if (NULL == (fd = fopen((const char *) fname.c_str(), "wx"))){
fd = 0;
throw sls::RuntimeError("Could not create/overwrite file " + fname);
}
} else if (NULL == (fd = fopen((const char *) fname.c_str(), "w"))){
fd = 0;
throw sls::RuntimeError("Could not create file " + fname);
}
//setting to no file buffering
setvbuf(fd, NULL, _IONBF, 0);
}
};

View File

@ -0,0 +1,160 @@
#pragma once
#include "receiver_defs.h"
#include "sls_detector_defs.h"
#include "Implementation.h"
#include "ServerSocket.h"
class MySocketTCP;
class ServerInterface;
#include <atomic>
#include <future>
class ClientInterface : private virtual slsDetectorDefs {
private:
enum numberMode { DEC, HEX };
public:
virtual ~ClientInterface();
ClientInterface(int portNumber = -1);
int64_t getReceiverVersion();
//***callback functions***
/** params: filepath, filename, fileindex, datasize */
void registerCallBackStartAcquisition(int (*func)(std::string, std::string, uint64_t,
uint32_t, void *),
void *arg);
/** params: total frames caught */
void registerCallBackAcquisitionFinished(void (*func)(uint64_t, void *),
void *arg);
/** params: sls_receiver_header frame metadata, dataPointer, dataSize */
void registerCallBackRawDataReady(void (*func)(char *, char *, uint32_t,
void *),
void *arg);
/** params: sls_receiver_header frame metadata, dataPointer, modified size */
void registerCallBackRawDataModifyReady(void (*func)(char *, char *,
uint32_t &, void *),
void *arg);
private:
void startTCPServer();
int functionTable();
int decodeFunction(sls::ServerInterface2 &socket);
void functionNotImplemented();
void modeNotImplemented(const std::string& modename, int mode);
template <typename T>
void validate(T arg, T retval, std::string modename, numberMode hex);
void verifyLock();
void verifyIdle(sls::ServerInterface2 &socket);
int exec_command(sls::ServerInterface2 &socket);
int exit_server(sls::ServerInterface2 &socket);
int lock_receiver(sls::ServerInterface2 &socket);
int get_last_client_ip(sls::ServerInterface2 &socket);
int set_port(sls::ServerInterface2 &socket);
int update_client(sls::ServerInterface2 &socket);
int send_update(sls::ServerInterface2 &socket);
int get_version(sls::ServerInterface2 &socket);
int set_detector_type(sls::ServerInterface2 &socket);
int set_detector_hostname(sls::ServerInterface2 &socket);
int set_roi(sls::ServerInterface2 &socket);
int set_num_frames(sls::ServerInterface2 &socket);
int set_num_analog_samples(sls::ServerInterface2 &socket);
int set_num_digital_samples(sls::ServerInterface2 &socket);
int set_exptime(sls::ServerInterface2 &socket);
int set_period(sls::ServerInterface2 &socket);
int set_subexptime(sls::ServerInterface2 &socket);
int set_subdeadtime(sls::ServerInterface2 &socket);
int set_dynamic_range(sls::ServerInterface2 &socket);
int set_streaming_frequency(sls::ServerInterface2 &socket);
int get_status(sls::ServerInterface2 &socket);
int start_receiver(sls::ServerInterface2 &socket);
int stop_receiver(sls::ServerInterface2 &socket);
int set_file_dir(sls::ServerInterface2 &socket);
int set_file_name(sls::ServerInterface2 &socket);
int set_file_index(sls::ServerInterface2 &socket);
int get_frame_index(sls::ServerInterface2 &socket);
int get_missing_packets(sls::ServerInterface2 &socket);
int get_frames_caught(sls::ServerInterface2 &socket);
int enable_file_write(sls::ServerInterface2 &socket);
int enable_master_file_write(sls::ServerInterface2 &socket);
int enable_compression(sls::ServerInterface2 &socket);
int enable_overwrite(sls::ServerInterface2 &socket);
int enable_tengiga(sls::ServerInterface2 &socket);
int set_fifo_depth(sls::ServerInterface2 &socket);
int set_activate(sls::ServerInterface2 &socket);
int set_data_stream_enable(sls::ServerInterface2 &socket);
int set_streaming_timer(sls::ServerInterface2 &socket);
int set_flipped_data(sls::ServerInterface2 &socket);
int set_file_format(sls::ServerInterface2 &socket);
int set_detector_posid(sls::ServerInterface2 &socket);
int set_multi_detector_size(sls::ServerInterface2 &socket);
int set_streaming_port(sls::ServerInterface2 &socket);
int set_streaming_source_ip(sls::ServerInterface2 &socket);
int set_silent_mode(sls::ServerInterface2 &socket);
int enable_gap_pixels(sls::ServerInterface2 &socket);
int restream_stop(sls::ServerInterface2 &socket);
int set_additional_json_header(sls::ServerInterface2 &socket);
int get_additional_json_header(sls::ServerInterface2 &socket);
int set_udp_socket_buffer_size(sls::ServerInterface2 &socket);
int get_real_udp_socket_buffer_size(sls::ServerInterface2 &socket);
int set_frames_per_file(sls::ServerInterface2 &socket);
int check_version_compatibility(sls::ServerInterface2 &socket);
int set_discard_policy(sls::ServerInterface2 &socket);
int set_padding_enable(sls::ServerInterface2 &socket);
int set_deactivated_padding_enable(sls::ServerInterface2 &socket);
int set_readout_mode(sls::ServerInterface2 &socket);
int set_adc_mask(sls::ServerInterface2 &socket);
int set_dbit_list(sls::ServerInterface2 &socket);
int get_dbit_list(sls::ServerInterface2 &socket);
int set_dbit_offset(sls::ServerInterface2 &socket);
int set_quad_type(sls::ServerInterface2 &socket);
int set_read_n_lines(sls::ServerInterface2 &socket);
int set_udp_ip(sls::ServerInterface2 &socket);
int set_udp_ip2(sls::ServerInterface2 &socket);
int set_udp_port(sls::ServerInterface2 &socket);
int set_udp_port2(sls::ServerInterface2 &socket);
int set_num_interfaces(sls::ServerInterface2 &socket);
int set_adc_mask_10g(sls::ServerInterface2 &socket);
int set_num_counters(sls::ServerInterface2 &socket);
Implementation *impl() {
if (receiver != nullptr) {
return receiver.get();
} else {
throw sls::SocketError(
"Receiver not set up. Please use rx_hostname first.\n");
}
}
detectorType myDetectorType;
std::unique_ptr<Implementation> receiver{nullptr};
int (ClientInterface::*flist[NUM_REC_FUNCTIONS])(
sls::ServerInterface2 &socket);
int ret{OK};
int fnum{-1};
int lockedByClient{0};
int portNumber{0};
std::atomic<bool> killTcpThread{false};
std::unique_ptr<std::thread> tcpThread;
//***callback parameters***
int (*startAcquisitionCallBack)(std::string, std::string, uint64_t, uint32_t,
void *) = nullptr;
void *pStartAcquisition{nullptr};
void (*acquisitionFinishedCallBack)(uint64_t, void *) = nullptr;
void *pAcquisitionFinished{nullptr};
void (*rawDataReadyCallBack)(char *, char *, uint32_t, void *) = nullptr;
void (*rawDataModifyReadyCallBack)(char *, char *, uint32_t &,
void *) = nullptr;
void *pRawDataReady{nullptr};
protected:
std::unique_ptr<sls::ServerSocket> server{nullptr};
};

View File

@ -0,0 +1,386 @@
#pragma once
/************************************************
* @file DataProcessor.h
* @short creates data processor thread that
* pulls pointers to memory addresses from fifos
* and processes data stored in them & writes them to file
***********************************************/
/**
*@short creates & manages a data processor thread each
*/
#include "ThreadObject.h"
#include "receiver_defs.h"
class GeneralData;
class Fifo;
class File;
class DataStreamer;
#include <vector>
#include <atomic>
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
* @apram mfwenable pointer to master file write enable
* @param dsEnable pointer to data stream enable
* @param gpEnable pointer to gap pixels enable
* @param dr pointer to dynamic range
* @param freq pointer to streaming frequency
* @param timer pointer to timer if streaming frequency is random
* @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, bool* gpEnable, uint32_t* dr,
uint32_t* freq, uint32_t* timer,
bool* fp, bool* act, bool* depaden, bool* sm, bool* qe,
std::vector <int> * cdl, int* cdo, int* cad);
/**
* Destructor
* Calls Base Class DestroyThread() and decrements NumberofDataProcessors
*/
~DataProcessor() override;
//*** getters ***
/**
* Returns if the thread is currently running
* @returns true if thread is running, else false
*/
bool IsRunning() override;
/**
* 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
*/
uint64_t GetCurrentFrameIndex();
/**
* Get Current Frame Index thats been processed
* @return -1 if no frames have been caught, else current frame index
*/
uint64_t GetProcessedIndex();
//*** setters ***
/**
* Set bit in RunningMask to allow thread to run
*/
void StartRunning();
/**
* Reset bit in RunningMask to prevent thread from running
*/
void StopRunning();
/**
* Set Fifo pointer to the one given
* @param f address of Fifo pointer
*/
void SetFifo(Fifo* f);
/**
* Reset parameters for new acquisition
*/
void ResetParametersforNewAcquisition();
/**
* Set GeneralData pointer to the one given
* @param g address of GeneralData (Detector Data) pointer
*/
void SetGeneralData(GeneralData* g);
/**
* Set File Format
* @param f 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();
/**
* 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();
/**
* Call back for raw data
* args to raw data ready callback are
* sls_receiver_header frame metadata
* dataPointer is the pointer to the data
* dataSize in bytes is the size of the data in bytes.
*/
void registerCallBackRawDataReady(void (*func)(char* ,
char*, uint32_t, void*),void *arg);
/**
* Call back for raw data (modified)
* args to raw data ready callback are
* sls_receiver_header frame metadata
* dataPointer is the pointer to the data
* revDatasize is the reference of data size in bytes.
* Can be modified to the new size to be written/streamed. (only smaller value).
*/
void registerCallBackRawDataModifyReady(void (*func)(char* ,
char*, uint32_t &, void*),void *arg);
private:
/**
* Record First Index
* @param fnum frame index to record
*/
void RecordFirstIndex(uint64_t fnum);
/**
* Thread Exeution for DataProcessor Class
* Pop bound addresses, process them,
* write to file if needed & free the address
*/
void ThreadExecution() override;
/**
* 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 buffer
*/
void ProcessAnImage(char* buf);
/**
* Calls CheckTimer and CheckCount for streaming frequency and timer
* and determines if the current image should be sent to streamer
* @returns true if it should to streamer, else false
*/
bool SendToStreamer();
/**
* This function should be called only in random frequency mode
* Checks if timer is done and ready to send to stream
* @returns true if ready to send to stream, else false
*/
bool CheckTimer();
/**
* This function should be called only in non random frequency mode
* Checks if count is done and ready to send to stream
* @returns true if ready to send to stream, else false
*/
bool CheckCount();
/**
* Pad Missing Packets from the bit mask
* @param buf buffer
*/
void PadMissingPackets(char* buf);
/**
* Align corresponding digital bits together (CTB only if ctbDbitlist is not empty)
*/
void RearrangeDbitData(char* buf);
/**
* Processing Function (inserting gap pixels) eiger specific
* @param buf pointer to image
* @param dr dynamic range
*/
void InsertGapPixels(char* buf, uint32_t dr);
/** type of thread */
static const std::string TypeName;
/** Object running status */
std::atomic<bool> runningFlag;
/** GeneralData (Detector Data) object */
const GeneralData* generalData;
/** Fifo structure */
Fifo* fifo;
//individual members
/** Detector Type */
detectorType myDetectorType;
/** File writer implemented as binary or hdf5 File */
File* file;
/** Data Stream Enable */
bool* dataStreamEnable;
/** File Format Type */
fileFormat* fileFormatType;
/** File Write Enable */
bool fileWriteEnable;
/** Master File Write Enable */
bool* masterFileWriteEnable;
/** Gap Pixels Enable */
bool* gapPixelsEnable;
/** Dynamic Range */
uint32_t* dynamicRange;
/** 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;
/** Current frequency count */
uint32_t currentFreqCount;
/** timer beginning stamp for random streaming */
struct timespec timerBegin;
/** temporary buffer for processing */
char* tempBuffer;
/** Activated/Deactivated */
bool* activated;
/** Deactivated padding enable */
bool* deactivatedPaddingEnable;
/** Silent Mode */
bool* silentMode;
/** quad enable */
bool* quadEnable;
/** frame padding */
bool* framePadding;
/** ctb digital bits enable list */
std::vector <int> *ctbDbitList;
/** ctb digital bits offset */
int* ctbDbitOffset;
/** ctb analog databytes */
int* ctbAnalogDataBytes;
//acquisition start
/** Aquisition Started flag */
bool startedFlag;
/** Frame Number of First Frame */
uint64_t firstIndex;
//for statistics
/** Number of complete frames caught */
uint64_t numFramesCaught;
/** Frame Number of latest processed frame number */
uint64_t currentFrameIndex;
//call back
/**
* Call back for raw data
* args to raw data ready callback are
* sls_receiver_header frame metadata
* dataPointer is the pointer to the data
* dataSize in bytes is the size of the data in bytes.
*/
void (*rawDataReadyCallBack)(char*,
char*, uint32_t, void*);
/**
* Call back for raw data (modified)
* args to raw data ready callback are
* sls_receiver_header frame metadata
* dataPointer is the pointer to the data
* revDatasize is the reference of data size in bytes. Can be modified to the new size to be written/streamed. (only smaller value).
*/
void (*rawDataModifyReadyCallBack)(char*,
char*, uint32_t &, void*);
void *pRawDataReady;
};

View File

@ -0,0 +1,210 @@
#pragma once
/************************************************
* @file DataStreamer.h
* @short streams data from receiver via ZMQ
***********************************************/
/**
*@short creates & manages a data streamer thread each
*/
#include "ThreadObject.h"
#include "network_utils.h"
class GeneralData;
class Fifo;
class DataStreamer;
class ZmqSocket;
#include <vector>
class DataStreamer : private virtual slsDetectorDefs, public ThreadObject {
public:
/**
* Constructor
* Calls Base Class CreateThread(), sets ErrorMask if error and increments NumberofDataStreamers
* @param ind self index
* @param f address of Fifo pointer
* @param dr pointer to dynamic range
* @param r roi
* @param fi pointer to file index
* @param fd flipped data enable for x dimension
* @param ajh additional json header
* @param nd pointer to number of detectors in each dimension
* @param gpEnable pointer to gap pixels enable
* @param qe pointer to quad Enable
*/
DataStreamer(int ind, Fifo* f, uint32_t* dr, ROI* r,
uint64_t* fi, int fd, std::string* ajh, int* nd, bool* gpEnable, bool* qe);
/**
* Destructor
* Calls Base Class DestroyThread() and decrements NumberofDataStreamers
*/
~DataStreamer();
//*** getters ***
/**
* Returns if the thread is currently running
* @returns true if thread is running, else false
*/
bool IsRunning();
//*** setters ***
/**
* Set bit in RunningMask to allow thread to run
*/
void StartRunning();
/**
* Reset bit in RunningMask to prevent thread from running
*/
void StopRunning();
/**
* Set Fifo pointer to the one given
* @param f address of Fifo pointer
*/
void SetFifo(Fifo* f);
/**
* Reset parameters for new acquisition
*/
void ResetParametersforNewAcquisition(const std::string& fname);
/**
* Set GeneralData pointer to the one given
* @param g address of GeneralData (Detector Data) pointer
*/
void SetGeneralData(GeneralData* g);
/**
* Set number of detectors
* @param number of detectors in both dimensions
*/
void SetNumberofDetectors(int* nd);
/**
* Set Flipped data enable across x dimension
* @param flipped data enable in x dimension
*/
void SetFlippedDataX(int fd);
/**
* Creates Zmq Sockets
* (throws an exception if it couldnt create zmq sockets)
* @param nunits pointer to number of theads/ units per detector
* @param port streaming port start index
* @param ip streaming source ip
*/
void CreateZmqSockets(int* nunits, uint32_t port, const sls::IpAddr ip);
/**
* Shuts down and deletes Zmq Sockets
*/
void CloseZmqSocket();
/**
* Restream stop dummy packet
*/
void RestreamStop();
private:
/**
* Record First Index
* @param fnum frame index to record
*/
void RecordFirstIndex(uint64_t fnum);
/**
* Thread Exeution for DataStreamer Class
* Stream an image via zmq
*/
void ThreadExecution();
/**
* 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 buffer
*/
void ProcessAnImage(char* buf);
/**
* Create and send Json Header
* @param rheader header of image
* @param size data size (could have been modified in call back)
* @param nx number of pixels in x dim
* @param ny number of pixels in y dim
* @param dummy true if its a dummy header
* @returns 0 if error, else 1
*/
int SendHeader(sls_receiver_header* rheader, uint32_t size = 0, uint32_t nx = 0, uint32_t ny = 0, bool dummy = true);
/** type of thread */
static const std::string TypeName;
/** Object running status */
bool runningFlag;
/** GeneralData (Detector Data) object */
const GeneralData* generalData;
/** Fifo structure */
Fifo* fifo;
/** ZMQ Socket - Receiver to Client */
ZmqSocket* zmqSocket;
/** Pointer to dynamic range */
uint32_t* dynamicRange;
/** ROI */
ROI* roi;
/** adc Configured */
int adcConfigured;
/** Pointer to file index */
uint64_t* fileIndex;
/** flipped data across x axis */
int flippedDataX;
/** additional json header */
std::string* additionJsonHeader;
/** Aquisition Started flag */
bool startedFlag;
/** Frame Number of First Frame */
uint64_t firstIndex;
/* File name to stream */
std::string fileNametoStream;
/** Complete buffer used for roi, eg. shortGotthard */
char* completeBuffer;
/** Number of Detectors in X and Y dimension */
int numDet[2];
/** Gap Pixels Enable */
bool* gapPixelsEnable;
/** Quad Enable */
bool* quadEnable;
};

110
slsReceiverSoftware/src/Fifo.h Executable file
View File

@ -0,0 +1,110 @@
#pragma once
/************************************************
* @file Fifo.h
* @short constructs the fifo structure
* which is a circular buffer with pointers to
* parts of allocated memory
***********************************************/
/**
*@short constructs the fifo structure
*/
#include "sls_detector_defs.h"
#include "logger.h"
#include "CircularFifo.h"
class Fifo : private virtual slsDetectorDefs {
public:
/**
* Constructor
* Calls CreateFifos that creates fifos and allocates memory
* @param ind self index
* @param fifoItemSize size of each fifo item
* @param depth fifo depth
*/
Fifo(int ind, uint32_t fifoItemSize, uint32_t depth);
/**
* Destructor
*/
~Fifo();
/**
* Frees the bound address by pushing into fifoFree
*/
void FreeAddress(char*& address);
/**
* Pops free address from fifoFree
*/
void GetNewAddress(char*& address);
/**
* Pushes bound address into fifoBound
*/
void PushAddress(char*& address);
/**
* Pops bound address from fifoBound to process data
*/
void PopAddress(char*& address);
/**
* Pushes bound address into fifoStream
*/
void PushAddressToStream(char*& address);
/**
* Pops bound address from fifoStream to stream data
*/
void PopAddressToStream(char*& address);
/**
* Get Maximum Level filled in Fifo Bound
* and reset this value for next intake
*/
int GetMaxLevelForFifoBound();
/**
* Get Minimum Level filled in Fifo Free
* and reset this value to max for next intake
*/
int GetMinLevelForFifoFree();
private:
/**
* Create Fifos, allocate memory & push addresses into fifo
* @param fifoItemSize size of each fifo item
*/
void CreateFifos(uint32_t fifoItemSize);
/**
* Destroy Fifos and deallocate memory
*/
void DestroyFifos();
/** Self Index */
int index;
/** Memory allocated, whose addresses are pushed into the fifos */
char* memory;
/** Circular Fifo pointing to addresses of bound data in memory */
CircularFifo<char>* fifoBound;
/** Circular Fifo pointing to addresses of freed data in memory */
CircularFifo<char>* fifoFree;
/** Circular Fifo pointing to addresses of to be streamed data in memory */
CircularFifo<char>* fifoStream;
/** Fifo depth set */
int fifoDepth;
volatile int status_fifoBound;
volatile int status_fifoFree;
};

194
slsReceiverSoftware/src/File.h Executable file
View File

@ -0,0 +1,194 @@
#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 "sls_detector_defs.h"
#include "logger.h"
#include "receiver_defs.h"
#include <string>
class File : private virtual slsDetectorDefs {
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
*/
File(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);
/**
* Destructor
*/
virtual ~File();
/**
* Get Current File Name
* @returns current file name
*/
std::string GetCurrentFileName();
void resetSubFileIndex();
/**
* Print all member values
*/
virtual void PrintMembers(TLogLevel level = logDEBUG1);
/**
* Get Type
* @return type
*/
virtual fileFormat GetFileType() = 0;
/**
* 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);
/**
* Create file
*/
virtual void CreateFile() = 0;
/**
* Close Current File
*/
virtual void CloseCurrentFile() = 0;
/**
* Close Files
*/
virtual void CloseAllFiles() = 0;
/**
* Write data to file
* @param buffer buffer to write from
* @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;
/**
* Create master file
* @param mfwenable master file write enable
* @param attr master file attributes
*/
virtual void CreateMasterFile(bool mfwenable, masterAttributes& attr) = 0;
// 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) {
FILE_LOG(logERROR) << "This is a generic function SetNumberofPixels 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) {
FILE_LOG(logERROR) << "This is a generic function EndofAcquisition that "
"should be overloaded by a derived class";
}
protected:
/** master file writer/reader */
bool master;
/** Self Index */
int index;
/** Maximum frames per file */
uint32_t* maxFramesPerFile;
/** Master File Name */
std::string masterFileName;
/** Current File Name */
std::string currentFileName;
/** Number of Detectors in X dimension */
int numDetX;
/** Number of Detectors in Y dimension */
int numDetY;
/** File Name Prefix */
std::string* fileNamePrefix;
/** File Path */
std::string* filePath;
/** File Index */
uint64_t* fileIndex;
/** Sub file index */
uint64_t subFileIndex{0};
/** Over write enable */
bool* overWriteEnable;
/** Detector Index */
int* detIndex;
/** Number of units per detector. Eg. Eiger has 2, others 1 */
int* numUnitsPerDetector;
/** Number of images in acquisition */
uint64_t* numImages;
/** Dynamic Range */
uint32_t* dynamicRange;
/** UDP Port Number for logging */
uint32_t* udpPortNumber;
/** Silent Mode */
bool* silentMode;
};

View File

@ -0,0 +1,827 @@
#pragma once
/************************************************
* @file GeneralData.h
* @short abstract for setting/getting properties of detector data
***********************************************/
/**
*@short abstract for setting/getting properties of detector data
*/
#include "sls_detector_defs.h"
#include "receiver_defs.h"
#include "logger.h"
#include <cmath> //ceil
#include <vector>
#include "ToString.h"
class GeneralData {
public:
/** DetectorType */
slsDetectorDefs::detectorType myDetectorType;
/** Number of Pixels in x axis */
uint32_t nPixelsX;
/** Number of Pixels in y axis */
uint32_t nPixelsY;
/** Size of header in Packet */
uint32_t headerSizeinPacket;
/** Size of just data in 1 packet (in bytes) */
uint32_t dataSize;
/** Size of 1 packet (in bytes) */
uint32_t packetSize;
/** Number of packets in an image (for each listening UDP port) */
uint32_t packetsPerFrame;
/** Image size (in bytes, for each listening UDP port) */
uint32_t imageSize;
/** Frame Number Mask */
uint64_t frameIndexMask;
/** Frame Index Offset */
uint32_t frameIndexOffset;
/** Packet Index Mask */
uint32_t packetIndexMask;
/** Packet Index Offset */
uint32_t packetIndexOffset;
/** Max Frames per binary file */
uint32_t maxFramesPerFile;
/** Header size of data saved into fifo buffer at a time*/
uint32_t fifoBufferHeaderSize;
/** Default Fifo depth */
uint32_t defaultFifoDepth;
/** Threads per receiver */
uint32_t threadsPerReceiver;
/** Size of a header packet */
uint32_t headerPacketSize;
/** Streaming (for ROI - mainly short Gotthard) - Number of Pixels in x axis */
uint32_t nPixelsXComplete;
/** Streaming (for ROI - mainly short Gotthard) - Number of Pixels in y axis */
uint32_t nPixelsYComplete;
/** Streaming (for ROI - mainly short Gotthard) - Image size (in bytes) */
uint32_t imageSizeComplete;
/** if standard header implemented in firmware */
bool standardheader;
/** default udp socket buffer size */
uint32_t defaultUdpSocketBufferSize;
/** Cosntructor */
GeneralData():
myDetectorType(slsDetectorDefs::GENERIC),
nPixelsX(0),
nPixelsY(0),
headerSizeinPacket(0),
dataSize(0),
packetSize(0),
packetsPerFrame(0),
imageSize(0),
frameIndexMask(0),
frameIndexOffset(0),
packetIndexMask(0),
packetIndexOffset(0),
maxFramesPerFile(0),
fifoBufferHeaderSize(0),
defaultFifoDepth(0),
threadsPerReceiver(1),
headerPacketSize(0),
nPixelsXComplete(0),
nPixelsYComplete(0),
imageSizeComplete(0),
standardheader(false),
defaultUdpSocketBufferSize(RECEIVE_SOCKET_BUFFER_SIZE)
{};
/** Destructor */
virtual ~GeneralData(){};
/**
* Get Header Infomation (frame number, packet number)
* @param index thread index for debugging purposes
* @param packetData pointer to data
* @param oddStartingPacket odd starting packet (gotthard)
* @param frameNumber frame number
* @param packetNumber packet number
*/
virtual void GetHeaderInfo(int index, char* packetData, bool oddStartingPacket,
uint64_t& frameNumber, uint32_t& packetNumber) const
{
frameNumber = ((uint32_t)(*((uint32_t*)(packetData))));
frameNumber++;
packetNumber = frameNumber&packetIndexMask;
frameNumber = (frameNumber & frameIndexMask) >> frameIndexOffset;
}
/**
* Set ROI
* @param i ROI
*/
virtual void SetROI(slsDetectorDefs::ROI i) {
FILE_LOG(logERROR) << "SetROI is a generic function that should be overloaded by a derived class";
};
/**
* Get Adc configured
* @param index thread index for debugging purposes
* @param ROI
* @returns adc configured
*/
virtual int GetAdcConfigured(int index, slsDetectorDefs::ROI i) const{
FILE_LOG(logERROR) << "GetAdcConfigured is a generic function that should be overloaded by a derived class";
return 0;
};
/**
* Setting dynamic range changes member variables
* @param dr dynamic range
* @param tgEnable true if 10GbE is enabled, else false
*/
virtual void SetDynamicRange(int dr, bool tgEnable) {
FILE_LOG(logERROR) << "SetDynamicRange is a generic function that should be overloaded by a derived class";
};
/**
* Setting ten giga enable changes member variables
* @param tgEnable true if 10GbE is enabled, else false
* @param dr dynamic range
*/
virtual void SetTenGigaEnable(bool tgEnable, int dr) {
FILE_LOG(logERROR) << "SetTenGigaEnable is a generic function that should be overloaded by a derived class";
};
/**
* Enable Gap Pixels changes member variables
* @param enable true if gap pixels enable, else false
* @param dr dynamic range
* @param q quad enable
*/
virtual void SetGapPixelsEnable(bool b, int dr, bool q) {
FILE_LOG(logERROR) << "SetGapPixelsEnable is a generic function that should be overloaded by a derived class";
};
/**
* Set odd starting packet (gotthard)
* @param index thread index for debugging purposes
* @param packetData pointer to data
* @returns true or false for odd starting packet number
*/
virtual bool SetOddStartingPacket(int index, char* packetData) {
FILE_LOG(logERROR) << "SetOddStartingPacket is a generic function that should be overloaded by a derived class";
return false;
};
/**
* Set databytes (ctb, moench)
* @param a adc enable mask
* @param as analog number of samples
* @param ds digital number of samples
* @param t tengiga enable
* @param f readout flags
* @returns analog data bytes
*/
virtual int setImageSize(uint32_t a, uint32_t as, uint32_t ds, bool t, slsDetectorDefs::readoutMode) {
FILE_LOG(logERROR) << "setImageSize is a generic function that should be overloaded by a derived class";
return 0;
};
/**
* set number of interfaces (jungfrau)
* @param n number of interfaces
*/
virtual void SetNumberofInterfaces(const int n) {
FILE_LOG(logERROR) << "SetNumberofInterfaces is a generic function that should be overloaded by a derived class";
}
/**
* set number of counters (mythen3)
* @param n number of counters
* @param dr dynamic range
*/
virtual void SetNumberofCounters(const int n, const int dr) {
FILE_LOG(logERROR) << "SetNumberofCounters is a generic function that should be overloaded by a derived class";
}
/**
* Print all variables
*/
virtual void Print(TLogLevel level = logDEBUG1) const {
FILE_LOG(level) << "\n\nDetector Data Variables:";
FILE_LOG(level) << "myDetectorType: " << sls::ToString(myDetectorType);
FILE_LOG(level) << "Pixels X: " << nPixelsX;
FILE_LOG(level) << "Pixels Y: " << nPixelsY;
FILE_LOG(level) << "Header Size in Packet: " << headerSizeinPacket;
FILE_LOG(level) << "Data Size: " << dataSize;
FILE_LOG(level) << "Packet Size: " << packetSize;
FILE_LOG(level) << "Packets per Frame: " << packetsPerFrame;
FILE_LOG(level) << "Image Size: " << imageSize;
FILE_LOG(level) << "Frame Index Mask: " << frameIndexMask;
FILE_LOG(level) << "Frame Index Offset: " << frameIndexOffset;
FILE_LOG(level) << "Packet Index Mask: " << packetIndexMask;
FILE_LOG(level) << "Packet Index Offset: " << packetIndexOffset;
FILE_LOG(level) << "Max Frames Per File: " << maxFramesPerFile;
FILE_LOG(level) << "Fifo Buffer Header Size: " << fifoBufferHeaderSize;
FILE_LOG(level) << "Default Fifo Depth: " << defaultFifoDepth;
FILE_LOG(level) << "Threads Per Receiver: " << threadsPerReceiver;
FILE_LOG(level) << "Header Packet Size: " << headerPacketSize;
FILE_LOG(level) << "Complete Pixels X: " << nPixelsXComplete;
FILE_LOG(level) << "Complete Pixels Y: " << nPixelsYComplete;
FILE_LOG(level) << "Complete Image Size: " << imageSizeComplete;
FILE_LOG(level) << "Standard Header: " << standardheader;
FILE_LOG(level) << "UDP Socket Buffer Size: " << defaultUdpSocketBufferSize;
};
};
class GotthardData : public GeneralData {
private:
const int nChip = 10;
const int nChan = 128;
const int nChipsPerAdc = 2;
public:
/** Constructor */
GotthardData(){
myDetectorType = slsDetectorDefs::GOTTHARD;
nPixelsX = 1280;
nPixelsY = 1;
headerSizeinPacket = 4;
dataSize = 1280;
packetSize = GOTTHARD_PACKET_SIZE;
packetsPerFrame = 2;
imageSize = dataSize*packetsPerFrame;
frameIndexMask = 0xFFFFFFFE;
frameIndexOffset = 1;
packetIndexMask = 1;
maxFramesPerFile = MAX_FRAMES_PER_FILE;
fifoBufferHeaderSize= FIFO_HEADER_NUMBYTES + sizeof(slsDetectorDefs::sls_receiver_header);
defaultFifoDepth = 50000;
};
/**
* Get Header Infomation (frame number, packet number)
* @param index thread index for debugging purposes
* @param packetData pointer to data
* @param oddStartingPacket odd starting packet (gotthard)
* @param frameNumber frame number
* @param packetNumber packet number
*/
void GetHeaderInfo(int index, char* packetData, bool oddStartingPacket,
uint64_t& frameNumber, uint32_t& packetNumber) const
{
if (nPixelsX == 1280) {
frameNumber = *reinterpret_cast<uint32_t*>(packetData);
if (oddStartingPacket)
frameNumber++;
packetNumber = frameNumber&packetIndexMask;
frameNumber = (frameNumber & frameIndexMask) >> frameIndexOffset;
} else {
frameNumber = *reinterpret_cast<uint32_t *>(packetData);
packetNumber = 0;
}
}
/**
* Set ROI
* @param i ROI
*/
void SetROI(slsDetectorDefs::ROI i) {
// all adcs
if(i.xmin == -1) {
nPixelsX = 1280;
dataSize = 1280;
packetSize = GOTTHARD_PACKET_SIZE;
packetsPerFrame = 2;
imageSize = dataSize*packetsPerFrame;
frameIndexMask = 0xFFFFFFFE;
frameIndexOffset = 1;
packetIndexMask = 1;
maxFramesPerFile = MAX_FRAMES_PER_FILE;
fifoBufferHeaderSize= FIFO_HEADER_NUMBYTES + sizeof(slsDetectorDefs::sls_receiver_header);
defaultFifoDepth = 50000;
nPixelsXComplete = 0;
nPixelsYComplete = 0;
imageSizeComplete = 0;
}
// single adc
else {
nPixelsX = 256;
dataSize = 512;
packetSize = 518;
packetsPerFrame = 1;
imageSize = dataSize*packetsPerFrame;
frameIndexMask = 0xFFFFFFFF;
frameIndexOffset = 0;
packetIndexMask = 0;
maxFramesPerFile = SHORT_MAX_FRAMES_PER_FILE;
fifoBufferHeaderSize= FIFO_HEADER_NUMBYTES + sizeof(slsDetectorDefs::sls_receiver_header);
defaultFifoDepth = 75000;
nPixelsXComplete = 1280;
nPixelsYComplete = 1;
imageSizeComplete = 1280 * 2;
}
};
/**
* Get Adc configured
* @param index thread index for debugging purposes
* @param i ROI
* @returns adc configured
*/
int GetAdcConfigured(int index, slsDetectorDefs::ROI i) const{
int adc = -1;
// single adc
if(i.xmin != -1) {
// gotthard can have only one adc per detector enabled (or all)
//adc = mid value/numchans also for only 1 roi
adc = ((((i.xmax) + (i.xmin))/2)/
(nChan * nChipsPerAdc));
if((adc < 0) || (adc > 4)) {
FILE_LOG(logWARNING) << index << ": Deleting ROI. "
"Adc value should be between 0 and 4";
adc = -1;
}
}
FILE_LOG(logINFO) << "Adc Configured: " << adc;
return adc;
};
/**
* Set odd starting packet (gotthard)
* @param index thread index for debugging purposes
* @param packetData pointer to data
* @returns true or false for odd starting packet number
*/
bool SetOddStartingPacket(int index, char* packetData) {
bool oddStartingPacket = true;
// care only if no roi
if (nPixelsX == 1280) {
uint32_t fnum = ((uint32_t)(*((uint32_t*)(packetData))));
uint32_t firstData = ((uint32_t)(*((uint32_t*)(packetData + 4))));
// first packet
if (firstData == 0xCACACACA) {
// packet number should be 0, but is 1 => so odd starting packet
if (fnum & packetIndexMask) {
oddStartingPacket = true;
} else {
oddStartingPacket = false;
}
}
// second packet
else {
// packet number should be 1, but is 0 => so odd starting packet
if (!(fnum & packetIndexMask)) {
oddStartingPacket = true;
} else {
oddStartingPacket = false;
}
}
}
return oddStartingPacket;
};
};
class EigerData : public GeneralData {
public:
/** Constructor */
EigerData(){
myDetectorType = slsDetectorDefs::EIGER;
nPixelsX = (256*2);
nPixelsY = 256;
headerSizeinPacket = sizeof(slsDetectorDefs::sls_detector_header);
dataSize = 1024;
packetSize = headerSizeinPacket + dataSize;
packetsPerFrame = 256;
imageSize = dataSize*packetsPerFrame;
maxFramesPerFile = EIGER_MAX_FRAMES_PER_FILE;
fifoBufferHeaderSize= FIFO_HEADER_NUMBYTES + sizeof(slsDetectorDefs::sls_receiver_header);
defaultFifoDepth = 100;
threadsPerReceiver = 2;
headerPacketSize = 40;
standardheader = true;
};
/**
* Setting dynamic range changes member variables
* @param dr dynamic range
* @param tgEnable true if 10GbE is enabled, else false
*/
void SetDynamicRange(int dr, bool tgEnable) {
packetsPerFrame = (tgEnable ? 4 : 16) * dr;
imageSize = dataSize*packetsPerFrame;
}
/**
* Setting ten giga enable changes member variables
* @param tgEnable true if 10GbE is enabled, else false
* @param dr dynamic range
*/
void SetTenGigaEnable(bool tgEnable, int dr) {
dataSize = (tgEnable ? 4096 : 1024);
packetSize = headerSizeinPacket + dataSize;
packetsPerFrame = (tgEnable ? 4 : 16) * dr;
imageSize = dataSize*packetsPerFrame;
};
/**
* Enable Gap Pixels changes member variables
* @param enable true if gap pixels enable, else false
* @param dr dynamic range
* @param q quad enable
*/
void SetGapPixelsEnable(bool b, int dr, bool q) {
if (dr == 4)
b = 0;
switch((int)b) {
case 1:
nPixelsX = (256 * 2) + 3;
if (q) {
nPixelsX = (256 * 2) + 2;
}
nPixelsY = 256 + 1;
imageSize = nPixelsX * nPixelsY * ((dr > 16) ? 4 : // 32 bit
((dr > 8) ? 2 : // 16 bit
((dr > 4) ? 1 : // 8 bit
0.5))); // 4 bit
break;
default:
nPixelsX = (256*2);
nPixelsY = 256;
imageSize = nPixelsX * nPixelsY * ((dr > 16) ? 4 : // 32 bit
((dr > 8) ? 2 : // 16 bit
((dr > 4) ? 1 : // 8 bit
0.5))); // 4 bit
break;
}
};
};
class JungfrauData : public GeneralData {
public:
/** Constructor */
JungfrauData(){
myDetectorType = slsDetectorDefs::JUNGFRAU;
nPixelsX = (256*4);
nPixelsY = 512;
headerSizeinPacket = sizeof(slsDetectorDefs::sls_detector_header);
dataSize = 8192;
packetSize = headerSizeinPacket + dataSize;
packetsPerFrame = 128;
imageSize = dataSize * packetsPerFrame;
maxFramesPerFile = JFRAU_MAX_FRAMES_PER_FILE;
fifoBufferHeaderSize= FIFO_HEADER_NUMBYTES + sizeof(slsDetectorDefs::sls_receiver_header);
defaultFifoDepth = 2500;
standardheader = true;
defaultUdpSocketBufferSize = (1000 * 1024 * 1024);
};
/**
* set number of interfaces (jungfrau)
* @param number of interfaces
*/
void SetNumberofInterfaces(const int n) {
// 2 interfaces
if (n == 2) {
nPixelsY = 256;
packetsPerFrame = 64;
imageSize = dataSize * packetsPerFrame;
threadsPerReceiver = 2;
defaultUdpSocketBufferSize = (500 * 1024 * 1024);
}
// 1 interface
else {
nPixelsY = 512;
packetsPerFrame = 128;
imageSize = dataSize * packetsPerFrame;
threadsPerReceiver = 1;
defaultUdpSocketBufferSize = (1000 * 1024 * 1024);
}
}
};
class Mythen3Data : public GeneralData {
private:
int ncounters;
const int NCHAN = 1280;
public:
/** Constructor */
Mythen3Data(){
myDetectorType = slsDetectorDefs::MYTHEN3;
ncounters = 3;
nPixelsX = (NCHAN * ncounters); // max 1280 channels x 3 counters
nPixelsY = 1;
headerSizeinPacket = sizeof(slsDetectorDefs::sls_detector_header);
dataSize = 7680;
packetSize = headerSizeinPacket + dataSize;
packetsPerFrame = 2;
imageSize = dataSize * packetsPerFrame;
maxFramesPerFile = MYTHEN3_MAX_FRAMES_PER_FILE;
fifoBufferHeaderSize= FIFO_HEADER_NUMBYTES + sizeof(slsDetectorDefs::sls_receiver_header);
defaultFifoDepth = 50000;
standardheader = true;
defaultUdpSocketBufferSize = (1000 * 1024 * 1024);
};
/**
* set number of counters (mythen3)
* @param n number of counters
* @param dr dynamic range
*/
virtual void SetNumberofCounters(const int n, const int dr) {
if (n < 1 || n > 3) {
throw sls::RuntimeError("Invalid number of counters " + std::to_string(n));
}
ncounters = n;
nPixelsX = NCHAN * ncounters;
FILE_LOG(logINFO) << "nPixelsX: " << nPixelsX;
imageSize = nPixelsX * nPixelsY * ((dr > 16) ? 4 : // 32 bit
((dr > 8) ? 2 : // 16 bit
((dr > 4) ? 0.5 : // 4 bit
0.125))); // 1 bit
dataSize = imageSize / packetsPerFrame;
packetSize = headerSizeinPacket + dataSize;
FILE_LOG(logINFO) << "PacketSize: " << packetSize;
}
/**
* Setting dynamic range changes member variables
* @param dr dynamic range
* @param tgEnable (discarded, of no value to mythen3)
*/
void SetDynamicRange(int dr, bool tgEnable) {
imageSize = nPixelsX * nPixelsY * ((dr > 16) ? 4 : // 32 bit
((dr > 8) ? 2 : // 16 bit
((dr > 4) ? 0.5 : // 4 bit
0.125))); // 1 bit
dataSize = imageSize / packetsPerFrame;
packetSize = headerSizeinPacket + dataSize;
FILE_LOG(logINFO) << "PacketSize: " << packetSize;
}
};
class Gotthard2Data : public GeneralData {
public:
/** Constructor */
Gotthard2Data(){
myDetectorType = slsDetectorDefs::GOTTHARD2;
nPixelsX = 128 * 10;
nPixelsY = 1;
headerSizeinPacket = sizeof(slsDetectorDefs::sls_detector_header);
dataSize = 2560; // 1280 channels * 2 bytes
packetSize = headerSizeinPacket + dataSize;
packetsPerFrame = 1;
imageSize = dataSize * packetsPerFrame;
maxFramesPerFile = GOTTHARD2_MAX_FRAMES_PER_FILE;
fifoBufferHeaderSize= FIFO_HEADER_NUMBYTES + sizeof(slsDetectorDefs::sls_receiver_header);
defaultFifoDepth = 50000;
standardheader = true;
defaultUdpSocketBufferSize = (1000 * 1024 * 1024);
};
};
class ChipTestBoardData : public GeneralData {
private:
/** Number of analog channels */
const int NCHAN_ANALOG = 32;
/** Number of digital channels */
const int NCHAN_DIGITAL = 64;
/** Number of bytes per analog channel */
const int NUM_BYTES_PER_ANALOG_CHANNEL = 2;
struct ctb_10g_packet_header {
unsigned char emptyHeader[6];
unsigned char reserved[4];
uint32_t packetFrameNumber;
uint64_t bunchid;
} __attribute__((packed));
public:
/** Constructor */
ChipTestBoardData(){
myDetectorType = slsDetectorDefs::CHIPTESTBOARD;
nPixelsX = 36; // total number of channels
nPixelsY = 1; // number of samples
headerSizeinPacket = sizeof(slsDetectorDefs::sls_detector_header);
dataSize = UDP_PACKET_DATA_BYTES;
packetSize = headerSizeinPacket + dataSize;
//packetsPerFrame = 1;
imageSize = nPixelsX * nPixelsY * 2;
frameIndexMask = 0xFFFFFF; // 10g
frameIndexOffset = 8; // 10g
packetIndexMask = 0xFF; //10g
packetsPerFrame = ceil((double)imageSize / (double)UDP_PACKET_DATA_BYTES);
maxFramesPerFile = CTB_MAX_FRAMES_PER_FILE;
fifoBufferHeaderSize= FIFO_HEADER_NUMBYTES + sizeof(slsDetectorDefs::sls_receiver_header);
defaultFifoDepth = 2500;
standardheader = true;
};
/**
* Set databytes (ctb, moench)
* @param a adc enable mask
* @param as analog number of samples
* @param ds digital number of samples
* @param t tengiga enable
* @param f readout flags
* @returns analog data bytes
*/
int setImageSize(uint32_t a, uint32_t as, uint32_t ds, bool t, slsDetectorDefs::readoutMode f) {
int nachans = 0, ndchans = 0;
int adatabytes = 0, ddatabytes = 0;
// analog channels (normal, analog/digital readout)
if (f == slsDetectorDefs::ANALOG_ONLY ||
f == slsDetectorDefs::ANALOG_AND_DIGITAL) {
if (a == BIT32_MASK) {
nachans = 32;
} else {
for (int ich = 0; ich < 32; ++ich) {
if (a & (1 << ich))
++nachans;
}
}
adatabytes = nachans * NUM_BYTES_PER_ANALOG_CHANNEL * as;
FILE_LOG(logDEBUG1) << " Number of Analog Channels:" << nachans
<< " Databytes: " << adatabytes;
}
// digital channels
if (f == slsDetectorDefs::DIGITAL_ONLY ||
f == slsDetectorDefs::ANALOG_AND_DIGITAL) {
ndchans = NCHAN_DIGITAL;
ddatabytes = (sizeof(uint64_t) * ds);
FILE_LOG(logDEBUG1) << "Number of Digital Channels:" << ndchans
<< " Databytes: " << ddatabytes;
}
FILE_LOG(logDEBUG1) << "Total Number of Channels:" << nachans + ndchans
<< " Databytes: " << adatabytes + ddatabytes;
nPixelsX = nachans + ndchans;
nPixelsY = 1;
// 10G
if (t) {
headerSizeinPacket = sizeof(slsDetectorDefs::sls_detector_header);
dataSize = 8144;
packetSize = headerSizeinPacket + dataSize;
imageSize = adatabytes + ddatabytes;
packetsPerFrame = ceil((double)imageSize / (double)dataSize);
standardheader = true;
/*
headerSizeinPacket = 22;
dataSize = 8192;
packetSize = headerSizeinPacket + dataSize;
imageSize = adatabytes + ddatabytes;
packetsPerFrame = ceil((double)imageSize / (double)dataSize);
standardheader = false;
*/
}
// 1g udp (via fifo readout)
else {
headerSizeinPacket = sizeof(slsDetectorDefs::sls_detector_header);
dataSize = UDP_PACKET_DATA_BYTES;
packetSize = headerSizeinPacket + dataSize;
imageSize = adatabytes + ddatabytes;
packetsPerFrame = ceil((double)imageSize / (double)dataSize);
standardheader = true;
}
return adatabytes;
}
/**
* Get Header Infomation (frame number, packet number)
* @param index thread index for debugging purposes
* @param packetData pointer to data
* @param oddStartingPacket odd starting packet (gotthard)
* @param frameNumber frame number
* @param packetNumber packet number
*/
void GetHeaderInfo(int index, char* packetData, bool oddStartingPacket,
uint64_t& frameNumber, uint32_t& packetNumber) const
{
auto header = reinterpret_cast<ctb_10g_packet_header*>(packetData);
frameNumber = (header->packetFrameNumber >> frameIndexOffset) & frameIndexMask;
packetNumber = header->packetFrameNumber & packetIndexMask;
}
};
class MoenchData : public GeneralData {
private:
/** Number of bytes per analog channel */
const int NUM_BYTES_PER_ANALOG_CHANNEL = 2;
public:
/** Constructor */
MoenchData() {
myDetectorType = slsDetectorDefs::MOENCH;
nPixelsX = 32; // total number of channels
nPixelsY = 1; // number of samples
headerSizeinPacket = sizeof(slsDetectorDefs::sls_detector_header);
dataSize = UDP_PACKET_DATA_BYTES;
packetSize = headerSizeinPacket + dataSize;
// packetsPerFrame = 1;
imageSize = nPixelsX * nPixelsY * 2;
packetsPerFrame = ceil((double)imageSize / (double)UDP_PACKET_DATA_BYTES);
frameIndexMask = 0xFFFFFF;
maxFramesPerFile = CTB_MAX_FRAMES_PER_FILE;
fifoBufferHeaderSize = FIFO_HEADER_NUMBYTES + sizeof(slsDetectorDefs::sls_receiver_header);
defaultFifoDepth = 2500;
standardheader = true;
};
/**
* Set databytes (ctb, moench)
* @param a adc enable mask
* @param as analog number of samples
* @param ds digital number of samples
* @param t tengiga enable
* @param f readout flags
* @returns analog data bytes
*/
int setImageSize(uint32_t a, uint32_t as, uint32_t ds, bool t, slsDetectorDefs::readoutMode) {
int nachans = 0;
int adatabytes = 0;
// analog channels (normal, analog/digital readout)
if (a == BIT32_MASK) {
nachans = 32;
} else {
for (int ich = 0; ich < 32; ++ich) {
if (a & (1 << ich))
++nachans;
}
}
adatabytes = nachans * NUM_BYTES_PER_ANALOG_CHANNEL * as;
FILE_LOG(logDEBUG1) << "Total Number of Channels:" << nachans
<< " Databytes: " << adatabytes;
nPixelsX = nachans;
nPixelsY = 1;
// 10G
if (t) {
headerSizeinPacket = sizeof(slsDetectorDefs::sls_detector_header);
dataSize = UDP_PACKET_DATA_BYTES;
packetSize = headerSizeinPacket + dataSize;
imageSize = adatabytes;
packetsPerFrame = ceil((double)imageSize / (double)dataSize);
}
// 1g udp (via fifo readout)
else {
headerSizeinPacket = sizeof(slsDetectorDefs::sls_detector_header);
dataSize = UDP_PACKET_DATA_BYTES;
packetSize = headerSizeinPacket + dataSize;
imageSize = adatabytes;
packetsPerFrame = ceil((double)imageSize / (double)dataSize);
}
return adatabytes;
}
};

View File

@ -0,0 +1,186 @@
#ifdef HDF5C
#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 "HDF5FileStatic.h"
#include "H5Cpp.h"
#ifndef H5_NO_NAMESPACE
using namespace H5;
#endif
#include <mutex>
class HDF5File : private virtual slsDetectorDefs, public File, public HDF5FileStatic {
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);
/**
* Destructor
*/
~HDF5File();
/**
* Print all member values
*/
void PrintMembers(TLogLevel level = logDEBUG1);
/**
* Set Number of pixels
* @param nx number of pixels in x direction
* @param ny number of pixels in y direction
*/
void SetNumberofPixels(uint32_t nx, uint32_t ny);
/**
* Create file
* @param fnum current frame index to include in file name
*/
void CreateFile();
/**
* Close Current File
*/
void CloseCurrentFile();
/**
* Close all Files
*/
void CloseAllFiles();
/**
* Write data to file
* @param buffer buffer to write from
* @param bsize size of buffer (not used)
* @param fnum current image number
* @param nump number of packets caught
*/
void WriteToFile(char* buffer, int bsize, uint64_t fnum, uint32_t nump);
/**
* Create master file
* @param mfwenable master file write enable
* @param attr master file attributes
*/
void CreateMasterFile(bool mfwenable, masterAttributes& attr);
/**
* 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);
private:
/**
* Create Virtual File
* @param numf number of images caught
*/
void CreateVirtualFile(uint64_t numf);
/**
* Link virtual file in master file
* Only for Jungfrau at the moment for 1 module and 1 data file
*/
void LinkVirtualFileinMasterFile();
/**
* Get Type
* @return type
*/
fileFormat GetFileType();
/**
* Updates data type depending on current dynamic range
*/
void UpdateDataType();
/** mutex to update static items among objects (threads)*/
static mutable std::mutex mutex;
/** Master File handle */
static H5File* masterfd;
/** Virtual File handle ( only file name because code in C as H5Pset_virtual doesnt exist yet in C++) */
static hid_t virtualfd;
/** File handle */
H5File* filefd;
/** Dataspace handle */
DataSpace* dataspace;
/** DataSet handle */
DataSet* dataset;
/** Datatype of dataset */
DataType datatype;
/** Number of pixels in x direction */
uint32_t nPixelsX;
/** Number of pixels in y direction */
uint32_t nPixelsY;
/** Number of frames in file */
uint32_t numFramesInFile;
/** Number of actual packets caught in file */
uint64_t numActualPacketsInFile;
/** Number of files in an acquisition - to verify need of virtual file */
int numFilesinAcquisition;
/** parameter names */
std::vector <const char*> parameterNames;
/** parameter data types */
std::vector <DataType> parameterDataTypes;
/** Dataspace of parameters */
DataSpace* dataspace_para;
/** Dataset array for parameters */
std::vector <DataSet*> dataset_para;
/** Number of Images (including extended during acquisition) */
uint64_t extNumImages;
};
#endif

View File

@ -0,0 +1,952 @@
#ifdef HDF5C
#pragma once
/************************************************
* @file HDF5FileStatic.h
* @short creating, closing, writing and reading
* from HDF5 files
***********************************************/
/**
*@short creating, closing, writing and reading from HDF5 files
*/
#include "H5Cpp.h"
#ifndef H5_NO_NAMESPACE
using namespace H5;
#endif
#include "sls_detector_defs.h"
#include "logger.h"
#include <iostream>
#include <string>
#include <vector>
#include <iomanip>
#include <stdlib.h> //malloc
#include <sstream>
#include <cstring> //memset
class HDF5FileStatic: public virtual slsDetectorDefs {
public:
/** Constructor */
HDF5FileStatic(){};
/** Destructor */
virtual ~HDF5FileStatic(){};
/**
* Create File Name in format fpath/fnameprefix_fx_dy_z.raw,
* where x is fnum, y is (dindex * numunits + unitindex) and z is findex
* @param fpath file path
* @param fnameprefix file name prefix
* @param findex file index
* @param subfindex sub file index
* @param dindex readout index
* @param numunits number of units per readout. eg. eiger has 2 udp units per readout
* @param unitindex unit index
* @returns complete file name created
*/
static std::string CreateFileName(std::string fpath, std::string fprefix,
uint64_t findex, uint64_t subfindex,
int dindex, int numunits = 1,
int unitindex = 0) {
std::ostringstream os;
os << fpath << "/" << fprefix << "_d"
<< (dindex * numunits + unitindex) << "_f" << subfindex << '_'
<< findex << ".h5";
return os.str();
}
/**
* Create master file name
* @param fpath file path
* @param fnameprefix file name prefix
* @param findex file index
* @returns master file name
*/
static std::string CreateMasterFileName(std::string fpath, std::string fnameprefix, uint64_t findex)
{
std::ostringstream os;
os << fpath << "/" << fnameprefix << "_master"
<< "_" << findex << ".h5";
return os.str();
}
/**
* Create virtual file name
* @param fpath file path
* @param fnameprefix file name prefix
* @param fnum current frame number
* @param findex file index
* @returns virtual file name
*/
static std::string CreateVirtualFileName(std::string fpath, std::string fnameprefix, uint64_t findex)
{
std::ostringstream osfn;
osfn << fpath << "/" << fnameprefix;
osfn << "_virtual";
osfn << "_" << findex;
osfn << ".h5";
return osfn.str();
}
/**
* Close File
* @param ind index for debugging
* @param fd file pointer
* @param dp dataspace pointer
* @param ds dataset pointer
* @param ds_para pointer to array of parameter datasets
*/
static void CloseDataFile(int ind, H5File*& fd)
{
try {
Exception::dontPrint(); //to handle errors
if (fd) {
delete fd;
fd = 0;
}
} catch(const Exception& error) {
FILE_LOG(logERROR) << "Could not close HDF5 handles of index " << ind;
error.printErrorStack();
}
}
/*
* Close master file
* @param fd master hdf5 file object
*/
static void CloseMasterDataFile(H5File*& fd)
{
try {
Exception::dontPrint(); //to handle errors
if (fd) {
delete fd;
fd = 0;
}
} catch(const Exception& error) {
FILE_LOG(logERROR) << "Could not close master HDF5 handles";
error.printErrorStack();
}
}
/*
* Close virtual file
* (in C because H5Pset_virtual doesnt exist yet in C++)
* @param fd virtual hdf5 file handle
*/
static void CloseVirtualDataFile(hid_t& fd)
{
if(fd) {
if (H5Fclose(fd) < 0 ) {
FILE_LOG(logERROR) << "Could not close virtual HDF5 handles";
}
fd = 0;
}
}
/**
* Write data to file
* @param ind object index for debugging
* @param buf buffer to write from
* @param nDimx image number in file (imagenumber%maxframesinfile)
* @param nDimy number of pixels in y direction
* @param nDimz number of pixels in x direction
* @param dspace dataspace pointer
* @param dset dataset pointer
* @param dtype datatype
*/
static void WriteDataFile(int ind, char* buf,
uint64_t nDimx, uint32_t nDimy, uint32_t nDimz,
DataSpace* dspace, DataSet* dset, DataType dtype)
{
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
dspace->selectHyperslab( H5S_SELECT_SET, count, start);
DataSpace memspace(2,dims2);
dset->write(buf, dtype, memspace, *dspace);
memspace.close();
}
catch(const Exception& error){
FILE_LOG(logERROR) << "Could not write to file in object " << ind;
error.printErrorStack();
throw RuntimeError("Could not write to file in object " + std::to_string(ind));
}
}
/**
* Write Parameter Arrays as datasets (to virtual file)
* @param ind self index
* @param dspace_para parameter dataspace
* @param fnum current frame number
* @param dset_para vector or dataset pointers of parameters
* @param rheader sls_receiver_header pointer
* @param parameterDataTypes parameter datatypes
*/
static void WriteParameterDatasets(int ind, DataSpace* dspace_para, uint64_t fnum,
std::vector <DataSet*> dset_para,sls_receiver_header* rheader,
std::vector <DataType> parameterDataTypes)
{
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
dspace_para->selectHyperslab( H5S_SELECT_SET, count, start);
DataSpace memspace(H5S_SCALAR);
dset_para[0]->write(&header.frameNumber, parameterDataTypes[0], memspace, *dspace_para);i=1;
dset_para[1]->write(&header.expLength, parameterDataTypes[1], memspace, *dspace_para);i=2;
dset_para[2]->write(&header.packetNumber, parameterDataTypes[2], memspace, *dspace_para);i=3;
dset_para[3]->write(&header.bunchId, parameterDataTypes[3], memspace, *dspace_para);i=4;
dset_para[4]->write(&header.timestamp, parameterDataTypes[4], memspace, *dspace_para);i=5;
dset_para[5]->write(&header.modId, parameterDataTypes[5], memspace, *dspace_para);i=6;
dset_para[6]->write(&header.row, parameterDataTypes[6], memspace, *dspace_para);i=7;
dset_para[7]->write(&header.column, parameterDataTypes[7], memspace, *dspace_para);i=8;
dset_para[8]->write(&header.reserved, parameterDataTypes[8], memspace, *dspace_para);i=9;
dset_para[9]->write(&header.debug, parameterDataTypes[9], memspace, *dspace_para);i=10;
dset_para[10]->write(&header.roundRNumber, parameterDataTypes[10], memspace, *dspace_para);i=11;
dset_para[11]->write(&header.detType, parameterDataTypes[11], memspace, *dspace_para);i=12;
dset_para[12]->write(&header.version, parameterDataTypes[12], memspace, *dspace_para);i=13;
// contiguous bitset
if (sizeof(sls_bitset) == sizeof(bitset_storage)) {
dset_para[13]->write((char*)&(rheader->packetsMask), parameterDataTypes[13], memspace, *dspace_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
dset_para[13]->write((char*)storage, parameterDataTypes[13], memspace, *dspace_para);
}i=14;
}
catch(const Exception& error){
error.printErrorStack();
throw RuntimeError("Could not write parameters (index:" + std::to_string(i) + ") to file in object " + std::to_string(ind));
}
}
/**
* Extend datasets in #images dimension (x dimension)
* @param ind self index
* @param dpace data space pointer address
* @param dset data set pointer
* @param dspace_para parameter dataspace address pointer
* @param dset dataset parameter pointer
* @param initialNumImages initial number of images
*/
static void ExtendDataset(int ind, DataSpace*& dspace, DataSet* dset,
DataSpace*& dspace_para, std::vector <DataSet*> dset_para,
uint64_t initialNumImages) {
try{
Exception::dontPrint(); //to handle errors
hsize_t dims[3];
dspace->getSimpleExtentDims(dims);
dims[0] += initialNumImages;
dset->extend(dims);
delete dspace;
dspace = 0;
dspace = new DataSpace(dset->getSpace());
hsize_t dims_para[1] = {dims[0]};
for (unsigned int i = 0; i < dset_para.size(); ++i)
dset_para[i]->extend(dims_para);
delete dspace_para;
dspace_para = 0;
dspace_para = new DataSpace(dset_para[0]->getSpace());
}
catch(const Exception& error){
error.printErrorStack();
throw RuntimeError("Could not extend dataset in object " + std::to_string(ind));
}
}
/**
* Create master file
* @param fname master file name
* @param owenable overwrite enable
* @param attr master file attributes
*/
static void CreateMasterDataFile(H5File*& fd, std::string fname, bool owenable,
masterAttributes& attr)
{
try {
Exception::dontPrint(); //to handle errors
FileAccPropList flist;
flist.setFcloseDegree(H5F_CLOSE_STRONG);
fd = 0;
if(!owenable)
fd = new H5File( fname.c_str(), H5F_ACC_EXCL,
FileCreatPropList::DEFAULT,
flist );
else
fd = new H5File( fname.c_str(), H5F_ACC_TRUNC,
FileCreatPropList::DEFAULT,
flist );
//variables
DataSpace dataspace = DataSpace (H5S_SCALAR);
Attribute attribute;
DataSet dataset;
int iValue=0;
double dValue=0;
StrType strdatatype(PredType::C_S1,256);
//create attributes
//version
dValue = attr.version;
attribute = fd->createAttribute("version",PredType::NATIVE_DOUBLE, dataspace);
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") );
//Dynamic Range
dataset = group5.createDataSet ( "dynamic range", PredType::NATIVE_INT, dataspace );
dataset.write ( &(attr.dynamicRange), PredType::NATIVE_INT);
attribute = dataset.createAttribute("unit",strdatatype, dataspace);
attribute.write(strdatatype, std::string("bits"));
//Ten Giga
iValue = attr.tenGiga;
dataset = group5.createDataSet ( "ten giga enable", PredType::NATIVE_INT, dataspace );
dataset.write ( &iValue, PredType::NATIVE_INT);
//Image Size
dataset = group5.createDataSet ( "image size", PredType::NATIVE_INT, dataspace );
dataset.write ( &(attr.imageSize), PredType::NATIVE_INT);
attribute = dataset.createAttribute("unit",strdatatype, dataspace);
attribute.write(strdatatype, std::string("bytes"));
//x
dataset = group5.createDataSet ( "number of pixels in x axis", PredType::NATIVE_INT, dataspace );
dataset.write ( &(attr.nPixelsX), PredType::NATIVE_INT);
//y
dataset = group5.createDataSet ( "number of pixels in y axis", PredType::NATIVE_INT, dataspace );
dataset.write ( &(attr.nPixelsY), PredType::NATIVE_INT);
//Maximum frames per file
dataset = group5.createDataSet ( "maximum frames per file", PredType::NATIVE_INT, dataspace );
dataset.write ( &(attr.maxFramesPerFile), PredType::NATIVE_INT);
//Total Frames
dataset = group5.createDataSet ( "total frames", PredType::STD_U64LE, dataspace );
dataset.write ( &(attr.totalFrames), PredType::STD_U64LE);
//Exptime
dataset = group5.createDataSet ( "exposure time", PredType::STD_U64LE, dataspace );
dataset.write ( &(attr.exptimeNs), PredType::STD_U64LE);
attribute = dataset.createAttribute("unit",strdatatype, dataspace);
attribute.write(strdatatype, std::string("ns"));
//SubExptime
dataset = group5.createDataSet ( "sub exposure time", PredType::STD_U64LE, dataspace );
dataset.write ( &(attr.subExptimeNs), PredType::STD_U64LE);
attribute = dataset.createAttribute("unit",strdatatype, dataspace);
attribute.write(strdatatype, std::string("ns"));
//SubPeriod
dataset = group5.createDataSet ( "sub period", PredType::STD_U64LE, dataspace );
dataset.write ( &(attr.subPeriodNs), PredType::STD_U64LE);
attribute = dataset.createAttribute("unit",strdatatype, dataspace);
attribute.write(strdatatype, std::string("ns"));
//Period
dataset = group5.createDataSet ( "acquisition period", PredType::STD_U64LE, dataspace );
dataset.write ( &(attr.periodNs), PredType::STD_U64LE);
attribute = dataset.createAttribute("unit",strdatatype, dataspace);
attribute.write(strdatatype, std::string("ns"));
//Gap Pixels Enable
dataset = group5.createDataSet ( "gap pixels enable", PredType::NATIVE_INT, dataspace );
dataset.write ( &(attr.gapPixelsEnable), PredType::NATIVE_INT);
//Quad Enable
dataset = group5.createDataSet ( "quad enable", PredType::NATIVE_INT, dataspace );
dataset.write ( &(attr.quadEnable), PredType::NATIVE_INT);
//Gap Pixels Enable
dataset = group5.createDataSet ( "gap pixels enable", PredType::NATIVE_INT, dataspace );
dataset.write ( &(attr.gapPixelsEnable), PredType::NATIVE_INT);
//Quad Enable
dataset = group5.createDataSet ( "quad enable", PredType::NATIVE_INT, dataspace );
dataset.write ( &(attr.quadEnable), PredType::NATIVE_INT);
//Analog Flag
dataset = group5.createDataSet ( "analog flag", PredType::NATIVE_INT, dataspace );
dataset.write ( &(attr.quadEnable), PredType::NATIVE_INT);
//Digital Flag
dataset = group5.createDataSet ( "digital flag", PredType::NATIVE_INT, dataspace );
dataset.write ( &(attr.gapPixelsEnable), PredType::NATIVE_INT);
//ADC Mask
dataset = group5.createDataSet ( "adc mask", PredType::NATIVE_INT, dataspace );
dataset.write ( &(attr.quadEnable), PredType::NATIVE_INT);
//Dbit Offset
dataset = group5.createDataSet ( "dbit offset", PredType::NATIVE_INT, dataspace );
dataset.write ( &(attr.gapPixelsEnable), PredType::NATIVE_INT);
// Dbit List
dataset = group5.createDataSet ( "dbit bitset list", PredType::STD_U64LE, dataspace );
dataset.write ( &(attr.periodNs), PredType::STD_U64LE);
// Roi xmin
dataset = group5.createDataSet ( "roi xmin", PredType::NATIVE_INT, dataspace );
dataset.write ( &(attr.roiXmin), PredType::NATIVE_INT);
// Roi xmax
dataset = group5.createDataSet ( "roi xmax", PredType::NATIVE_INT, dataspace );
dataset.write ( &(attr.roiXmax), PredType::NATIVE_INT);
//Timestamp
time_t t = time(0);
dataset = group5.createDataSet ( "timestamp", strdatatype, dataspace );
dataset.write ( std::string(ctime(&t)), strdatatype );
fd->close();
} catch(const Exception& error) {
error.printErrorStack();
if (fd) fd->close();
throw RuntimeError("Could not create master HDF5 handles");
}
}
/**
* Create File
* @param ind object index for debugging
* @param owenable overwrite enable
* @param fname complete file name
* @param frindexenable frame index enable
* @param fnum current image number
* @param nDimx number of pixels in x dim (#frames)
* @param nDimy number of pixels in y dim (height y dir)
* @param nDimz number of pixels in z dim (width x dir)
* @param dtype data type
* @param fd file pointer
* @param dspace dataspace pointer
* @param dset dataset pointer
* @param version version of software for hdf5 writing
* @param maxchunkedimages maximum chunked images
* @param dspace_para dataspace of parameters
* @param dset_para vector of datasets of parameters
* @param parameterNames parameter names
* @param parameterDataTypes parameter datatypes
*/
static void CreateDataFile(int ind, bool owenable, std::string fname, bool frindexenable,
uint64_t fnum, uint64_t nDimx, uint32_t nDimy, uint32_t nDimz,
DataType dtype, H5File*& fd, DataSpace*& dspace, DataSet*& dset,
double version, uint64_t maxchunkedimages,
DataSpace*& dspace_para, std::vector<DataSet*>& dset_para,
std::vector <const char*> parameterNames,
std::vector <DataType> parameterDataTypes)
{
try {
Exception::dontPrint(); //to handle errors
//file
FileAccPropList fapl;
fapl.setFcloseDegree(H5F_CLOSE_STRONG);
fd = 0;
if(!owenable)
fd = new H5File( fname.c_str(), H5F_ACC_EXCL,
FileCreatPropList::DEFAULT,
fapl );
else
fd = new H5File( fname.c_str(), H5F_ACC_TRUNC,
FileCreatPropList::DEFAULT,
fapl );
//attributes - version
double dValue=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};
dspace = 0;
dspace = new DataSpace (3,srcdims,srcdimsmax);
//dataset name
std::ostringstream osfn;
osfn << "/data";
if (frindexenable) osfn << "_f" << std::setfill('0') << std::setw(12) << fnum;
std::string dsetname = osfn.str();
//dataset
//fill value
DSetCreatPropList plist;
int fill_value = -1;
plist.setFillValue(dtype, &fill_value);
// always create chunked dataset as unlimited is only supported with chunked layout
hsize_t chunk_dims[3] ={maxchunkedimages, nDimy, nDimz};
plist.setChunk(3, chunk_dims);
dset = 0;
dset = new DataSet (fd->createDataSet(dsetname.c_str(), dtype, *dspace, plist));
//create parameter datasets
hsize_t dims[1] = {nDimx};
hsize_t dimsmax[1] = {H5S_UNLIMITED};
dspace_para = 0;
dspace_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] = {maxchunkedimages};
paralist.setChunk(1, chunkpara_dims);
for (unsigned int i = 0; i < parameterNames.size(); ++i){
DataSet* ds = new DataSet(fd->createDataSet(parameterNames[i],
parameterDataTypes[i], *dspace_para, paralist));
dset_para.push_back(ds);
}
}
catch(const Exception& error){
error.printErrorStack();
if (fd) fd->close();
throw RuntimeError("Could not create HDF5 handles in object " + ind);
}
}
/**
* Create virtual file
* (in C because H5Pset_virtual doesnt exist yet in C++)
* @param virtualFileName virtual file name
* @param fd virtual file handle
* @param masterFileName master file name
* @param fpath file path
* @param fnameprefix file name prefix
* @param findex file index
* @param frindexenable frame index enable
* @param dindex readout index
* @param numunits number of units per readout. eg. eiger has 2 udp units per readout
* @param maxFramesPerFile maximum frames per file
* @param numf number of frames caught
* @param srcDataseName source dataset name
* @param dataType datatype of data dataset
* @param numDety number of readouts in Y dir
* @param numDetz number of readouts in Z dir
* @param nDimy number of objects in y dimension in source file (Number of pixels in y dir)
* @param nDimz number of objects in z dimension in source file (Number of pixels in x dir)
* @param version version of software for hdf5 writing
* @param parameterNames parameter names
* @param parameterDataTypes parameter datatypes
*/
static void CreateVirtualDataFile(
std::string virtualFileName,
hid_t& fd, std::string masterFileName,
std::string fpath, std::string fnameprefix, uint64_t findex, bool frindexenable,
int dindex, int numunits,
uint32_t maxFramesPerFile, uint64_t numf,
std::string srcDataseName, DataType dataType,
int numDety, int numDetz, uint32_t nDimy, uint32_t nDimz,
double version,
std::vector <const char*> parameterNames,
std::vector <DataType> parameterDataTypes)
{
try {
//file
hid_t dfal = H5Pcreate (H5P_FILE_ACCESS);
if (dfal < 0)
throw RuntimeError("Could not create file access property for virtual file " + virtualFileName);
if (H5Pset_fclose_degree (dfal, H5F_CLOSE_STRONG) < 0)
throw RuntimeError("Could not set strong file close degree for virtual file " + virtualFileName);
fd = H5Fcreate( virtualFileName.c_str(), H5F_ACC_TRUNC, H5P_DEFAULT, dfal);
if (fd < 0)
throw RuntimeError("Could not create virtual file " + virtualFileName);
//attributes - version
hid_t dataspace_attr = H5Screate (H5S_SCALAR);
if (dataspace_attr < 0)
throw RuntimeError("Could not create dataspace for attribute in virtual file " + virtualFileName);
hid_t attrid = H5Acreate2 (fd, "version", H5T_NATIVE_DOUBLE, dataspace_attr, H5P_DEFAULT, H5P_DEFAULT);
if (attrid < 0)
throw RuntimeError("Could not create attribute in virtual file " + virtualFileName);
double attr_data = version;
if (H5Awrite (attrid, H5T_NATIVE_DOUBLE, &attr_data) < 0)
throw RuntimeError("Could not write attribute in virtual file " + virtualFileName);
if (H5Aclose (attrid) < 0)
throw RuntimeError("Could not close attribute in virtual file " + virtualFileName);
//virtual dataspace
hsize_t vdsdims[3] = {numf, numDety * nDimy, numDetz * nDimz};
hid_t vdsDataspace = H5Screate_simple(3, vdsdims ,NULL);
if (vdsDataspace < 0)
throw RuntimeError("Could not create virtual dataspace in virtual file " + virtualFileName);
hsize_t vdsdims_para[2] = {numf, (unsigned int) numDety * numDetz};
hid_t vdsDataspace_para = H5Screate_simple(2, vdsdims_para, NULL);
if (vdsDataspace_para < 0)
throw RuntimeError("Could not create virtual dataspace (parameters) in virtual file " + virtualFileName);
//fill values
hid_t dcpl = H5Pcreate (H5P_DATASET_CREATE);
if (dcpl < 0)
throw RuntimeError("Could not create file creation properties in virtual file " + virtualFileName);
int fill_value = -1;
if (H5Pset_fill_value (dcpl, GetDataTypeinC(dataType), &fill_value) < 0)
throw RuntimeError("Could not create fill value in virtual file " + virtualFileName);
hid_t 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 RuntimeError("Could not create file creation properties (parameters) in virtual file " + virtualFileName);
if (H5Pset_fill_value (dcpl_para[i], GetDataTypeinC(parameterDataTypes[i]), &fill_value) < 0)
throw RuntimeError("Could not create fill value (parameters) in virtual file " + virtualFileName);
}
//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, NULL, count, NULL) < 0) {
throw RuntimeError("Could not select hyperslab");
}
if (H5Sselect_hyperslab (vdsDataspace_para, H5S_SELECT_SET,
offset_para, NULL, count_para, NULL) < 0) {
throw RuntimeError("Could not select hyperslab for parameters");
}
//source file name
std::string srcFileName = HDF5FileStatic::CreateFileName(fpath, fnameprefix, findex,
j, dindex, numunits, i);
FILE_LOG(logERROR) << 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 (frindexenable) 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 RuntimeError("Could not create source dataspace in virtual file " + virtualFileName);
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 RuntimeError("Could not create source dataspace (parameters) in virtual file " + virtualFileName);
//mapping
if (H5Pset_virtual(dcpl, vdsDataspace, relative_srcFileName.c_str(),
srcDatasetName.c_str(), srcDataspace) < 0) {
throw 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], srcDataspace_para) < 0) {
throw 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 = srcDataseName;
hid_t vdsdataset = H5Dcreate2 (fd, virtualDatasetName.c_str(),
GetDataTypeinC(dataType), vdsDataspace, H5P_DEFAULT, dcpl, H5P_DEFAULT);
if (vdsdataset < 0)
throw RuntimeError("Could not create virutal dataset in virtual file " + virtualFileName);
//virtual parameter dataset
for (unsigned int i = 0; i < parameterNames.size(); ++i) {
hid_t vdsdataset_para = H5Dcreate2 (fd,
parameterNames[i],
GetDataTypeinC(parameterDataTypes[i]), vdsDataspace_para,
H5P_DEFAULT, dcpl_para[i], H5P_DEFAULT);
if (vdsdataset_para < 0)
throw RuntimeError("Could not create virutal dataset (parameters) in virtual file " + virtualFileName);
}
//close
H5Fclose(fd);
fd = 0;
//link
LinkVirtualInMaster(masterFileName, virtualFileName, virtualDatasetName, parameterNames);
} catch (const RuntimeError &e) {
if (fd > 0)
H5Fclose(fd);
fd = 0;
}
}
/**
* Copy file to another file (mainly to view virutal files in hdfviewer)
* @param dataType data type
* @param owenable overwrite enable
* @param oldFileName file name including path of file to copy
* @param oldDatasetName dataset name to copy
* @param newFileName file name including path of file to copy to
* @param newDatasetName dataset name to copy to
* @param rank rank
* @param nDimx Number of objects in x dimension
* @param nDimy Number of objects in y dimension
* @param nDimz Number of objects in z dimension
*/
template <typename T>
static void CopyVirtualFile(T datatype, bool owenable, std::string oldFileName, std::string oldDatasetName,
std::string newFileName, std::string newDatasetName, int rank,
uint64_t nDimx, uint32_t nDimy, uint32_t nDimz=0)
{
T *data_out;
switch (rank) {
case 2:
data_out = (T*)malloc(sizeof(T)*(nDimx*nDimy));
break;
case 3:
data_out = (T*)malloc(sizeof(T)*(nDimx*nDimy*nDimz));
break;
default:
throw RuntimeError("Invalid rank. Options: 2 or 3");
}
if (datatype == PredType::STD_U16LE) {
FILE_LOG(logINFO) << "datatype:16";
} else if (datatype == PredType::STD_U32LE) {
FILE_LOG(logINFO) << "datatype:32";
} else if (datatype == PredType::STD_U64LE) {
FILE_LOG(logINFO) << "datatype:64";
} else if (datatype == PredType::STD_U8LE) {
FILE_LOG(logINFO) << "datatype:8";
} else {
throw RuntimeError("Unknown datatype:" + std::to_string(datatype));
}
FILE_LOG(logINFO) << "owenable:" << (owenable?1:0) << std::endl
<< "oldFileName:" << oldFileName << std::endl
<< "oldDatasetName:" << oldDatasetName << std::endl
<< "newFileName:" << newFileName << std::endl
<< "newDatasetName:" << newDatasetName << std::endl
<< "rank:" << rank << std::endl
<< "nDimx:" << nDimx << std::endl
<< "nDimy:" << nDimy << std::endl
<< "nDimz:" << nDimz;
H5File* oldfd;
H5File* newfd;
try {
Exception::dontPrint(); //to handle errors
//open old file
oldfd = new H5File( oldFileName.c_str(), H5F_ACC_RDONLY);
DataSet oldDataset = oldfd->openDataSet( oldDatasetName.c_str());
//read dataset
oldDataset.read( data_out, datatype);
//new file
FileAccPropList fapl;
fapl.setFcloseDegree(H5F_CLOSE_STRONG);
newfd = 0;
if(!owenable)
newfd = new H5File( newFileName.c_str(), H5F_ACC_EXCL,
FileCreatPropList::DEFAULT,
fapl );
else
newfd = new H5File( newFileName.c_str(), H5F_ACC_TRUNC,
FileCreatPropList::DEFAULT,
fapl );
//dataspace and dataset
DataSpace* newDataspace = 0;
if (rank == 3) {
hsize_t dims[3] = {nDimx, nDimy, nDimz};
newDataspace = new DataSpace (3,dims);
} else if (rank == 2) {
hsize_t dims[2] = {nDimx, nDimy};
newDataspace = new DataSpace (2,dims);
}
DataSet* newDataset = 0;
newDataset = new DataSet( newfd->createDataSet(newDatasetName.c_str(), datatype, *newDataspace));
//write and close
newDataset->write(data_out,datatype);
newfd->close();
oldfd->close();
} catch(const Exception& error){
error.printErrorStack();
free(data_out);
oldfd->close();
newfd->close();
throw RuntimeError("Could not copy virtual files");
}
free(data_out);
}
/**
* Link the Virtual File in the Master File
* In C because H5Lcreate_external exists only in C
* @param masterFileName master file name
* @param virtualfname virtual file name
* @param virtualDatasetname virtual dataset name
* @param parameterNames parameter names
*/
static void LinkVirtualInMaster(std::string masterFileName, std::string virtualfname,
std::string virtualDatasetname, std::vector <const char*> parameterNames) {
char linkname[100];
hid_t vfd = 0;
try {
hid_t dfal = H5Pcreate (H5P_FILE_ACCESS);
if (dfal < 0)
throw RuntimeError("Could not create file access property for link");
if (H5Pset_fclose_degree (dfal, H5F_CLOSE_STRONG) < 0)
throw 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 RuntimeError("Could not open master file");
//open virtual file
vfd = H5Fopen( virtualfname.c_str(), H5F_ACC_RDWR, dfal);
if (vfd < 0) {
H5Fclose(mfd); mfd = 0;
throw RuntimeError("Could not open virtual file");
}
// find relative path
std::string relative_virtualfname = virtualfname;
{
size_t i = virtualfname.rfind('/', virtualfname.length());
if (i != std::string::npos)
relative_virtualfname = (virtualfname.substr(i+1, virtualfname.length() - i));
}
//**data dataset**
hid_t vdset = H5Dopen2( vfd, virtualDatasetname.c_str(), H5P_DEFAULT);
if (vdset < 0) {
H5Fclose(mfd);
throw RuntimeError("Could not open virtual data dataset");
}
sprintf(linkname, "/entry/data/%s",virtualDatasetname.c_str());
if(H5Lcreate_external( relative_virtualfname.c_str(), virtualDatasetname.c_str(),
mfd, linkname, H5P_DEFAULT, H5P_DEFAULT) < 0) {
H5Fclose(mfd); mfd = 0;
throw 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 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(), (std::string (parameterNames[i])).c_str(),
mfd, linkname, H5P_DEFAULT, H5P_DEFAULT) < 0) {
H5Fclose(mfd); mfd = 0;
throw 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;
}
}
/**
* Get Data type in C
* @param dtype datatype in C++
* @returns datatype in C
*/
static hid_t 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;
}
}
};
#endif

View File

@ -0,0 +1,308 @@
#pragma once
#include "container_utils.h"
#include "logger.h"
#include "receiver_defs.h"
#include "network_utils.h"
class GeneralData;
class Listener;
class DataProcessor;
class DataStreamer;
class Fifo;
class slsDetectorDefs;
#include <atomic>
#include <exception>
#include <memory>
#include <vector>
class Implementation : private virtual slsDetectorDefs {
public:
Implementation(const detectorType d);
virtual ~Implementation();
/**************************************************
* *
* Configuration Parameters *
* *
* ************************************************/
void setDetectorType(const detectorType d);
int *getMultiDetectorSize() const;
void setMultiDetectorSize(const int *size);
int getDetectorPositionId() const;
void setDetectorPositionId(const int id);
std::string getDetectorHostname() const;
void setDetectorHostname(const std::string& c);
bool getSilentMode() const;
void setSilentMode(const bool i);
uint32_t getFifoDepth() const;
void setFifoDepth(const uint32_t i);
frameDiscardPolicy getFrameDiscardPolicy() const;
void setFrameDiscardPolicy(const frameDiscardPolicy i);
bool getFramePaddingEnable() const;
void setFramePaddingEnable(const bool i);
/**************************************************
* *
* File Parameters *
* *
* ************************************************/
fileFormat getFileFormat() const;
void setFileFormat(slsDetectorDefs::fileFormat f);
std::string getFilePath() const;
/* check for existence */
void setFilePath(const std::string& c);
std::string getFileName() const;
void setFileName(const std::string& c);
uint64_t getFileIndex() const;
void setFileIndex(const uint64_t i);
bool getFileWriteEnable() const;
void setFileWriteEnable(const bool b);
bool getMasterFileWriteEnable() const;
void setMasterFileWriteEnable(const bool b);
bool getOverwriteEnable() const;
void setOverwriteEnable(const bool b);
uint32_t getFramesPerFile() const;
/* 0 means infinite */
void setFramesPerFile(const uint32_t i);
/**************************************************
* *
* Acquisition *
* *
* ************************************************/
runStatus getStatus() const;
uint64_t getFramesCaught() const;
uint64_t getAcquisitionIndex() const;
std::vector<uint64_t> getNumMissingPackets() const;
void startReceiver();
void setStoppedFlag(bool stopped);
void stopReceiver();
void startReadout();
void shutDownUDPSockets();
void closeFiles();
void restreamStop();
/**************************************************
* *
* Network Configuration (UDP) *
* *
* ************************************************/
int getNumberofUDPInterfaces() const;
/* [Jungfrau] */
void setNumberofUDPInterfaces(const int n);
std::string getEthernetInterface() const;
void setEthernetInterface(const std::string &c);
std::string getEthernetInterface2() const;
/* [Jungfrau] */
void setEthernetInterface2(const std::string &c);
uint32_t getUDPPortNumber() const;
void setUDPPortNumber(const uint32_t i);
uint32_t getUDPPortNumber2() const;
/* [Eiger][Jungfrau] */
void setUDPPortNumber2(const uint32_t i);
int64_t getUDPSocketBufferSize() const;
void setUDPSocketBufferSize(const int64_t s);
int64_t getActualUDPSocketBufferSize() const;
/**************************************************
* *
* ZMQ Streaming Parameters (ZMQ) *
* *
* ************************************************/
bool getDataStreamEnable() const;
void setDataStreamEnable(const bool enable);
uint32_t getStreamingFrequency() const;
/* 0 for timer */
void setStreamingFrequency(const uint32_t freq);
uint32_t getStreamingTimer() const;
void setStreamingTimer(const uint32_t time_in_ms);
uint32_t getStreamingPort() const;
void setStreamingPort(const uint32_t i);
sls::IpAddr getStreamingSourceIP() const;
void setStreamingSourceIP(const sls::IpAddr ip);
std::string getAdditionalJsonHeader() const;
void setAdditionalJsonHeader(const std::string& c);
/**************************************************
* *
* Detector Parameters *
* *
* ************************************************/
uint64_t getNumberOfFrames() const;
void setNumberOfFrames(const uint64_t i);
uint64_t getAcquisitionTime() const;
void setAcquisitionTime(const uint64_t i);
uint64_t getAcquisitionPeriod() const;
void setAcquisitionPeriod(const uint64_t i);
uint64_t getSubExpTime() const;
/* [Eiger] */
void setSubExpTime(const uint64_t i);
uint64_t getSubPeriod() const;
/* [Eiger] */
void setSubPeriod(const uint64_t i);
uint32_t getNumberofAnalogSamples() const;
/**[Ctb][Moench] */
void setNumberofAnalogSamples(const uint32_t i);
uint32_t getNumberofDigitalSamples() const;
/**[Ctb] */
void setNumberofDigitalSamples(const uint32_t i);
int getNumberofCounters() const;
void setNumberofCounters(const int i);
uint32_t getDynamicRange() const;
void setDynamicRange(const uint32_t i);
ROI getROI() const;
/* [Gotthard] */
void setROI(ROI arg);
bool getTenGigaEnable() const;
/* [Eiger][Ctb] */
void setTenGigaEnable(const bool b);
int getFlippedDataX() const;
void setFlippedDataX(int enable = -1);
bool getGapPixelsEnable() const;
/* [Eiger] */
void setGapPixelsEnable(const bool b);
bool getQuad() const;
/* [Eiger] */
void setQuad(const bool b);
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);
bool getDeactivatedPadding() const;
/* [Eiger] */
bool setDeactivatedPadding(const bool enable);
int getReadNLines() const;
/* [Eiger] */
void setReadNLines(const int value);
readoutMode getReadoutMode() const;
/* [Ctb] */
void setReadoutMode(const readoutMode f);
uint32_t getADCEnableMask() const;
/* [Ctb][Moench] */
void setADCEnableMask(const uint32_t mask);
uint32_t getTenGigaADCEnableMask() const;
/* [Ctb][Moench] */
void setTenGigaADCEnableMask(const uint32_t mask);
std::vector<int> getDbitList() const;
/* [Ctb] */
void setDbitList(const std::vector<int> v);
int getDbitOffset() const;
/* [Ctb] */
void setDbitOffset(const int s);
/**************************************************
* *
* Callbacks *
* *
* ************************************************/
void registerCallBackStartAcquisition(
int (*func)(std::string, std::string, uint64_t, uint32_t, void *), void *arg);
void registerCallBackAcquisitionFinished(
void (*func)(uint64_t, void *), void *arg);
void registerCallBackRawDataReady(
void (*func)(char *, char *, uint32_t, void *), void *arg);
void registerCallBackRawDataModifyReady(
void (*func)(char *, char *, uint32_t &, void *), void *arg);
private:
void DeleteMembers();
void InitializeMembers();
void SetLocalNetworkParameters();
void SetThreadPriorities();
void SetupFifoStructure();
void ResetParametersforNewAcquisition();
void CreateUDPSockets();
void SetupWriter();
void StartRunning();
/**************************************************
* *
* Class Members *
* *
* ************************************************/
// config parameters
int numThreads;
detectorType myDetectorType;
int numDet[MAX_DIMENSIONS];
int detID;
std::string detHostname;
bool silentMode;
uint32_t fifoDepth;
frameDiscardPolicy frameDiscardMode;
bool framePadding;
// file parameters
fileFormat fileFormatType;
std::string filePath;
std::string fileName;
uint64_t fileIndex;
bool fileWriteEnable;
bool masterFileWriteEnable;
bool overwriteEnable;
uint32_t framesPerFile;
// acquisition
std::atomic<runStatus> status;
bool stoppedFlag;
// network configuration (UDP)
int numUDPInterfaces;
std::vector <std::string> eth;
std::vector <uint32_t> udpPortNum;
int64_t udpSocketBufferSize;
int64_t actualUDPSocketBufferSize;
// zmq parameters
bool dataStreamEnable;
uint32_t streamingFrequency;
uint32_t streamingTimerInMs;
uint32_t streamingPort;
sls::IpAddr streamingSrcIP;
std::string additionalJsonHeader;
// detector parameters
uint64_t numberOfFrames;
uint64_t acquisitionPeriod;
uint64_t acquisitionTime;
uint64_t subExpTime;
uint64_t subPeriod;
uint64_t numberOfAnalogSamples;
uint64_t numberOfDigitalSamples;
int numberOfCounters;
uint32_t dynamicRange;
ROI roi;
bool tengigaEnable;
int flippedDataX;
bool gapPixelsEnable;
bool quadEnable;
bool activated;
bool deactivatedPaddingEnable;
int numLinesReadout;
readoutMode readoutType;
uint32_t adcEnableMaskOneGiga;
uint32_t adcEnableMaskTenGiga;
std::vector<int> ctbDbitList;
int ctbDbitOffset;
int ctbAnalogDataBytes;
// callbacks
int (*startAcquisitionCallBack)(std::string, std::string, uint64_t, uint32_t, void *);
void *pStartAcquisition;
void (*acquisitionFinishedCallBack)(uint64_t, void *);
void *pAcquisitionFinished;
void (*rawDataReadyCallBack)(char *, char *, uint32_t, void *);
void (*rawDataModifyReadyCallBack)(char *, char *, uint32_t &, void *);
void *pRawDataReady;
// class objects
GeneralData *generalData;
std::vector<std::unique_ptr<Listener>> listener;
std::vector<std::unique_ptr<DataProcessor>> dataProcessor;
std::vector<std::unique_ptr<DataStreamer>> dataStreamer;
std::vector<std::unique_ptr<Fifo>> fifo;
};

View File

@ -0,0 +1,284 @@
#pragma once
/************************************************
* @file Listener.h
* @short creates the listener thread that
* listens to udp sockets, writes data to memory
* & puts pointers to their memory addresses into fifos
***********************************************/
/**
*@short creates & manages a listener thread each
*/
#include <memory>
#include <atomic>
#include "ThreadObject.h"
class GeneralData;
class Fifo;
class genericSocket;
class Listener : private virtual slsDetectorDefs, public ThreadObject {
public:
/**
* Constructor
* Calls Base Class CreateThread(), sets ErrorMask if error and increments NumberofListerners
* @param ind self index
* @param dtype detector type
* @param f address of Fifo pointer
* @param s pointer to receiver status
* @param portno pointer to udp port number
* @param e ethernet interface
* @param nf pointer to number of images to catch
* @param dr pointer to dynamic range
* @param us pointer to udp socket buffer size
* @param as pointer to actual udp socket buffer size
* @param fpf pointer to frames per file
* @param fdp frame discard policy
* @param act pointer to activated
* @param depaden pointer to deactivated padding enable
* @param sm pointer to silent mode
*/
Listener(int ind, detectorType dtype, Fifo* f, std::atomic<runStatus>* s,
uint32_t* portno, std::string* e, uint64_t* nf, uint32_t* dr,
int64_t* us, int64_t* as, uint32_t* fpf,
frameDiscardPolicy* fdp, bool* act, bool* depaden, bool* sm);
/**
* Destructor
* Calls Base Class DestroyThread() and decrements NumberofListerners
*/
~Listener();
//*** getters ***
/**
* Returns if the thread is currently running
* @returns true if thread is running, else false
*/
bool IsRunning() override;
/**
* Get Packets caught
* @return Packets caught
*/
uint64_t GetPacketsCaught();
/**
* Get Last Frame index caught
* @return last frame index caught
*/
uint64_t GetLastFrameIndexCaught();
/** Get number of missing packets */
uint64_t GetNumMissingPacket(bool stoppedFlag, uint64_t numPackets);
//*** setters ***
/**
* Set bit in RunningMask to allow thread to run
*/
void StartRunning();
/**
* Reset bit in RunningMask to prevent thread from running
*/
void StopRunning();
/**
* Set Fifo pointer to the one given
* @param f address of Fifo pointer
*/
void SetFifo(Fifo* f);
/**
* Reset parameters for new acquisition
*/
void ResetParametersforNewAcquisition();
/**
* Set GeneralData pointer to the one given
* @param g address of GeneralData (Detector Data) pointer
*/
void SetGeneralData(GeneralData* g);
/**
* Creates UDP Sockets
*/
void CreateUDPSockets();
/**
* Shuts down and deletes UDP Sockets
*/
void ShutDownUDPSocket();
/**
* Create & closes a dummy UDP socket
* to set & get actual buffer size
* @param s UDP socket buffer size to be set
*/
void CreateDummySocketForUDPSocketBufferSize(int64_t s);
/**
* Set hard coded (calculated but not from detector) row and column
* r is in row index if detector has not send them yet in firmware,
* c is in col index for jungfrau and eiger (for missing packets/deactivated eiger)
* c when used is in 2d
*/
void SetHardCodedPosition(uint16_t r, uint16_t c);
private:
/**
* Record First Acquisition Index
* @param fnum frame index to record
*/
void RecordFirstIndex(uint64_t fnum);
/**
* Thread Exeution for Listener Class
* Pop free addresses, listen to udp socket,
* write to memory & push the address into fifo
*/
void ThreadExecution() override;
/**
* Pushes non empty buffers into fifo/ frees empty buffer,
* pushes dummy buffer into fifo
* and reset running mask by calling StopRunning()
* @param buf address of buffer
*/
void StopListening(char* buf);
/**
* Listen to the UDP Socket for an image,
* place them in the right order
* @param buffer
* @returns number of bytes of relevant data, can be image size or 0 (stop acquisition)
* or -1 to discard image
*/
uint32_t ListenToAnImage(char* buf);
/**
* Print Fifo Statistics
*/
void PrintFifoStatistics();
/** type of thread */
static const std::string TypeName;
/** Object running status */
std::atomic<bool> runningFlag;
/** GeneralData (Detector Data) object */
GeneralData* generalData;
/** Fifo structure */
Fifo* fifo;
// individual members
/** Detector Type */
detectorType myDetectorType;
/** Receiver Status */
std::atomic<runStatus>* status;
/** UDP Socket - Detector to Receiver */
std::unique_ptr<genericSocket> udpSocket;
/** UDP Port Number */
uint32_t* udpPortNumber;
/** ethernet interface */
std::string* eth;
/** Number of Images to catch */
uint64_t* numImages;
/** Dynamic Range */
uint32_t* dynamicRange;
/** UDP Socket Buffer Size */
int64_t* udpSocketBufferSize;
/** actual UDP Socket Buffer Size (double due to kernel bookkeeping) */
int64_t* actualUDPSocketBufferSize;
/** frames per file */
uint32_t* framesPerFile;
/** frame discard policy */
frameDiscardPolicy* frameDiscardMode;
/** Activated/Deactivated */
bool* activated;
/** Deactivated padding enable */
bool* deactivatedPaddingEnable;
/** Silent Mode */
bool* silentMode;
/** row hardcoded as 1D or 2d,
* if detector does not send them yet or
* missing packets/deactivated (eiger/jungfrau sends 2d pos) **/
uint16_t row;
/** column hardcoded as 2D,
* deactivated eiger/missing packets (eiger/jungfrau sends 2d pos) **/
uint16_t column;
// acquisition start
/** Aquisition Started flag */
std::atomic<bool> startedFlag;
/** Frame Number of First Frame */
uint64_t firstIndex;
// for acquisition summary
/** Number of complete Packets caught */
std::atomic<uint64_t> numPacketsCaught;
/** Last Frame Index caught from udp network */
std::atomic<uint64_t> lastCaughtFrameIndex;
// parameters to acquire image
/** Current Frame Index, default value is 0
* ( always check startedFlag for validity first)
*/
uint64_t currentFrameIndex;
/** True if there is a packet carry over from previous Image */
bool carryOverFlag;
/** Carry over packet buffer */
std::unique_ptr<char []> carryOverPacket;
/** Listening buffer for one packet - might be removed when we can peek and eiger fnum is in header */
std::unique_ptr<char []> listeningPacket;
/** if the udp socket is connected */
std::atomic<bool> udpSocketAlive;
/** Semaphore to synchonize deleting udp socket */
sem_t semaphore_socket;
// for print progress during acqusition
/** number of packets for statistic */
uint32_t numPacketsStatistic;
/** number of images for statistic */
uint32_t numFramesStatistic;
/**
* starting packet number is odd or evern, accordingly increment frame number
* to get first packet number as 0
* (pecific to gotthard, can vary between modules, hence defined here) */
bool oddStartingPacket;
};

View File

@ -1,4 +1,5 @@
#include "Receiver.h"
#include "ClientInterface.h"
#include "sls_detector_exceptions.h"
#include "versionAPI.h"
#include "container_utils.h"
@ -13,6 +14,7 @@
#include <string>
#include <syscall.h>
Receiver::~Receiver() = default;
Receiver::Receiver(int argc, char *argv[]):
tcpipInterface (nullptr) {

View File

@ -0,0 +1,47 @@
#pragma once
/************************************************
* @file ThreadObject.h
* @short creates/destroys a thread
***********************************************/
/**
*@short creates/destroys a thread
*/
#include "sls_detector_defs.h"
#include "logger.h"
#include <semaphore.h>
#include <string>
#include <atomic>
#include <future>
class ThreadObject : private virtual slsDetectorDefs {
public:
ThreadObject(int threadIndex, std::string threadType);
virtual ~ThreadObject();
virtual bool IsRunning() = 0;
void Continue();
void SetThreadPriority(int priority);
protected:
virtual void ThreadExecution() = 0;
private:
/**
* Thread called: An infinite while loop in which,
* semaphore starts executing its contents as long RunningMask is satisfied
* Then it exits the thread on its own if killThread is true
*/
void RunningThread();
protected:
int index{0};
std::string type;
std::atomic<bool> killThread{false};
std::unique_ptr<std::thread> threadObject;
sem_t semaphore;
};

View File

@ -4,6 +4,7 @@
#include "logger.h"
#include "Receiver.h"
#include "sls_detector_defs.h"
#include "container_utils.h"
#include <csignal> //SIGINT
#include <cstdlib> //system

View File

@ -18,6 +18,7 @@ It is linked in manual/manual-api from slsReceiverSoftware/include ]
#include "sls_detector_defs.h"
#include "Receiver.h"
#include "container_utils.h"
#include <csignal> //SIGINT
#include <cstdlib> //system

View File

@ -0,0 +1,77 @@
#pragma once
#include "sls_detector_defs.h"
#include <cstdint>
#define MAX_DIMENSIONS (2)
#define MAX_NUMBER_OF_LISTENING_THREADS (2)
//socket
#define GOODBYE (-200)
#define RECEIVE_SOCKET_BUFFER_SIZE (100*1024*1024)
#define MAX_SOCKET_INPUT_PACKET_QUEUE (250000)
//files
#define DO_NOTHING (0)
#define DO_EVERYTHING (1)
#define STATISTIC_FRAMENUMBER_INFINITE (20000)
//binary
#define FILE_BUFFER_SIZE (16*1024*1024) //16mb
//fifo
#define FIFO_HEADER_NUMBYTES (8)
#define FIFO_DATASIZE_NUMBYTES (4)
#define FIFO_PADDING_NUMBYTES (4) // for 8 byte alignment due to sls_receiver_header structure
//hdf5
#define MAX_CHUNKED_IMAGES (1)
//versions
#define HDF5_WRITER_VERSION (5.0) //1 decimal places
#define BINARY_WRITER_VERSION (5.0) //1 decimal places
//parameters to calculate fifo depth
#define SAMPLE_TIME_IN_NS (100000000)//100ms
#define MAX_EIGER_ROWS_PER_READOUT (256)
//to differentiate between gotthard and short gotthard
#define GOTTHARD_PACKET_SIZE (1286)
#define DUMMY_PACKET_VALUE (0xFFFFFFFF)
#define LISTENER_PRIORITY (90)
#define PROCESSOR_PRIORITY (70)
#define STREAMER_PRIORITY (10)
#define TCP_PRIORITY (10)
struct masterAttributes {
double version;
uint32_t detectorType;
uint32_t dynamicRange;
uint32_t tenGiga;
uint32_t imageSize;
uint32_t nPixelsX;
uint32_t nPixelsY;
uint32_t maxFramesPerFile;
uint64_t totalFrames;
uint64_t exptimeNs;
uint64_t subExptimeNs;
uint64_t subPeriodNs;
uint64_t periodNs;
uint32_t gapPixelsEnable;
uint32_t quadEnable;
uint32_t analogFlag;
uint32_t digitalFlag;
uint32_t adcmask;
uint32_t dbitoffset;
uint64_t dbitlist;
uint32_t roiXmin;
uint32_t roiXmax;
};