commit 8c72246ce7e7d6442c0d811a55faa516ecd5aa6c Author: Maliakal Dhanya Date: Wed May 21 09:59:37 2014 +0200 new separate receiver diff --git a/slsReceiverSoftware/Makefile b/slsReceiverSoftware/Makefile new file mode 100644 index 000000000..f8df05639 --- /dev/null +++ b/slsReceiverSoftware/Makefile @@ -0,0 +1,71 @@ + +include ../Makefile.include + +DESTDIR ?= ../bin +LIBDIR ?= $(DESTDIR) +DOCDIR ?= docs + + +CFLAGS= -g -DC_ONLY -fPIC +#FLAGS+= #-DVERBOSE -DVERYVERBOSE + +DFLAGS= -g -DDACS_INT -DSLS_RECEIVER_UDP_FUNCTIONS + +INCLUDES?= -I. -Iincludes -IMySocketTCP -IslsReceiver -IslsDetectorCalibration -IslsReceiver/eigerReceiver -I$(ASM) +#-IslsReceiverInterface + +SRC_CLNT= MySocketTCP/MySocketTCP.cpp slsReceiver/slsReceiverUDPFunctions.cpp slsReceiver/slsReceiverTCPIPInterface.cpp slsReceiver/slsReceiverUsers.cpp +#slsReceiverInterface/receiverInterface.cpp + +OBJS = $(SRC_CLNT:.cpp=.o) +OBJS += slsReceiver/eigerReceiver.o + + +.PHONY: all intdoc package eigerReceiver clean + +all: package $(SRC_CLNT) + +intdoc: $(SRC_H) $(SRC_CLNT) + doxygen doxy.config + + +%.o : %.cpp %.h Makefile +ifeq ($(EIGERSLS),yes) + $(CXX) -DEIGERSLS -o $@ -c $< $(INCLUDES) $(DFLAGS) $(EIGERFLAGS) -fPIC $(EPICSFLAGS) -L/usr/lib64/ #$(FLAGS) +else ifeq ($(ROOTSLS),yes) + echo "with root" + $(CXX) -DROOTSLS -o $@ -c $< $(INCLUDES) $(DFLAGS) $(ROOTFLAGS) -fPIC $(EPICSFLAGS) -L/usr/lib64/ #$(FLAGS) +else + echo "without root" + $(CXX) -o $@ -c $< $(INCLUDES) $(DFLAGS) -fPIC $(EPICSFLAGS) -lpthread #$(FLAGS) +endif + +# LEO: not satisfied by eigerReceiver +package: eigerReceiver $(OBJS) $(DESTDIR)/libSlsReceiver.so $(DESTDIR)/libSlsReceiver.a + +eigerReceiver: + cd slsReceiver && make eigerReceiver + +$(DESTDIR)/libSlsReceiver.so: $(OBJS) + $(CXX) -shared -Wl,-soname,libSlsReceiver.so -o libSlsReceiver.so $(OBJS) -lc $(INCLUDES) $(DFLAGS) $(FLAGS) $(EPICSFLAGS) -L/usr/lib64 -lpthread + $(shell test -d $(DESTDIR) || mkdir -p $(DESTDIR)) + mv libSlsReceiver.so $(DESTDIR) + +$(DESTDIR)/libSlsReceiver.a: $(OBJS) + ar rcs libSlsReceiver.a $(OBJS) + mv libSlsReceiver.a $(DESTDIR) + +clean: + rm -rf $(OBJS) + cd slsReceiver && make clean + cd + +#------------------------------------------------------------------------------- + +install: package + +install_inc: + $(shell test -d $(DESTDIR) || mkdir -p $(DESTDIR)) + cp -P slsReceiver/slsReceiverUsers.h $(DESTDIR) + + diff --git a/slsReceiverSoftware/MySocketTCP/._.DS_Store b/slsReceiverSoftware/MySocketTCP/._.DS_Store new file mode 100644 index 000000000..c9474ea62 Binary files /dev/null and b/slsReceiverSoftware/MySocketTCP/._.DS_Store differ diff --git a/slsReceiverSoftware/MySocketTCP/Makefile b/slsReceiverSoftware/MySocketTCP/Makefile new file mode 100644 index 000000000..69634f361 --- /dev/null +++ b/slsReceiverSoftware/MySocketTCP/Makefile @@ -0,0 +1,23 @@ + +TOBECLEANED = MySocketTCP.o + +PROGRAMS = rec send + +all: $(PROGRAMS) + +clean: + @rm -f $(TOBECLEANED) $(PROGRAMS) + +rec: MySocketTCP.o rec.cxx + g++ -o $@ $^ + @echo "$@ done" + +send: MySocketTCP.o send.cxx + g++ -o $@ $^ + @echo "$@ done" + +MySocketTCP.o: MySocketTCP.cxx MySocketTCP.h + g++ -c $< + @echo "$@ done" + + diff --git a/slsReceiverSoftware/MySocketTCP/MySocketTCP.c b/slsReceiverSoftware/MySocketTCP/MySocketTCP.c new file mode 120000 index 000000000..a995312db --- /dev/null +++ b/slsReceiverSoftware/MySocketTCP/MySocketTCP.c @@ -0,0 +1 @@ +MySocketTCP.cxx \ No newline at end of file diff --git a/slsReceiverSoftware/MySocketTCP/MySocketTCP.cpp b/slsReceiverSoftware/MySocketTCP/MySocketTCP.cpp new file mode 120000 index 000000000..a995312db --- /dev/null +++ b/slsReceiverSoftware/MySocketTCP/MySocketTCP.cpp @@ -0,0 +1 @@ +MySocketTCP.cxx \ No newline at end of file diff --git a/slsReceiverSoftware/MySocketTCP/MySocketTCP.cxx b/slsReceiverSoftware/MySocketTCP/MySocketTCP.cxx new file mode 100644 index 000000000..ba9583c1c --- /dev/null +++ b/slsReceiverSoftware/MySocketTCP/MySocketTCP.cxx @@ -0,0 +1,53 @@ + +//version 1.0, base development, Ian 19/01/09 + + +#include "MySocketTCP.h" +#include +#include +#include + +using namespace std; + + + + + + + + + +int MySocketTCP::SendData(void* buf,int length){//length in characters + int ndata = SendDataAndKeepConnection(buf,length); + Disconnect(); + return ndata; +} + +int MySocketTCP::SendDataAndKeepConnection(void* buf,int length){//length in characters + if(last_keep_connection_open_action_was_a_send) Disconnect(); //to keep a structured data flow; + + Connect(); + int total_sent=SendDataOnly(buf,length); + last_keep_connection_open_action_was_a_send=1; + return total_sent; +} + + + + +int MySocketTCP::ReceiveData(void* buf,int length){//length in characters + int ndata = ReceiveDataAndKeepConnection(buf,length); + Disconnect(); + return ndata; +} + +int MySocketTCP::ReceiveDataAndKeepConnection(void* buf,int length){//length in characters + if(!last_keep_connection_open_action_was_a_send) Disconnect(); //to a keep structured data flow; + + Connect(); + // should preform two reads one to receive incomming char count + int total_received=ReceiveDataOnly(buf,length); + last_keep_connection_open_action_was_a_send=0; + return total_received; +} + diff --git a/slsReceiverSoftware/MySocketTCP/MySocketTCP.h b/slsReceiverSoftware/MySocketTCP/MySocketTCP.h new file mode 100644 index 000000000..31f56d453 --- /dev/null +++ b/slsReceiverSoftware/MySocketTCP/MySocketTCP.h @@ -0,0 +1,79 @@ + +#ifndef MY_SOCKET_TCP_H +#define MY_SOCKET_TCP_H + + + + +/** + * + * @libdoc The MySocketTCP class provides a simple interface for creating and sending/receiving data over a TCP socket. + * + * @short This class provides a simple interface for creating and sending/receiving data over a TCP socket. + * @author Ian Johnson + * @version 1.0 + */ + + + +//version 1.0, base development, Ian 19/01/09 + +/* Modified by anna on 19.01.2009 */ +/* + canceled SetupParameters() and varaibles intialized in the constructors' headers; + defined SEND_REC_MAX_SIZE (for compatibilty with mythen (and possibly other) pure C servers (i would move it to the common header file) + + added #ifndef C_ONLY... to cutout class definition when including in pure C servers (can be removed if SEND_REC_MAX_SIZE is moved to the common header file) + + defined private variables char hostname[1000] and int portno to store connection informations; + + defined public functions int getHostname(char *name) and int getPortNumber() to retrieve connection informations + + added public function int getErrorStatus() returning 1 if socketDescriptor<0 + + remove exits in the constructors and replace them with socketDescriptor=-1 + + replaced the argument of send/receive data with void (to avoid too much casting or compiler errors/warnings) + + added a function which really does not close the socket between send/receive (senddataonly, receivedataonly) + +*/ + + +/* Modified by Anna on 31.10.2012 + +developed and + +*/ + + +#include "genericSocket.h" +#define TCP_PACKET_SIZE 4096 + +class MySocketTCP: public genericSocket { + + public: + MySocketTCP(const char* const host_ip_or_name, unsigned short int const port_number): genericSocket(host_ip_or_name, port_number,TCP), last_keep_connection_open_action_was_a_send(0){setPacketSize(TCP_PACKET_SIZE);}; // sender (client): where to? ip + MySocketTCP(unsigned short int const port_number):genericSocket(port_number,TCP), last_keep_connection_open_action_was_a_send(0) {setPacketSize(TCP_PACKET_SIZE);}; // receiver (server) local no need for ip + + + //The following two functions will connectioned->send/receive->disconnect + int SendData(void* buf,int length);//length in characters + int ReceiveData(void* buf,int length); + + + //The following two functions stay connected, blocking other connections, and must be manually disconnected, + // when the last call is a SendData() or ReceiveData() the disconnection will be done automatically + //These function will also automatically disconnect->reconnect if + // two reads (or two writes) are called in a row to preserve the data send/receive structure + int SendDataAndKeepConnection(void* buf,int length); + int ReceiveDataAndKeepConnection(void* buf,int length); + + private: + + + bool last_keep_connection_open_action_was_a_send; + + +}; +#endif diff --git a/slsReceiverSoftware/MySocketTCP/genericSocket.h b/slsReceiverSoftware/MySocketTCP/genericSocket.h new file mode 100644 index 000000000..28ae7b650 --- /dev/null +++ b/slsReceiverSoftware/MySocketTCP/genericSocket.h @@ -0,0 +1,686 @@ + +#ifndef GENERIC_SOCKET_H +#define GENERIC_SOCKET_H + + + + + +/** + * + * @libdoc genericSocket provides some functions to open/close sockets both TCP and UDP + * + * @short some functions to open/close sockets both TCP and UDP + * @author Anna Bergamaschi + * @version 0.0 + */ + + + +//version 1.0, base development, Ian 19/01/09 + +/* Modified by anna on 19.01.2009 */ +/* + canceled SetupParameters() and varaibles intialized in the constructors' headers; + defined SEND_REC_MAX_SIZE (for compatibilty with mythen (and possibly other) pure C servers (i would move it to the common header file) + + added #ifndef C_ONLY... to cutout class definition when including in pure C servers (can be removed if SEND_REC_MAX_SIZE is moved to the common header file) + + defined private variables char hostname[1000] and int portno to store connection informations; + + defined public functions int getHostname(char *name) and int getPortNumber() to retrieve connection informations + + added public function int getErrorStatus() returning 1 if socketDescriptor<0 + + remove exits in the constructors and replace them with socketDescriptor=-1 + + replaced the argument of send/receive data with void (to avoid too much casting or compiler errors/warnings) + + added a function which really does not close the socket between send/receive (senddataonly, receivedataonly) +*/ + +#ifdef __CINT__ +//class sockaddr_in; +class socklen_t; +class uint32_t; +class uint32_t_ss; +// CINT view of types: +class sockaddr_in; +// { +// unsigned short int sa_family; +// unsigned char sa_data[14]; +// }; +#else + +#include +#include +#include +#include +#include +#include + +#endif + +#include +#include +#include + +#include +#include +#include + +using namespace std; + +#define DEFAULT_PACKET_SIZE 1286 +#define DEFAULT_PACKETS_PER_FRAME 2 +#define SOCKET_BUFFER_SIZE (100*1024*1024) //100MB +#define DEFAULT_PORTNO 1952 +#define DEFAULT_BACKLOG 5 +#define DEFAULT_UDP_PORTNO 50001 +#define DEFAULT_GUI_PORTNO 65000 + +class genericSocket{ + + public: + + /** + Communication protocol +*/ +enum communicationProtocol{ + TCP, /**< TCP/IP */ + UDP /**< UDP */ +}; + + + genericSocket(const char* const host_ip_or_name, unsigned short int const port_number, communicationProtocol p, int ps = DEFAULT_PACKET_SIZE, int t = DEFAULT_PACKETS_PER_FRAME) : + // portno(port_number), + protocol(p), + is_a_server(0), + socketDescriptor(-1), + file_des(-1), + packet_size(ps), + nsending(0), + nsent(0), + total_sent(0), + packets_per_frame(t)// sender (client): where to? ip + { + + // strcpy(hostname,host_ip_or_name); + struct hostent *hostInfo = gethostbyname(host_ip_or_name); + if (hostInfo == NULL){ + cerr << "Exiting: Problem interpreting host: " << host_ip_or_name << "\n"; + } else { + // Set some fields in the serverAddress structure. + serverAddress.sin_family = hostInfo->h_addrtype; + memcpy((char *) &serverAddress.sin_addr.s_addr, + hostInfo->h_addr_list[0], hostInfo->h_length); + serverAddress.sin_port = htons(port_number); + socketDescriptor=0; //You can use send and recv, //would it work????? + } + clientAddress_length=sizeof(clientAddress); + } + + + int getProtocol(communicationProtocol p) { + switch (p) { + case TCP: + return SOCK_STREAM; + break; + case UDP: + return SOCK_DGRAM; + + default: + cerr << "unknow protocol " << p << endl; + return -1; + } + } + + int getProtocol() {return getProtocol(protocol);}; + + + + + /** + The constructor for a server + @short the contructor for a server + \param port_number port number to listen to + \param p TCP or UDP + \param eth interface name or IP address to listen to (if NULL, listen to all interfaces) + + */ + + genericSocket(unsigned short int const port_number, communicationProtocol p, int ps = DEFAULT_PACKET_SIZE, int t = DEFAULT_PACKETS_PER_FRAME, const char *eth=NULL): + //portno(port_number), + protocol(p), + is_a_server(1), + socketDescriptor(-1), + file_des(-1), + packet_size(ps), + nsending(0), + nsent(0), + total_sent(0), + packets_per_frame(t) + { + +/* // you can specify an IP address: */ +/* */ + +/* // or you can let it automatically select one: */ +/* myaddr.sin_addr.s_addr = INADDR_ANY; */ + + if(serverAddress.sin_port == htons(port_number)){ + socketDescriptor = -10; + return; + } + + char ip[20]; + + strcpy(ip,"0.0.0.0"); + clientAddress_length=sizeof(clientAddress); + if (eth) { + strcpy(ip,nameToIp(string(eth)).c_str()); + if (string(ip)==string("0.0.0.0")) + strcpy(ip,eth); + } + + // strcpy(hostname,"localhost"); //needed?!?!?!? + + + socketDescriptor = socket(AF_INET, getProtocol(),0); //tcp + + if (socketDescriptor < 0) { + cerr << "Can not create socket "<= 0){ \ + close(socketDescriptor); \ + } \ + file_des=-1; \ + serverAddress.sin_port=-1; \ + }; + + +/* /\** @short if client returns hostname for connection */ +/* \param name string to write the hostname to */ +/* \returns 0 if client, 1 if server (in this case ignore name return value) */ + +/* *\/ */ +/* int getHostname(char *name){ */ +/* if (is_a_server==0) { */ +/* strcpy(name,getHostname().c_str()); */ +/* } */ +/* return is_a_server; */ +/* }; */ +/* /\** @short if client returns hostname for connection */ +/* \returns hostname */ + +/* *\/ */ +/* string getHostname(){return string(hostname);}; */ + +/* /\** @short returns port number for connection */ +/* \returns port number */ +/* *\/ */ +/* int getPortNumber(){return portno;}; */ + + /** @short returns communication protocol + \returns TCP or UDP + */ + int getCommunicationProtocol(){return protocol;}; + + + /** @short returns error status + \returns 1 if error + */ + int getErrorStatus(){if (socketDescriptor==-10) return -10; else if (socketDescriptor<0) return 1; else return 0;}; + + + /** @short etablishes connection; disconnect should always follow + \returns 1 if error + */ + int Connect(){//cout<<"connect"<0) return file_des; + if (protocol==UDP) return -1; + + if(is_a_server && protocol==TCP){ //server tcp; the server will wait for the clients connection + if (socketDescriptor>0) { + if ((file_des = accept(socketDescriptor,(struct sockaddr *) &clientAddress, &clientAddress_length)) < 0) { + cerr << "Error: with server accept, connection refused"<=0){ //then was open + if(is_a_server){ + close(file_des); + } + else { + close(socketDescriptor); + socketDescriptor=-1; + } + file_des=-1; + } + } + }; + + + void ShutDownSocket(){ + while(!shutdown(socketDescriptor, SHUT_RDWR)); + }; + + + + /** Set the socket timeout ts is in seconds */ + int SetTimeOut(int ts){ + + + if (ts<=0) + return -1; + + //cout << "socketdescriptor "<< socketDescriptor << endl; + struct timeval tout; + tout.tv_sec = 0; + tout.tv_usec = 0; + if(::setsockopt(socketDescriptor, SOL_SOCKET, SO_RCVTIMEO, &tout, sizeof(struct timeval)) <0) + { + cerr << "Error in setsockopt SO_RCVTIMEO "<< 0 << endl; + } + tout.tv_sec = ts; + tout.tv_usec = 0; + if(::setsockopt(socketDescriptor, SOL_SOCKET, SO_SNDTIMEO, &tout, sizeof(struct timeval)) < 0) + { + cerr << "Error in setsockopt SO_SNDTIMEO " << ts << endl; + } + return 0; + + + }; + + + int setPacketSize(int i=-1) { if (i>=0) packet_size=i; return packet_size;}; + + + + static string ipToName(string ip) { + struct ifaddrs *addrs, *iap; + struct sockaddr_in *sa; + char buf[32]; + + strcpy(buf,"none"); + + getifaddrs(&addrs); + for (iap = addrs; iap != NULL; iap = iap->ifa_next) { + if (iap->ifa_addr && (iap->ifa_flags & IFF_UP) && iap->ifa_addr->sa_family == AF_INET) { + sa = (struct sockaddr_in *)(iap->ifa_addr); + inet_ntop(iap->ifa_addr->sa_family, (void *)&(sa->sin_addr), buf, sizeof(buf)); + if (ip==string(buf)) { + //printf("%s\n", iap->ifa_name); + strcpy(buf,iap->ifa_name); + break; + } + } + } + freeifaddrs(addrs); + return string(buf); + }; + + static string nameToMac(string inf) { + struct ifreq ifr; + int sock, j, k; + char mac[32]; + + sock=getSock(inf,&ifr); + + if (-1==ioctl(sock, SIOCGIFHWADDR, &ifr)) { + perror("ioctl(SIOCGIFHWADDR) "); + return string("00:00:00:00:00:00"); + } + for (j=0, k=0; j<6; j++) { + k+=snprintf(mac+k, sizeof(mac)-k-1, j ? ":%02X" : "%02X", + (int)(unsigned int)(unsigned char)ifr.ifr_hwaddr.sa_data[j]); + } + mac[sizeof(mac)-1]='\0'; + + return string(mac); + + }; + + + + static string nameToIp(string inf){ + struct ifreq ifr; + int sock; + char *p, addr[32]; + + sock=getSock(inf,&ifr); + + if (-1==ioctl(sock, SIOCGIFADDR, &ifr)) { + perror("ioctl(SIOCGIFADDR) "); + return string("0.0.0.0"); + } + p=inet_ntoa(((struct sockaddr_in *)(&ifr.ifr_addr))->sin_addr); + strncpy(addr,p,sizeof(addr)-1); + addr[sizeof(addr)-1]='\0'; + + return string(addr); + + }; + + static int getSock(string inf, struct ifreq *ifr) { + + int sock; + sock=socket(PF_INET, SOCK_STREAM, 0); + if (-1==sock) { + perror("socket() "); + return 1; + } + strncpy(ifr->ifr_name,inf.c_str(),sizeof(ifr->ifr_name)-1); + ifr->ifr_name[sizeof(ifr->ifr_name)-1]='\0'; + + return sock; + + }; + + + int ReceiveDataOnly(void* buf,int length=0){ + + + if (buf==NULL) return -1; + + + total_sent=0; + + switch(protocol) { + case TCP: + if (file_des<0) return -1; + while(length>0){ + nsending = (length>packet_size) ? packet_size:length; + nsent = read(file_des,(char*)buf+total_sent,nsending); + if(!nsent) break; + length-=nsent; + total_sent+=nsent; + } + break; + case UDP: + if (socketDescriptor<0) return -1; + //if length given + if(length){ + while(length>0){ + nsending=packet_size; + nsent = recvfrom(socketDescriptor,(char*)buf+total_sent,nsending, 0, (struct sockaddr *) &clientAddress, &clientAddress_length); + if(!nsent) break; + length-=nsent; + total_sent+=nsent; + } + } + //depends on packets per frame + else{ + for(int i=0;i0) + strcpy(thisClientIP,dummyClientIP); + + if (strcmp(lastClientIP,thisClientIP)) + differentClients=1; + else + differentClients=0; + + return total_sent; + + + + } + + + int SendDataOnly(void *buf, int length) { +#ifdef VERY_VERBOSE + cout << "want to send "<< length << " Bytes" << endl; +#endif + if (buf==NULL) return -1; + + total_sent=0; + + + switch(protocol) { + case TCP: + if (file_des<0) return -1; + while(length>0){ + nsending = (length>packet_size) ? packet_size:length; + nsent = write(file_des,(char*)buf+total_sent,nsending); + if(!nsent) break; + length-=nsent; + total_sent+=nsent; + } + break; + case UDP: + if (socketDescriptor<0) return -1; + while(length>0){ + nsending = (length>packet_size) ? packet_size:length; + nsent = sendto(socketDescriptor,(char*)buf+total_sent,nsending, 0, (struct sockaddr *) &clientAddress, clientAddress_length); + if(!nsent) break; + length-=nsent; + total_sent+=nsent; + } + + break; + default: + ; + } +#ifdef VERY_VERBOSE + cout << "sent "<< total_sent << " Bytes" << endl; +#endif + return total_sent; + + + } + + char lastClientIP[INET_ADDRSTRLEN]; + char thisClientIP[INET_ADDRSTRLEN]; + int differentClients; + + + protected: + + communicationProtocol protocol; + + + + int is_a_server; + + + int socketDescriptor; + int file_des; + + int packet_size; + + struct sockaddr_in clientAddress, serverAddress; + socklen_t clientAddress_length; + + + char dummyClientIP[INET_ADDRSTRLEN]; + + + private: + + int nsending; + int nsent; + int total_sent; + int packets_per_frame; + + + + // pthread_mutex_t mp; +}; +#endif diff --git a/slsReceiverSoftware/MySocketTCP/rec b/slsReceiverSoftware/MySocketTCP/rec new file mode 100755 index 000000000..b652bb8f4 Binary files /dev/null and b/slsReceiverSoftware/MySocketTCP/rec differ diff --git a/slsReceiverSoftware/MySocketTCP/rec.cxx b/slsReceiverSoftware/MySocketTCP/rec.cxx new file mode 100644 index 000000000..fe937cb14 --- /dev/null +++ b/slsReceiverSoftware/MySocketTCP/rec.cxx @@ -0,0 +1,31 @@ + +//version 1.0, base development ij 19/01/09 + +#include +#include "MySocketTCP.h" + +using namespace std; + +int main(){ + + char data[50000]; + int length=50000; + + unsigned short int portnum = 1952; + MySocketTCP* sock = new MySocketTCP(portnum); + + cout<<"\tReceived :"<ReceiveDataAndKeepConnection(data,23000)<ReceiveData(data,32200)<ReceiveData(data,33300)<ReceiveData(data,30000)<ReceiveData(data,3222)< +#include "MySocketTCP.h" + +using namespace std; + +int main(int argc, char *argv[]){ + + if(argc!=2){ + cout<<"Usage: send ip_addess/hostName"<SendDataAndKeepConnection(data,2000)<SendData(data,2200)<SendData(data,1200)<SendData(data,25000)<SendData(data,222)< +#include +#include +using namespace std; + +typedef double double32_t; +typedef float float32_t; +typedef int int32_t; + + + +/** Circular Fifo (a.k.a. Circular Buffer) +* Thread safe for one reader, and one writer */ +template +class CircularFifo { +public: + + CircularFifo(unsigned int Size) : tail(0), head(0){ + Capacity = Size + 1; + array.resize(Capacity); + sem_init(&free_mutex,0,0); + } + virtual ~CircularFifo() {} + + bool push(Element*& item_); + bool pop(Element*& item_); + + bool isEmpty() const; + bool isFull() const; + + int getSemValue(); + +private: + volatile unsigned int tail; // input index + vector array; + volatile unsigned int head; // output index + unsigned int Capacity; + sem_t free_mutex; + + unsigned int increment(unsigned int idx_) const; +}; + +template +int CircularFifo::getSemValue() +{ + int value; + sem_getvalue(&free_mutex, &value); + return value; +} + + +/** Producer only: Adds item to the circular queue. +* If queue is full at 'push' operation no update/overwrite +* will happen, it is up to the caller to handle this case +* +* \param item_ copy by reference the input item +* \return whether operation was successful or not */ +template +bool CircularFifo::push(Element*& item_) +{ + + int nextTail = increment(tail); + if(nextTail != head) + { + array[tail] = item_; + tail = nextTail; + sem_post(&free_mutex); + return true; + } + + // queue was full + return false; +} + +/** Consumer only: Removes and returns item from the queue +* If queue is empty at 'pop' operation no retrieve will happen +* It is up to the caller to handle this case +* +* \param item_ return by reference the wanted item +* \return whether operation was successful or not */ +template +bool CircularFifo::pop(Element*& item_) +{ + // if(head == tail) + // return false; // empty queue + sem_wait(&free_mutex); + + item_ = array[head]; + head = increment(head); + return true; +} + +/** Useful for testinng and Consumer check of status + * Remember that the 'empty' status can change quickly + * as the Procuder adds more items. + * + * \return true if circular buffer is empty */ +template +bool CircularFifo::isEmpty() const +{ + return (head == tail); +} + +/** Useful for testing and Producer check of status + * Remember that the 'full' status can change quickly + * as the Consumer catches up. + * + * \return true if circular buffer is full. */ +template +bool CircularFifo::isFull() const +{ + int tailCheck = (tail+1) % Capacity; + return (tailCheck == head); +} + +/** Increment helper function for index of the circular queue +* index is inremented or wrapped +* +* \param idx_ the index to the incremented/wrapped +* \return new value for the index */ +template +unsigned int CircularFifo::increment(unsigned int idx_) const +{ + // increment or wrap + // ================= + // index++; + // if(index == array.lenght) -> index = 0; + // + //or as written below: + // index = (index+1) % array.length + idx_ = (idx_+1) % Capacity; + return idx_; +} + +#endif /* CIRCULARFIFO_H_ */ + + + + + +/* +#ifndef CIRCULARFIFO_H_ +#define CIRCULARFIFO_H_ + +#include "sls_receiver_defs.h" + +#include "/usr/include/alsa/atomic.h" +#include +using namespace std; + +template +class CircularFifo { +public: + + CircularFifo(unsigned int Size) : tail(0), head(0){ + Capacity = Size + 1; + array.resize(Capacity); + } + virtual ~CircularFifo() {} + + bool push(Element*& item_); + bool pop(Element*& item_); + + bool wasEmpty() const; + bool wasFull() const; + bool isLockFree() const; + +private: + vector array; + unsigned int Capacity; + + std::atomic tail; // input index + std::atomic head; // output index + + unsigned int increment(unsigned int idx_) const; +}; + + +template +bool CircularFifo::push(Element*& item_) +{ + auto currentTail = tail.load(); + auto nextTail = increment(currentTail); + if(nextTail != head.load()) + { + array[currentTail] = item_; + tail.store(nextTail); + return true; + } + + // queue was full + return false; +} + + +template +bool CircularFifo::pop(Element*& item_) +{ + const auto currentHead = head.load(); + if(currentHead == tail.load()) + return false; // empty queue + + item_ = array[currentHead]; + head.store(increment(currentHead)); + return true; +} + + +template +bool CircularFifo::wasEmpty() const +{ + return (head.load() == tail.load()); +} + + +template +bool CircularFifo::wasFull() const +{ + const auto nextTail = increment(tail.load()); + return (nextTail == head.load()); +} + +template +bool CircularFifo::isLockFree() const +{ + return (tail.is_lock_free() && head.is_lock_free()); +} + + +template +unsigned int CircularFifo::increment(unsigned int idx_) const +{ + // increment or wrap + // ================= + // index++; + // if(index == array.lenght) -> index = 0; + // + //or as written below: + // index = (index+1) % array.length + return (idx_ + 1) % Capacity; +} + +#endif */ diff --git a/slsReceiverSoftware/includes/receiver_defs.h b/slsReceiverSoftware/includes/receiver_defs.h new file mode 100755 index 000000000..8dfbf7c99 --- /dev/null +++ b/slsReceiverSoftware/includes/receiver_defs.h @@ -0,0 +1,72 @@ +#ifndef RECEIVER_DEFS_H +#define RECEIVER_DEFS_H + +#include "sls_receiver_defs.h" + +#include + +#define GOODBYE -200 + +#define DO_NOTHING 0 +#define CREATE_FILES 1 +#define DO_EVERYTHING 2 + +#define BUF_SIZE (16*1024*1024) //16mb +#define SAMPLE_TIME_IN_NS 100000000//100ms +#define MAX_JOBS_PER_THREAD 1000 +#define HEADER_SIZE_NUM_TOT_PACKETS 2 +#define HEADER_SIZE_NUM_FRAMES 2 +#define HEADER_SIZE_NUM_PACKETS 1 + + +//all max frames defined in sls_receiver_defs.h. 20000 gotthard, 100000 for short gotthard, 1000 for moench + + +#define GOTTHARD_FIFO_SIZE 25000 //cannot be less than max jobs per thread = 1000 +/*#define GOTTHARD_ALIGNED_FRAME_SIZE 4096*/ +#define GOTTHARD_PACKETS_PER_FRAME 2 +#define GOTTHARD_ONE_PACKET_SIZE 1286 +#define GOTTHARD_BUFFER_SIZE (GOTTHARD_ONE_PACKET_SIZE*GOTTHARD_PACKETS_PER_FRAME) //1286*2 +#define GOTTHARD_DATA_BYTES (1280*GOTTHARD_PACKETS_PER_FRAME) //1280*2 + +#define GOTTHARD_SHORT_PACKETS_PER_FRAME 1 +#define GOTTHARD_SHORT_BUFFER_SIZE 518 +#define GOTTHARD_SHORT_DATABYTES 512 +#define GOTTHARD_SHORT_FRAME_INDEX_MASK 0xFFFFFFFF +#define GOTTHARD_SHORT_FRAME_INDEX_OFFSET 0 +#define GOTTHARD_SHORT_PACKET_INDEX_MASK 0 +#define GOTTHARD_SHORT_PIXELS_IN_ROW 256 +#define GOTTHARD_SHORT_PIXELS_IN_COL 1 + + +#define GOTTHARD_FRAME_INDEX_MASK 0xFFFFFFFE +#define GOTTHARD_FRAME_INDEX_OFFSET 1 +#define GOTTHARD_PACKET_INDEX_MASK 0x1 + +#define GOTTHARD_PIXELS_IN_ROW 1280 +#define GOTTHARD_PIXELS_IN_COL 1 + + + +#define MOENCH_FIFO_SIZE 2500 //cannot be less than max jobs per thread = 1000 +/*#define MOENCH_ALIGNED_FRAME_SIZE 65536*/ +#define MOENCH_PACKETS_PER_FRAME 40 +#define MOENCH_ONE_PACKET_SIZE 1286 +#define MOENCH_BUFFER_SIZE (MOENCH_ONE_PACKET_SIZE*MOENCH_PACKETS_PER_FRAME) //1286*40 +#define MOENCH_DATA_BYTES (1280*MOENCH_PACKETS_PER_FRAME) //1280*40 + +#define MOENCH_BYTES_PER_ADC (40*2) +#define MOENCH_PIXELS_IN_ONE_ROW 160 +#define MOENCH_BYTES_IN_ONE_ROW (MOENCH_PIXELS_IN_ONE_ROW*2) + + +#define MOENCH_FRAME_INDEX_MASK 0xFFFFFF00 +#define MOENCH_FRAME_INDEX_OFFSET 8 +#define MOENCH_PACKET_INDEX_MASK 0xFF + + + + + +//#define THIS_SOFTWARE_VERSION 0x20120919 +#endif diff --git a/slsReceiverSoftware/includes/sls_receiver_defs.h b/slsReceiverSoftware/includes/sls_receiver_defs.h new file mode 100755 index 000000000..c4c1fc63e --- /dev/null +++ b/slsReceiverSoftware/includes/sls_receiver_defs.h @@ -0,0 +1,118 @@ +#ifndef SLS_RECEIVER_DEFS_H +#define SLS_RECEIVER_DEFS_H + + +#ifdef __CINT__ +#define MYROOT +#define __cplusplus +#endif + +#include + + +typedef double double32_t; +typedef float float32_t; +typedef int int32_t; + +/** default maximum string length */ +#define MAX_STR_LENGTH 1000 +#define MAX_FRAMES_PER_FILE 20000 +#define SHORT_MAX_FRAMES_PER_FILE 100000 +#define MOENCH_MAX_FRAMES_PER_FILE 1000 + + +/** + \file sls_receiver_defs.h +This file contains all the basic definitions common to the slsReceiver class +and to the server programs running on the receiver + * @author Anna Bergamaschi + * @version 0.1alpha (any string) + * @see slsDetector +$Revision: 809 $ + */ + + +#ifdef __cplusplus + +/** @short class containing all the constants and enum definitions */ +class slsReceiverDefs { +public: + + slsReceiverDefs(){}; + +#endif + + /** + Type of the detector + */ + enum detectorType { + GET_DETECTOR_TYPE=-1, /**< the detector will return its type */ + GENERIC, /**< generic sls detector */ + MYTHEN, /**< mythen */ + PILATUS, /**< pilatus */ + EIGER, /**< eiger */ + GOTTHARD, /**< gotthard */ + PICASSO, /**< picasso */ + AGIPD, /**< agipd */ + MOENCH /**< moench */ + }; + + + /** + return values + */ + enum { + OK, /**< function succeeded */ + FAIL, /**< function failed */ + FINISHED, /**< acquisition finished */ + FORCE_UPDATE + }; + + + /** + indexes for the acquisition timers + */ + enum timerIndex { + FRAME_NUMBER, /**< number of real time frames: total number of acquisitions is number or frames*number of cycles */ + ACQUISITION_TIME, /**< exposure time */ + FRAME_PERIOD, /**< period between exposures */ + DELAY_AFTER_TRIGGER, /**< delay between trigger and start of exposure or readout (in triggered mode) */ + GATES_NUMBER, /**< number of gates per frame (in gated mode) */ + PROBES_NUMBER, /**< number of probe types in pump-probe mode */ + CYCLES_NUMBER, /**< number of cycles: total number of acquisitions is number or frames*number of cycles */ + ACTUAL_TIME, /**< Actual time of the detector's internal timer */ + MEASUREMENT_TIME, /**< Time of the measurement from the detector (fifo) */ + + PROGRESS, /**< fraction of measurement elapsed - only get! */ + MEASUREMENTS_NUMBER + }; + + + /** + staus mask + */ + enum runStatus { + IDLE, /**< detector ready to start acquisition - no data in memory */ + ERROR, /**< error i.e. normally fifo full */ + WAITING, /**< waiting for trigger or gate signal */ + RUN_FINISHED, /**< acquisition not running but data in memory */ + TRANSMITTING, /**< acquisition running and data in memory */ + RUNNING /**< acquisition running, no data in memory */ + }; + + + +#ifdef __cplusplus +protected: +#endif + +#ifndef MYROOT +#include "sls_receiver_funcs.h" +#endif + +#ifdef __cplusplus +}; +#endif +; +#endif +; diff --git a/slsReceiverSoftware/includes/sls_receiver_funcs.h b/slsReceiverSoftware/includes/sls_receiver_funcs.h new file mode 100644 index 000000000..298eb39b1 --- /dev/null +++ b/slsReceiverSoftware/includes/sls_receiver_funcs.h @@ -0,0 +1,55 @@ +/** + @internal + function indexes to call on the server + All set functions with argument -1 work as get, when possible + */ +#ifndef SLS_RECEIVER_FUNCS_H +#define SLS_RECEIVER_FUNCS_H + +enum { + //General functions + F_EXEC_RECEIVER_COMMAND=0, /**< command is executed */ + F_EXIT_RECEIVER, /**< turn off receiver server */ + F_LOCK_RECEIVER, /**< Locks/Unlocks server communication to the given client */ + F_GET_LAST_RECEIVER_CLIENT_IP, /**< returns the IP of the client last connected to the receiver */ + F_SET_RECEIVER_PORT, /**< Changes communication port of the receiver */ + F_UPDATE_RECEIVER_CLIENT, /**< Returns all the important parameters to update the shared memory of the client */ + + // Identification + F_GET_RECEIVER_ID, /**< get receiver id of version */ + F_GET_RECEIVER_TYPE, /**< return receiver type */ + F_SEND_RECEIVER_DETHOSTNAME, /**< set detector hostname to receiver */ + + //network functions + F_RECEIVER_SHORT_FRAME, /**< Sets receiver to receive short frames */ + F_SETUP_RECEIVER_UDP, /**< sets the receiver udp connection and returns receiver mac address */ + + //Acquisition setup functions + F_SET_RECEIVER_TIMER, /**< set/get timer value */ + F_SET_RECEIVER_DYNAMIC_RANGE, /**< set/get detector dynamic range */ + F_READ_RECEIVER_FREQUENCY, /**< sets the frequency of receiver sending frames to gui */ + + // Acquisition functions + F_GET_RECEIVER_STATUS, /**< gets the status of receiver listening mode */ + F_START_RECEIVER, /**< starts the receiver listening mode */ + F_STOP_RECEIVER, /**< stops the receiver listening mode */ + F_START_RECEIVER_READOUT, /**< acquisition has stopped. start remaining readout in receiver */ + F_READ_RECEIVER_FRAME, /**< read one frame to gui*/ + + //file functions + F_SET_RECEIVER_FILE_PATH, /**< sets receiver file directory */ + F_SET_RECEIVER_FILE_NAME, /**< sets receiver file name */ + F_SET_RECEIVER_FILE_INDEX, /**< sets receiver file index */ + F_SET_RECEIVER_FRAME_INDEX, /**< sets the receiver frame index */ + F_GET_RECEIVER_FRAME_INDEX, /**< gets the receiver frame index */ + F_GET_RECEIVER_FRAMES_CAUGHT, /**< gets the number of frames caught by receiver */ + F_RESET_RECEIVER_FRAMES_CAUGHT, /**< resets the frames caught by receiver */ + F_ENABLE_RECEIVER_FILE_WRITE, /**< sets the receiver file write */ + F_ENABLE_RECEIVER_COMPRESSION, /**< enable compression in receiver */ + F_ENABLE_RECEIVER_OVERWRITE /**< set overwrite flag in receiver */ + + /* Always append functions hereafter!!! */ +}; + +#endif +/** @endinternal */ diff --git a/slsReceiverSoftware/includes/svnInfoReceiver.h b/slsReceiverSoftware/includes/svnInfoReceiver.h new file mode 100644 index 000000000..5b0ab940b --- /dev/null +++ b/slsReceiverSoftware/includes/svnInfoReceiver.h @@ -0,0 +1,11 @@ +//#define SVNPATH "" +#define SVNURL "file:///afs/psi.ch/project/sls_det_software/svn/slsReceiverSoftware/includes" +//#define SVNREPPATH "" +#define SVNREPUUID "5644e8d6-1a0c-4dbd-ab0e-45e7522ac187" +//#define SVNREV 0x5 +//#define SVNKIND "" +//#define SVNSCHED "" +#define SVNAUTH "l_maliakal_d" +#define SVNREV 0x5 +#define SVNDATE 0x20140515 +// diff --git a/slsReceiverSoftware/includes/svnInfoReceiverTmp.h b/slsReceiverSoftware/includes/svnInfoReceiverTmp.h new file mode 100644 index 000000000..58e48f497 --- /dev/null +++ b/slsReceiverSoftware/includes/svnInfoReceiverTmp.h @@ -0,0 +1,11 @@ +//#define SVNPATH "" +#define SVNURL "" +//#define SVNREPPATH "" +#define SVNREPUUID "" +//#define SVNREV "" +//#define SVNKIND "" +//#define SVNSCHED "" +#define SVNAUTH "" +#define SVNREV "" +#define SVNDATE "" +// diff --git a/slsReceiverSoftware/slsDetectorCalibration/MovingStat.h b/slsReceiverSoftware/slsDetectorCalibration/MovingStat.h new file mode 100755 index 000000000..9d3720b1b --- /dev/null +++ b/slsReceiverSoftware/slsDetectorCalibration/MovingStat.h @@ -0,0 +1,130 @@ +#ifndef MOVINGSTAT_H +#define MOVINGSTAT_H + +#include + + +class MovingStat + { + + /** @short approximated moving average structure */ + public: + + + /** constructor + \param nn number of samples parameter to be used + */ + MovingStat(int nn=1000) : n(nn), m_n(0) {} + + /** + clears the moving average number of samples parameter, mean and standard deviation + */ + void Clear() + { + m_n = 0; + m_newM=0; + m_newM2=0; + } + + + /** sets number of samples parameter + \param i number of samples parameter to be set + */ + + void SetN(int i) {if (i>=1) n=i;}; + + /** + gets number of samples parameter + \returns actual number of samples parameter + */ + int GetN() {return n;}; + + /** calculates the moving average i.e. adds if number of elements is lower than number of samples parameter, pushes otherwise + \param x value to calculate the moving average + */ + inline void Calc(double x) { + if (m_n 0) ? m_newM/m_n : 0.0; + } + + /** returns the squared mean, 0 if no elements are inside + \returns returns the squared average + */ + double M2() const + { + return ( (m_n > 1) ? m_newM2/m_n : 0.0 ); + } + + /** returns the variance, 0 if no elements are inside + \returns returns the variance + */ + inline double Variance() const + { + return ( (m_n > 1) ? (M2()-Mean()*Mean()) : 0.0 ); + } + + /** returns the standard deviation, 0 if no elements are inside + \returns returns the standard deviation + */ + inline double StandardDeviation() const + { + return ( (Variance() > 0) ? sqrt( Variance() ) : -1 ); + } + + private: + int n; /**< number of samples parameter */ + int m_n; /**< current number of elements */ + double m_newM; /**< accumulated average */ + double m_newM2; /**< accumulated squared average */ + }; +#endif diff --git a/slsReceiverSoftware/slsDetectorCalibration/RunningStat.h b/slsReceiverSoftware/slsDetectorCalibration/RunningStat.h new file mode 100755 index 000000000..1197ffc0f --- /dev/null +++ b/slsReceiverSoftware/slsDetectorCalibration/RunningStat.h @@ -0,0 +1,55 @@ + class RunningStat + { + public: + RunningStat() : m_n(0) {} + + void Clear() + { + m_n = 0; + } + + void Push(double x) + { + m_n++; + + // See Knuth TAOCP vol 2, 3rd edition, page 232 + if (m_n == 1) + { + m_oldM = m_newM = x; + m_oldS = 0.0; + } + else + { + m_newM = m_oldM + (x - m_oldM)/m_n; + m_newS = m_oldS + (x - m_oldM)*(x - m_newM); + + // set up for next iteration + m_oldM = m_newM; + m_oldS = m_newS; + } + } + + int NumDataValues() const + { + return m_n; + } + + double Mean() const + { + return (m_n > 0) ? m_newM : 0.0; + } + + double Variance() const + { + return ( (m_n > 1) ? m_newS/(m_n - 1) : 0.0 ); + } + + double StandardDeviation() const + { + return sqrt( Variance() ); + } + + private: + int m_n; + double m_oldM, m_newM, m_oldS, m_newS; + }; diff --git a/slsReceiverSoftware/slsDetectorCalibration/chiptestBoardData.h b/slsReceiverSoftware/slsDetectorCalibration/chiptestBoardData.h new file mode 100644 index 000000000..0ef633c44 --- /dev/null +++ b/slsReceiverSoftware/slsDetectorCalibration/chiptestBoardData.h @@ -0,0 +1,89 @@ +#ifndef CHIPTESTDATA_H +#define CHIPTESTDATA_H + +#include "slsDetectorData.h" + +class chiptestBoardData : public slsDetectorData { + + + public: + + /** + chiptestBoard data structure. Works for data acquired using the chiptestBoard. + Inherits and implements slsDetectorData. + + Constructor (no error checking if datasize and offsets are compatible!) + \param npx number of pixels in the x direction + \param npy number of pixels in the y direction (1 for strips) + \param nadc number of adcs + \param offset offset at the beginning of the pattern + \param dMap array of size nx*ny storing the pointers to the data in the dataset (as offset) + \param dMask Array of size nx*ny storing the polarity of the data in the dataset (should be 0 if no inversion is required, 0xffffffff is inversion is required) + \param dROI Array of size nx*ny. The elements are 1s if the channel is good or in the ROI, 0 is bad or out of the ROI. NULL (default) means all 1s. + + */ + chiptestBoardData(int npx, int npy, int nadc, int offset, int **dMap=NULL, uint16_t **dMask=NULL, int **dROI=NULL): slsDetectorData(npx, npy, nadc*(npx*npy)+offset, dMap, dMask, dROI), nAdc(nadc), offSize(offset), iframe(0) {}; // should be? nadc*(npx*npy+offset) + + + + /** + + Returns the frame number for the given dataset. Virtual func: works for slsDetectorReceiver data (also for each packet), but can be overloaded. + \param buff pointer to the dataset + \returns frame number + + */ + + virtual int getFrameNumber(char *buff){(void)buff; return iframe;}; + + + /** + + Loops over a memory slot until a complete frame is found (i.e. all packets 0 to nPackets, same frame number). Can be overloaded for different kind of detectors! + \param data pointer to the memory to be analyzed + \param ndata size of frame returned + \param dsize size of the memory slot to be analyzed + \returns always return the pointer to data (no frame loss!) + */ + + virtual char *findNextFrame(char *data, int &ndata, int dsize) {ndata=dsize;setDataSize(dsize); return data;}; + + /** + Loops over a file stream until a complete frame is found (i.e. all packets 0 to nPackets, same frame number). Can be overloaded for different kind of detectors! + \param filebin input file stream (binary) + \returns pointer to the first packet of the last good frame, NULL if no frame is found or last frame is incomplete + */ + + virtual char *readNextFrame(ifstream &filebin) { + + int afifo_length=0; + uint16_t *afifo_cont; + + if (filebin.is_open()) { + if (filebin.read((char*)&afifo_length,sizeof(uint32_t))) { + setDataSize(afifo_length*nAdc*sizeof(uint16_t)); + afifo_cont=new uint16_t[afifo_length*nAdc]; + if (filebin.read((char*)afifo_cont,afifo_length*sizeof(uint16_t)*nAdc)) { + iframe++; + return (char*)afifo_cont; + } else { + delete [] afifo_cont; + return NULL; + } + } else { + return NULL; + } + } + return NULL; + }; + + private: + const int nAdc; /**0) cmStat[i].Calc(cmPed[i]/nCm[i]); + nCm[i]=0; + cmPed[i]=0; + }}; + + /** adds the pixel to the sum of pedestals -- virtual func must be overloaded to define the regions of interest + \param val value to add + \param ix pixel x coordinate + \param iy pixel y coordinate + */ + virtual void addToCommonMode(double val, int ix=0, int iy=0) { + (void) ix; (void) iy; + + //if (isc>=0 && isc0) return cmPed[0]/nCm[0]-cmStat[0].Mean(); + return 0;}; + + + + + + protected: + MovingStat *cmStat; /**SetName("cds_g4"); + hs2N->SetTitle("cds_g4"); + (TH2F*)(hs2N->GetHists()->At(0))->Write(); + + (TH2F*)(hs2N->GetHists()->At(1))->Write(); + (TH2F*)(hs2N->GetHists()->At(2))->Write(); + (TH2F*)(hs2N->GetHists()->At(3))->Write(); + (TH2F*)(hs2N->GetHists()->At(4))->Write(); + + + fout->Close(); + + + +} + diff --git a/slsReceiverSoftware/slsDetectorCalibration/doxy.config b/slsReceiverSoftware/slsDetectorCalibration/doxy.config new file mode 100644 index 000000000..7d2a396ff --- /dev/null +++ b/slsReceiverSoftware/slsDetectorCalibration/doxy.config @@ -0,0 +1,85 @@ +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. +# Private class members and static file members will be hidden unless +# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES + +EXTRACT_ALL = YES + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class +# will be included in the documentation. + +EXTRACT_PRIVATE = NO + + + +# If the EXTRACT_STATIC tag is set to YES all static members of a file +# will be included in the documentation. + +EXTRACT_STATIC = YES + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) +# defined locally in source files will be included in the documentation. +# If set to NO only classes defined in header files are included. + +EXTRACT_LOCAL_CLASSES = YES + +# This flag is only useful for Objective-C code. When set to YES local +# methods, which are defined in the implementation section but not in +# the interface are included in the documentation. +# If set to NO (the default) only methods in the interface are included. + +EXTRACT_LOCAL_METHODS = YES + +# If this flag is set to YES, the members of anonymous namespaces will be +# extracted and appear in the documentation as a namespace called +# 'anonymous_namespace{file}', where file will be replaced with the base +# name of the file that contains the anonymous namespace. By default +# anonymous namespace are hidden. + +EXTRACT_ANON_NSPACES = NO + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all +# undocumented members of documented classes, files or namespaces. +# If set to NO (the default) these members will be included in the +# various overviews, but no documentation section is generated. +# This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. +# If set to NO (the default) these classes will be included in the various +# overviews. This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all +# friend (class|struct|union) declarations. +# If set to NO (the default) these declarations will be included in the +# documentation. + +HIDE_FRIEND_COMPOUNDS = NO + +INTERNAL_DOCS = NO + +SHOW_INCLUDE_FILES = NO + +SHOW_FILES = NO + +SHOW_NAMESPACES = NO + +COMPACT_LATEX = YES + +PAPER_TYPE = a4 + +PDF_HYPERLINKS = YES + +USE_PDFLATEX = YES + +LATEX_HIDE_INDICES = YES + +PREDEFINED = __cplusplus + +INPUT = MovingStat.h slsDetectorData.h slsReceiverData.h moench02ModuleData.h pedestalSubtraction.h commonModeSubtraction.h moenchCommonMode.h singlePhotonDetector.h energyCalibration.h moenchReadData.C single_photon_hit.h chiptestBoardData.h jungfrau02Data.h jungfrauReadData.C jungfrau02CommonMode.h +OUTPUT_DIRECTORY = docs + diff --git a/slsReceiverSoftware/slsDetectorCalibration/energyCalibration.cpp b/slsReceiverSoftware/slsDetectorCalibration/energyCalibration.cpp new file mode 100644 index 000000000..691122095 --- /dev/null +++ b/slsReceiverSoftware/slsDetectorCalibration/energyCalibration.cpp @@ -0,0 +1,527 @@ +#include "energyCalibration.h" + +#ifdef __CINT +#define MYROOT +#endif + + +#ifdef MYROOT +#include +#include +#include +#include +#endif + +#include + +#define max(a,b) ((a) > (b) ? (a) : (b)) +#define min(a,b) ((a) < (b) ? (a) : (b)) +#define ELEM_SWAP(a,b) { register int t=(a);(a)=(b);(b)=t; } + + +using namespace std; + +#ifdef MYROOT + +Double_t energyCalibrationFunctions::pedestal(Double_t *x, Double_t *par) { + return par[0]-par[1]*sign*x[0]; +} + + +Double_t energyCalibrationFunctions::gaussChargeSharing(Double_t *x, Double_t *par) { + Double_t f, arg=0; + if (par[3]!=0) arg=sign*(x[0]-par[2])/par[3]; + f=TMath::Exp(-1*arg*arg/2.); + f=f+par[5]/2.*(TMath::Erfc(arg/(TMath::Sqrt(2.)))); + return par[4]*f+pedestal(x,par); +} + +Double_t energyCalibrationFunctions::gaussChargeSharingPixel(Double_t *x, Double_t *par) { + Double_t f; + if (par[3]<=0 || par[2]*(*x)<=0 || par[5]<0 || par[4]<=0) return 0; + + Double_t pp[3]; + + pp[0]=0; + pp[1]=par[2]; + pp[2]=par[3]; + + + f=(par[5]-par[6]*(TMath::Log(*x/par[2])))*erfBox(x,pp); + f+=par[4]*TMath::Gaus(*x, par[2], par[3], kTRUE); + return f+pedestal(x,par); +} + +Double_t energyCalibrationFunctions::erfBox(Double_t *z, Double_t *par) { + + + + Double_t m=par[0]; + Double_t M=par[1]; + + if (par[0]>par[1]) { + m=par[1]; + M=par[0]; + } + + if (m==M) + return 0; + + + if (par[2]<=0) { + if (*z>=m && *z<=M) + return 1./(M-m); + else + return 0; + + } + + return (TMath::Erfc((z[0]-M)/par[2])-TMath::Erfc((z[0]-m)/par[2]))*0.5/(M-m); + +} + + +// basic erf function +Double_t energyCalibrationFunctions::erfFunction(Double_t *x, Double_t *par) { + double arg=0; + if (par[1]!=0) arg=(par[0]-x[0])/par[1]; + return ((par[2]/2.*(1+TMath::Erf(sign*arg/(TMath::Sqrt(2)))))); +}; + + +Double_t energyCalibrationFunctions::erfFunctionChargeSharing(Double_t *x, Double_t *par) { + Double_t f; + + f=erfFunction(x, par+2)*(1+par[5]*(par[2]-x[0]))+par[0]-par[1]*x[0]*sign; + return f; +}; + + +Double_t energyCalibrationFunctions::erfFuncFluo(Double_t *x, Double_t *par) { + Double_t f; + f=erfFunctionChargeSharing(x, par)+erfFunction(x, par+6)*(1+par[9]*(par[6]-x[0])); + return f; +}; +#endif + +double energyCalibrationFunctions::median(double *x, int n){ + // sorts x into xmed array and returns median + // n is number of values already in the xmed array + double xmed[n]; + int k,i,j; + + for (i=0; i*(x+j)) + k++; + if (*(x+i)==*(x+j)) { + if (i>j) + k++; + } + } + xmed[k]=*(x+i); + } + k=n/2; + return xmed[k]; +} + + +int energyCalibrationFunctions::quick_select(int arr[], int n){ + int low, high ; + int median; + int middle, ll, hh; + + low = 0 ; high = n-1 ; median = (low + high) / 2; + for (;;) { + if (high <= low) /* One element only */ + return arr[median] ; + + if (high == low + 1) { /* Two elements only */ + if (arr[low] > arr[high]) + ELEM_SWAP(arr[low], arr[high]) ; + return arr[median] ; + } + + /* Find median of low, middle and high items; swap into position low */ + middle = (low + high) / 2; + if (arr[middle] > arr[high]) ELEM_SWAP(arr[middle], arr[high]) ; + if (arr[low] > arr[high]) ELEM_SWAP(arr[low], arr[high]) ; + if (arr[middle] > arr[low]) ELEM_SWAP(arr[middle], arr[low]) ; + + /* Swap low item (now in position middle) into position (low+1) */ + ELEM_SWAP(arr[middle], arr[low+1]) ; + + /* Nibble from each end towards middle, swapping items when stuck */ + ll = low + 1; + hh = high; + for (;;) { + do ll++; while (arr[low] > arr[ll]) ; + do hh--; while (arr[hh] > arr[low]) ; + + if (hh < ll) + break; + + ELEM_SWAP(arr[ll], arr[hh]) ; + } + + /* Swap middle item (in position low) back into correct position */ + ELEM_SWAP(arr[low], arr[hh]) ; + + /* Re-set active partition */ + if (hh <= median) + low = ll; + if (hh >= median) + high = hh - 1; + } +} + +int energyCalibrationFunctions::kth_smallest(int *a, int n, int k){ + register int i,j,l,m ; + register double x ; + + l=0 ; m=n-1 ; + while (lSetParNames("Background Offset","Background Slope","Inflection Point","Noise RMS", "Number of Photons","Charge Sharing Slope"); + + fspectrum=new TF1("fspectrum",funcs,&energyCalibrationFunctions::spectrum,0,1000,6,"energyCalibrationFunctions","spectrum"); + fspectrum->SetParNames("Background Pedestal","Background slope", "Peak position","Noise RMS", "Number of Photons","Charge Sharing Pedestal"); + + fspixel=new TF1("fspixel",funcs,&energyCalibrationFunctions::spectrumPixel,0,1000,7,"energyCalibrationFunctions","spectrumPixel"); + fspixel->SetParNames("Background Pedestal","Background slope", "Peak position","Noise RMS", "Number of Photons","Charge Sharing Pedestal","Corner"); + +#endif + + +} + + + +void energyCalibration::fixParameter(int ip, Double_t val){ + + fscurve->FixParameter(ip, val); + fspectrum->FixParameter(ip, val); +} + + +void energyCalibration::releaseParameter(int ip){ + + fscurve->ReleaseParameter(ip); + fspectrum->ReleaseParameter(ip); +} + + + + + + + +energyCalibration::~energyCalibration(){ +#ifdef MYROOT + delete fscurve; + delete fspectrum; +#endif + +} + +#ifdef MYROOT + + + + + +TH1F* energyCalibration::createMedianHistogram(TH2F* h2, int ch0, int nch, int direction) { + + if (h2==NULL || nch==0) + return NULL; + + double *x=new double[nch]; + TH1F *h1=NULL; + + double val=-1; + + if (direction==0) { + h1=new TH1F("median","Median",h2->GetYaxis()->GetNbins(),h2->GetYaxis()->GetXmin(),h2->GetYaxis()->GetXmax()); + for (int ib=0; ibGetXaxis()->GetNbins(); ib++) { + for (int ich=0; ichGetBinContent(ch0+ich+1,ib+1); + } + val=energyCalibrationFunctions::median(x, nch); + h1->SetBinContent(ib+1,val); + } + } else if (direction==1) { + h1=new TH1F("median","Median",h2->GetXaxis()->GetNbins(),h2->GetXaxis()->GetXmin(),h2->GetXaxis()->GetXmax()); + for (int ib=0; ibGetYaxis()->GetNbins(); ib++) { + for (int ich=0; ichGetBinContent(ib+1,ch0+ich+1); + } + val=energyCalibrationFunctions::median(x, nch); + h1->SetBinContent(ib+1,val); + } + } + delete [] x; + + return h1; + +} + + + + + + + + + + + + + + +void energyCalibration::setStartParameters(Double_t *par){ + bg_offset=par[0]; + bg_slope=par[1]; + flex=par[2]; + noise=par[3]; + ampl=par[4]; + cs_slope=par[5]; +} + + +void energyCalibration::getStartParameters(Double_t *par){ + par[0]=bg_offset; + par[1]=bg_slope; + par[2]=flex; + par[3]=noise; + par[4]=ampl; + par[5]=cs_slope; +} + +#endif +int energyCalibration::setChargeSharing(int p) { + if (p>=0) { + cs_flag=p; +#ifdef MYROOT + if (p) { + fscurve->ReleaseParameter(5); + fspectrum->ReleaseParameter(1); + } else { + fscurve->FixParameter(5,0); + fspectrum->FixParameter(1,0); + } +#endif + } + + return cs_flag; +} + + +#ifdef MYROOT +void energyCalibration::initFitFunction(TF1 *fun, TH1 *h1) { + + Double_t min=fit_min, max=fit_max; + + Double_t mypar[6]; + + if (max==-1) + max=h1->GetXaxis()->GetXmax(); + + if (min==-1) + min=h1->GetXaxis()->GetXmin(); + + + if (bg_offset==-1) + mypar[0]=0; + else + mypar[0]=bg_offset; + + + if (bg_slope==-1) + mypar[1]=0; + else + mypar[1]=bg_slope; + + + if (flex==-1) + mypar[2]=(min+max)/2.; + else + mypar[2]=flex; + + + if (noise==-1) + mypar[3]=0.1; + else + mypar[3]=noise; + + if (ampl==-1) + mypar[4]=h1->GetBinContent(h1->GetXaxis()->FindBin(0.5*(max+min))); + else + mypar[4]=ampl; + + if (cs_slope==-1) + mypar[5]=0; + else + mypar[5]=cs_slope; + + fun->SetParameters(mypar); + + fun->SetRange(min,max); + +} + + +TF1* energyCalibration::fitFunction(TF1 *fun, TH1 *h1, Double_t *mypar, Double_t *emypar) { + + + TF1* fitfun; + + char fname[100]; + + strcpy(fname, fun->GetName()); + + if (plot_flag) { + h1->Fit(fname,"R0Q"); + } else + h1->Fit(fname,"R0Q"); + + + fitfun= h1->GetFunction(fname); + fitfun->GetParameters(mypar); + for (int ip=0; ip<6; ip++) { + emypar[ip]=fitfun->GetParError(ip); + } + return fitfun; +} + +TF1* energyCalibration::fitSCurve(TH1 *h1, Double_t *mypar, Double_t *emypar) { + initFitFunction(fscurve,h1); + return fitFunction(fscurve, h1, mypar, emypar); +} + + + + + +TF1* energyCalibration::fitSpectrum(TH1 *h1, Double_t *mypar, Double_t *emypar) { + initFitFunction(fspectrum,h1); + return fitFunction(fspectrum, h1, mypar, emypar); +} + + + +TGraphErrors* energyCalibration::linearCalibration(int nscan, Double_t *en, Double_t *een, Double_t *fl, Double_t *efl, Double_t &gain, Double_t &off, Double_t &egain, Double_t &eoff) { + + TGraphErrors *gr; + + Double_t mypar[2]; + + gr = new TGraphErrors(nscan,en,fl,een,efl); + + if (plot_flag) { + gr->Fit("pol1"); + gr->SetMarkerStyle(20); + } else + gr->Fit("pol1","0Q"); + + TF1 *fitfun= gr->GetFunction("pol1"); + fitfun->GetParameters(mypar); + + egain=fitfun->GetParError(1); + eoff=fitfun->GetParError(0); + + gain=funcs->setScanSign()*mypar[1]; + + off=mypar[0]; + + return gr; +} + + +TGraphErrors* energyCalibration::calibrate(int nscan, Double_t *en, Double_t *een, TH1F **h1, Double_t &gain, Double_t &off, Double_t &egain, Double_t &eoff, int integral) { + + TH1F *h; + + Double_t mypar[6], emypar[6]; + Double_t fl[nscan], efl[nscan]; + + + for (int ien=0; ien +#include +class TH1F; +class TH2F; +class TGraphErrors; +#endif + + +using namespace std; + + + + +const double conven=1000./3.6; /**< electrons/keV */ +const double el=1.67E-4; /**< electron charge in fC */ + + + +/** + \mainpage Common Root library for SLS detectors data analysis + * + * \section intro_sec Introduction + We know very well s-curves etc. but at the end everybody uses different functions ;-). + + * \subsection mot_sec Motivation + It would be greate to use everybody the same functions... + +*/ + + +/** + * + * +@libdoc The energiCalibration class contains all the necessary functions for s-curve fitting and linear calibration of the threshold. + * + * @short Energy calibration functions + * @author Anna Bergamaschi + * @version 0.1alpha + + + */ + +/** + class containing all the possible energy calibration functions (scurves with and without charge sharing, gaussian spectrum with and without charge sharing, possibility of chosing the sign of the X-axis) + +*/ +class energyCalibrationFunctions { + + public: + + energyCalibrationFunctions(int s=-1) {setScanSign(s);}; + + /** sets scan sign + \param s can be 1 (energy and x-axis have the same direction) or -1 (energy and x-axis have opposite directions) otherwise gets + \returns current scan sign can be 1 (energy and x-axis have the same direction) or -1 (energy and x-axis have opposite directions) + */ + int setScanSign(int s=0) {if (s==1 || s==-1) sign=s; return sign;};; + + +#ifdef MYROOT + /** + Gaussian Function with charge sharing pedestal + par[0] is the absolute height of the background pedestal + par[1] is the slope of the background pedestal + */ + Double_t pedestal(Double_t *x, Double_t *par); + + /** + Gaussian Function with charge sharing pedestal + par[0] is the absolute height of the background pedestal + par[1] is the slope of the background pedestal + par[2] is the gaussian peak position + par[3] is the RMS of the gaussian (and of the pedestal) + par[4] is the height of the function + par[5] is the fractional height of the charge sharing pedestal (scales with par[3]) + */ + Double_t gaussChargeSharing(Double_t *x, Double_t *par); + /** + Gaussian Function with charge sharing pedestal + par[0] is the absolute height of the background pedestal + par[1] is the slope of the background pedestal + par[2] is the gaussian peak position + par[3] is the RMS of the gaussian (and of the pedestal) + par[4] is the height of the function + par[5] is the fractional height of the charge sharing pedestal (scales with par[3]) + */ + Double_t gaussChargeSharingPixel(Double_t *x, Double_t *par); + + /** + Basic erf function + par[0] is the inflection point + par[1] is the RMS + par[2] is the amplitude + */ +Double_t erfFunction(Double_t *x, Double_t *par) ; + Double_t erfBox(Double_t *z, Double_t *par); + /** Erf function with charge sharing slope + par[0] is the pedestal + par[1] is the slope of the pedestal + par[2] is the inflection point + par[3] is the RMS + par[4] is the amplitude + par[5] is the angual coefficient of the charge sharing slope (scales with par[3]) + */ +Double_t erfFunctionChargeSharing(Double_t *x, Double_t *par); + + /** Double Erf function with charge sharing slope + par[0] is the pedestal + par[1] is the slope of the pedestal + par[2] is the inflection point of the first energy + par[3] is the RMS of the first energy + par[4] is the amplitude of the first energy + par[5] is the angual coefficient of the charge sharing slope of the first energy (scales with par[3]) + par[6] is the inflection point of the second energy + par[7] is the RMS of the second energy + par[8] is the amplitude of the second energy + par[9] is the angual coefficient of the charge sharing slope of the second energy (scales with par[8]) + */ + +Double_t erfFuncFluo(Double_t *x, Double_t *par); + + + /** + static function Gaussian with charge sharing pedestal with the correct scan sign + par[0] is the absolute height of the background pedestal + par[1] is the slope of the pedestal + par[2] is the gaussian peak position + par[3] is the RMS of the gaussian (and of the pedestal) + par[4] is the height of the function + par[5] is the fractional height of the charge sharing pedestal (scales with par[4] + */ + Double_t spectrum(Double_t *x, Double_t *par); + + /** + static function Gaussian with charge sharing pedestal with the correct scan sign + par[0] is the absolute height of the background pedestal + par[1] is the slope of the pedestal + par[2] is the gaussian peak position + par[3] is the RMS of the gaussian (and of the pedestal) + par[4] is the height of the function + par[5] is the fractional height of the charge sharing pedestal (scales with par[4] + */ + Double_t spectrumPixel(Double_t *x, Double_t *par); + + + /** Erf function with charge sharing slope with the correct scan sign + par[0] is the pedestal + par[1] is the slope of the pedestal + par[2] is the inflection point + par[3] is the RMS + par[4] is the amplitude + par[5] is the angual coefficient of the charge sharing slope (scales with par[3]) + */ + Double_t scurve(Double_t *x, Double_t *par); + + + + /** Double Erf function with charge sharing slope + par[0] is the pedestal + par[1] is the slope of the pedestal + par[2] is the inflection point of the first energy + par[3] is the RMS of the first energy + par[4] is the amplitude of the first energy + par[5] is the angual coefficient of the charge sharing slope of the first energy (scales with par[3]) + par[6] is the inflection point of the second energy + par[7] is the RMS of the second energy + par[8] is the amplitude of the second energy + par[9] is the angual coefficient of the charge sharing slope of the second energy (scales with par[8]) + */ + Double_t scurveFluo(Double_t *x, Double_t *par); + +#endif + +/** Calculates the median of an array of n elements */ + static double median(double *x, int n); +/** Calculates the median of an array of n elements (swaps the arrays!)*/ + static int quick_select(int arr[], int n); +/** Calculates the median of an array of n elements (swaps the arrays!)*/ + static int kth_smallest(int *a, int n, int k); + + private: + int sign; + + +}; + +/** + class alowing the energy calibration of photon counting and anlogue detectors + +*/ + +class energyCalibration { + + + public: + /** + default constructor - creates the function with which the s-curves will be fitted + */ + energyCalibration(); + + /** + default destructor - deletes the function with which the s-curves will be fitted + */ + ~energyCalibration(); + + /** sets plot flag + \param p plot flag (-1 gets, 0 unsets, >0 plot) + \returns current plot flag + */ + int setPlotFlag(int p=-1) {if (p>=0) plot_flag=p; return plot_flag;}; + + /** sets scan sign + \param s can be 1 (energy and x-axis have the same direction) or -1 (energy and x-axis have opposite directions) otherwise gets + \returns current scan sign can be 1 (energy and x-axis have the same direction) or -1 (energy and x-axis have opposite directions) + */ + int setScanSign(int s=0) {return funcs->setScanSign(s);}; + + /** sets plot flag + \param p plot flag (-1 gets, 0 unsets, >0 plot) + \returns current plot flag + */ + int setChargeSharing(int p=-1); + + + void fixParameter(int ip, Double_t val); + + void releaseParameter(int ip); + +#ifdef MYROOT + + /** + Creates an histogram with the median of nchannels starting from a specified one. the direction on which it is mediated can be selected (defaults to x=0) + \param h2 2D histogram on which the median will be calculated + \param ch0 starting channel + \param nch number of channels to be mediated + \param direction can be either 0 (x, default) or 1 (y) + \returns a TH1F histogram with the X-axis as a clone of the h2 Y (if direction=0) or X (if direction=0) axis, and on the Y axis the median of the counts of the mediated channels f h2 + */ + static TH1F* createMedianHistogram(TH2F* h2, int ch0, int nch, int direction=0); + + + /** sets the s-curve fit range + \param mi minimum of the fit range (-1 is histogram x-min) + \param ma maximum of the fit range (-1 is histogram x-max) + */ + void setFitRange(Double_t mi, Double_t ma){fit_min=mi; fit_max=ma;}; + + /** gets the s-curve fit range + \param mi reference for minimum of the fit range (-1 is histogram x-min) + \param ma reference for maximum of the fit range (-1 is histogram x-max) + */ + void getFitRange(Double_t &mi, Double_t &ma){mi=fit_min; ma=fit_max;}; + + +/** set start parameters for the s-curve function + \param par parameters, -1 sets to auto-calculation + par[0] is the pedestal + par[1] is the slope of the pedestal + par[2] is the inflection point + par[3] is the RMS + par[4] is the amplitude + par[5] is the angual coefficient of the charge sharing slope (scales with par[3]) -- always positive + */ + void setStartParameters(Double_t *par); + +/** get start parameters for the s-curve function + \param par parameters, -1 means auto-calculated + par[0] is the pedestal + par[1] is the slope of the pedestal + par[2] is the inflection point + par[3] is the RMS + par[4] is the amplitude + par[5] is the angual coefficient of the charge sharing slope (scales with par[3]) -- always positive + */ + void getStartParameters(Double_t *par); + + /** + fits histogram with the s-curve function + \param h1 1d-histogram to be fitted + \param mypar pointer to fit parameters array + \param emypar pointer to fit parameter errors + \returns the fitted function - can be used e.g. to get the Chi2 or similar + */ + TF1 *fitSCurve(TH1 *h1, Double_t *mypar, Double_t *emypar); + + + /** + fits histogram with the spectrum + \param h1 1d-histogram to be fitted + \param mypar pointer to fit parameters array + \param emypar pointer to fit parameter errors + \returns the fitted function - can be used e.g. to get the Chi2 or similar + */ + TF1 *fitSpectrum(TH1 *h1, Double_t *mypar, Double_t *emypar); + + + /** + calculates gain and offset for the set of inflection points + \param nscan number of energy scans + \param en array of energies (nscan long) + \param een array of errors on energies (nscan long) - can be NULL! + \param fl array of inflection points (nscan long) + \param efl array of errors on the inflection points (nscan long) + \param gain reference to gain resulting from the fit + \param off reference to offset resulting from the fit + \param egain reference to error on the gain resulting from the fit + \param eoff reference to the error on the offset resulting from the fit + \returns graph energy vs inflection point + */ + TGraphErrors* linearCalibration(int nscan, Double_t *en, Double_t *een, Double_t *fl, Double_t *efl, Double_t &gain, Double_t &off, Double_t &egain, Double_t &eoff); + + /** + calculates gain and offset for the set of energy scans + \param nscan number of energy scans + \param en array of energies (nscan long) + \param een array of errors on energies (nscan long) - can be NULL! + \param h1 array of TH1 + \param gain reference to gain resulting from the fit + \param off reference to offset resulting from the fit + \param egain reference to error on the gain resulting from the fit + \param eoff reference to the error on the offset resulting from the fit + \returns graph energy vs inflection point + */ + TGraphErrors* calibrateScurves(int nscan, Double_t *en, Double_t *een, TH1F **h1, Double_t &gain, Double_t &off, Double_t &egain, Double_t &eoff){return calibrate(nscan, en, een, h1, gain, off, egain, eoff, 1);}; + + /** + calculates gain and offset for the set of energy spectra + \param nscan number of energy scans + \param en array of energies (nscan long) + \param een array of errors on energies (nscan long) - can be NULL! + \param h1 array of TH1 + \param gain reference to gain resulting from the fit + \param off reference to offset resulting from the fit + \param egain reference to error on the gain resulting from the fit + \param eoff reference to the error on the offset resulting from the fit + \returns graph energy vs peak + */ + TGraphErrors* calibrateSpectra(int nscan, Double_t *en, Double_t *een, TH1F **h1, Double_t &gain, Double_t &off, Double_t &egain, Double_t &eoff){return calibrate(nscan, en, een, h1, gain, off, egain, eoff, 0);}; + + +#endif + private: + +#ifdef MYROOT + /** + calculates gain and offset for the set of energies + \param nscan number of energy scans + \param en array of energies (nscan long) + \param een array of errors on energies (nscan long) - can be NULL! + \param h1 array of TH1 + \param gain reference to gain resulting from the fit + \param off reference to offset resulting from the fit + \param egain reference to error on the gain resulting from the fit + \param eoff reference to the error on the offset resulting from the fit + \param integral 1 is an s-curve set (default), 0 spectra + \returns graph energy vs peak/inflection point + */ + TGraphErrors* calibrate(int nscan, Double_t *en, Double_t *een, TH1F **h1, Double_t &gain, Double_t &off, Double_t &egain, Double_t &eoff, int integral=1); + + + /** + Initializes the start parameters and the range of the fit depending on the histogram characteristics and/or on the start parameters specified by the user + \param fun pointer to function to be initialized + \param h1 histogram from which to extract the range and start parameters, if not already specified by the user + +*/ + + void initFitFunction(TF1 *fun, TH1 *h1); + + + /** + Performs the fit according to the flags specified and returns the fitted function + \param fun function to fit + \param h1 histogram to fit + \param mypar pointer to fit parameters array + \param emypar pointer to fit parameter errors + \returns the fitted function - can be used e.g. to get the Chi2 or similar + */ + TF1 *fitFunction(TF1 *fun, TH1 *h1, Double_t *mypar, Double_t *emypar); + +#endif + +#ifdef MYROOT + Double_t fit_min; /**< minimum of the s-curve fitting range, -1 is histogram x-min */ + Double_t fit_max; /**< maximum of the s-curve fitting range, -1 is histogram x-max */ + + Double_t bg_offset; /**< start value for the background pedestal */ + Double_t bg_slope; /**< start value for the background slope */ + Double_t flex; /**< start value for the inflection point */ + Double_t noise; /**< start value for the noise */ + Double_t ampl; /**< start value for the number of photons */ + Double_t cs_slope; /**< start value for the charge sharing slope */ + + + TF1 *fscurve; /**< function with which the s-curve will be fitted */ + + TF1 *fspectrum; /**< function with which the spectrum will be fitted */ + + TF1 *fspixel; /**< function with which the spectrum will be fitted */ + +#endif + + energyCalibrationFunctions *funcs; + int plot_flag; /**< 0 does not plot, >0 plots (flags?) */ + + int cs_flag; /**< 0 functions without charge sharing contribution, >0 with charge sharing contribution */ + +}; + +#endif + + + + + + + + + + + + + + + + + + + diff --git a/slsReceiverSoftware/slsDetectorCalibration/gMapDemo.C b/slsReceiverSoftware/slsDetectorCalibration/gMapDemo.C new file mode 100644 index 000000000..51addf69a --- /dev/null +++ b/slsReceiverSoftware/slsDetectorCalibration/gMapDemo.C @@ -0,0 +1,11 @@ +{ + //.L energyCalibration.cpp+ + //.L gainMap.C+ + TFile fin("/data/moench_xbox_20140113/MoTarget_45kV_0_8mA_120V_cds_g4.root"); + TH2F *h2=fin.Get("h2"); + TH2F *gMap=gainMap(h2,4); + gMap->Draw("colz"); + + + +} diff --git a/slsReceiverSoftware/slsDetectorCalibration/gainMap.C b/slsReceiverSoftware/slsDetectorCalibration/gainMap.C new file mode 100644 index 000000000..7923fe687 --- /dev/null +++ b/slsReceiverSoftware/slsDetectorCalibration/gainMap.C @@ -0,0 +1,228 @@ +#define MYROOT +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace std; + + +#define FOPT "0" + +TH2F *gainMap(TH2F *h2, float g) { + // int npx, npy; + int npx=160, npy=160; + // det->getDetectorSize(npx, npy); + + TH2F *gMap=new TH2F("gmap",h2->GetTitle(), npx, -0.5, npx-0.5, npy, -0.5, npy-0.5); + + Double_t ens[3]={0,8,17.5}, eens[3]={0.,0.1,0.1}; + Double_t peaks[3], epeaks[3]; + + + + int ibin; + TH1D *px; + + + energyCalibration *enCal=new energyCalibration(); + enCal->setPlotFlag(0); + // enCal->setChargeSharing(0); + enCal->setScanSign(1); + + Double_t gain, off, egain, eoff; + + + TList *functions; + TPolyMarker *pm ; + Double_t *peakX, *peakY; + TSpectrum *s=new TSpectrum(); + Double_t mypar[10], emypar[10]; + Double_t prms, np; + int iit=0; + TGraph *glin; + Double_t peakdum, hpeakdum; + + for (int ix=1; ixProjectionX("px",ibin+1,ibin+1); + prms=10*g; + iit=0; + np=s->Search(px,prms,"",0.2); + while (np !=2) { + if (np>2) + prms+=0.5*prms; + else + prms-=0.5*prms; + iit++; + if (iit>=10) + break; + np=s->Search(px,prms,"",0.2); + } + if (np!=2) + cout << "peak search could not converge " << ibin << endl; + if (np==2) { + pm=NULL; + functions=px->GetListOfFunctions(); + if (functions) + pm = (TPolyMarker*)functions->FindObject("TPolyMarker"); + if (pm) { + peakX=pm->GetX(); + peakY=pm->GetY(); + + + if (peakX[0]>peakX[1]) { + peakdum=peakX[0]; + hpeakdum=peakY[0]; + peakX[0]= peakX[1]; + peakY[0]= peakY[1]; + peakX[1]= peakdum; + peakY[1]= hpeakdum; + + } + + cout << "("<< ix << "," << iy << ") " << endl; + for (int ip=0; ipsetFitRange(peakX[ip]-10*g,peakX[ip]+10*g); + mypar[0]=0; + mypar[1]=0; + mypar[2]=peakX[ip]; + mypar[3]=g*10; + mypar[4]=peakY[ip]; + mypar[5]=0; + + + + enCal->setStartParameters(mypar); + enCal->fitSpectrum(px,mypar,emypar); + + + peaks[ip+1]=mypar[2]; + epeaks[ip+1]=emypar[2]; + } + + peaks[0]=0; + epeaks[0]=1; + + // for (int i=0; i<3; i++) cout << i << " " << ens[i] << " " << eens[i]<< " "<< peaks[i]<< " " << epeaks[i] << endl; + + glin= enCal->linearCalibration(3,ens,eens,peaks,epeaks,gain,off,egain,eoff); + + // cout << "Gain " << gain << " off " << off << endl; + if (off>-10 && off<10) { + gMap->SetBinContent(ix+1,iy+1,gain); + gMap->SetBinError(ix+1,iy+1,egain); + } + if (glin) + delete glin; + } + } + + + } + } + + return gMap; +} + + +TH2F *noiseMap(TH2F *h2) { + // int npx, npy; + int npx=160, npy=160; + // det->getDetectorSize(npx, npy); + + TH2F *nMap=new TH2F("nmap",h2->GetTitle(), npx, -0.5, npx-0.5, npy, -0.5, npy-0.5); + + int ibin; + TH1D *px; + + for (int ix=0; ixProjectionX("px",ibin+1,ibin+1); + px->Fit("gaus", FOPT); + if (px->GetFunction("gaus")) { + nMap->SetBinContent(ix+1,iy+1,px->GetFunction("gaus")->GetParameter(2)); + } + // delete px; + } + } + + return nMap; +} + + +THStack *noiseHistos(char *tit) { + char fname[10000]; + + sprintf(fname,"/data/moench_xbox_20140116/noise_map_%s.root",tit); + TFile *fn=new TFile(fname); + TH2F *nmap=(TH2F*)fn->Get("nmap"); + + if (nmap==NULL) { + cout << "No noise map in file " << fname << endl; + + return NULL; + } + + sprintf(fname,"/data/moench_xbox_20140113/gain_map_%s.root",tit); + TFile *fg=new TFile(fname); + TH2F *gmap=(TH2F*)fg->Get("gmap"); + + if (gmap==NULL) { + cout << "No gain map in file " << fname << endl; + + return NULL; + } + + nmap->Divide(gmap); + nmap->Scale(1000./3.6); + + THStack *hs=new THStack(tit,tit); + hs->SetTitle(tit); + + TH1F *h; + char hname[100]; + + cout << tit << endl; + for (int is=0; is<4; is++) { + sprintf(hname,"h%ds",is+1); + + h=new TH1F(hname,tit,500,0,500); + hs->Add(h); + // cout << hs->GetHists()->GetEntries() << endl; + for (int ix=40*is+2; ix<40*(is+1)-2; ix++) { + + for (int iy=2; iy<158; iy++) { + if (ix<100 || ix>120) + h->Fill(nmap->GetBinContent(ix+1,iy+1)); + } + } + cout << is+1 << "SC: " << "" << h->GetMean() << "+-" << h->GetRMS(); + h->Fit("gaus","0Q"); + h->SetLineColor(is+1); + if (h->GetFunction("gaus")) { + h->GetFunction("gaus")->SetLineColor(is+1); + cout << " or " << h->GetFunction("gaus")->GetParameter(1) << "+-" << h->GetFunction("gaus")->GetParError(1); + } + cout << endl; + } + + // cout << hs->GetHists()->GetEntries() << endl; + + return hs; + + +} diff --git a/slsReceiverSoftware/slsDetectorCalibration/gotthardModuleData.h b/slsReceiverSoftware/slsDetectorCalibration/gotthardModuleData.h new file mode 100644 index 000000000..3f674af57 --- /dev/null +++ b/slsReceiverSoftware/slsDetectorCalibration/gotthardModuleData.h @@ -0,0 +1,148 @@ +#ifndef GOTTHARDMODULEDATA_H +#define GOTTHARDMODULEDATA_H +#include "slsReceiverData.h" + + + + + +#define FRAMEMASK 0xFFFFFFFE +#define PACKETMASK 1 +#define FRAMEOFFSET 0x1 + + +class gotthardModuleData : public slsReceiverData { +public: + + + + + /** + Implements the slsReceiverData structure for the gotthard read out by a module i.e. using the slsReceiver + (1x1280 pixels, 2 packets 1286 large etc.) + \param c crosstalk parameter for the output buffer + + */ + + + gotthardModuleData(double c=0): slsReceiverData(xpixels, ypixels, npackets, buffersize), xtalk(c) { + + uint16_t **dMask; + int **dMap; + int ix, iy; + int initial_offset = 2; + int offset = initial_offset; + + dMask=new uint16_t*[ypixels]; + dMap=new int*[ypixels]; + for (int i = 0; i < ypixels; i++) { + dMap[i] = new int[xpixels]; + dMask[i] = new uint16_t[xpixels]; + } + + for(ix=0; ix>FRAMEOFFSET); + }; + + + + /** + gets the packets number (last packet is labelled with 0 and is replaced with 40) + \param buff pointer to the memory + \returns packet number + + */ + + int getPacketNumber(char *buff){ + int np=(*(int*)buff); + //gotthards frame header must be incremented + ++np; + //packet index should be 1 or 2 + return ((np&PACKETMASK)+1); + }; + + + /** + returns the pixel value as double correcting for the output buffer crosstalk + \param data pointer to the memory + \param ix coordinate in the x direction + \param iy coordinate in the y direction + \returns channel value as double + + */ + double getValue(char *data, int ix, int iy=0) { + //check how it is for gotthard + if (xtalk==0) + return slsDetectorData::getValue(data, ix, iy); + else + return slsDetectorData::getValue(data, ix, iy)-xtalk*slsDetectorData::getValue(data, ix-1, iy); + }; + + + + /** sets the output buffer crosstalk correction parameter + \param c output buffer crosstalk correction parameter to be set + \returns current value for the output buffer crosstalk correction parameter + + */ + double setXTalk(double c) {xtalk=c; return xtalk;} + + + /** gets the output buffer crosstalk parameter + \returns current value for the output buffer crosstalk correction parameter + */ + double getXTalk() {return xtalk;} + + + + + + + +private: + + double xtalk; /** { +public: + + + + + /** + Implements the slsReceiverData structure for the gotthard short read out by a module i.e. using the slsReceiver + (1x256 pixels, 1 packet 256 large etc.) + \param c crosstalk parameter for the output buffer + + */ + + + gotthardShortModuleData(double c=0): slsReceiverData(xpixels, ypixels, npackets, buffersize), xtalk(c){ + + uint16_t **dMask; + int **dMap; + int ix, iy; + int offset = 2; + + dMask=new uint16_t*[ypixels]; + dMap=new int*[ypixels]; + for (int i = 0; i < ypixels; i++) { + dMap[i] = new int[xpixels]; + dMask[i] = new uint16_t[xpixels]; + } + + for(ix=0; ix::getValue(data, ix, iy); + else + return slsDetectorData::getValue(data, ix, iy)-xtalk*slsDetectorData::getValue(data, ix-1, iy); + }; + + + + /** sets the output buffer crosstalk correction parameter + \param c output buffer crosstalk correction parameter to be set + \returns current value for the output buffer crosstalk correction parameter + + */ + double setXTalk(double c) {xtalk=c; return xtalk;} + + + /** gets the output buffer crosstalk parameter + \returns current value for the output buffer crosstalk correction parameter + */ + double getXTalk() {return xtalk;} + + + + + + + +private: + + double xtalk; /**=0 && ix=0 && iy=0 && dataMap[iy][ix]8000) //exchange if gainBits==2 is returned! + d|=(1<<14); // gain bit 1 + if (*((uint16_t*)(data)+dataMap[iy][ix]+1)>8000) //exchange if gainBits==2 is returned! + d|=(1<<15); // gain bit 0 + + } + + } + return d^m; + }; + + /** + returns the pixel value as double correcting for the output buffer crosstalk + \param data pointer to the memory + \param ix coordinate in the x direction + \param iy coordinate in the y direction + \returns channel value as double + + */ + double getValue(char *data, int ix, int iy=0) { + // cout << "##" << (void*)data << " " << ix << " " < the gain bits are read out the wrong way around (i.e. GB0 and GB1 have to be reversed!) + \param data pointer to the memory + \param ix coordinate in the x direction + \param iy coordinate in the y direction + \returns gain bits as int + */ + int getGainBits(char *data, int ix, int iy=0) { + uint16_t d=getChannel(data, ix, iy); + return ((d&0xc000)>>14); + }; + //*/ + + + + + /** sets the output buffer crosstalk correction parameter + \param c output buffer crosstalk correction parameter to be set + \returns current value for the output buffer crosstalk correction parameter + + */ + double setXTalk(double c) {xtalk=c; return xtalk;} + + + /** gets the output buffer crosstalk parameter + \returns current value for the output buffer crosstalk correction parameter + */ + double getXTalk() {return xtalk;} + + + + + + + + private: + + double xtalk; /** +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +//#include +//#include +//#include +#include +#include "jungfrau02Data.h" +#include "jungfrau02CommonMode.h" +#include "singlePhotonDetector.h" + +//#include "MovingStat.h" + +using namespace std; + +#define NC 48 +#define NR 48 + + +#define MY_DEBUG 1 +#ifdef MY_DEBUG +#include +#endif + +/** + +Loops over data file to find single photons, fills the tree (and writes it to file, although the root file should be opened before) and creates 1x1, 2x2, 3x3 cluster histograms with ADCu on the x axis, channel number (48*x+y) on the y axis. + + \param fformat file name format + \param tit title of the tree etc. + \param runmin minimum run number + \param runmax max run number + \param nbins number of bins for spectrum hists + \param hmin histo minimum for spectrum hists + \param hmax histo maximum for spectrum hists + \param sign sign of the spectrum to find hits + \param hc readout correlation coefficient with previous pixel + \param xmin minimum x coordinate + \param xmax maximum x coordinate + \param ymin minimum y coordinate + \param ymax maximum y coordinate + \param cmsub enable commonmode subtraction + \param hitfinder if 0: performs pedestal subtraction, not hit finding; if 1: performs both pedestal subtraction and hit finding + \returns pointer to histo stack with cluster spectra +*/ + + +THStack *jungfrauReadData(char *fformat, char *tit, int runmin, int runmax, int nbins=1500, int hmin=-500, int hmax=1000, int sign=1, double hc=0, int xmin=1, int xmax=NC-1, int ymin=1, int ymax=NR-1, int cmsub=0, int hitfinder=1){ +/* + // read in calibration file + ifstream calfile("/home/l_msdetect/TriesteBeam2014/dummy data for scripts/CalibrationParametersTest_fake.txt"); + if (calfile.is_open()==0){cout << "Unable to open calibration file!" << endl;} + int pix; + double of0,sl0,of1,sl1,of2,sl2; + double of_0[NC*NR], of_1[NC*NR], of_2[NC*NR], sl_0[NC*NR], sl_1[NC*NR], sl_2[NC*NR]; + while (calfile >> pix >> of0 >> sl0 >> of1 >> sl1 >> of2 >> sl2){ + of_0[pix]=of0; + sl_0[pix]=sl0; + of_1[pix]=of1; + sl_1[pix]=sl1; + of_2[pix]=of2; + sl_2[pix]=sl2; //if(pix==200) cout << "sl_2[200] " << sl_2[200] << endl; + } + calfile.close(); +*/ + double adc_value, num_photon; + + jungfrau02Data *decoder=new jungfrau02Data(1,0,0);//(1,0,0); // (adc,offset,crosstalk) //(1,0,0) //(3,0,0) for readout of GB + jungfrau02CommonMode *cmSub=NULL; + if (cmsub) + cmSub=new jungfrau02CommonMode(); + + int nph=0; + int iev=0; + singlePhotonDetector *filter=new singlePhotonDetector(decoder, 3, 5, sign, cmSub); + + char *buff; + char fname[10000]; + int nf=0; + + eventType thisEvent=PEDESTAL; + + // int iframe; + // double *data, ped, sigma; + + // data=decoder->getCluster(); + + TH2F *h2; + TH2F *h3; + TH2F *hetaX; // not needed for JF? + TH2F *hetaY; // not needed for JF? + + THStack *hs=new THStack("hs",fformat); + + + TH2F *h1=new TH2F("h1",tit,nbins,hmin-0.5,hmax-0.5,NC*NR,-0.5,NC*NR-0.5); + hs->Add(h1); + + if (hitfinder) { + h2=new TH2F("h2",tit,nbins,hmin-0.5,hmax-0.5,NC*NR,-0.5,NC*NR-0.5); + h3=new TH2F("h3",tit,nbins,hmin-0.5,hmax-0.5,NC*NR,-0.5,NC*NR-0.5); + hetaX=new TH2F("hetaX",tit,nbins,-1,2,NC*NR,-0.5,NC*NR-0.5); // not needed for JF? + hetaY=new TH2F("hetaY",tit,nbins,-1,2,NC*NR,-0.5,NC*NR-0.5); // not needed for JF? + hs->Add(h2); + hs->Add(h3); + hs->Add(hetaX); // not needed for JF? + hs->Add(hetaY); // not needed for JF? + } + + + ifstream filebin; + + + int ix=20, iy=20, ir, ic; + + + Int_t iFrame; + TTree *tall; + if (hitfinder) + tall=filter->initEventTree(tit, &iFrame); + + + + +#ifdef MY_DEBUG + + TCanvas *myC; + TH2F *he; + TCanvas *cH1; + TCanvas *cH2; + TCanvas *cH3; + + if (hitfinder) { + myC=new TCanvas(); + he=new TH2F("he","Event Mask",xmax-xmin, xmin, xmax, ymax-ymin, ymin, ymax); + he->SetStats(kFALSE); + he->Draw("colz"); + cH1=new TCanvas(); + cH1->SetLogz(); + h1->Draw("colz"); + cH2=new TCanvas(); + cH2->SetLogz(); + h2->Draw("colz"); + cH3=new TCanvas(); + cH3->SetLogz(); + h3->Draw("colz"); + } +#endif + filter->newDataSet(); + + + for (int irun=runmin; irun<=runmax; irun++){ + sprintf(fname,fformat,irun); + cout << "file name " << fname << endl; + filebin.open((const char *)(fname), ios::in | ios::binary); + nph=0; + while ((buff=decoder->readNextFrame(filebin))) { + + + if (hitfinder) { + filter->newFrame(); + + //calculate pedestals and common modes + if (cmsub) { + // cout << "cm" << endl; + for (ix=xmin-1; ixgetEventType(buff, ix, iy,0); + } + } + } + + // cout << "new frame " << endl; + + for (ix=xmin-1; ixgetEventType(buff, ix, iy, cmsub); + int gainBits=decoder->getGainBits(buff,ix,iy); //XXX + +#ifdef MY_DEBUG + if (hitfinder) { + if (iev%1000==0) + //he->SetBinContent(ix+1-xmin, iy+1-ymin, (int)thisEvent); // show single photon hits // original + //he->SetBinContent(ix+1-xmin, iy+1-ymin, cmSub->getCommonMode(ix,iy)); //show common mode! + he->SetBinContent(iy+1-ymin, ix+1-xmin, (int)gainBits); //show gain bits + //he->SetBinContent(ix+1-xmin, iy+1-ymin, (int)gainBits); // rows and columns reversed!!! + } +#endif + + if (nf>1000) { // only start filing data after 1000 frames + + // h1->Fill(decoder->getValue(buff,ix,iy), iy+NR*ix); + h1->Fill(filter->getClusterTotal(1), iy+NR*ix); + + + if (hitfinder) { + + if (thisEvent==PHOTON_MAX ) { + nph++; + + h2->Fill(filter->getClusterTotal(2), iy+NR*ix); + h3->Fill(filter->getClusterTotal(3), iy+NR*ix); + iFrame=decoder->getFrameNumber(buff); + + tall->Fill(); + + + } + + + } + + + } + } + ////////////////////////////////////////////////////////// + +#ifdef MY_DEBUG + if (iev%1000==0) { + myC->Modified(); + myC->Update(); + cH1->Modified(); + cH1->Update(); + cH2->Modified(); + cH2->Update(); + cH3->Modified(); + cH3->Update(); + } + iev++; +#endif + nf++; + + cout << "="; // one "=" for every frame that's been processed + delete [] buff; + } + cout << nph << endl; // number of photons found in file + if (filebin.is_open()) + filebin.close(); + else + cout << "Could not open file :( ... " << fname << endl; + } + if (hitfinder) + tall->Write(tall->GetName(),TObject::kOverwrite); + + + + delete decoder; + cout << "Read " << nf << " frames." << endl; + return hs; +} + diff --git a/slsReceiverSoftware/slsDetectorCalibration/moench02ModuleData.h b/slsReceiverSoftware/slsDetectorCalibration/moench02ModuleData.h new file mode 100644 index 000000000..34b4f1783 --- /dev/null +++ b/slsReceiverSoftware/slsDetectorCalibration/moench02ModuleData.h @@ -0,0 +1,137 @@ +#ifndef MOENCH02MODULEDATA_H +#define MOENCH02MODULEDATA_H +#include "slsReceiverData.h" + + + +class moench02ModuleData : public slsReceiverData { + public: + + + + + /** + Implements the slsReceiverData structure for the moench02 prototype read out by a module i.e. using the slsReceiver + (160x160 pixels, 40 packets 1286 large etc.) + \param c crosstalk parameter for the output buffer + + */ + + + moench02ModuleData(double c=0): slsReceiverData(160, 160, 40, 1286), + xtalk(c) { + + + + + uint16_t **dMask; + int **dMap; + int ix, iy; + + + + dMask=new uint16_t*[160]; + dMap=new int*[160]; + for (int i = 0; i < 160; i++) { + dMap[i] = new int[160]; + dMask[i] = new uint16_t[160]; + } + + for (int isc=0; isc<4; isc++) { + for (int ip=0; ip<10; ip++) { + + for (int ir=0; ir<16; ir++) { + for (int ic=0; ic<40; ic++) { + + ix=isc*40+ic; + iy=ip*16+ir; + + dMap[iy][ix]=1286*(isc*10+ip)+2*ir*40+2*ic+4; + // cout << ix << " " << iy << " " << dMap[ix][iy] << endl; + } + } + } + } + + for (ix=0; ix<120; ix++) { + for (iy=0; iy<160; iy++) + dMask[iy][ix]=0x3fff; + } + for (ix=120; ix<160; ix++) { + for (iy=0; iy<160; iy++) + dMask[iy][ix]=0x0; + } + + + setDataMap(dMap); + setDataMask(dMask); + + + + + }; + + + + /** + gets the packets number (last packet is labelled with 0 and is replaced with 40) + \param buff pointer to the memory + \returns packet number + + */ + + int getPacketNumber(char *buff){ + int np=(*(int*)buff)&0xff; + if (np==0) + np=40; + return np; + }; + + + /** + returns the pixel value as double correcting for the output buffer crosstalk + \param data pointer to the memory + \param ix coordinate in the x direction + \param iy coordinate in the y direction + \returns channel value as double + + */ + double getValue(char *data, int ix, int iy=0) { + // cout << "##" << (void*)data << " " << ix << " " <::getValue(data, ix, iy); + else + return slsDetectorData::getValue(data, ix, iy)-xtalk*slsDetectorData::getValue(data, ix-1, iy); + }; + + + + /** sets the output buffer crosstalk correction parameter + \param c output buffer crosstalk correction parameter to be set + \returns current value for the output buffer crosstalk correction parameter + + */ + double setXTalk(double c) {xtalk=c; return xtalk;} + + + /** gets the output buffer crosstalk parameter + \returns current value for the output buffer crosstalk correction parameter + */ + double getXTalk() {return xtalk;} + + + + + + + + private: + + double xtalk; /**=0 && isc=0 && isc0) return cmPed[isc]/nCm[isc]-cmStat[isc].Mean(); + } + return 0; + }; + +}; + + +#endif diff --git a/slsReceiverSoftware/slsDetectorCalibration/moenchMakeTree.C b/slsReceiverSoftware/slsDetectorCalibration/moenchMakeTree.C new file mode 100644 index 000000000..372052285 --- /dev/null +++ b/slsReceiverSoftware/slsDetectorCalibration/moenchMakeTree.C @@ -0,0 +1,244 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "RunningStat.h" +#include "MovingStat.h" +#include "moench02ModuleData.h" +#include + +using namespace std; + + +//tree variables + int xC,yC,iFrameC; + double meC,sigC; + Double_t dataC[3][3]; +TTree* tall; + +typedef struct task_s{ + char *fformat; + char *tname; + int runmin; + int runmax; + int sign; +} Task; + +void setUpTree(char *tname){ + tall=new TTree(tname,tname); + tall->Branch("iFrame",&iFrameC,"iframe/I"); + tall->Branch("x",&xC,"x/I"); + tall->Branch("y",&yC,"y/I"); + tall->Branch("data",dataC,"data[3][3]/D"); + tall->Branch("pedestal",&meC,"pedestal/D"); + tall->Branch("rms",&sigC,"rms/D"); +} + +inline void storeEvent(int iF,int x,int y, Double_t data[][3], double me, double sig){ + TThread::Lock(); + xC = x; yC = y; iFrameC = iF; + memcpy(dataC,data,sizeof(Double_t)*3*3); + //cout << "X: " << x << " Y: " << y << endl; + /* for(int i = 0; i < 3; i++){ + for(int j = 0; j < 3; j++){ + cout << "i: " << i << " j: " << j << " dataC " << dataC[i][j] << " data " << data[i][j] << endl; + } + }*/ + meC = me; sigC = sig; + tall->Fill(); + TThread::UnLock(); +} + +void moenchMakeTree(char *fformat, char *tname, int runmin, int runmax, int sign=1) { + double nThSigma = 3.; + moench02ModuleData *decoder=new moench02ModuleData(); + char *buff; + char fname[10000]; + + int nf=0; + + int dum, nPhotons; + double me, sig, tot, maxNei, val, valNei; + + MovingStat stat[160][160]; + MovingStat nPhotonsStat; + + ifstream filebin; + + int nbg=20; + + int ix, iy, ir, ic, mx,my; + Double_t data[3][3]; + + nPhotonsStat.Clear(); + nPhotonsStat.SetN(1000); + + for (ir=0; ir<160; ir++) { + for (ic=0; ic<160; ic++) { + stat[ir][ic].Clear(); + stat[ir][ic].SetN(nbg); + } + } + + for (int irun=runmin; irunreadNextFrame(filebin))) { + nPhotons=0; + //for (ix=0; ix<160; ix++){ + for (ix=0; ix<40; ix++){ + for (iy=0; iy<160; iy++) { + + + + dum=0; //no hit + // tot=0; + + me=stat[iy][ix].Mean(); + sig=stat[iy][ix].StandardDeviation(); + val=sign*(decoder->getChannelShort(buff,ix,iy)-me); + + + if (nf>nbg) { + me=stat[iy][ix].Mean(); + sig=stat[iy][ix].StandardDeviation(); + val=sign*decoder->getChannel(buff,ix,iy)-me; + + // dum=0; //no hit + tot=0; + maxNei = 0; + + if (val>nThSigma*sig)//{ //hit check if neighbors are higher + dum=1; + for (ir=-1; ir<2; ir++){ + for (ic=-1; ic<2; ic++){ + if ((ix+ic)>=0 && (ix+ic)<160 && (iy+ir)>=0 && (iy+ir)<160) { + valNei = sign*decoder->getChannel(buff,ix+ic,iy+ir)-stat[iy+ir][ix+ic].Mean(); + if (sign*decoder->getChannel(buff,ix+ic,iy+ir)>(stat[iy+ir][ix+ic].Mean()+3.*stat[iy+ir][ix+ic].StandardDeviation())) dum=1; //is a hit or neighbour is a hit! + tot+=valNei; + data[ir+1][ic+1] = valNei; + if(valNei/stat[iy+ir][ix+ic].StandardDeviation() > maxNei){ + maxNei = valNei/stat[iy+ir][ix+ic].StandardDeviation(); + mx = ir; + my = ic; + } + } + } + } + // } + + if (val<(-nThSigma*sig)) dum=2; //discard negative events! + + if(dum == 1 && mx == 0 && my == 0){ // this is an event and we are in the center + storeEvent(nf,ix,iy,data,me,sig); + nPhotons++; + //cout << "BF X: " << ix << " Y: " << iy << " val: " << val << " tot: " << tot << " me: " << me << " sig: " << sig << endl; + } + + + //if (tot>9.*sig && dum == 1){ dum=3;} + //cout << dum; + } + //if (ix==20 && iy==40) + //cout << decoder->getChannelShort(buff,ix,iy)<< " " << val << " " << me << " " << sig << " " << dum << endl; + + if ( dum==0) { + + stat[iy][ix].Calc(decoder->getChannelShort(buff,ix,iy)); + } + if (nfgetChannel(buff,ix,iy)); + + } + } + delete [] buff; + //cout << "="; cout.flush(); + if(nf>nbg) nPhotonsStat.Calc((double)nPhotons); + nf++; + } + //cout << endl; + cout << "processed File " << fname << " done. Avg. Photons/Frame: " << nPhotonsStat.Mean() << " sig: " << nPhotonsStat.StandardDeviation() << " " << runmax-irun << " files need processing" << endl; + if (filebin.is_open()) + filebin.close(); + else + cout << "could not open file " << fname << endl; + } + + delete decoder; + cout << "Read " << nf << " frames" << endl; + + +} + +void *moenchMakeTreeTask(void *p){ + Task *t = (Task *)p; + moenchMakeTree(t->fformat,t->tname,t->runmin,t->runmax,t->sign); + return 0; +} + + +//to compile: g++ -DMYROOT -g `root-config --cflags --glibs` -o moenchMakeTree moenchMakeTree.C +int main(int argc, char **argv){ + if(argc != 6){ cout << "Usage: inFile outdir tname fileNrStart fileNrEnd" << endl; exit(-1); } + + int nThreads = 10; + TThread *threads[nThreads]; + + char *inFile = argv[1]; + char *outDir = argv[2]; + char *tName = argv[3]; + int start = atoi(argv[4]); + int end = atoi(argv[5]); + + TFile *f; + char outfname[1000]; + char threadName[1000]; + + sprintf(outfname,"%s/%s.root",outDir,tName); + f=new TFile(outfname,"RECREATE"); + + cout << "outputfile: " << outfname << endl; + setUpTree(tName); + + for(int i = 0; i < nThreads; i++){ + sprintf(threadName,"t%i",i); + Task *t = (Task *)malloc(sizeof(Task)); + t->fformat = inFile; + t->tname = tName; + t->sign = 1.; + t->runmin = start + (end-start)/(nThreads)*i; + t->runmax = start + (end-start)/(nThreads)*(i+1); + if(i == nThreads - 1) t->runmax = end; + cout << "start thread " << i << " start: " << t->runmin << " end " << t->runmax << endl; + threads[i] = new TThread(threadName, moenchMakeTreeTask, t); + threads[i]->Run(); + //moenchMakeTreeTask(t); + } + + + //TThread::Ps(); + + for(int i = 0; i < nThreads; i++){ + threads[i]->Join(); + } + + + tall->Write(); + tall->Print(); + f->Close(); +} + diff --git a/slsReceiverSoftware/slsDetectorCalibration/moenchReadData.C b/slsReceiverSoftware/slsDetectorCalibration/moenchReadData.C new file mode 100644 index 000000000..bf7173f0b --- /dev/null +++ b/slsReceiverSoftware/slsDetectorCalibration/moenchReadData.C @@ -0,0 +1,236 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +//#include +//#include +//#include +#include +#include "moench02ModuleData.h" +#include "moenchCommonMode.h" +#include "singlePhotonDetector.h" + +//#include "MovingStat.h" + +using namespace std; + +#define NC 160 +#define NR 160 + + +#define MY_DEBUG 1 +#ifdef MY_DEBUG +#include +#endif + +/** + +Loops over data file to find single photons, fills the tree (and writes it to file, althoug the root file should be opened before) and creates 1x1, 2x2, 3x3 cluster histograms with ADCu on the x axis, channel number (160*x+y) on the y axis. + + \param fformat file name format + \param tit title of the tree etc. + \param runmin minimum run number + \param runmax max run number + \param nbins number of bins for spectrum hists + \param hmin histo minimum for spectrum hists + \param hmax histo maximum for spectrum hists + \param sign sign of the spectrum to find hits + \param hc readout correlation coefficient with previous pixel + \param xmin minimum x coordinate + \param xmax maximum x coordinate + \param ymin minimum y coordinate + \param ymax maximum y coordinate + \param cmsub enable commonmode subtraction + \returns pointer to histo stack with cluster spectra +*/ + + +THStack *moenchReadData(char *fformat, char *tit, int runmin, int runmax, int nbins=1500, int hmin=-500, int hmax=1000, int sign=1, double hc=0, int xmin=1, int xmax=NC-1, int ymin=1, int ymax=NR-1, int cmsub=0, int hitfinder=1) { + + moench02ModuleData *decoder=new moench02ModuleData(hc); + moenchCommonMode *cmSub=NULL; + if (cmsub) + cmSub=new moenchCommonMode(); + + int nph=0; + + singlePhotonDetector *filter=new singlePhotonDetector(decoder, 3, 5, sign, cmSub); + + char *buff; + char fname[10000]; + int nf=0; + + eventType thisEvent=PEDESTAL; + + // int iframe; + // double *data, ped, sigma; + + // data=decoder->getCluster(); + + TH2F *h2; + TH2F *h3; + TH2F *hetaX; + TH2F *hetaY; + + THStack *hs=new THStack("hs",fformat); + + + + TH2F *h1=new TH2F("h1",tit,nbins,hmin-0.5,hmax-0.5,NC*NR,-0.5,NC*NR-0.5); + hs->Add(h1); + + if (hitfinder) { + h2=new TH2F("h2",tit,nbins,hmin-0.5,hmax-0.5,NC*NR,-0.5,NC*NR-0.5); + h3=new TH2F("h3",tit,nbins,hmin-0.5,hmax-0.5,NC*NR,-0.5,NC*NR-0.5); + hetaX=new TH2F("hetaX",tit,nbins,-1,2,NC*NR,-0.5,NC*NR-0.5); + hetaY=new TH2F("hetaY",tit,nbins,-1,2,NC*NR,-0.5,NC*NR-0.5); + hs->Add(h2); + hs->Add(h3); + hs->Add(hetaX); + hs->Add(hetaY); + } + + + + ifstream filebin; + + + int ix=20, iy=20, ir, ic; + + + Int_t iFrame; + TTree *tall; + if (hitfinder) + tall=filter->initEventTree(tit, &iFrame); + + + + +#ifdef MY_DEBUG + + TCanvas *myC; + TH2F *he; + TCanvas *cH1; + TCanvas *cH2; + TCanvas *cH3; + + if (hitfinder) { + myC=new TCanvas(); + he=new TH2F("he","Event Mask",xmax-xmin, xmin, xmax, ymax-ymin, ymin, ymax); + he->SetStats(kFALSE); + he->Draw("colz"); + cH1=new TCanvas(); + cH1->SetLogz(); + h1->Draw("colz"); + cH2=new TCanvas(); + cH2->SetLogz(); + h2->Draw("colz"); + cH3=new TCanvas(); + cH3->SetLogz(); + h3->Draw("colz"); + } +#endif + filter->newDataSet(); + + + for (int irun=runmin; irunreadNextFrame(filebin))) { + + + if (hitfinder) { + filter->newFrame(); + + //calculate pedestals and common modes + if (cmsub) { + // cout << "cm" << endl; + for (ix=xmin-1; ixgetEventType(buff, ix, iy,0); + } + } + } + + // cout << "new frame " << endl; + + for (ix=xmin-1; ixgetEventType(buff, ix, iy, cmsub); + +#ifdef MY_DEBUG + if (hitfinder) { + if (iev%1000==0) + he->SetBinContent(ix+1-xmin, iy+1-ymin, (int)thisEvent); + } +#endif + + if (nf>1000) { + h1->Fill(filter->getClusterTotal(1), iy+NR*ix); + if (hitfinder) { + + if (thisEvent==PHOTON_MAX ) { + nph++; + + h2->Fill(filter->getClusterTotal(2), iy+NR*ix); + h3->Fill(filter->getClusterTotal(3), iy+NR*ix); + iFrame=decoder->getFrameNumber(buff); + + tall->Fill(); + + + } + + + } + + + } + } + ////////////////////////////////////////////////////////// + +#ifdef MY_DEBUG + if (iev%1000==0) { + myC->Modified(); + myC->Update(); + cH1->Modified(); + cH1->Update(); + cH2->Modified(); + cH2->Update(); + cH3->Modified(); + cH3->Update(); + } + iev++; +#endif + nf++; + + cout << "=" ; + delete [] buff; + } + cout << nph << endl; + if (filebin.is_open()) + filebin.close(); + else + cout << "could not open file " << fname << endl; + } + if (hitfinder) + tall->Write(tall->GetName(),TObject::kOverwrite); + + + + delete decoder; + cout << "Read " << nf << " frames" << endl; + return hs; +} + diff --git a/slsReceiverSoftware/slsDetectorCalibration/moenchReadDataMT.C b/slsReceiverSoftware/slsDetectorCalibration/moenchReadDataMT.C new file mode 100644 index 000000000..0720909c4 --- /dev/null +++ b/slsReceiverSoftware/slsDetectorCalibration/moenchReadDataMT.C @@ -0,0 +1,52 @@ +#include +#include +#include "moenchReadData.C" + +typedef struct task_s{ + char *fformat; + char *tname; + char *tdir; + int runmin; + int runmax; + int treeIndex; +} Task; + +void *moenchMakeTreeTask(void *p){ + TThread::Lock(); + char fname[1000]; + Task *t = (Task *)p; + sprintf(fname,"%s%s_%i.root",t->tdir,t->tname,t->treeIndex); + TFile *f = new TFile(fname,"RECREATE"); + cout << "Call moenchReadData(" << t->fformat << "," << t->tname << "," << t->runmin<< "," << t->runmax <<")" << endl; + TThread::UnLock(); + moenchReadData(t->fformat,t->tname,t->runmin,t->runmax); + f->Close(); + return 0; +} + + +void moenchReadDataMT(char *fformat, char *tit, char *tdir, int runmin, int runoffset, int nThreads, int treeIndexStart=0){ + char threadName[1000]; + TThread *threads[nThreads]; + for(int i = 0; i < nThreads; i++){ + sprintf(threadName,"t%i",i); + Task *t = (Task *)malloc(sizeof(Task)); + t->fformat = fformat; + t->tname = tit; + t->tdir = tdir; + t->runmin = runmin + i*runoffset; + t->runmax = runmin + (i+1)*runoffset - 1; + t->treeIndex = treeIndexStart + i; + cout << "start thread " << i << " start: " << t->runmin << " end " << t->runmax << endl; + threads[i] = new TThread(threadName, moenchMakeTreeTask, t); + threads[i]->Run(); + } + + for(int i = 0; i < nThreads; i++){ + threads[i]->Join(); + } + +} + + + diff --git a/slsReceiverSoftware/slsDetectorCalibration/pedestalSubtraction.h b/slsReceiverSoftware/slsDetectorCalibration/pedestalSubtraction.h new file mode 100644 index 000000000..ee3aff8aa --- /dev/null +++ b/slsReceiverSoftware/slsDetectorCalibration/pedestalSubtraction.h @@ -0,0 +1,48 @@ +#ifndef PEDESTALSUBTRACTION_H +#define PEDESTALSUBTRACTION_H + +#include "MovingStat.h" + +class pedestalSubtraction { + /** @short class defining the pedestal subtraction based on an approximated moving average */ + public: + /** constructor + \param nn number of samples to calculate the moving average (defaults to 1000) + */ + pedestalSubtraction (int nn=1000) : stat(nn) {}; + + /** virtual destructorr + */ + virtual ~pedestalSubtraction() {}; + + /** clears the moving average */ + virtual void Clear() {stat.Clear();} + + /** adds the element to the moving average + \param val value to be added + */ + virtual void addToPedestal(double val){stat.Calc(val);}; + + /** returns the average value of the pedestal + \returns mean of the moving average + */ + virtual double getPedestal(){return stat.Mean();}; + + /** returns the standard deviation of the moving average + \returns standard deviation of the moving average + */ + virtual double getPedestalRMS(){return stat.StandardDeviation();}; + + /**sets/gets the number of samples for the moving average + \param i number of elements for the moving average. If -1 (default) or negative, gets. + \returns actual number of samples for the moving average + */ + virtual int SetNPedestals(int i=-1) {if (i>0) stat.SetN(i); return stat.GetN();}; + + + + private: + MovingStat stat; /**< approximated moving average struct */ + +}; +#endif diff --git a/slsReceiverSoftware/slsDetectorCalibration/raedNoiseData.C b/slsReceiverSoftware/slsDetectorCalibration/raedNoiseData.C new file mode 100644 index 000000000..b2021b29f --- /dev/null +++ b/slsReceiverSoftware/slsDetectorCalibration/raedNoiseData.C @@ -0,0 +1,136 @@ +#include "moenchReadData.C" + + + +void raedNoiseData(char *tit, int sign=1){ + + + + + + char fname[1000]; + char f[1000]; + TFile *fout; + THStack *hs2N; + + sprintf(fname,"/data/moench_xbox_20140113/MoTarget_45kV_0_8mA_120V_%s_0.root",tit); + fout=new TFile(fname,"RECREATE"); + + sprintf(fname,"/data/moench_xbox_20140113/MoTarget_45kV_0_8mA_120V_%s_f00000%%04d000_0.raw",tit); + + hs2N=moenchReadData(fname,0,3000,1500,-500,2500,1,0.,1,159,1,159, 0,1); + hs2N->SetName(tit); + hs2N->SetTitle(tit); + (TH2F*)(hs2N->GetHists()->At(0))->Write(); + + (TH2F*)(hs2N->GetHists()->At(1))->Write(); + (TH2F*)(hs2N->GetHists()->At(2))->Write(); + (TH2F*)(hs2N->GetHists()->At(3))->Write(); + (TH2F*)(hs2N->GetHists()->At(4))->Write(); + + + fout->Close(); + + + +} + + + +void raedNoiseDataN(char *tit, int sign=1){ + + + + char fname[1000]; + char f[1000]; + TFile *fout; + THStack *hs2N; + + sprintf(fname,"/data/moench_xbox_20140116/noise_%s.root",tit); + fout=new TFile(fname,"RECREATE"); + + sprintf(fname,"/data/moench_xbox_20140116/noise_%s_f00000%%04d000_0.raw",tit); + + hs2N=moenchReadData(fname,tit,0,3000,1500,-500,2500,sign,0.,1,159,1,159, 0,0); + hs2N->SetName(tit); + hs2N->SetTitle(tit); + (TH2F*)(hs2N->GetHists()->At(0))->Write(); + + // (TH2F*)(hs2N->GetHists()->At(1))->Write(); + // (TH2F*)(hs2N->GetHists()->At(2))->Write(); + // (TH2F*)(hs2N->GetHists()->At(3))->Write(); + // (TH2F*)(hs2N->GetHists()->At(4))->Write(); + + + fout->Close(); + + + +} + + + +void g4() { + + raedNoiseData("cds_g4_low_gain"); + raedNoiseData("cds_g4_sto1_only"); + raedNoiseData("cds_g4_no sto"); + + + +} + +void no_cds() { + + raedNoiseData("cds_disable_low_gain",-1); + raedNoiseData("cds_disable_sto1_only",-1); + raedNoiseData("cds_disable_no sto",-1); + + + +} + +void all_gains() { + + raedNoiseData("cds_g2"); + raedNoiseData("cds_g2HC"); + raedNoiseData("cds_g1_2"); + raedNoiseData("cds_g2_3"); + + + +} + +void all_low_gains() { + + raedNoiseData("cds_g2_low_gain"); + raedNoiseData("cds_g2HC_low_gain"); + raedNoiseData("cds_g1_2_low_gain"); + raedNoiseData("cds_g2_3_low_gain"); +} + +/* +clkdivider data +/data/moench_xbox_20140114/MoTarget_45kV_0_8mA_12us_120V_cds_g1_clkdiv17_f000000010000_0.raw +-rw-rw-r-- 1 l_msdetect l_msdetect 51440000 Jan 14 12:40 /data/moench_xbox_20140114/MoTarget_45kV_0_8mA_12us_120V_cds_g1_clkdiv25_f000000010000_0.raw +-rw-rw-r-- 1 l_msdetect l_msdetect 51440000 Jan 14 13:26 /data/moench_xbox_20140114/MoTarget_45kV_0_8mA_12us_120V_cds_g1_clkdiv35_f000000010000_0.raw +-rw-rw-r-- 1 l_msdetect l_msdetect 51440000 Jan 14 14:09 /data/moench_xbox_20140114/MoTarget_45kV_0_8mA_12us_120V_cds_g1_clkdiv50_f000000010000_0.raw +-rw-rw-r-- 1 l_msdetect l_msdetect 51440000 Jan 14 14:54 /data/moench_xbox_20140114/MoTarget_45kV_0_8mA_12us_120V_cds_g1_clkdiv70_f000000010000_0.raw +-rw-rw-r-- 1 l_msdetect l_msdetect 51440000 Jan 14 16:42 /data/moench_xbox_20140114/MoTarget_45kV_0_8mA_12us_120V_cds_g1_clkdiv110_f000000010000_0.raw +-rw-rw-r-- 1 l_msdetect l_msdetect 51440000 Jan 14 17:27 /data/moench_xbox_20140114/MoTarget_45kV_0_8mA_12us_120V_cds_g1_clkdiv170_f000000010000_0.raw +*/ + + +/* oversampled data +-rw-rw-r-- 1 l_msdetect l_msdetect 51440000 Jan 14 18:12 /data/moench_xbox_20140114/MoTarget_45kV_0_8mA_12us_120V_os10_16rows_f000000010000_0.raw +-rw-rw-r-- 1 l_msdetect l_msdetect 51440000 Jan 14 18:47 /data/moench_xbox_20140114/MoTarget_45kV_0_8mA_12us_120V_os10_16rows_f000000010000_1.raw +-rw-rw-r-- 1 l_msdetect l_msdetect 51440000 Jan 14 19:22 /data/moench_xbox_20140114/MoTarget_45kV_0_8mA_12us_120V_os10_16rows_f000000010000_2.raw +-rw-rw-r-- 1 l_msdetect l_msdetect 51440000 Jan 14 20:02 /data/moench_xbox_20140114/MoTarget_45kV_0_8mA_12us_120V_os10_16rows_f000000010000_3.raw +-rw-rw-r-- 1 l_msdetect l_msdetect 51440000 Jan 14 20:41 /data/moench_xbox_20140114/MoTarget_45kV_0_8mA_12us_120V_os10_16rows_f000000010000_4.raw +-rw-rw-r-- 1 l_msdetect l_msdetect 51440000 Jan 14 21:16 /data/moench_xbox_20140114/MoTarget_45kV_0_8mA_12us_120V_os10_16rows_f000000010000_5.raw +-rw-rw-r-- 1 l_msdetect l_msdetect 51440000 Jan 14 21:56 /data/moench_xbox_20140114/MoTarget_45kV_0_8mA_12us_120V_os10_16rows_f000000010000_6.raw +-rw-rw-r-- 1 l_msdetect l_msdetect 51440000 Jan 14 22:35 /data/moench_xbox_20140114/MoTarget_45kV_0_8mA_12us_120V_os10_16rows_f000000010000_7.raw +-rw-rw-r-- 1 l_msdetect l_msdetect 51440000 Jan 14 23:11 /data/moench_xbox_20140114/MoTarget_45kV_0_8mA_12us_120V_os10_16rows_f000000010000_8.raw +-rw-rw-r-- 1 l_msdetect l_msdetect 51440000 Jan 14 23:50 /data/moench_xbox_20140114/MoTarget_45kV_0_8mA_12us_120V_os10_16rows_f000000010000_9.raw +*/ + diff --git a/slsReceiverSoftware/slsDetectorCalibration/readJungfrauData.C b/slsReceiverSoftware/slsDetectorCalibration/readJungfrauData.C new file mode 100644 index 000000000..504a15258 --- /dev/null +++ b/slsReceiverSoftware/slsDetectorCalibration/readJungfrauData.C @@ -0,0 +1,31 @@ +{ // script to run Jungfrau data analysis + + gROOT->ProcessLine(".L jungfrauReadData.C++");//"); + + TFile *fout; // output file + THStack *hs2N; // collection of objects + + //fout=new TFile("/mnt/slitnas/datadir_jungfrau02/analysis_tests/tests_random.root","RECREATE"); // + fout=new TFile("/mnt/slitnas/datadir_jungfrau02/20140404_lowEXrays/test.root","RECREATE"); + + hs2N=jungfrauReadData("/mnt/slitnas/datadir_jungfrau02/20140404_lowEXrays/Ti_1000clk_13kV40mA_%d.bin","tit",0,86,3000,-499.5,2500.5,1,0,1,47,1,47,1,1); //1,1); + + //hs2N=jungfrauReadData("/mnt/slitnas/datadir_jungfrau02/20140228_GainBits/GSdata_laser_%d.bin","tit",0,5,1500,-500,2500,1,0.,1,47,1,47,0,1);//,"/mnt/slitnas/datadir_jungfrau02/analysis_tests/CalibrationParametersTest_fake.txt"); //1,1); // data set test GB -> set (3,0,0) in junfrauReadData.C + + //hs2N=jungfrauReadData("/mnt/slitnas/datadir_jungfrau02/digital_bit_adc_test/vb_1825_%d.bin","tit",0,7,1500,-500,2500,1,0.,1,47,1,47,0,1);//,"/mnt/slitnas/datadir_jungfrau02/analysis_tests/CalibrationParametersTest_fake.txt"); //1,1); // data set test GB -> set (3,0,0) in junfrauReadData.C + + //hs2N->SetName("cds_g4"); + //hs2N->SetTitle("cds_g4"); + + (TH2F*)(hs2N->GetHists()->At(0))->Write(); // write hists + (TH2F*)(hs2N->GetHists()->At(1))->Write(); + (TH2F*)(hs2N->GetHists()->At(2))->Write(); + (TH2F*)(hs2N->GetHists()->At(3))->Write(); + (TH2F*)(hs2N->GetHists()->At(4))->Write(); + //(TH2F*)(hs2N->GetHists()->At(5))->Write(); + //(TH2F*)(hs2N->GetHists()->At(6))->Write(); + + fout->Close(); // uncomment + +} + diff --git a/slsReceiverSoftware/slsDetectorCalibration/singlePhotonDetector.h b/slsReceiverSoftware/slsDetectorCalibration/singlePhotonDetector.h new file mode 100644 index 000000000..f090730a1 --- /dev/null +++ b/slsReceiverSoftware/slsDetectorCalibration/singlePhotonDetector.h @@ -0,0 +1,387 @@ +#ifndef SINGLEPHOTONDETECTOR_H +#define SINGLEPHOTONDETECTOR_H + + +#include "slsDetectorData.h" + +#include "single_photon_hit.h" +#include "pedestalSubtraction.h" +#include "commonModeSubtraction.h" + + +//#define MYROOT1 + +#ifdef MYROOT1 +#include + +#endif + + +#include + +using namespace std; + + + enum eventType { + PEDESTAL=0, + NEIGHBOUR=1, + PHOTON=2, + PHOTON_MAX=3, + NEGATIVE_PEDESTAL=4, + UNDEFINED_EVENT=-1 + }; + + enum quadrant { + TOP_LEFT=0, + TOP_RIGHT=1, + BOTTOM_LEFT=2, + BOTTOM_RIGHT=3, + UNDEFINED_QUADRANT=-1 + }; + + + +template +class singlePhotonDetector { + + /** @short class to perform pedestal subtraction etc. and find single photon clusters for an analog detector */ + + public: + + + /** + + Constructor (no error checking if datasize and offsets are compatible!) + \param d detector data structure to be used + \param csize cluster size (should be an odd number). Defaults to 3 + \param nsigma number of rms to discriminate from the noise. Defaults to 5 + \param sign 1 if photons are positive, -1 if negative + \param cm common mode subtraction algorithm, if any. Defaults to NULL i.e. none + \param nped number of samples for pedestal averaging + \param nd number of dark frames to average as pedestals without photon discrimination at the beginning of the measurement + + + */ + + + singlePhotonDetector(slsDetectorData *d, + int csize=3, + double nsigma=5, + int sign=1, + commonModeSubtraction *cm=NULL, + int nped=1000, + int nd=100) : det(d), nx(0), ny(0), stat(NULL), cmSub(cm), nDark(nd), eventMask(NULL),nSigma (nsigma), clusterSize(csize), clusterSizeY(csize), cluster(NULL), iframe(-1), dataSign(sign), quad(UNDEFINED_QUADRANT), tot(0), quadTot(0) { + + + det->getDetectorSize(nx,ny); + + + + stat=new pedestalSubtraction*[ny]; + eventMask=new eventType*[ny]; + for (int i=0; iSetNPedestals(nped); + eventMask[i]=new eventType[nx]; + } + + if (ny==1) + clusterSizeY=1; + + cluster=new single_photon_hit(clusterSize,clusterSizeY); + setClusterSize(csize); + + }; + /** + destructor. Deletes the cluster structure and the pdestalSubtraction array + */ + virtual ~singlePhotonDetector() {delete cluster; for (int i=0; iClear(); }; + + /** resets the eventMask to undefined and the commonModeSubtraction */ + void newFrame(){iframe++; for (int iy=0; iynewFrame();}; + + + /** sets the commonModeSubtraction algorithm to be used + \param cm commonModeSubtraction algorithm to be used (NULL unsets) + \returns pointer to the actual common mode subtraction algorithm + */ + commonModeSubtraction setCommonModeSubtraction(commonModeSubtraction *cm) {cmSub=cm; return cmSub;}; + + + /** + sets the sign of the data + \param sign 1 means positive values for photons, -1 negative, 0 gets + \returns current sign for the data + */ + int setDataSign(int sign=0) {if (sign==1 || sign==-1) dataSign=sign; return dataSign;}; + + + /** + adds value to pedestal (and common mode) for the given pixel + \param val value to be added + \param ix pixel x coordinate + \param iy pixel y coordinate + */ + virtual void addToPedestal(double val, int ix, int iy){ + // cout << "*"<< ix << " " << iy << " " << val << endl; + if (ix>=0 && ix=0 && iyisGood(ix, iy) ) + cmSub->addToCommonMode(val, ix, iy); + }; + }; + + /** + gets pedestal (and common mode) + \param ix pixel x coordinate + \param iy pixel y coordinate + \param cm 0 (default) without common mode subtraction, 1 with common mode subtraction (if defined) + */ + virtual double getPedestal(int ix, int iy, int cm=0){if (ix>=0 && ix=0 && iy0) return stat[iy][ix].getPedestal()-cmSub->getCommonMode(); else return stat[iy][ix].getPedestal(); else return -1;}; + + /** + gets pedestal rms (i.e. noise) + \param ix pixel x coordinate + \param iy pixel y coordinate + */ + double getPedestalRMS(int ix, int iy){if (ix>=0 && ix=0 && iy0) nSigma=n; return nSigma;} + + /** sets/gets cluster size + \param n cluster size to be set, (0 or negative gets). If even is incremented by 1. + \returns actual cluster size + */ + int setClusterSize(int n=-1){ + if (n>0 && n!=clusterSize) { + if (n%2==0) + n+=1; + clusterSize=n; + if (cluster) + delete cluster; + if (ny>1) + clusterSizeY=clusterSize; + cluster=new single_photon_hit(clusterSize,clusterSizeY); + } + return clusterSize; + } + + + + + /** finds event type for pixel and fills cluster structure. The algorithm loops only if the evenMask for this pixel is still undefined. + if pixel or cluster around it are above threshold (nsigma*pedestalRMS) cluster is filled and pixel mask is PHOTON_MAX (if maximum in cluster) or NEIGHBOUR; If PHOTON_MAX, the elements of the cluster are also set as NEIGHBOURs in order to speed up the looping + if below threshold the pixel is either marked as PEDESTAL (and added to the pedestal calculator) or NEGATIVE_PEDESTAL is case it's lower than -threshold, otherwise the pedestal average would drift to negative values while it should be 0. + + /param data pointer to the data + /param ix pixel x coordinate + /param iy pixel y coordinate + /param cm enable(1)/disable(0) common mode subtraction (if defined). + /returns event type for the given pixel + */ + eventType getEventType(char *data, int ix, int iy, int cm=0) { + + // eventType ret=PEDESTAL; + double max=0, tl=0, tr=0, bl=0,br=0, v; + // cout << iframe << endl; + + tot=0; + quadTot=0; + quad=UNDEFINED_QUADRANT; + + + if (iframex=ix; + cluster->y=iy; + cluster->rms=getPedestalRMS(ix,iy); + cluster->ped=getPedestal(ix,iy, cm); + + + for (int ir=-(clusterSizeY/2); ir<(clusterSizeY/2)+1; ir++) { + for (int ic=-(clusterSize/2); ic<(clusterSize/2)+1; ic++) { + if ((iy+ir)>=0 && (iy+ir)=0 && (ix+ic)set_data(dataSign*(det->getValue(data, ix+ic, iy+ir)-getPedestal(ix+ic,iy+ir,cm)), ic, ir ); + v=cluster->get_data(ic,ir); + tot+=v; + if (ir<=0 && ic<=0) + bl+=v; + if (ir<=0 && ic>=0) + br+=v; + if (ir>=0 && ic<=0) + tl+=v; + if (ir>=0 && ic>=0) + tr+=v; + + if (cluster->get_data(ic,ir)>max) { + max=v; + } + if (ir==0 && ic==0) { + if (v>nSigma*cluster->rms) { + eventMask[iy][ix]=PHOTON; + } else if (cluster->get_data(ic,ir)<-nSigma*cluster->rms) + eventMask[iy][ix]=NEGATIVE_PEDESTAL; + } + } + } + } + + if (eventMask[iy][ix]!=PHOTON && tot>sqrt(clusterSizeY*clusterSize)*nSigma*cluster->rms) { + eventMask[iy][ix]=NEIGHBOUR; + } else if (eventMask[iy][ix]==PHOTON) { + if (cluster->get_data(0,0)>=max) { + eventMask[iy][ix]=PHOTON_MAX; + } + } else if (eventMask[iy][ix]==PEDESTAL) { + if (cm==0) + addToPedestal(det->getValue(data, ix, iy),ix,iy); + } + + + if (bl>=br && bl>=tl && bl>=tr) { + quad=BOTTOM_LEFT; + quadTot=bl; + } else if (br>=bl && br>=tl && br>=tr) { + quad=BOTTOM_RIGHT; + quadTot=br; + } else if (tl>=br && tl>=bl && tl>=tr) { + quad=TOP_LEFT; + quadTot=tl; + } else if (tr>=bl && tr>=tl && tr>=br) { + quad=TOP_RIGHT; + quadTot=tr; + } + + + return eventMask[iy][ix]; + + }; + + /**< + retrurns the total signal in a cluster + \param size cluser size should be 1,2 or 3 + \returns cluster center if size=1, sum of the maximum quadrant if size=2, total of the cluster if size=3 or anything else + */ + + double getClusterTotal(int size) { + switch (size) { + case 1: + return getClusterElement(0,0); + case 2: + return quadTot; + default: + return tot; + }; + }; + + /**< + retrurns the quadrant with maximum signal + \returns quadrant where the cluster is located */ + + quadrant getQuadrant() {return quad;}; + + /** sets/gets number of samples for moving average pedestal calculation + \param i number of samples to be set (0 or negative gets) + \returns actual number of samples + */ + int SetNPedestals(int i=-1) {int ix=0, iy=0; if (i>0) for (ix=0; ixget_data(ic,ir);}; + + /** returns event mask for the given pixel + \param ic x coordinate (center is (0,0)) + \param ir y coordinate (center is (0,0)) + \returns event mask enum for the given pixel + */ + eventType getEventMask(int ic, int ir=0){return eventMask[ir][ic];}; + + +#ifdef MYROOT1 + /** generates a tree and maps the branches + \param tname name for the tree + \param iFrame pointer to the frame number + \returns returns pointer to the TTree + */ + TTree *initEventTree(char *tname, int *iFrame=NULL) { + TTree* tall=new TTree(tname,tname); + + if (iFrame) + tall->Branch("iFrame",iFrame,"iframe/I"); + else + tall->Branch("iFrame",&(cluster->iframe),"iframe/I"); + + tall->Branch("x",&(cluster->x),"x/I"); + tall->Branch("y",&(cluster->y),"y/I"); + char tit[100]; + sprintf(tit,"data[%d]/D",clusterSize*clusterSizeY); + tall->Branch("data",cluster->data,tit); + tall->Branch("pedestal",&(cluster->ped),"pedestal/D"); + tall->Branch("rms",&(cluster->rms),"rms/D"); + return tall; + }; +#else + /** write cluster to filer*/ + void writeCluster(FILE* myFile){cluster->write(myFile);}; + +#endif + + + private: + + slsDetectorData *det; /**< slsDetectorData to be used */ + int nx; /**< Size of the detector in x direction */ + int ny; /**< Size of the detector in y direction */ + + + pedestalSubtraction **stat; /**< pedestalSubtraction class */ + commonModeSubtraction *cmSub;/**< commonModeSubtraction class */ + int nDark; /**< number of frames to be used at the beginning of the dataset to calculate pedestal without applying photon discrimination */ + eventType **eventMask; /**< matrix of event type or each pixel */ + double nSigma; /**< number of sigma parameter for photon discrimination */ + int clusterSize; /**< cluster size in the x direction */ + int clusterSizeY; /**< cluster size in the y direction i.e. 1 for strips, clusterSize for pixels */ + single_photon_hit *cluster; /**< single photon hit data structure */ + int iframe; /**< frame number (not from file but incremented within the dataset every time newFrame is called */ + int dataSign; /**< sign of the data i.e. 1 if photon is positive, -1 if negative */ + quadrant quad; /**< quadrant where the photon is located */ + double tot; /**< sum of the 3x3 cluster */ + double quadTot; /**< sum of the maximum 2x2cluster */ + + +}; + + + + + +#endif diff --git a/slsReceiverSoftware/slsDetectorCalibration/single_photon_hit.h b/slsReceiverSoftware/slsDetectorCalibration/single_photon_hit.h new file mode 100644 index 000000000..dda4d7571 --- /dev/null +++ b/slsReceiverSoftware/slsDetectorCalibration/single_photon_hit.h @@ -0,0 +1,62 @@ +#ifndef SINGLE_PHOTON_HIT_H +#define SINGLE_PHOTON_HIT_h + +typedef double double32_t; +typedef float float32_t; +typedef int int32_t; + + +class single_photon_hit { + + /** @short Structure for a single photon hit */ + + public: + /** constructor, instantiates the data array -- all class elements are public! + \param nx cluster size in x direction + \param ny cluster size in y direction (defaults to 1 for 1D detectors) + */ + single_photon_hit(int nx, int ny=1): dx(nx), dy(ny) {data=new double[dx*dy];}; + + ~single_photon_hit(){delete [] data;}; /**< destructor, deletes the data array */ + + /** binary write to file of all elements of the structure, except size of the cluster + \param myFile file descriptor + */ + void write(FILE *myFile) {fwrite((void*)this, 1, 3*sizeof(int)+2*sizeof(double), myFile); fwrite((void*)data, 1, dx*dy*sizeof(double), myFile);}; + + /** + binary read from file of all elements of the structure, except size of the cluster. The structure is then filled with those args + \param myFile file descriptor + */ + void read(FILE *myFile) {fread((void*)this, 1, 3*sizeof(int)+2*sizeof(double), myFile); fread((void*)data, 1, dx*dy*sizeof(double), myFile);}; + + /** + assign the value to the element of the cluster matrix, with relative coordinates where the center of the cluster is (0,0) + \param v value to be set + \param ix coordinate x within the cluster (center is (0,0)) + \param iy coordinate y within the cluster (center is (0,0)) + */ + void set_data(double v, int ix, int iy=0){data[(iy+dy/2)*dx+ix+dx/2]=v;}; + + + /** + gets the value to the element of the cluster matrix, with relative coordinates where the center of the cluster is (0,0) + \param ix coordinate x within the cluster (center is (0,0)) + \param iy coordinate y within the cluster (center is (0,0)) + \returns value of the cluster element + */ + double get_data(int ix, int iy=0){return data[(iy+dy/2)*dx+ix+dx/2];}; + + int x; /**< x-coordinate of the center of hit */ + int y; /**< x-coordinate of the center of hit */ + double rms; /**< noise of central pixel l -- at some point it can be removed*/ + double ped; /**< pedestal of the central pixel -- at some point it can be removed*/ + int iframe; /**< frame number */ + double *data; /**< pointer to data */ + const int dx; /**< size of data cluster in x */ + const int dy; /**< size of data cluster in y */ +}; + + + +#endif diff --git a/slsReceiverSoftware/slsDetectorCalibration/slsDetectorData.h b/slsReceiverSoftware/slsDetectorCalibration/slsDetectorData.h new file mode 100644 index 000000000..294f7c871 --- /dev/null +++ b/slsReceiverSoftware/slsDetectorCalibration/slsDetectorData.h @@ -0,0 +1,251 @@ +#ifndef SLSDETECTORDATA_H +#define SLSDETECTORDATA_H + +#include +#include +#include + +using namespace std; + + +template +class slsDetectorData { + + + public: + + /** + + + General slsDetectors data structure. Works for data acquired using the slsDetectorReceiver. Can be generalized to other detectors (many virtual funcs). + + Constructor (no error checking if datasize and offsets are compatible!) + \param npx number of pixels in the x direction + \param npy number of pixels in the y direction (1 for strips) + \param dsize size of the data + \param dMap array of size nx*ny storing the pointers to the data in the dataset (as offset) + \param dMask Array of size nx*ny storing the polarity of the data in the dataset (should be 0 if no inversion is required, 0xffffffff is inversion is required) + \param dROI Array of size nx*ny. The elements are 1s if the channel is good or in the ROI, 0 is bad or out of the ROI. NULL (default) means all 1s. + + */ + slsDetectorData(int npx, int npy, int dsize, int **dMap=NULL, dataType **dMask=NULL, int **dROI=NULL): nx(npx), ny(npy), dataSize(dsize) { + + + + dataMask=new dataType*[ny]; + for(int i = 0; i < ny; i++) { + dataMask[i] = new dataType[nx]; + } + dataMap=new int*[ny]; + for(int i = 0; i < ny; i++) { + dataMap[i] = new int[nx]; + } + + dataROIMask=new int*[ny]; + for(int i = 0; i < ny; i++) { + dataROIMask[i] = new int[nx]; + for (int j=0; j=0 && ix=0 && iy=0 && ix=0 && iy=0 && ix=0 && iy=0 && dataMap[iy][ix] +class slsReceiverData : public slsDetectorData { + + +public: + + /** + slsReceiver data structure. Works for data acquired using the slsDetectorReceiver subdivided in different packets with headers and footers. + Inherits and implements slsDetectorData. + + Constructor (no error checking if datasize and offsets are compatible!) + \param npx number of pixels in the x direction + \param npy number of pixels in the y direction (1 for strips) + \param np number of packets + \param psize packets size + \param dMap array of size nx*ny storing the pointers to the data in the dataset (as offset) + \param dMask Array of size nx*ny storing the polarity of the data in the dataset (should be 0 if no inversion is required, 0xffffffff is inversion is required) + \param dROI Array of size nx*ny. The elements are 1s if the channel is good or in the ROI, 0 is bad or out of the ROI. NULL (default) means all 1s. + + */ + slsReceiverData(int npx, int npy, int np, int psize, int **dMap=NULL, dataType **dMask=NULL, int **dROI=NULL): slsDetectorData(npx, npy, np*psize, dMap, dMask, dROI), nPackets(np), packetSize(psize) {}; + + + /** + + Returns the frame number for the given dataset. Virtual func: works for slsDetectorReceiver data (also for each packet), but can be overloaded. + \param buff pointer to the dataset + \returns frame number + + */ + + virtual int getFrameNumber(char *buff){return ((*(int*)buff)&(0xffffff00))>>8;}; + + /** + + Returns the packet number for the given dataset. Virtual func: works for slsDetectorReceiver packets, but can be overloaded. + \param buff pointer to the dataset + \returns packet number number + + */ + + virtual int getPacketNumber(char *buff){return (*(int*)buff)&0xff;}; + + + + + /** + + Loops over a memory slot until a complete frame is found (i.e. all packets 0 to nPackets, same frame number). Can be overloaded for different kind of detectors! + \param data pointer to the memory to be analyzed + \param ndata size of frame returned + \param dsize size of the memory slot to be analyzed + \returns pointer to the first packet of the last good frame (might be incomplete if npackets lower than the number of packets), or NULL if no frame is found + + */ + + virtual char *findNextFrame(char *data, int &ndata, int dsize) { + char *retval=NULL, *p=data; + int dd=0; + int fn, fnum=-1, np=0, pnum=-1; + while (dd<=(dsize-packetSize)) { + pnum=getPacketNumber(p); + fn=getFrameNumber(p); + + + if (pnum<1 || pnum>nPackets) { + cout << "Bad packet number " << pnum << " frame "<< fn << endl; + retval=NULL; + np=0; + } else if (pnum==1) { + retval=p; + if (np>0) + /*cout << "*Incomplete frame number " << fnum << endl;*/ + np=0; + fnum=fn; + } else if (fn!=fnum) { + if (fnum!=-1) { + /* cout << " **Incomplete frame number " << fnum << " pnum " << pnum << " " << getFrameNumber(p) << endl;*/ + retval=NULL; + } + np=0; + } + p+=packetSize; + dd+=packetSize; + np++; + // cout << pnum << " " << fn << " " << np << " " << dd << " " << dsize << endl; + if (np==nPackets) + if (pnum==nPackets) { + // cout << "Frame found!" << endl; + break; + } else { + cout << "Too many packets for this frame! "<< fnum << " " << pnum << endl; + retval=NULL; + } + } + if (np0) + cout << "Too few packets for this frame! "<< fnum << " " << pnum << endl; + } + + ndata=np*packetSize; + // cout << "return " << ndata << endl; + return retval; + }; + + /** + + Loops over a file stream until a complete frame is found (i.e. all packets 0 to nPackets, same frame number). Can be overloaded for different kind of detectors! + \param filebin input file stream (binary) + \returns pointer to the first packet of the last good frame, NULL if no frame is found or last frame is incomplete + + */ + + virtual char *readNextFrame(ifstream &filebin) { + char *data=new char[packetSize*nPackets]; + char *retval=0; + int np=0, nd; + + if (filebin.is_open()) { + while (filebin.read(data+np*packetSize,packetSize)) { + + if (np==(nPackets-1)) { + + retval=findNextFrame(data,nd,packetSize*nPackets); + np=nd/packetSize; + // cout << np << endl; + + + if (retval==data && np==nPackets) { + // cout << "-" << endl; + return data; + + } else if (np>nPackets) { + cout << "too many packets!!!!!!!!!!" << endl; + delete [] data; + return NULL; + } else if (retval!=NULL) { + // cout << "+" << endl;; + for (int ip=0; ipnPackets) { + cout << "*******too many packets!!!!!!!!!!" << endl; + delete [] data; + return NULL; + } else { + // cout << "." << endl;; + np++; + } + } + } + delete [] data; + return NULL; + }; + + + +private: + const int nPackets; /** + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/slsReceiverSoftware/slsReceiver/.project b/slsReceiverSoftware/slsReceiver/.project new file mode 100644 index 000000000..3c7b96561 --- /dev/null +++ b/slsReceiverSoftware/slsReceiver/.project @@ -0,0 +1,28 @@ + + + Receiver + + + newMythenSoftware + + + + org.eclipse.cdt.managedbuilder.core.genmakebuilder + clean,full,incremental, + + + + + org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder + full,incremental, + + + + + + org.eclipse.cdt.core.cnature + org.eclipse.cdt.core.ccnature + org.eclipse.cdt.managedbuilder.core.managedBuildNature + org.eclipse.cdt.managedbuilder.core.ScannerConfigNature + + diff --git a/slsReceiverSoftware/slsReceiver/Makefile b/slsReceiverSoftware/slsReceiver/Makefile new file mode 100644 index 000000000..0fd416ca0 --- /dev/null +++ b/slsReceiverSoftware/slsReceiver/Makefile @@ -0,0 +1,68 @@ +include ../../Makefile.include + +DESTDIR ?= ../../bin +LIBDIR ?= $(DESTDIR) +PROGS = $(DESTDIR)/slsReceiver + + +CFLAGS += -DSLS_RECEIVER_UDP_FUNCTIONS -O3 +CPPFLAGS = ${CFLAGS} # for MAC + + +LDFLAGRXR ?= -L$(LIBDIR) -lSlsReceiver -L/usr/lib64/ -lpthread +LDFLAGRXR += -lm -lstdc++ + + +INCLUDES ?= -I ../MySocketTCP -I ../slsDetectorCalibration -I ../includes -I eigerReceiver -I . +SRC_CLNT = slsReceiver.cpp + + +INSTMODE = 0777 +OBJS = $(SRC_CLNT:.cpp=.o) + + +.PHONY: all receiver clean static_receiver boot eigerReceiver lib + +all: receiver + +receiver: $(DESTDIR)/slsReceiver + +static_receiver: $(DESTDIR)/sslsReceiver + +boot: $(OBJS) + +$(DESTDIR)/sslsReceiver: lib + echo $(OBJS) + echo $(LDFLAGRXR) + echo $(LIBS) + mkdir -p $(DESTDIR) + $(CXX) -static -o $@ $(SRC_CLNT) $(FLAGS) $(INCLUDES) $(CLAGS) $(LIBS) $(LDFLAGRXR) + + +$(DESTDIR)/slsReceiver: eigerReceiver lib + $(CXX) -o $@ $(SRC_CLNT) $(FLAGS) $(INCLUDES) $(CLAGS) $(LIBS) $(LDFLAGRXR) -fPIC +#$(EIGERFLAGS) + + +ifeq ($(EIGERSLS), yes) +eigerReceiver: + $(CXX) $(FLAGS) $(CFLAGS) -fPIC -c -o eigerReceiverTest.o eigerReceiver/eigerReceiverTest.cpp $(EIGERFLAGS) + $(CXX) $(FLAGS) $(CFLAGS) -fPIC -c -o eigerReceiver.o eigerReceiver/eigerReceiver.cpp $(EIGERFLAGS) + $(CXX) eigerReceiverTest.o eigerReceiver.o -o eigerReceiver/eigerReceiverTest $(EIGERFLAGS) +else ifeq ($(ROOTSLS), yes) +eigerReceiver: eigerReceiver/eigerReceiverDummy.cpp + echo "Compiling with root" + $(CXX) $(FLAGS) $(CFLAGS) -fPIC -c -o eigerReceiver.o eigerReceiver/eeigerReceiverDummy.cpp $(ROOTFLAGS) +else +eigerReceiver: eigerReceiver/eigerReceiverDummy.cpp + $(CXX) $(FLAGS) $(CFLAGS) $(INCLUDES) -fPIC -c -o eigerReceiver.o eigerReceiver/eigerReceiverDummy.cpp +endif + +lib: + cd ../ && $(MAKE) DESTDIR=../bin LIBDIR=../bin + +clean: + rm -rf $(PROGS) *.o eigerReceiverTest $(DESTDIR)/libSlsReceiver.a $(DESTDIR)/libSlsReceiver.so core + + + diff --git a/slsReceiverSoftware/slsReceiver/eigerReceiver/RestHelper.h b/slsReceiverSoftware/slsReceiver/eigerReceiver/RestHelper.h new file mode 100644 index 000000000..6f423f5e1 --- /dev/null +++ b/slsReceiverSoftware/slsReceiver/eigerReceiver/RestHelper.h @@ -0,0 +1,195 @@ +/** + * @file RestHelper.h + * @author Leonardo Sala + * @date Tue Mar 25 09:28:19 2014 + * + * @brief + * + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "JsonBox/Value.h" + +#include +#include +#include + +/// HTTP timeout in seconds, default is 8 +#define HTTP_TIMEOUT 10 +/// Number of connection tries +#define N_CONNECTION_TRIES 3 + +using namespace Poco::Net; +using namespace Poco; +using namespace std; + +class RestHelper { + public: + + ~RestHelper(){}; + + void init(string hostname, int port){ + /** Initialize the RestHelper. Hostname and port parameters are not supposed to change. + * + * + * @param hostname FQDN of the host to connect to , e.g. www.iamfake.org, or sodoi.org + * @param port + * + * @return + */ + + full_hostname = "http://"+hostname; + session = new HTTPClientSession(hostname,port ); + session->setKeepAliveTimeout( Timespan( HTTP_TIMEOUT,0) ); + }; + + + int get_json(string request, string* answer){ + /** Retrieves a reply from the RESTful webservice. + * + * + * @param request Request without the hostname, e.g. if the full request would have been http://fake.org/fakemethod, request=fakemethod + * @param answer + * + * @return 0 if successful, -1 if failure happens. + */ + URI * uri = new URI(full_hostname+"/"+request); + string path(uri->getPathAndQuery()); + if (path.empty()) path = "/"; + + // send request + HTTPRequest req(HTTPRequest::HTTP_GET, path, HTTPMessage::HTTP_1_1); + req.setContentType("application/json\r\n"); + int code = send_request(session, req, answer); + delete uri; + return code; + }; + + + int get_json(string request, JsonBox::Value* json_value){ + /** + * + * + * @param request + * @param json_value + * + * @return + */ + URI *uri = new URI(full_hostname+"/"+request); + string path(uri->getPathAndQuery()); + if (path.empty()) path = "/"; + // send request + HTTPRequest req(HTTPRequest::HTTP_GET, path, HTTPMessage::HTTP_1_1); + req.setContentType("application/json\r\n"); + string answer; + int code = send_request(session, req, &answer); + json_value->loadFromString(answer); + delete uri; + return code; + }; + + + int post_json(string request, string *answer, string request_body=""){ + /** + * + * + * @param request + * @param answer + * @param request_body Eventual arguments to the URL, e.g. action=login&name=mammamia + * + * @return + */ + //from: http://stackoverflow.com/questions/1499086/poco-c-net-ssl-how-to-post-https-request + URI *uri = new URI(full_hostname+"/"+request); + string path(uri->getPathAndQuery()); + if (path.empty()) path = "/"; + HTTPRequest req(HTTPRequest::HTTP_POST, path, HTTPMessage::HTTP_1_1 ); + req.setContentType("application/json\r\n"); + req.setContentLength( request.length() ); + int code = send_request(session, req, answer, request_body); + delete uri; + return code; + } + + + int post_json(string request, JsonBox::Value* json_value, string request_body=""){ + /** + * + * + * @param request + * @param json_value + * @param request_body Eventual arguments to the URL, e.g. action=login&name=mammamia + * + * @return + */ + + URI *uri = new URI(full_hostname+"/"+request); + string path(uri->getPathAndQuery()); + if (path.empty()) path = "/"; + HTTPRequest req(HTTPRequest::HTTP_POST, path, HTTPMessage::HTTP_1_1 ); + req.setContentType("application/json\r\n"); + req.setContentLength( request.length() ); + string answer; + int code = send_request(session, req, &answer, request_body); + json_value->loadFromString(answer); + delete uri; + return code; + } + + + private: + //URI * uri; + HTTPClientSession *session; + string full_hostname; + + int send_request(HTTPClientSession *session, HTTPRequest &req, string *answer, string request_body=""){ + /** + * + * + * @param session + * @param req + * @param answer + * @param request_body + * + * @return + */ + + int n=0; + int code = -1; + while(nsendRequest( (req) ); + else + session->sendRequest( (req) ) << request_body; + + HTTPResponse res; + istream &is = session->receiveResponse(res); + StreamCopier::copyToString(is, *answer); + code = res.getStatus(); + if (code != 200){ + cout << "HTTP ERROR " << res.getStatus() << ": " << res.getReason() << endl; + code = -1; + } + return code; + } + catch (exception& e){ + cout << "Exception connecting to "<< full_hostname << ": "<< e.what() << ", sleeping " << HTTP_TIMEOUT << " seconds\n"; + sleep(HTTP_TIMEOUT); + } + n+=1; + } + + return code; + } + +}; diff --git a/slsReceiverSoftware/slsReceiver/eigerReceiver/eigerReceiver.cpp b/slsReceiverSoftware/slsReceiver/eigerReceiver/eigerReceiver.cpp new file mode 100644 index 000000000..fa19895be --- /dev/null +++ b/slsReceiverSoftware/slsReceiver/eigerReceiver/eigerReceiver.cpp @@ -0,0 +1,254 @@ +/* + * eigerReceiver.cpp + * + * Created on: Mar 11, 2014 + * Author: billich + */ + +#include +#include +#include "eigerReceiver.h" + + +/* uncomment next line to enable debug output */ +#define EIGER_DEBUG + +/* macro for debug output http://stackoverflow.com/a/14256296 */ +#ifdef EIGER_DEBUG +#define DEBUG(x) do { std::cerr << x << std::endl; } while (0) +#else +#define DEBUG(x) +#endif + + +using namespace std; + +struct EigerReceiverInitializationConfiguration { + + string detectorHostname; +}; + +struct EigerReceiverScanConfiguration { + + string fileName; + string filePath; + int dynamicRange; + int scanTag; + int numberOfFrames; + bool doFileWrite; + bool doFileOverWrite; + + EigerReceiverScanConfiguration(): + dynamicRange(-1), + scanTag(-1), + numberOfFrames(-1), + doFileWrite(false), + doFileOverWrite(false){}; +}; + +class EigerReceiverImplementation: public EigerReceiver { + +public: + + EigerReceiverImplementation() : isInitialized(false), status(slsReceiverDefs::ERROR) {}; + + void initialize(const char *detectorHostname) { + + string name; + if (detectorHostname != NULL) { + name = detectorHostname; + } + + if (name.empty()) { + DEBUG("initialize(): can't initialize with empty string or NULL for detectorHostname"); + } else if (isInitialized == true) { + DEBUG("initialize(): already initialized, can't initialize several times"); + } else { + DEBUG("initialize(): initialize() with: detectorHostName=" << name << "."); + init_config.detectorHostname = name; + isInitialized = true; + status = slsReceiverDefs::IDLE; + } + +#ifdef SALA + //REST call - hardcoded + RestHelper rest ; + rest.init("localhost",8080); + std::string answer; + std::cout << "---- REST test 1: true, string "<< std::endl; + int code = rest.get_json("status", &answer); + std::cout << "Answer: " << answer << std::endl; + + std::cout << "---- REST test 2: 404, string "<< std::endl; + code = rest.get_json("statuss", &answer); + if (code != 0){ + //throw -1; + std::cout << "I SHOULD THROW AN EXCEPTION!!!" << std::endl; + } + + std::cout << "---- REST test 3: true, json object "<< std::endl; + JsonBox::Value json_value; + code = rest.get_json("status", &json_value); + std::cout << "JSON " << json_value["status"] << std::endl; + + answer = ""; + std::cout << "---- REST test 4: POST, string "<< std::endl; + code = rest.post_json("recipes/cassoela", &answer); + std::cout << "POST answer: " << answer << std::endl; + if (code != 0){ + //throw -1; + std::cout << "I SHOULD THROW AN EXCEPTION!!!" << std::endl; + } + + RestHelper rest2 ; + rest2.init("reallyfake",8080); + std::cout << "---- REST test 4: host not found, json object "<< std::endl; + JsonBox::Value json_value2; + code = rest2.get_json("status", &json_value2); + if (code != 0){ + //throw -1; + std::cout << "I SHOULD THROW AN EXCEPTION!!!" << std::endl; + } + +#endif + } + + + char *getDetectorHostname() const { + string name = init_config.detectorHostname; + if (name.empty()) { + DEBUG("getDetectorHostname(): Return NULL"); + return(NULL); + } + char *c = new char[name.length()+1]; + name.copy(c, name.length()); + c[name.length()] = '\0'; + DEBUG("getDetectorHostname(): Return " << c << "."); + return(c); + } + + char *getFileName() const { + string name = scan_config.fileName; + + char *c = new char[name.length()+1]; + name.copy(c, name.length()); + c[name.length()] = '\0'; + DEBUG("getFileName(): Return " << c); + return(c); + } + + char *getFilePath() const { + string name = scan_config.filePath; + + char *c = new char[name.length()+1]; + name.copy(c, name.length()); + c[name.length()] = '\0'; + DEBUG("getFilePath(): Return " << c); + return(c); + } + + int getDynamicRange() const { + DEBUG("getDynamicRange(): Return " << scan_config.dynamicRange); + return(scan_config.dynamicRange); + } + + int getScanTag() const { + DEBUG("getScanTag(): returns " << scan_config.scanTag); + return(scan_config.scanTag); + } + + int getNumberOfFrames() const { + DEBUG("getNumberOfFrames(): return " << scan_config.numberOfFrames); + return(scan_config.numberOfFrames); + } + + int getEnableFileWrite() const { + DEBUG("getEnableFileWrite() returns " << scan_config.doFileWrite); + return(scan_config.doFileWrite); + } + + int getEnableOverwrite() const { + DEBUG("getEnableOverwrite() returns " << scan_config.doFileOverWrite); + return(scan_config.doFileOverWrite); + } + + slsReceiverDefs::runStatus getStatus() const { + DEBUG("getStatus(): return " <getFileName()); + } + + char *setFilePath(const char c[]) { + DEBUG("setFilePath() called with " << c << "."); + scan_config.filePath = c; + return(this->getFilePath()); + } + + int setDynamicRange (const int dr) { + DEBUG("setDynamicRange() called with " << dr << '.'); + scan_config.dynamicRange = dr; + return(getDynamicRange()); + } + + int setScanTag (const int tag) { + DEBUG("setScanTag() called with " << tag); + scan_config.scanTag = tag; + return(getScanTag()); + } + + int setNumberOfFrames (const int fnum) { + DEBUG("setNumberOfFrames() called with " << fnum); + scan_config.numberOfFrames = fnum; + return(getNumberOfFrames()); + } + + int setEnableFileWrite(const int i) { + DEBUG("enableFileWrite() called with " << i); + scan_config.doFileWrite = i; + return(getEnableFileWrite()); + } + + int setEnableOverwrite(const int i) { + DEBUG("setEnableOverwrite() called with " << i); + scan_config.doFileOverWrite = i; + return(getEnableOverwrite()); + } + + int startReceiver(char message[]) { + DEBUG("startReceiver(): return 0."); + status = slsReceiverDefs::RUNNING; + message = NULL; + return(0); + } + + int stopReceiver() { + DEBUG("stopReceiver(): return 0."); + status = slsReceiverDefs::IDLE; + return(0); + } + + void abort() { + DEBUG("abort(): return 0."); + status = slsReceiverDefs::IDLE; + } + +private: + EigerReceiverScanConfiguration scan_config; + EigerReceiverInitializationConfiguration init_config; + bool isInitialized; + slsReceiverDefs::runStatus status; +}; + +EigerReceiver *EigerReceiver::create(void) { + DEBUG("create(): Return new EigerReceiverImplementation instance."); + return new EigerReceiverImplementation(); +} + + + + diff --git a/slsReceiverSoftware/slsReceiver/eigerReceiver/eigerReceiver.h b/slsReceiverSoftware/slsReceiver/eigerReceiver/eigerReceiver.h new file mode 100644 index 000000000..9d26b185b --- /dev/null +++ b/slsReceiverSoftware/slsReceiver/eigerReceiver/eigerReceiver.h @@ -0,0 +1,211 @@ +#ifndef EIGERRECEIVER_H +#define EIGERRECEIVER_H +/*********************************************** + * @file eigerReceiver.h + * @short does all the functions for a receiver, set/get parameters, start/stop etc. + ***********************************************/ + +/** + * @short does all the functions for a receiver, set/get parameters, start/stop etc. + */ + +#include "sls_receiver_defs.h" +#ifdef SALA +#include "RestHelper.h" +#endif +class EigerReceiver { + /* abstract class that defines the public interface of an eiger data receiver. + * + * Use the factory method EigerReceiver::create() to get an instance: + * + * EigerReceiver *receiver = EigerReceiver::create() + * + * supported sequence of method-calls: + * + * initialize() : once and only once after create() + * + * get*() : anytime after initialize(), multiples times + * set*() : anytime after initialize(), multiple times + * + * startReceiver(): anytime after initialize(). Will fail if state already is 'running' + * + * abort(), + * stopReceiver() : anytime after initialize(). Will do nothing if state already is idle. + * + * getStatus() returns the actual state of the data receiver - running or idle. All other + * get*() and set*() methods access the local cache of configuration values only and *do not* modify the data receiver settings. + * + * Only startReceiver() does change the data receiver configuration, it does pass the whole configuration cache to the data receiver. + * + * get- and set-methods that return a char array (char *) allocate a new array at each call. The caller is responsible to free the allocated space: + * + * char *c = receiver->getFileName(); + * .... + * delete[] c; + * + * always: 1:YES 0:NO for int as bool-like arguments + * + */ + +public: + + /** + * factory method to create instances + */ + static EigerReceiver *create(); + + /** + * Destructor + */ + virtual ~EigerReceiver() {}; + + /** + * Initialize the Receiver + @param detectorHostName detector hostname + * you can call this function only once. You must call it before you call startReceiver() for the first time. + */ + virtual void initialize(const char *detectorHostName) = 0; + + + /* Returns detector hostname + /returns hostname + * caller needs to deallocate the returned char array. + * if uninitialized, it must return NULL + */ + virtual char *getDetectorHostname() const = 0; + + /** + * Returns status of receiver: idle, running or error + */ + virtual slsReceiverDefs::runStatus getStatus() const = 0; + + /** + * Returns File Name + * caller is responsible to deallocate the returned char array. + */ + virtual char *getFileName() const = 0; + + + /** + * Returns File Path + * caller is responsible to deallocate the returned char array + */ + virtual char *getFilePath() const = 0; //FIXME: Does the caller need to free() the returned pointer? + + + /** + * Returns the number of bits per pixel + */ + virtual int getDynamicRange() const = 0; + + /** + * Returns scan tag + */ + virtual int getScanTag() const = 0; + + /* + * Returns number of frames to receive + * This is the number of frames to expect to receiver from the detector. + * The data receiver will change from running to idle when it got this number of frames + */ + virtual int getNumberOfFrames() const = 0; + + /** + * Returns file write enable + * 1: YES 0: NO + */ + virtual int getEnableFileWrite() const = 0; + + /** + * Returns file over write enable + * 1: YES 0: NO + */ + virtual int getEnableOverwrite() const = 0; + + /** + * Set File Name (without frame index, file index and extension) + @param c file name + /returns file name + * returns NULL on failure (like bad file name) + * does not check the existence of the file - we don't know which path we'll finally use, so no point to check. + * caller is responsible to deallocate the returned char array. + */ + virtual char* setFileName(const char c[]) = 0; + + /** + * Set File Path + @param c file path + /returns file path + * checks the existence of the directory. returns NULL if directory does not exist or is not readable. + * caller is responsible to deallocate the returned char array. + */ + virtual char* setFilePath(const char c[]) = 0; + + /** + * Returns the number of bits per pixel + @param dr sets dynamic range + /returns dynamic range + * returns -1 on failure + * FIXME: what are the allowd values - should we use an enum as argument? + */ + virtual int setDynamicRange(const int dr) = 0; + + + /** + * Set scan tag + @param tag scan tag + /returns scan tag (always non-negative) + * FIXME: valid range - only positive? 16bit ore 32bit? + * returns -1 on failure + */ + virtual int setScanTag(const int tag) = 0; + + /** + * Sets number of frames + @param fnum number of frames + /returns number of frames + */ + virtual int setNumberOfFrames(const int fnum) = 0; + + /** + * Set enable file write + * @param i file write enable + /returns file write enable + */ + virtual int setEnableFileWrite(const int i) = 0; + + /** + * Set enable file overwrite + * @param i file overwrite enable + /returns file overwrite enable + */ + virtual int setEnableOverwrite(const int i) = 0; + + /** + * Starts Receiver - activate all configuration settings to the eiger receiver and start to listen for packets + @param message is the error message if there is an error + /returns 0 on success or -1 on failure + */ + //FIXME: success == 0 or success == 1? + virtual int startReceiver(char message[]) = 0; //FIXME: who allocates message[]? + + /** + * Stops Receiver - stops listening for packets + /returns success + * same as abort(). Always returns 0. + */ + virtual int stopReceiver() = 0; + + /** + * abort acquisition with minimum damage: close open files, cleanup. + * does nothing if state already is 'idle' + */ + virtual void abort() = 0; + +protected: + +private: + +}; + +#endif /* #ifndef EIGERRECEIVER_H */ diff --git a/slsReceiverSoftware/slsReceiver/eigerReceiver/eigerReceiverDummy.cpp b/slsReceiverSoftware/slsReceiver/eigerReceiver/eigerReceiverDummy.cpp new file mode 100644 index 000000000..f45c7517e --- /dev/null +++ b/slsReceiverSoftware/slsReceiver/eigerReceiver/eigerReceiverDummy.cpp @@ -0,0 +1,99 @@ +/* + * eigerReceiver.cpp + * + * Created on: Mar 11, 2014 + * Author: billich + */ + +#include +#include +#include "eigerReceiver.h" + + +using namespace std; + +struct EigerReceiverInitializationConfiguration { + string detectorHostname; +}; + +struct EigerReceiverScanConfiguration { + + string fileName; + string filePath; + int dynamicRange; + int scanTag; + int numberOfFrames; + bool doFileWrite; + bool doFileOverWrite; + + EigerReceiverScanConfiguration(): + dynamicRange(-1), + scanTag(-1), + numberOfFrames(-1), + doFileWrite(false), + doFileOverWrite(false){}; +}; + +class EigerReceiverImplementation: public EigerReceiver { + +public: + + EigerReceiverImplementation(){}; + + ~EigerReceiverImplementation(){}; + + void initialize(const char *detectorHostname) {} + + char *getDetectorHostname() const { return (char*)"";} + + char *getFileName() const {return (char*)"";} + + char *getFilePath() const {return (char*)"";} + + int getDynamicRange() const { return 0;} + + int getScanTag() const {return 0;} + + int getNumberOfFrames() const {return 0;} + + int getEnableFileWrite() const {return 0;} + + int getEnableOverwrite() const {return 0;} + + slsReceiverDefs::runStatus getStatus() const { return slsReceiverDefs::IDLE;} + + char *setFileName(const char c[]) {return (char*)"";} + + char *setFilePath(const char c[]) {return (char*)"";} + + int setDynamicRange (const int dr) {return 0;} + + int setScanTag (const int tag) {return 0;} + + int setNumberOfFrames (const int fnum) {return 0;} + + int setEnableFileWrite(const int i) {return 0;} + + int setEnableOverwrite(const int i) {return 0;} + + int startReceiver(char message[]) {return 0;} + + int stopReceiver() {return 0;} + + void abort() {} + +private: + EigerReceiverScanConfiguration scan_config; + EigerReceiverInitializationConfiguration init_config; + bool isInitialized; + slsReceiverDefs::runStatus status; + +}; + +EigerReceiver *EigerReceiver::create(void) { + return new EigerReceiverImplementation(); +} + + + + diff --git a/slsReceiverSoftware/slsReceiver/eigerReceiver/eigerReceiverTest.cpp b/slsReceiverSoftware/slsReceiver/eigerReceiver/eigerReceiverTest.cpp new file mode 100644 index 000000000..bdfcba7a1 --- /dev/null +++ b/slsReceiverSoftware/slsReceiver/eigerReceiver/eigerReceiverTest.cpp @@ -0,0 +1,97 @@ +/* + * eigerReceiverTest.cpp + + * + * Created on: Mar 11, 2014 + * Author: billich + */ + +#include +#include +#include "eigerReceiver.h" + +using namespace std; + +int main(int argc, char *argv[]){ + + const char *name = "detectors_host_name"; + const char *empty = ""; + std::string prefix = "main: "; + cout <getStatus(); + char *c0 = receiver->getDetectorHostname(); + if (c0 == NULL) { + cout <initialize(empty); + status = receiver->getStatus(); + receiver->initialize(name); + status = receiver->getStatus(); + receiver->initialize(name); + status = receiver->getStatus(); + receiver->initialize((char *)NULL); + + cout << endl; + + status = receiver->getStatus(); + char *c6 = receiver->getDetectorHostname(); + cout <getFileName(); + cout <." << endl; + delete[] c1; + + char *c2 = receiver->getFilePath(); + cout <." << endl; + delete[]c2; + + int range = receiver->getDynamicRange(); + cout <getScanTag(); + cout <setFileName( "some_other_name"); + cout < after setting to " << endl << endl; + delete[] c3; + + char *c4 = receiver->setFilePath( "some_other_path"); + cout < after setting to " << endl << endl; + delete[] c4; + + range = receiver->setDynamicRange(8); + cout <setScanTag(99); + cout << "got scan tag " << tag << " after setting to 99." << endl << endl; + + int n = receiver->setNumberOfFrames(11); + cout << "got number of frames " << n << " after setting to 11." << endl << endl; + + int w = receiver->setEnableFileWrite(1); + cout << "got enable file write " << w << " after setting to 1." << endl << endl; + + char *c5; + status = receiver->getStatus(); + receiver->startReceiver(c5); + status = receiver->getStatus(); + receiver->stopReceiver(); + status = receiver->getStatus(); + receiver->abort(); + status = receiver->getStatus(); + +} + + + + diff --git a/slsReceiverSoftware/slsReceiver/slsReceiver.cpp b/slsReceiverSoftware/slsReceiver/slsReceiver.cpp new file mode 100644 index 000000000..104fafad9 --- /dev/null +++ b/slsReceiverSoftware/slsReceiver/slsReceiver.cpp @@ -0,0 +1,81 @@ +/* A simple server in the internet domain using TCP + The port number is passed as an argument */ + +#include "sls_receiver_defs.h" +#include "slsReceiverUsers.h" + +#include +using namespace std; + + + + + + +int main(int argc, char *argv[]) { + int ret = slsReceiverDefs::OK; + + slsReceiverUsers *user = new slsReceiverUsers(argc, argv, ret); + + if(ret==slsReceiverDefs::FAIL) + return -1; + + + //register callbacks + + + /** + callback arguments are + filepath + filename + fileindex + datasize + + return value is + 0 raw data ready callback takes care of open,close,write file + 1 callback writes file, we have to open, close it + 2 we open, close, write file, callback does not do anything + + + registerCallBackStartAcquisition(int (*func)(char*, char*,int, int, void*),void *arg); + */ + + //receiver->registerCallBackStartAcquisition(func,arg); + + + /** + callback argument is + total farmes caught + registerCallBackAcquisitionFinished(void (*func)(int, void*),void *arg); + */ + + + //receiver->registerCallBackAcquisitionFinished(func,arg); + + + + /** + args to raw data ready callback are + framenum + datapointer + file descriptor + guidatapointer (NULL, no data required) + + NEVER DELETE THE DATA POINTER + REMEMBER THAT THE CALLBACK IS BLOCKING + + registerCallBackRawDataReady(void (*func)(int, char*, FILE*, char*, void*),void *arg); + + */ + + //receiver->registerCallBackRawDataReady(func,arg); + + + + + user->start(); + + + return 0; +} + diff --git a/slsReceiverSoftware/slsReceiver/slsReceiverTCPIPInterface.cpp b/slsReceiverSoftware/slsReceiver/slsReceiverTCPIPInterface.cpp new file mode 100644 index 000000000..c3720ad05 --- /dev/null +++ b/slsReceiverSoftware/slsReceiver/slsReceiverTCPIPInterface.cpp @@ -0,0 +1,1991 @@ +/********************************************//** + * @file slsReceiverTCPIPInterface.h + * @short interface between receiver and client + ***********************************************/ + +#include "slsReceiverTCPIPInterface.h" +#include "slsReceiverUDPFunctions.h" +#include "svnInfoReceiver.h" +#include "slsReceiverUsers.h" + +#include //SIGINT +#include //EXIT + +#include +#include +#include +#include +#include +using namespace std; + + +int slsReceiverTCPIPInterface::file_des(-1); +int slsReceiverTCPIPInterface::socketDescriptor(-1); + + +slsReceiverTCPIPInterface::~slsReceiverTCPIPInterface() { + if(socket) delete socket; + closeFile(0); +} + + +slsReceiverTCPIPInterface::slsReceiverTCPIPInterface(int argc, char *argv[], int &success): + myDetectorType(GOTTHARD), + ret(OK), + lockStatus(0), + shortFrame(-1), + packetsPerFrame(GOTTHARD_PACKETS_PER_FRAME), + socket(NULL){ + + int port_no = DEFAULT_PORTNO+2; + ifstream infile; + string sLine,sargname; + int iline = 0; + + + success=OK; + string fname = ""; + + //parse command line for config + for(int iarg=1;iarg> sargname; + + //tcp port + if(sargname=="rx_tcpport"){ + if(sstr.good()) { + sstr >> sargname; + if(sscanf(sargname.c_str(),"%d",&port_no)) + cout<<"dataport:"<getErrorStatus()) { + success = FAIL; + delete socket; + socket=NULL; + } else { + //initialize variables + strcpy(socket->lastClientIP,"none"); + strcpy(socket->thisClientIP,"none1"); + strcpy(mess,"dummy message"); + + function_table(); +#ifdef VERBOSE + cout << "Function table assigned." << endl; +#endif + slsReceiverFunctions = new slsReceiverUDPFunctions(); + + //Catch signal SIGINT to close files properly + signal(SIGINT,staticCloseFile); + + + file_des=socket->getFileDes(); + socketDescriptor=socket->getsocketDescriptor(); + + //success = OK; + } + } + +} + +void slsReceiverTCPIPInterface::start(){ + + int v=slsReceiverDefs::OK; + + while(v!=GOODBYE) { +#ifdef VERBOSE + cout<< endl; +#endif +#ifdef VERY_VERBOSE + cout << "Waiting for client call" << endl; +#endif + if(socket->Connect()>=0){ +#ifdef VERY_VERBOSE + cout << "Conenction accepted" << endl; +#endif + v = decode_function(); +#ifdef VERY_VERBOSE + cout << "function executed" << endl; +#endif + socket->Disconnect(); +#ifdef VERY_VERBOSE + cout << "connection closed" << endl; +#endif + } + } + + + +} + + +int slsReceiverTCPIPInterface::function_table(){ + + for (int i=0;iReceiveDataOnly(&fnum,sizeof(fnum)); + if (n <= 0) { +#ifdef VERBOSE + cout << "ERROR reading from socket " << n << ", " << fnum << endl; +#endif + return FAIL; + } +#ifdef VERBOSE + else + cout << "size of data received " << n <numberOfFunctions-1) + fnum = numberOfFunctions-1; + //calling function + (this->*flist[fnum])(); + if (ret==FAIL) + cout << "Error executing the function = " << fnum << endl; + + return ret; +} + + + + + + +int slsReceiverTCPIPInterface::M_nofunc(){ + + ret=FAIL; + sprintf(mess,"Unrecognized Function\n"); + cout << mess << endl; + + socket->SendDataOnly(&ret,sizeof(ret)); + socket->SendDataOnly(mess,sizeof(mess)); + + return GOODBYE; +} + + + + +void slsReceiverTCPIPInterface::closeFile(int p){ + cout<<"Closing Files... "<closeFile(); + cout << "Goodbye!" << endl; + exit(-1); +} + +void slsReceiverTCPIPInterface::staticCloseFile(int p){ + slsReceiverUsers::receiver->closeFile(p); +} + + +int slsReceiverTCPIPInterface::set_detector_type(){ + ret=OK; + int retval=FAIL; + detectorType dr; + strcpy(mess,"Could not set detector type range\n"); + + + // receive arguments + if(socket->ReceiveDataOnly(&dr,sizeof(dr)) < 0 ){ + strcpy(mess,"Error reading from socket\n"); + ret = FAIL; + } + + // execute action if the arguments correctly arrived +#ifdef SLS_RECEIVER_UDP_FUNCTIONS + if (ret==OK) { + if (lockStatus==1 && socket->differentClients==1){ + sprintf(mess,"Receiver locked by %s\n", socket->lastClientIP); + ret=FAIL; + } + else{ + myDetectorType = dr; + ret=slsReceiverFunctions->setDetectorType(dr); + retval = myDetectorType; + } + } +//#ifdef VERBOSE + if(ret!=FAIL) + cout << "detector type" << dr << endl; + else + cout << mess << endl; +//#endif +#endif + + if(ret==OK && socket->differentClients){ + cout << "Force update" << endl; + ret=FORCE_UPDATE; + } + + // send answer + socket->SendDataOnly(&ret,sizeof(ret)); + if(ret==FAIL) + socket->SendDataOnly(mess,sizeof(mess)); + socket->SendDataOnly(&retval,sizeof(retval)); + + //return ok/fail + return ret; +} + + + + + + + +int slsReceiverTCPIPInterface::set_file_name() { + ret=OK; + char retval[MAX_STR_LENGTH]=""; + char fName[MAX_STR_LENGTH]; + strcpy(mess,"Could not set file name"); + + // receive arguments + if(socket->ReceiveDataOnly(fName,MAX_STR_LENGTH) < 0 ){ + strcpy(mess,"Error reading from socket\n"); + ret = FAIL; + } + + // execute action if the arguments correctly arrived +#ifdef SLS_RECEIVER_UDP_FUNCTIONS + if (ret==OK) { + + if (lockStatus==1 && socket->differentClients==1){ + sprintf(mess,"Receiver locked by %s\n", socket->lastClientIP); + ret=FAIL; + } + else + strcpy(retval,slsReceiverFunctions->setFileName(fName)); + } +#ifdef VERBOSE + if(ret!=FAIL) + cout << "file name:" << retval << endl; + else + cout << mess << endl; +#endif +#endif + + if(ret==OK && socket->differentClients){ + cout << "Force update" << endl; + ret=FORCE_UPDATE; + } + + // send answer + socket->SendDataOnly(&ret,sizeof(ret)); + if(ret==FAIL) + socket->SendDataOnly(mess,sizeof(mess)); + socket->SendDataOnly(retval,MAX_STR_LENGTH); + + //return ok/fail + return ret; +} + + + + + + +int slsReceiverTCPIPInterface::set_file_dir() { + ret=OK; + char retval[MAX_STR_LENGTH]=""; + char fPath[MAX_STR_LENGTH]; + strcpy(mess,"Could not set file path\n"); + + // receive arguments + if(socket->ReceiveDataOnly(fPath,MAX_STR_LENGTH) < 0 ){ + strcpy(mess,"Error reading from socket\n"); + ret = FAIL; + } + + // execute action if the arguments correctly arrived +#ifdef SLS_RECEIVER_UDP_FUNCTIONS + if (ret==OK) { + if (lockStatus==1 && socket->differentClients==1){ + sprintf(mess,"Receiver locked by %s\n", socket->lastClientIP); + ret=FAIL; + }/* + else if((strlen(fPath))&&(slsReceiverFunctions->getStatus()==RUNNING)){ + strcpy(mess,"Can not set file path while receiver running\n"); + ret = FAIL; + }*/ + else{ + strcpy(retval,slsReceiverFunctions->setFilePath(fPath)); + // if file path doesnt exist + if(strlen(fPath)) + if (strcmp(retval,fPath)){ + strcpy(mess,"receiver file path does not exist\n"); + ret=FAIL; + } + } + + } +#ifdef VERBOSE + if(ret!=FAIL) + cout << "file path:" << retval << endl; + else + cout << mess << endl; +#endif +#endif + + if(ret==OK && socket->differentClients){ + cout << "Force update" << endl; + ret=FORCE_UPDATE; + } + + // send answer + socket->SendDataOnly(&ret,sizeof(ret)); + if(ret==FAIL) + socket->SendDataOnly(mess,sizeof(mess)); + socket->SendDataOnly(retval,MAX_STR_LENGTH); + + //return ok/fail + return ret; +} + + + + + + +int slsReceiverTCPIPInterface::set_file_index() { + ret=OK; + int retval=-1; + int index; + strcpy(mess,"Could not set file index\n"); + + + // receive arguments + if(socket->ReceiveDataOnly(&index,sizeof(index)) < 0 ){ + strcpy(mess,"Error reading from socket\n"); + ret = FAIL; + } + + // execute action if the arguments correctly arrived +#ifdef SLS_RECEIVER_UDP_FUNCTIONS + if (ret==OK) { + if (lockStatus==1 && socket->differentClients==1){ + sprintf(mess,"Receiver locked by %s\n", socket->lastClientIP); + ret=FAIL; + } + else + retval=slsReceiverFunctions->setFileIndex(index); + } +#ifdef VERBOSE + if(ret!=FAIL) + cout << "file index:" << retval << endl; + else + cout << mess << endl; +#endif +#endif + + if(ret==OK && socket->differentClients){ + cout << "Force update" << endl; + ret=FORCE_UPDATE; + } + + // send answer + socket->SendDataOnly(&ret,sizeof(ret)); + if(ret==FAIL) + socket->SendDataOnly(mess,sizeof(mess)); + socket->SendDataOnly(&retval,sizeof(retval)); + + //return ok/fail + return ret; +} + + + + + + + + +int slsReceiverTCPIPInterface::set_frame_index() { + ret=OK; + int retval=-1; + int index; + strcpy(mess,"Could not set frame index\n"); + + + // receive arguments + if(socket->ReceiveDataOnly(&index,sizeof(index)) < 0 ){ + strcpy(mess,"Error reading from socket\n"); + ret = FAIL; + } + + // execute action if the arguments correctly arrived +#ifdef SLS_RECEIVER_UDP_FUNCTIONS + if (ret==OK) { + if (lockStatus==1 && socket->differentClients==1){ + sprintf(mess,"Receiver locked by %s\n", socket->lastClientIP); + ret=FAIL; + } + else + retval=slsReceiverFunctions->setFrameIndexNeeded(index); + } +#ifdef VERBOSE + if(ret!=FAIL) + cout << "frame index:" << retval << endl; + else + cout << mess << endl; +#endif +#endif + + if(ret==OK && socket->differentClients){ + cout << "Force update" << endl; + ret=FORCE_UPDATE; + } + + // send answer + socket->SendDataOnly(&ret,sizeof(ret)); + if(ret==FAIL) + socket->SendDataOnly(mess,sizeof(mess)); + socket->SendDataOnly(&retval,sizeof(retval)); + + //return ok/fail + return ret; +} + + + + + + + +int slsReceiverTCPIPInterface::setup_udp(){ + ret=OK; + strcpy(mess,"could not set up udp connection"); + char retval[MAX_STR_LENGTH]=""; + char args[2][MAX_STR_LENGTH]; + + string temp; + int udpport; + char eth[MAX_STR_LENGTH]; + + + // receive arguments + + if(socket->ReceiveDataOnly(args,sizeof(args)) < 0 ){ + strcpy(mess,"Error reading from socket\n"); + ret = FAIL; + } + + // execute action if the arguments correctly arrived +#ifdef SLS_RECEIVER_UDP_FUNCTIONS + if (ret==OK) { + if (lockStatus==1 && socket->differentClients==1){ + sprintf(mess,"Receiver locked by %s\n", socket->lastClientIP); + ret=FAIL; + } + else if(slsReceiverFunctions->getStatus()==RUNNING){ + ret = FAIL; + strcpy(mess,"cannot set up udp when receiver is running\n"); + } + else{ + //set up udp port + sscanf(args[1],"%d",&udpport); + slsReceiverFunctions->setUDPPortNo(udpport); + + //setup udpip + //get ethernet interface or IP to listen to + temp = genericSocket::ipToName(args[0]); + if(temp=="none"){ + ret = FAIL; + strcpy(mess, "failed to get ethernet interface or IP to listen to\n"); + } + else{ + strcpy(eth,temp.c_str()); + if (strchr(eth,'.')!=NULL) { + strcpy(eth,""); + ret = FAIL; + } + cout<<"eth:"<setEthernetInterface(eth); + + //get mac address from ethernet interface + if (ret != FAIL) + temp = genericSocket::nameToMac(eth); + + + if ((temp=="00:00:00:00:00:00") || (ret == FAIL)){ + ret = FAIL; + strcpy(mess,"failed to get mac adddress to listen to\n"); + cout << "mess:" << mess << endl; + } + else{ + strcpy(retval,temp.c_str()); + cout<<"mac:"<differentClients){ + cout << "Force update" << endl; + ret=FORCE_UPDATE; + } + + // send answer + socket->SendDataOnly(&ret,sizeof(ret)); + if(ret==FAIL) + socket->SendDataOnly(mess,sizeof(mess)); + socket->SendDataOnly(retval,MAX_STR_LENGTH); + + //return ok/fail + return ret; +} + + + + + + +int slsReceiverTCPIPInterface::start_receiver(){ + ret=OK; + ret=OK; + enum runStatus s; + char cstatus[15]; + strcpy(mess,"Could not start receiver\n"); + + // execute action if the arguments correctly arrived +#ifdef SLS_RECEIVER_UDP_FUNCTIONS + if (lockStatus==1 && socket->differentClients==1){ + sprintf(mess,"Receiver locked by %s\n", socket->lastClientIP); + ret=FAIL; + } + /* + else if(!strlen(slsReceiverFunctions->getFilePath())){ + strcpy(mess,"receiver not set up. set receiver ip again.\n"); + ret = FAIL; + } + */ + else { + s = slsReceiverFunctions->getStatus(); + switch (s) { + case ERROR: strcpy(cstatus,"error"); break; + case WAITING: strcpy(cstatus,"waiting"); break; + case RUNNING: strcpy(cstatus,"running"); break; + case TRANSMITTING: strcpy(cstatus,"data"); break; + case RUN_FINISHED: strcpy(cstatus,"finished"); break; + default: strcpy(cstatus,"idle"); break; + } + if(s == IDLE) + ret=slsReceiverFunctions->startReceiver(mess); + else{ + sprintf(mess,"Cannot start Receiver as it is in %s state\n",cstatus); + ret=FAIL; + } + } + +#endif + + if(ret==OK && socket->differentClients){ + cout << "Force update" << endl; + ret=FORCE_UPDATE; + } + + // send answer + socket->SendDataOnly(&ret,sizeof(ret)); + if(ret==FAIL) + socket->SendDataOnly(mess,sizeof(mess)); + cout<<"ret of start receiver:"<differentClients==1){ + sprintf(mess,"Receiver locked by %s\n", socket->lastClientIP); + ret=FAIL; + } + else if(slsReceiverFunctions->getStatus()!=IDLE) + ret=slsReceiverFunctions->stopReceiver(); +#endif + + if(ret==OK && socket->differentClients){ + cout << "Force update" << endl; + ret=FORCE_UPDATE; + } + + // send answer + socket->SendDataOnly(&ret,sizeof(ret)); + if(ret==FAIL) + socket->SendDataOnly(mess,sizeof(mess)); + //return ok/fail + return ret; + + +} + + +int slsReceiverTCPIPInterface::get_status(){ + ret=OK; + enum runStatus retval; + + // execute action if the arguments correctly arrived +#ifdef SLS_RECEIVER_UDP_FUNCTIONS + retval=slsReceiverFunctions->getStatus(); +#endif + + if(socket->differentClients){ + cout << "Force update" << endl; + ret=FORCE_UPDATE; + } + + // send answer + socket->SendDataOnly(&ret,sizeof(ret)); + socket->SendDataOnly(&retval,sizeof(retval)); + //return ok/fail + return ret; + + +} + + +int slsReceiverTCPIPInterface::get_frames_caught(){ + ret=OK; + int retval=-1; + + // execute action if the arguments correctly arrived +#ifdef SLS_RECEIVER_UDP_FUNCTIONS + retval=slsReceiverFunctions->getTotalFramesCaught(); +#endif + if(socket->differentClients){ + cout << "Force update" << endl; + ret=FORCE_UPDATE; + } + + // send answer + socket->SendDataOnly(&ret,sizeof(ret)); + socket->SendDataOnly(&retval,sizeof(retval)); + //return ok/fail + return ret; + + +} + + +int slsReceiverTCPIPInterface::get_frame_index(){ + ret=OK; + int retval=-1; + + // execute action if the arguments correctly arrived +#ifdef SLS_RECEIVER_UDP_FUNCTIONS + retval=slsReceiverFunctions->getAcquisitionIndex(); +#endif + + if(socket->differentClients){ + cout << "Force update" << endl; + ret=FORCE_UPDATE; + } + + // send answer + socket->SendDataOnly(&ret,sizeof(ret)); + socket->SendDataOnly(&retval,sizeof(retval)); + //return ok/fail + return ret; + + +} + + +int slsReceiverTCPIPInterface::reset_frames_caught(){ + ret=OK; + + strcpy(mess,"Could not reset frames caught\n"); + + + // execute action if the arguments correctly arrived +#ifdef SLS_RECEIVER_UDP_FUNCTIONS + if (ret==OK) { + if (lockStatus==1 && socket->differentClients==1){ + sprintf(mess,"Receiver locked by %s\n", socket->lastClientIP); + ret=FAIL; + } + else + slsReceiverFunctions->resetTotalFramesCaught(); + } +#endif + + if(ret==OK && socket->differentClients){ + cout << "Force update" << endl; + ret=FORCE_UPDATE; + } + + // send answer + socket->SendDataOnly(&ret,sizeof(ret)); + if(ret==FAIL) + socket->SendDataOnly(mess,sizeof(mess)); + + //return ok/fail + return ret; + + +} + + + + + + +int slsReceiverTCPIPInterface::set_short_frame() { + ret=OK; + int index=0; + int retval=-100; + strcpy(mess,"Could not set/reset short frame for receiver\n"); + + //does not exist for moench + if(myDetectorType==MOENCH){ + strcpy(mess,"can not set short frame for moench\n"); + ret = FAIL; + } + + // receive arguments + if(socket->ReceiveDataOnly(&index,sizeof(index)) < 0 ){ + strcpy(mess,"Error reading from socket\n"); + ret = FAIL; + } + + + // execute action if the arguments correctly arrived +#ifdef SLS_RECEIVER_UDP_FUNCTIONS + if (ret==OK) { + if (lockStatus==1 && socket->differentClients==1){ + sprintf(mess,"Receiver locked by %s\n", socket->lastClientIP); + ret=FAIL; + } + else if(slsReceiverFunctions->getStatus()==RUNNING){ + strcpy(mess,"Cannot set short frame while status is running\n"); + ret=FAIL; + } + else{ + retval=slsReceiverFunctions->setShortFrame(index); + shortFrame = retval; + if(shortFrame==-1) + packetsPerFrame=GOTTHARD_PACKETS_PER_FRAME; + else + packetsPerFrame=GOTTHARD_SHORT_PACKETS_PER_FRAME; + } + } +#endif + + if(ret==OK && socket->differentClients){ + cout << "Force update" << endl; + ret=FORCE_UPDATE; + } + + // send answer + socket->SendDataOnly(&ret,sizeof(ret)); + if(ret==FAIL) + socket->SendDataOnly(mess,sizeof(mess)); + socket->SendDataOnly(&retval,sizeof(retval)); + + //return ok/fail + return ret; +} + + + + +int slsReceiverTCPIPInterface::read_frame(){ + switch(myDetectorType){ + case MOENCH: + return moench_read_frame(); + default: + return gotthard_read_frame(); + } +} + + + +int slsReceiverTCPIPInterface::moench_read_frame(){ + ret=OK; + char fName[MAX_STR_LENGTH]=""; + int arg = -1,i; + + + int bufferSize = MOENCH_BUFFER_SIZE; + int rnel = bufferSize/(sizeof(int)); + int* retval = new int[rnel]; + int* origVal = new int[rnel]; + //all initialized to 0 + for(i=0;igetFramesCaught()){ + arg = -1; + cout<<"haven't caught any frame yet"<getStartFrameIndex(); + slsReceiverFunctions->readFrame(fName,&raw); + + /**send garbage with -1 index to try again*/ + if (raw == NULL){ + arg = -1; +#ifdef VERBOSE + cout<<"data not ready for gui yet"<> MOENCH_FRAME_INDEX_OFFSET); + + uint32_t numPackets = MOENCH_PACKETS_PER_FRAME; //40 + uint32_t onePacketSize = MOENCH_DATA_BYTES / MOENCH_PACKETS_PER_FRAME; //1280*40 / 40 = 1280 + uint32_t packetDatabytes_row = onePacketSize * (MOENCH_BYTES_IN_ONE_ROW / MOENCH_BYTES_PER_ADC); //1280 * 4 = 5120 + uint32_t partsPerFrame = onePacketSize / MOENCH_BYTES_PER_ADC; // 1280 / 80 = 16 + uint32_t packetOffset = 0; + int packetIndex,x,y; + int iPacket = 0; + offset = 4; + + + while (iPacket < (int)numPackets){ +#ifdef VERBOSE + printf("iPacket:%d\n",iPacket);cout << endl; +#endif + //if missing packets, dont send to gui + bindex = (*((uint32_t*)(((char*)origVal)+packetOffset))); + if (bindex == 0xFFFFFFFF){ + cout << "Missing Packet,Not sending to gui" << endl; + index = startIndex - 1; + break;//use continue and change index above if you want to display missing packets with 0 value anyway in gui + } + + packetIndex = bindex & MOENCH_PACKET_INDEX_MASK; + //cout<<"packetIndex:"<= 40) && (packetIndex < 0)) + cout << "cannot decode packet index:" << packetIndex << endl; + else{ + + x = packetIndex / 10; + y = packetIndex % 10; +#ifdef VERBOSE + cout<<"x:"<differentClients){ + cout << "Force update" << endl; + ret=FORCE_UPDATE; + } + + // send answer + socket->SendDataOnly(&ret,sizeof(ret)); + if(ret==FAIL){ + cout << "mess:" << mess << endl; + socket->SendDataOnly(mess,sizeof(mess)); + } + else{ + socket->SendDataOnly(fName,MAX_STR_LENGTH); + socket->SendDataOnly(&arg,sizeof(arg)); + socket->SendDataOnly(retval,MOENCH_DATA_BYTES); + } + //return ok/fail + + + delete [] retval; + delete [] origVal; + delete [] raw; + + return ret; + +} + + + + +int slsReceiverTCPIPInterface::gotthard_read_frame(){ + ret=OK; + char fName[MAX_STR_LENGTH]=""; + int arg = -1,i; + + + //retval is a full frame + int bufferSize = GOTTHARD_BUFFER_SIZE; + int rnel = bufferSize/(sizeof(int)); + int* retval = new int[rnel]; + int* origVal = new int[rnel]; + //all initialized to 0 + for(i=0;igetFramesCaught()){ + arg=-1; + cout<<"haven't caught any frame yet"<getStartFrameIndex(); + slsReceiverFunctions->readFrame(fName,&raw); + + /**send garbage with -1 index to try again*/ + if (raw == NULL){ + arg = -1; +#ifdef VERBOSE + cout<<"data not ready for gui yet"<> GOTTHARD_SHORT_FRAME_INDEX_OFFSET); +#ifdef VERBOSE + cout << "index:" << hex << index << endl; +#endif + }else{ + bindex = ((uint32_t)(*((uint32_t*)raw)))+1; + pindex = (bindex & GOTTHARD_PACKET_INDEX_MASK); + index = ((bindex & GOTTHARD_FRAME_INDEX_MASK) >> GOTTHARD_FRAME_INDEX_OFFSET); + bindex2 = ((uint32_t)(*((uint32_t*)((char*)(raw+onebuffersize)))))+1; + pindex2 =(bindex2 & GOTTHARD_PACKET_INDEX_MASK); + index2 =((bindex2 & GOTTHARD_FRAME_INDEX_MASK) >> GOTTHARD_FRAME_INDEX_OFFSET); +#ifdef VERBOSE + cout << "index1:" << hex << index << endl; + cout << "index2:" << hex << index << endl; +#endif + } + + memcpy(origVal,raw,bufferSize); + raw=NULL; + + + //1 adc + if(shortFrame!=-1){ + if(bindex != 0xFFFFFFFF) + memcpy((((char*)retval)+(GOTTHARD_SHORT_DATABYTES*shortFrame)),((char*) origVal)+4, GOTTHARD_SHORT_DATABYTES); + else{ + index = startIndex - 1; + cout << "Missing Packet,Not sending to gui" << endl; + } + } + //all adc + else{ + //ignore if half frame is missing + if ((bindex != 0xFFFFFFFF) && (bindex2 != 0xFFFFFFFF)){ + + //should be same frame + if (index == index2){ + //ideal situation (should be odd, even(index+1)) + if(!pindex){ + memcpy(retval,((char*) origVal)+4, onedatasize); + memcpy((((char*)retval)+onedatasize), ((char*) origVal)+10+onedatasize, onedatasize); + } + //swap to even,odd + else{ + memcpy((((char*)retval)+onedatasize),((char*) origVal)+4, onedatasize); + memcpy(retval, ((char*) origVal)+10+onedatasize, onedatasize); + index=index2; + } + }else + cout << "different frames caught. frame1:"<< hex << index << ":"<differentClients){ + cout << "Force update" << endl; + ret=FORCE_UPDATE; + } + + // send answer + socket->SendDataOnly(&ret,sizeof(ret)); + if(ret==FAIL){ + cout << "mess:" << mess << endl; + socket->SendDataOnly(mess,sizeof(mess)); + } + else{ + socket->SendDataOnly(fName,MAX_STR_LENGTH); + socket->SendDataOnly(&arg,sizeof(arg)); + socket->SendDataOnly(retval,GOTTHARD_DATA_BYTES); + } + + delete [] retval; + delete [] origVal; + delete [] raw; + + return ret; +} + + + + +int slsReceiverTCPIPInterface::set_read_frequency(){ + ret=OK; + int retval=-1; + int index; + strcpy(mess,"Could not set receiver read frequency\n"); + + + // receive arguments + if(socket->ReceiveDataOnly(&index,sizeof(index)) < 0 ){ + strcpy(mess,"Error reading from socket\n"); + ret = FAIL; + } + + // execute action if the arguments correctly arrived +#ifdef SLS_RECEIVER_UDP_FUNCTIONS + if (ret==OK) { + if (lockStatus==1 && socket->differentClients==1){ + sprintf(mess,"Receiver locked by %s\n", socket->lastClientIP); + ret=FAIL; + }/* + else if((slsReceiverFunctions->getStatus()==RUNNING) && (index >= 0)){ + ret = FAIL; + strcpy(mess,"cannot set up receiver mode when receiver is running\n"); + }*/ + else + retval=slsReceiverFunctions->setNFrameToGui(index); + } + +#endif + + if(ret==OK && socket->differentClients){ + cout << "Force update" << endl; + ret=FORCE_UPDATE; + } + + // send answer + socket->SendDataOnly(&ret,sizeof(ret)); + if(ret==FAIL) + socket->SendDataOnly(mess,sizeof(mess)); + socket->SendDataOnly(&retval,sizeof(retval)); + + //return ok/fail + return ret; +} + + + + + + +int slsReceiverTCPIPInterface::enable_file_write(){ + ret=OK; + int retval=-1; + int enable; + strcpy(mess,"Could not set/get enable file write\n"); + + + // receive arguments + if(socket->ReceiveDataOnly(&enable,sizeof(enable)) < 0 ){ + strcpy(mess,"Error reading from socket\n"); + ret = FAIL; + } + + // execute action if the arguments correctly arrived +#ifdef SLS_RECEIVER_UDP_FUNCTIONS + if (ret==OK) { + if (lockStatus==1 && socket->differentClients==1){ + sprintf(mess,"Receiver locked by %s\n", socket->lastClientIP); + ret=FAIL; + } + else{ + retval=slsReceiverFunctions->setEnableFileWrite(enable); + if((enable!=-1)&&(enable!=retval)) + ret=FAIL; + } + } +#endif + + if(ret==OK && socket->differentClients){ + cout << "Force update" << endl; + ret=FORCE_UPDATE; + } + + // send answer + socket->SendDataOnly(&ret,sizeof(ret)); + if(ret==FAIL) + socket->SendDataOnly(mess,sizeof(mess)); + socket->SendDataOnly(&retval,sizeof(retval)); + + //return ok/fail + return ret; +} + + + +int slsReceiverTCPIPInterface::get_id(){ + ret=OK; + int64_t retval=-1; + + // execute action if the arguments correctly arrived +#ifdef SLS_RECEIVER_UDP_FUNCTIONS + retval = get_version(); +#endif + + if(socket->differentClients){ + cout << "Force update" << endl; + ret=FORCE_UPDATE; + } + + // send answer + socket->SendDataOnly(&ret,sizeof(ret)); + socket->SendDataOnly(&retval,sizeof(retval)); + + //return ok/fail + return ret; +} + + + +int64_t slsReceiverTCPIPInterface::get_version(){ + int64_t retval = SVNREV; + retval= (retval <<32) | SVNDATE; + return retval; +} + + + + +int slsReceiverTCPIPInterface::start_readout(){ + ret=OK; + enum runStatus retval; + + // execute action if the arguments correctly arrived +#ifdef SLS_RECEIVER_UDP_FUNCTIONS + slsReceiverFunctions->startReadout(); + retval = slsReceiverFunctions->getStatus(); + if((retval == TRANSMITTING) || (retval == RUN_FINISHED) || (retval == IDLE)) + ret = OK; + else + ret = FAIL; +#endif + + if(socket->differentClients){ + cout << "Force update" << endl; + ret=FORCE_UPDATE; + } + + // send answer + socket->SendDataOnly(&ret,sizeof(ret)); + socket->SendDataOnly(&retval,sizeof(retval)); + //return ok/fail + return ret; + + +} + + + + +int slsReceiverTCPIPInterface::set_timer() { + ret=OK; + int64_t retval = -1; + int64_t index[2]; + index[1] = -1; + strcpy(mess,"Could not set acquisition period or frame number in receiver\n"); + + + // receive arguments + if(socket->ReceiveDataOnly(index,sizeof(index)) < 0 ){ + strcpy(mess,"Error reading from socket\n"); + ret = FAIL; + } + + // execute action if the arguments correctly arrived +#ifdef SLS_RECEIVER_UDP_FUNCTIONS + if (ret==OK) { + if (lockStatus==1 && socket->differentClients==1){ + sprintf(mess,"Receiver locked by %s\n", socket->lastClientIP); + ret=FAIL; + } + else{ + if(index[0] == slsReceiverDefs::FRAME_PERIOD) + retval=slsReceiverFunctions->setAcquisitionPeriod(index[1]); + else + retval=slsReceiverFunctions->setNumberOfFrames(index[1]); + } + } +#ifdef VERBOSE + if(ret!=FAIL){ + if(index[0] == slsReceiverDefs::FRAME_PERIOD) + cout << "acquisition period:" << retval << endl; + else + cout << "frame number:" << retval << endl; + }else + cout << mess << endl; +#endif +#endif + + if(ret==OK && socket->differentClients){ + cout << "Force update" << endl; + ret=FORCE_UPDATE; + } + + // send answer + socket->SendDataOnly(&ret,sizeof(ret)); + if(ret==FAIL) + socket->SendDataOnly(mess,sizeof(mess)); + socket->SendDataOnly(&retval,sizeof(retval)); + + //return ok/fail + return ret; +} + + + + + + +int slsReceiverTCPIPInterface::enable_compression() { + ret=OK; + int enable=-1; + int retval=-100; + strcpy(mess,"Could not enable/disable compression for receiver\n"); + + // receive arguments + if(socket->ReceiveDataOnly(&enable,sizeof(enable)) < 0 ){ + strcpy(mess,"Error reading from socket\n"); + ret = FAIL; + } + + + // execute action if the arguments correctly arrived +#ifdef SLS_RECEIVER_UDP_FUNCTIONS + if (ret==OK) { + if(enable >= 0){ + if (lockStatus==1 && socket->differentClients==1){ + sprintf(mess,"Receiver locked by %s\n", socket->lastClientIP); + ret=FAIL; + } + else if(slsReceiverFunctions->getStatus()==RUNNING){ + strcpy(mess,"Cannot enable/disable compression while status is running\n"); + ret=FAIL; + } + else + ret = slsReceiverFunctions->enableDataCompression(enable); + } + + retval=slsReceiverFunctions->getDataCompression(); + } +#endif + + if(ret==OK && socket->differentClients){ + cout << "Force update" << endl; + ret=FORCE_UPDATE; + } + + // send answer + socket->SendDataOnly(&ret,sizeof(ret)); + if(ret==FAIL) + socket->SendDataOnly(mess,sizeof(mess)); + socket->SendDataOnly(&retval,sizeof(retval)); + + //return ok/fail + return ret; +} + + + + +int slsReceiverTCPIPInterface::set_detector_hostname() { + ret=OK; + char retval[MAX_STR_LENGTH]=""; + char hostname[MAX_STR_LENGTH]=""; + strcpy(mess,"Could not set detector hostname"); + + // receive arguments + if(socket->ReceiveDataOnly(hostname,MAX_STR_LENGTH) < 0 ){ + strcpy(mess,"Error reading from socket\n"); + ret = FAIL; + } + + // execute action if the arguments correctly arrived +#ifdef SLS_RECEIVER_UDP_FUNCTIONS + if (ret==OK) { + + if (lockStatus==1 && socket->differentClients==1){ + sprintf(mess,"Receiver locked by %s\n", socket->lastClientIP); + ret=FAIL; + } + else + strcpy(retval,slsReceiverFunctions->setDetectorHostname(hostname)); + } +#ifdef VERBOSE + if(ret!=FAIL) + cout << "hostname:" << retval << endl; + else + cout << mess << endl; +#endif +#endif + + if(ret==OK && socket->differentClients){ + cout << "Force update" << endl; + ret=FORCE_UPDATE; + } + + // send answer + socket->SendDataOnly(&ret,sizeof(ret)); + if(ret==FAIL) + socket->SendDataOnly(mess,sizeof(mess)); + socket->SendDataOnly(retval,MAX_STR_LENGTH); + + //return ok/fail + return ret; +} + + + + + + + +int slsReceiverTCPIPInterface::set_dynamic_range() { + ret=OK; + int retval=-1; + int dr; + strcpy(mess,"Could not set dynamic range\n"); + + + // receive arguments + if(socket->ReceiveDataOnly(&dr,sizeof(dr)) < 0 ){ + strcpy(mess,"Error reading from socket\n"); + ret = FAIL; + } + + // execute action if the arguments correctly arrived +#ifdef SLS_RECEIVER_UDP_FUNCTIONS + if (ret==OK) { + if (lockStatus==1 && socket->differentClients==1){ + sprintf(mess,"Receiver locked by %s\n", socket->lastClientIP); + ret=FAIL; + } + else + retval=slsReceiverFunctions->setDynamicRange(dr); + } +#ifdef VERBOSE + if(ret!=FAIL) + cout << "dynamic range" << dr << endl; + else + cout << mess << endl; +#endif +#endif + + if(ret==OK && socket->differentClients){ + cout << "Force update" << endl; + ret=FORCE_UPDATE; + } + + // send answer + socket->SendDataOnly(&ret,sizeof(ret)); + if(ret==FAIL) + socket->SendDataOnly(mess,sizeof(mess)); + socket->SendDataOnly(&retval,sizeof(retval)); + + //return ok/fail + return ret; +} + + + + + + + +int slsReceiverTCPIPInterface::enable_overwrite() { + ret=OK; + int retval=-1; + int index; + strcpy(mess,"Could not enable/disable overwrite\n"); + + + // receive arguments + if(socket->ReceiveDataOnly(&index,sizeof(index)) < 0 ){ + strcpy(mess,"Error reading from socket\n"); + ret = FAIL; + } + + // execute action if the arguments correctly arrived +#ifdef SLS_RECEIVER_UDP_FUNCTIONS + if (ret==OK) { + if (lockStatus==1 && socket->differentClients==1){ + sprintf(mess,"Receiver locked by %s\n", socket->lastClientIP); + ret=FAIL; + } + else + retval=slsReceiverFunctions->enableOverwrite(index); + } +#ifdef VERBOSE + if(ret!=FAIL) + cout << "overwrite:" << retval << endl; + else + cout << mess << endl; +#endif +#endif + + if(ret==OK && socket->differentClients){ + cout << "Force update" << endl; + ret=FORCE_UPDATE; + } + + // send answer + socket->SendDataOnly(&ret,sizeof(ret)); + if(ret==FAIL) + socket->SendDataOnly(mess,sizeof(mess)); + socket->SendDataOnly(&retval,sizeof(retval)); + + //return ok/fail + return ret; +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +int slsReceiverTCPIPInterface::lock_receiver() { + ret=OK; + int lock; + + // receive arguments + if(socket->ReceiveDataOnly(&lock,sizeof(lock)) < 0 ){ + sprintf(mess,"Error reading from socket\n"); + cout << "Error reading from socket (lock)" << endl; + ret=FAIL; + } + // execute action if the arguments correctly arrived + if(ret==OK){ + if (lock>=0) { + if (lockStatus==0 || strcmp(socket->lastClientIP,socket->thisClientIP)==0 || strcmp(socket->lastClientIP,"none")==0) { + lockStatus=lock; + strcpy(socket->lastClientIP,socket->thisClientIP); + } else { + ret=FAIL; + sprintf(mess,"Receiver already locked by %s\n", socket->lastClientIP); + } + } + } + + if (socket->differentClients && ret==OK) + ret=FORCE_UPDATE; + + // send answer + socket->SendDataOnly(&ret,sizeof(ret)); + if (ret==FAIL) + socket->SendDataOnly(mess,sizeof(mess)); + else + socket->SendDataOnly(&lockStatus,sizeof(lockStatus)); + + //return ok/fail + return ret; +} + + + + + + + +int slsReceiverTCPIPInterface::set_port() { + ret=OK; + MySocketTCP* mySocket=NULL; + int sd=-1; + enum runStatus p_type; /* just to get the input */ + int p_number; + + // receive arguments + if(socket->ReceiveDataOnly(&p_type,sizeof(p_type)) < 0 ){ + strcpy(mess,"Error reading from socket\n"); + cout << mess << endl; + ret=FAIL; + } + + if(socket->ReceiveDataOnly(&p_number,sizeof(p_number)) < 0 ){ + strcpy(mess,"Error reading from socket\n"); + cout << mess << endl; + ret=FAIL; + } + + // execute action if the arguments correctly arrived + if (ret==OK) { + if (socket->differentClients==1 && lockStatus==1 ) { + ret=FAIL; + sprintf(mess,"Detector locked by %s\n",socket->lastClientIP); + } + else { + if (p_number<1024) { + sprintf(mess,"Too low port number %d\n", p_number); + cout << mess << endl; + ret=FAIL; + } + cout << "set port " << p_type << " to " << p_number <getErrorStatus(); + if (!sd){ + ret=OK; + if (mySocket->differentClients) + ret=FORCE_UPDATE; + } else { + ret=FAIL; + sprintf(mess,"Could not bind port %d\n", p_number); + cout << mess << endl; + if (sd==-10) { + sprintf(mess,"Port %d already set\n", p_number); + cout << mess << endl; + } + } + } + } + + // send answer + socket->SendDataOnly(&ret,sizeof(ret)); + if (ret==FAIL) { + socket->SendDataOnly(mess,sizeof(mess)); + } else { + socket->SendDataOnly(&p_number,sizeof(p_number)); + if(sd>=0){ + socket->Disconnect(); + delete socket; + socket = mySocket; + file_des=socket->getFileDes(); + } + } + + //return ok/fail + return ret; +} + + + + + + +int slsReceiverTCPIPInterface::get_last_client_ip() { + ret=OK; + + if (socket->differentClients ) + ret=FORCE_UPDATE; + + socket->SendDataOnly(&ret,sizeof(ret)); + socket->SendDataOnly(socket->lastClientIP,sizeof(socket->lastClientIP)); + + return ret; +} + + + + + + + +int slsReceiverTCPIPInterface::send_update() { + ret=OK; + int ind; + char path[MAX_STR_LENGTH]; + + socket->SendDataOnly(socket->lastClientIP,sizeof(socket->lastClientIP)); + + //index +#ifdef SLS_RECEIVER_UDP_FUNCTIONS + + /*if(myDetectorType != EIGER)*/ + ind=slsReceiverFunctions->getFileIndex(); + + socket->SendDataOnly(&ind,sizeof(ind)); +#endif + + //filepath +#ifdef SLS_RECEIVER_UDP_FUNCTIONS + strcpy(path,slsReceiverFunctions->getFilePath()); +#endif + socket->SendDataOnly(path,MAX_STR_LENGTH); + + + //filename +#ifdef SLS_RECEIVER_UDP_FUNCTIONS + strcpy(path,slsReceiverFunctions->getFileName()); +#endif + socket->SendDataOnly(path,MAX_STR_LENGTH); + + + if (lockStatus==0) { + strcpy(socket->lastClientIP,socket->thisClientIP); + } + + return ret; + + +} + + + + + + +int slsReceiverTCPIPInterface::update_client() { + ret=OK; + socket->SendDataOnly(&ret,sizeof(ret)); + + return send_update(); +} + + + + + + + +int slsReceiverTCPIPInterface::exit_server() { + ret=GOODBYE; + socket->SendDataOnly(&ret,sizeof(ret)); + strcpy(mess,"closing server"); + socket->SendDataOnly(mess,sizeof(mess)); + cout << mess << endl; + return ret; +} + + + + + +int slsReceiverTCPIPInterface::exec_command() { + ret = OK; + char cmd[MAX_STR_LENGTH]; + char answer[MAX_STR_LENGTH]; + int sysret=0; + + // receive arguments + if(socket->ReceiveDataOnly(cmd,MAX_STR_LENGTH) < 0 ){ + sprintf(mess,"Error reading from socket\n"); + ret=FAIL; + } + + // execute action if the arguments correctly arrived + if (ret==OK) { +#ifdef VERBOSE + cout << "executing command " << cmd << endl; +#endif + if (lockStatus==0 || socket->differentClients==0) + sysret=system(cmd); + + //should be replaced by popen + if (sysret==0) { + strcpy(answer,"Succeeded\n"); + if (lockStatus==1 && socket->differentClients==1) + sprintf(answer,"Detector locked by %s\n", socket->lastClientIP); + } else { + strcpy(answer,"Failed\n"); + ret=FAIL; + } + } else + strcpy(answer,"Could not receive the command\n"); + + + // send answer + socket->SendDataOnly(&ret,sizeof(ret)); + if(socket->SendDataOnly(answer,MAX_STR_LENGTH) < 0){ + strcpy(mess,"Error writing to socket"); + ret=FAIL; + } + + //return ok/fail + return ret; +} + + + + + diff --git a/slsReceiverSoftware/slsReceiver/slsReceiverTCPIPInterface.h b/slsReceiverSoftware/slsReceiver/slsReceiverTCPIPInterface.h new file mode 100644 index 000000000..b0cd6e780 --- /dev/null +++ b/slsReceiverSoftware/slsReceiver/slsReceiverTCPIPInterface.h @@ -0,0 +1,238 @@ + /********************************************//** + * @file slsReceiverTCPIPInterface.h + * @short interface between receiver and client + ***********************************************/ +#ifndef SLS_RECEIVER_TCP_IP_INTERFACE_H +#define SLS_RECEIVER_TCP_IP_INTERFACE_H + + +#include "sls_receiver_defs.h" +#include "receiver_defs.h" +#include "MySocketTCP.h" +#include "slsReceiverUDPFunctions.h" + + + +/** + *@short interface between receiver and client + */ + +class slsReceiverTCPIPInterface : private virtual slsReceiverDefs { + +public: + /** + * Constructor + * reads config file, creates socket, assigns function table + * @param argc from command line + * @param argv from command line + * @param succecc socket creation was successfull + */ + slsReceiverTCPIPInterface(int argc, char *argv[], int &success); + + + /** starts listening on the TCP port for client comminication */ + + void start(); + + /** Destructor */ + virtual ~slsReceiverTCPIPInterface(); + + /** Close all threaded Files and exit */ + void closeFile(int p); + + /** Static function to call closeFile */ + static void staticCloseFile(int p); + + /** gets version */ + int64_t get_version(); + + /** + callback arguments are + filepath + filename + fileindex + data size + + return value is + 0 callback takes care of open,close,wrie file + 1 callback writes file, we have to open, close it + 2 we open, close, write file, callback does not do anything + + */ + + void registerCallBackStartAcquisition(int (*func)(char*, char*,int, int, void*),void *arg){slsReceiverFunctions->registerCallBackStartAcquisition(func,arg);};; + + + /** + callback argument is + toatal farmes caught + + */ + + + void registerCallBackAcquisitionFinished(void (*func)(int, void*),void *arg){slsReceiverFunctions->registerCallBackAcquisitionFinished(func,arg);}; + + + + /** + args to raw data ready callback are + framenum + datapointer + datasize in bytes + file descriptor + guidatapointer (NULL, no data required) + */ + + void registerCallBackRawDataReady(void (*func)(int, char*, int, FILE*, char*, void*),void *arg){slsReceiverFunctions->registerCallBackRawDataReady(func,arg);}; + + + private: + /** assigns functions to the fnum enum */ + int function_table(); + + /** Decodes Function */ + int decode_function(); + + /** Unrecognized Function */ + int M_nofunc(); + + /** Set detector type */ + int set_detector_type(); + + /** Set File name without frame index, file index and extension */ + int set_file_name(); + + /** Set File path */ + int set_file_dir(); + + /** Set up UDP Details */ + int setup_udp(); + + /** Set File index */ + int set_file_index(); + + /** Set Frame index */ + int set_frame_index(); + + /** Start Receiver - starts listening to udp packets from detector */ + int start_receiver(); + + /** Stop Receiver - stops listening to udp packets from detector*/ + int stop_receiver(); + + /** Gets receiver status */ + int get_status(); + + /** Gets Total Frames Caught */ + int get_frames_caught(); + + /** Gets frame index for each acquisition */ + int get_frame_index(); + + /** Resets Total Frames Caught */ + int reset_frames_caught(); + + /** set short frame */ + int set_short_frame(); + + /** Reads Frame/ buffer */ + int read_frame(); + + /** gotthard specific read frame */ + int gotthard_read_frame(); + + /** moench specific read frame */ + int moench_read_frame(); + + /** Sets the receiver to send every nth frame to gui, or only upon gui request */ + int set_read_frequency(); + + /** Enable File Write*/ + int enable_file_write(); + + /** get version, calls get_version */ + int get_id(); + + /** set status to transmitting and + * when fifo is empty later, sets status to run_finished */ + int start_readout(); + + /** set acquisition period, frame number etc */ + int set_timer(); + + /** enable compression */ + int enable_compression(); + + /** set detector hostname */ + int set_detector_hostname(); + + /** set dynamic range */ + int set_dynamic_range(); + + /** enable overwrite */ + int enable_overwrite(); + + + //General Functions + /** Locks Receiver */ + int lock_receiver(); + + /** Set port */ + int set_port(); + + /** Get Last Client IP*/ + int get_last_client_ip(); + + /** Updates Client if different clients connect */ + int update_client(); + + /** Sends the updated parameters to client */ + int send_update(); + + /** Exit Receiver Server */ + int exit_server(); + + /** Execute command */ + int exec_command(); + + + + //private: + /** detector type */ + detectorType myDetectorType; + + /** slsReceiverUDPFunctions object */ + slsReceiverUDPFunctions *slsReceiverFunctions; + + /** Number of functions */ + static const int numberOfFunctions = 256; + + /** Function List */ + int (slsReceiverTCPIPInterface::*flist[numberOfFunctions])(); + + /** Message */ + char mess[MAX_STR_LENGTH]; + + /** success/failure */ + int ret; + + /** Lock Status if server locked to a client */ + int lockStatus; + + /** Short frame */ + int shortFrame; + + /** Packets per frame */ + int packetsPerFrame; + + static int file_des; + static int socketDescriptor; + +//private: + protected: + /** Socket */ + MySocketTCP* socket; +}; + + +#endif diff --git a/slsReceiverSoftware/slsReceiver/slsReceiverUDPFunctions.cpp b/slsReceiverSoftware/slsReceiver/slsReceiverUDPFunctions.cpp new file mode 100644 index 000000000..0b710f199 --- /dev/null +++ b/slsReceiverSoftware/slsReceiver/slsReceiverUDPFunctions.cpp @@ -0,0 +1,1968 @@ +#ifdef SLS_RECEIVER_UDP_FUNCTIONS +/********************************************//** + * @file slsReceiverUDPFunctions.cpp + * @short does all the functions for a receiver, set/get parameters, start/stop etc. + ***********************************************/ + + +#include "slsReceiverUDPFunctions.h" + +#include "moench02ModuleData.h" +#include "gotthardModuleData.h" +#include "gotthardShortModuleData.h" + + +#include // SIGINT +#include // stat +#include // socket(), bind(), listen(), accept(), shut down +#include // sock_addr_in, htonl, INADDR_ANY +#include // exit() +#include //set precision +#include //munmap + + + +#include +#include +using namespace std; + + + + +slsReceiverUDPFunctions::slsReceiverUDPFunctions(): + receiver(NULL), + server_port(DEFAULT_UDP_PORTNO), + thread_started(0), + udpSocket(NULL), + eth(NULL), + latestData(NULL), + guiFileName(NULL), + mem0(NULL), + fifo(NULL), + fifoFree(NULL){ + + for(int i=0;i /proc/sys/net/core/rmem_max")) + cout << "\nWARNING: Could not change socket receiver buffer size in file /proc/sys/net/core/rmem_max" << endl; + else if(system("echo 250000 > /proc/sys/net/core/netdev_max_backlog")) + cout << "\nWARNING: Could not change max length of input queue in file /proc/sys/net/core/netdev_max_backlog" << endl; + /** permanent setting heiner + net.core.rmem_max = 104857600 # 100MiB + net.core.netdev_max_backlog = 250000 + sysctl -p + // from the manual + sysctl -w net.core.rmem_max=16777216 + sysctl -w net.core.netdev_max_backlog=250000 + */ +} + + + +slsReceiverUDPFunctions::~slsReceiverUDPFunctions(){ + createListeningThreads(true); + createWriterThreads(true); + deleteMembers(); +} + + + + +void slsReceiverUDPFunctions::deleteMembers(){ + //kill threads + if(thread_started){ + createListeningThreads(true); + createWriterThreads(true); + } + + for(int i=0;isetFileName(fileName); + } + + onePacketSize = bufferSize/packetsPerFrame; + latestData = new char[bufferSize]; + + + setupFifoStructure(); + + if(createListeningThreads() == FAIL){ + cout << "ERROR: Could not create listening thread" << endl; + exit (-1); + } + + if(createWriterThreads() == FAIL){ + cout << "ERROR: Could not create writer threads" << endl; + exit (-1); + } + + setThreadPriorities(); + + cout << "Ready..." << endl; + + return OK; +} + + + + + +/*Frame indices and numbers caught*/ + +bool slsReceiverUDPFunctions::getAcquistionStarted(){return acqStarted;}; + +bool slsReceiverUDPFunctions::getMeasurementStarted(){return measurementStarted;}; + +int slsReceiverUDPFunctions::getFramesCaught(){return (packetsCaught/packetsPerFrame);} + +int slsReceiverUDPFunctions::getTotalFramesCaught(){return (totalPacketsCaught/packetsPerFrame);} + +uint32_t slsReceiverUDPFunctions::getStartFrameIndex(){return startFrameIndex;} + +uint32_t slsReceiverUDPFunctions::getFrameIndex(){ + if(!packetsCaught) + frameIndex=0; + else + frameIndex = currframenum - startFrameIndex; + return frameIndex; +} + +uint32_t slsReceiverUDPFunctions::getAcquisitionIndex(){ + if(!totalPacketsCaught) + acquisitionIndex=0; + else + acquisitionIndex = currframenum - startAcquisitionIndex; + return acquisitionIndex; +} + + +void slsReceiverUDPFunctions::resetTotalFramesCaught(){ + acqStarted = false; + startAcquisitionIndex = 0; + totalPacketsCaught = 0; +} + + + + + + + + + +/*file parameters*/ + +char* slsReceiverUDPFunctions::getFilePath(){ + if(myDetectorType == EIGER) + return receiver->getFilePath(); + else + return filePath; +} + +char* slsReceiverUDPFunctions::setFilePath(char c[]){ + if(strlen(c)){ + //check if filepath exists + struct stat st; + if(stat(c,&st) == 0){ + if(myDetectorType == EIGER) + receiver->setFilePath(c); + else + strcpy(filePath,c); + }else{ + strcpy(filePath,""); + cout << "FilePath does not exist:" << filePath << endl; + } + } + return getFilePath(); +} + + +char* slsReceiverUDPFunctions::getFileName(){ + if(myDetectorType == EIGER) + return receiver->getFileName(); + else + return fileName; +} + +char* slsReceiverUDPFunctions::setFileName(char c[]){ + if(strlen(c)){ + if(myDetectorType == EIGER) + receiver->setFileName(c); + else + strcpy(fileName,c); + + } + return getFileName(); + +} + + +int slsReceiverUDPFunctions::getFileIndex(){ + return fileIndex; +} + +int slsReceiverUDPFunctions::setFileIndex(int i){ + if(i>=0) + fileIndex = i; + return getFileIndex(); +} + + +int slsReceiverUDPFunctions::setFrameIndexNeeded(int i){ + frameIndexNeeded = i; + return frameIndexNeeded; +} + + +int slsReceiverUDPFunctions::setEnableFileWrite(int i){ + if(i!=-1){ + if(myDetectorType == EIGER) + receiver->setEnableFileWrite(i); + else + enableFileWrite=i; + + } + if(myDetectorType == EIGER) + return receiver->getEnableFileWrite(); + else + return enableFileWrite; + +} + + + +int slsReceiverUDPFunctions::enableOverwrite(int i){ + if(i!=-1){ + if(myDetectorType == EIGER) + receiver->setEnableOverwrite(i); + else + overwrite=i; + + } + if(myDetectorType == EIGER) + return receiver->getEnableOverwrite(); + else + return overwrite; + +} + + + + +/*other parameters*/ + +slsReceiverDefs::runStatus slsReceiverUDPFunctions::getStatus(){ + if(myDetectorType == EIGER) + return receiver->getStatus(); + else + return status; +} + + +char* slsReceiverUDPFunctions::setDetectorHostname(char c[]){ + if(strlen(c)){ + if(myDetectorType == EIGER){ + if(receiver->getDetectorHostname()== NULL) + receiver->initialize(c); + }else + strcpy(detHostname,c); + } + + if(myDetectorType == EIGER) + return receiver->getDetectorHostname(); + else + return detHostname; +} + + +void slsReceiverUDPFunctions::setEthernetInterface(char* c){ + strcpy(eth,c); +} + + +void slsReceiverUDPFunctions::setUDPPortNo(int p){ + server_port = p; +} + + +int32_t slsReceiverUDPFunctions::setNumberOfFrames(int32_t fnum){ + if(fnum >= 0){ + if(myDetectorType == EIGER) + receiver->setNumberOfFrames(fnum); + else + numberOfFrames = fnum; + } + + if(myDetectorType == EIGER) + return receiver->getNumberOfFrames(); + else + return numberOfFrames; +} + +int32_t slsReceiverUDPFunctions::setScanTag(int32_t stag){ + if(stag >= 0){ + if(myDetectorType == EIGER) + receiver->setScanTag(stag); + else + scanTag = stag; + } + + if(myDetectorType == EIGER) + return receiver->getScanTag(); + else + return scanTag; +} + +int32_t slsReceiverUDPFunctions::setDynamicRange(int32_t dr){ + if(dr >= 0){ + if(myDetectorType == EIGER) + receiver->setDynamicRange(dr); + else + dynamicRange = dr; + } + + if(myDetectorType == EIGER) + return receiver->getDynamicRange(); + else + return dynamicRange; +} + + + +int slsReceiverUDPFunctions::setShortFrame(int i){ + shortFrame=i; + + if(shortFrame!=-1){ + bufferSize = GOTTHARD_SHORT_BUFFER_SIZE; + maxPacketsPerFile = SHORT_MAX_FRAMES_PER_FILE * GOTTHARD_SHORT_PACKETS_PER_FRAME; + packetsPerFrame = GOTTHARD_SHORT_PACKETS_PER_FRAME; + frameIndexMask = GOTTHARD_SHORT_FRAME_INDEX_MASK; + frameIndexOffset = GOTTHARD_SHORT_FRAME_INDEX_OFFSET; + + }else{ + bufferSize = GOTTHARD_BUFFER_SIZE; + maxPacketsPerFile = MAX_FRAMES_PER_FILE * GOTTHARD_PACKETS_PER_FRAME; + packetsPerFrame = GOTTHARD_PACKETS_PER_FRAME; + frameIndexMask = GOTTHARD_FRAME_INDEX_MASK; + frameIndexOffset = GOTTHARD_FRAME_INDEX_OFFSET; + } + + onePacketSize = bufferSize/packetsPerFrame; + + deleteFilter(); + if(dataCompression) + setupFilter(); + + return shortFrame; +} + + +int slsReceiverUDPFunctions::setNFrameToGui(int i){ + if(i>=0){ + nFrameToGui = i; + setupFifoStructure(); + } + return nFrameToGui; +} + + + +int64_t slsReceiverUDPFunctions::setAcquisitionPeriod(int64_t index){ + + if(index >= 0){ + if(index != acquisitionPeriod){ + acquisitionPeriod = index; + if(myDetectorType != EIGER) + setupFifoStructure(); + } + } + return acquisitionPeriod; +} + + +bool slsReceiverUDPFunctions::getDataCompression(){return dataCompression;} + +int slsReceiverUDPFunctions::enableDataCompression(bool enable){ + cout << "Data compression "; + if(enable) + cout << "enabled" << endl; + else + cout << "disabled" << endl; +#ifdef MYROOT1 + cout << " WITH ROOT" << endl; +#else + cout << " WITHOUT ROOT" << endl; +#endif + //delete filter for the current number of threads + deleteFilter(); + + dataCompression = enable; + pthread_mutex_lock(&status_mutex); + writerthreads_mask = 0x0; + pthread_mutex_unlock(&(status_mutex)); + + createWriterThreads(true); + + if(enable) + numWriterThreads = MAX_NUM_WRITER_THREADS; + else + numWriterThreads = 1; + + if(createWriterThreads() == FAIL){ + cout << "ERROR: Could not create writer threads" << endl; + return FAIL; + } + setThreadPriorities(); + + + if(enable) + setupFilter(); + + return OK; +} + + + + + + + + + + + + +/*other functions*/ + + +void slsReceiverUDPFunctions::deleteFilter(){ + int i; + cmSub=NULL; + + for(i=0;i(receiverdata[i], csize, sigma, sign, cmSub); + +} + + + + +void slsReceiverUDPFunctions::setupFifoStructure(){ + int64_t i; + int oldn = numJobsPerThread; + + //if every nth frame mode + if(nFrameToGui) + numJobsPerThread = nFrameToGui; + + //random nth frame mode + else{ + if(!acquisitionPeriod) + i = SAMPLE_TIME_IN_NS; + else + i = SAMPLE_TIME_IN_NS/acquisitionPeriod; + if (i > MAX_JOBS_PER_THREAD) + numJobsPerThread = MAX_JOBS_PER_THREAD; + else if (i < 1) + numJobsPerThread = 1; + else + numJobsPerThread = i; + } + + //if same, return + if(oldn == numJobsPerThread) + return; + + + //otherwise memory too much if numjobsperthread is at max = 1000 + fifosize = GOTTHARD_FIFO_SIZE; + if(myDetectorType == MOENCH) + fifosize = MOENCH_FIFO_SIZE; + + if(fifosize % numJobsPerThread) + fifosize = (fifosize/numJobsPerThread)+1; + else + fifosize = fifosize/numJobsPerThread; + + + cout << "Number of Frames per buffer:" << numJobsPerThread << endl; + cout << "Fifo Size:" << fifosize << endl; + + /* + //for testing + numJobsPerThread = 3; fifosize = 11; + */ + + //deleting old structure and creating fifo structure + if(fifoFree){ + while(!fifoFree->isEmpty()) + fifoFree->pop(buffer); + delete fifoFree; + } + if(fifo) delete fifo; + if(mem0) free(mem0); + fifoFree = new CircularFifo(fifosize); + fifo = new CircularFifo(fifosize); + + + //allocate memory + mem0=(char*)malloc((bufferSize * numJobsPerThread + HEADER_SIZE_NUM_TOT_PACKETS)*fifosize); + /** shud let the client know about this */ + if (mem0==NULL){ + cout<<"++++++++++++++++++++++ COULD NOT ALLOCATE MEMORY FOR LISTENING !!!!!!!+++++++++++++++++++++" << endl; + exit(-1); + } + buffer=mem0; + //push the addresses into freed fifoFree and writingFifoFree + while (buffer<(mem0+(bufferSize * numJobsPerThread + HEADER_SIZE_NUM_TOT_PACKETS)*(fifosize-1))) { + fifoFree->push(buffer); + buffer+=(bufferSize * numJobsPerThread + HEADER_SIZE_NUM_TOT_PACKETS); + } + + cout << "Fifo structure reconstructed" << endl; +} + + + + + + + +/** acquisition functions */ + +void slsReceiverUDPFunctions::readFrame(char* c,char** raw){ + //point to gui data + if (guiData == NULL) + guiData = latestData; + + //copy data and filename + strcpy(c,guiFileName); + + //could not get gui data + if(!guiDataReady){ + *raw = NULL; + } + //data ready, set guidata to receive new data + else{ + *raw = guiData; + guiData = NULL; + + pthread_mutex_lock(&dataReadyMutex); + guiDataReady = 0; + pthread_mutex_unlock(&dataReadyMutex); + if((nFrameToGui) && (writerthreads_mask)){ + //release after getting data + sem_post(&smp); + } + } +} + + + + + +void slsReceiverUDPFunctions::copyFrameToGui(char* startbuf){ + + //random read when gui not ready + if((!nFrameToGui) && (!guiData)){ + pthread_mutex_lock(&dataReadyMutex); + guiDataReady=0; + pthread_mutex_unlock(&dataReadyMutex); + } + + //random read or nth frame read, gui needs data now + else{ + //nth frame read, block current process if the guireader hasnt read it yet + if(nFrameToGui) + sem_wait(&smp); + + pthread_mutex_lock(&dataReadyMutex); + guiDataReady=0; + //send the first one + memcpy(latestData,startbuf,bufferSize); + strcpy(guiFileName,savefilename); + guiDataReady=1; + pthread_mutex_unlock(&dataReadyMutex); + } +} + + + + + +int slsReceiverUDPFunctions::createUDPSocket(){ + + if(udpSocket) + udpSocket->ShutDownSocket(); + + //if eth is mistaken with ip address + if (strchr(eth,'.')!=NULL) + strcpy(eth,""); + + if(udpSocket){delete udpSocket; udpSocket = NULL;} + + //if no eth, listen to all + if(!strlen(eth)){ + cout<<"warning:eth is empty.listening to all"<getErrorStatus(); + if (iret){ +#ifdef VERBOSE + cout << "Could not create UDP socket on port " << server_port << " error:" << iret << endl; +#endif + + return FAIL; + } + return OK; +} + + + + +int slsReceiverUDPFunctions::createListeningThreads(bool destroy){ + void* status; + + killListeningThread = 0; + + pthread_mutex_lock(&status_mutex); + listening_thread_running = 0; + pthread_mutex_unlock(&(status_mutex)); + + if(!destroy){ + //listening thread + cout << "Creating Listening Thread" << endl; + sem_init(&listensmp,1,0); + if(pthread_create(&listening_thread, NULL,startListeningThread, (void*) this)){ + cout << "Could not create listening thread" << endl; + return FAIL; + } +#ifdef VERBOSE + cout << "Listening thread created successfully." << endl; +#endif + }else{ + cout<<"Destroying Listening Thread"<initEventTree(temp, &iframe); + //resets the pedestalSubtraction array and the commonModeSubtraction + singlePhotonDet[ithr]->newDataSet(); + if(myFile[ithr]==NULL){ + cout<<"file null"<IsOpen()){ + cout<<"file not open"< DO_NOTHING){ + //close + if(sfilefd){ + fclose(sfilefd); + sfilefd = NULL; + } + //open file + if(!overwrite){ + if (NULL == (sfilefd = fopen((const char *) (savefilename), "wx"))){ + cout << "Error: Could not create new file " << savefilename << endl; + return FAIL; + } + }else if (NULL == (sfilefd = fopen((const char *) (savefilename), "w"))){ + cout << "Error: Could not create file " << savefilename << endl; + return FAIL; + } + //setting buffer + setvbuf(sfilefd,NULL,_IOFBF,BUF_SIZE); + + //printing packet losses and file names + if(!packetsCaught) + cout << savefilename << endl; + else{ + cout << savefilename + << "\tpacket loss " + << setw(4)<GetCurrentFile(); + + if(myFile[ithr]->Write()) + //->Write(tall->GetName(),TObject::kOverwrite); + cout << "Thread " << ithr <<": wrote frames to file" << endl; + else + cout << "Thread " << ithr << ": could not write frames to file" << endl; + + }else + cout << "Thread " << ithr << ": could not write frames to file: No file or No Tree" << endl; + //close file + if(myTree[ithr] && myFile[ithr]) + myFile[ithr] = myTree[ithr]->GetCurrentFile(); + if(myFile[ithr] != NULL) + myFile[ithr]->Close(); + myFile[ithr] = NULL; + myTree[ithr] = NULL; + pthread_mutex_unlock(&write_mutex); + +#endif + } +} + + + + + +int slsReceiverUDPFunctions::startReceiver(char message[]){ + + if(myDetectorType == EIGER) + return receiver->startReceiver(message); + + +// #ifdef VERBOSE + cout << "Starting Receiver" << endl; +//#endif + + + //reset listening thread variables + measurementStarted = false; + startFrameIndex = 0; + totalListeningFrameCount = 0; + + //udp socket + if(createUDPSocket() == FAIL){ + strcpy(message,"Could not create UDP Socket.\n"); + cout << endl << message << endl; + return FAIL; + } + cout << "UDP socket created successfully on port " << server_port << endl; + + + if(setupWriter() == FAIL){ + //stop udp socket + if(udpSocket) + udpSocket->ShutDownSocket(); + + sprintf(message,"Could not create file %s.\n",savefilename); + return FAIL; + } + cout << "Successfully created file(s)" << endl; + + //done to give the gui some proper name instead of always the last file name + if(dataCompression) + sprintf(savefilename, "%s/%s_fxxx_%d_xx.root", filePath,fileName,fileIndex); + + //initialize semaphore + sem_init(&smp,1,0); + + //status + pthread_mutex_lock(&status_mutex); + status = RUNNING; + for(int i=0;istopReceiver(); + + +//#ifdef VERBOSE + cout << "Stopping Receiver" << endl; +//#endif + + if(status == RUNNING) + startReadout(); + + while(status == TRANSMITTING) + usleep(5000); + + //semaphore destroy + sem_post(&smp); + sem_destroy(&smp); + + //change status + pthread_mutex_lock(&status_mutex); + status = IDLE; + pthread_mutex_unlock(&(status_mutex)); + + cout << "Receiver Stopped.\nStatus:" << status << endl; + return OK; +} + + + + + +void slsReceiverUDPFunctions::startReadout(){ + + if(myDetectorType == EIGER){ + receiver->stopReceiver(); + return; + } + + + //wait so that all packets which take time has arrived + usleep(50000); + + pthread_mutex_lock(&status_mutex); + status = TRANSMITTING; + pthread_mutex_unlock(&status_mutex); + cout << "Status: Transmitting" << endl; + + //kill udp socket to tell the listening thread to push last packet + if(udpSocket){ + udpSocket->ShutDownSocket(); + delete udpSocket; + udpSocket = NULL; + } + +} + + + +void* slsReceiverUDPFunctions::startListeningThread(void* this_pointer){ + ((slsReceiverUDPFunctions*)this_pointer)->startListening(); + + return this_pointer; +} + + + +void* slsReceiverUDPFunctions::startWritingThread(void* this_pointer){ + ((slsReceiverUDPFunctions*)this_pointer)->startWriting(); + return this_pointer; +} + + + + + + +int slsReceiverUDPFunctions::startListening(){ +#ifdef VERYVERBOSE + cout << "In startListening()" << endl; +#endif + + int lastpacketoffset, expected, rc, packetcount, maxBufferSize, carryonBufferSize; + uint32_t lastframeheader;// for moench to check for all the packets in last frame + char* tempchar = NULL; + + + while(1){ + //variables that need to be checked/set before each acquisition + carryonBufferSize = 0; + maxBufferSize = packetsPerFrame * numJobsPerThread * onePacketSize; + if(tempchar) {delete [] tempchar;tempchar = NULL;} + tempchar = new char[onePacketSize * (packetsPerFrame - 1)]; //gotthard: 1packet size, moench:39 packet size + + + while(listening_thread_running){ + + //pop + fifoFree->pop(buffer); +#ifdef VERYDEBUG + cout << "*** popped from fifo free" << (void*)buffer << endl; +#endif + + //receive + if(udpSocket == NULL) + rc = 0; + else if(!carryonBufferSize){ + rc = udpSocket->ReceiveDataOnly(buffer + HEADER_SIZE_NUM_TOT_PACKETS, maxBufferSize); + expected = maxBufferSize; + }else{ +#ifdef VERYDEBUG + cout << "***carry on buffer" << carryonBufferSize << endl; + cout<<"framennum in temochar:"<<((((uint32_t)(*((uint32_t*)tempchar))) + & (frameIndexMask)) >> frameIndexOffset)<ReceiveDataOnly((buffer + HEADER_SIZE_NUM_TOT_PACKETS + carryonBufferSize),maxBufferSize - carryonBufferSize); + expected = maxBufferSize - carryonBufferSize; + } + +#ifdef VERYDEBUG + cout << "*** rc:" << dec << rc << endl; + cout << "*** expected:" << dec << expected << endl; +#endif + //start indices + //start of scan + if((!measurementStarted) && (rc > 0)){ + //gotthard has +1 for frame number + if ((myDetectorType == GOTTHARD) && (shortFrame == -1)) + startFrameIndex = (((((uint32_t)(*((uint32_t*)(buffer + HEADER_SIZE_NUM_TOT_PACKETS))))+1) + & (frameIndexMask)) >> frameIndexOffset); + else + startFrameIndex = ((((uint32_t)(*((uint32_t*)(buffer+HEADER_SIZE_NUM_TOT_PACKETS)))) + & (frameIndexMask)) >> frameIndexOffset); + cout<<"startFrameIndex:"<push(buffer); + exit(-1); + continue; + } + //push the last buffer into fifo + if(rc > 0){ + packetcount = (rc/onePacketSize); +#ifdef VERYDEBUG + cout << "*** last packetcount:" << packetcount << endl; +#endif + (*((uint16_t*)(buffer))) = packetcount; + totalListeningFrameCount += packetcount; + while(!fifo->push(buffer)); +#ifdef VERYDEBUG + cout << "*** last lbuf1:" << (void*)buffer << endl; +#endif + } + + + //push dummy buffer + for(int i=0;ipop(buffer); + (*((uint16_t*)(buffer))) = 0xFFFF; + while(!fifo->push(buffer)); +#ifdef VERYDEBUG + cout << "pushed in dummy buffer:" << (void*)buffer << endl; +#endif + } + cout << "Total count listened to " << totalListeningFrameCount/packetsPerFrame << endl; + pthread_mutex_lock(&status_mutex); + listening_thread_running = 0; + pthread_mutex_unlock(&(status_mutex)); + break; + } + + + //reset + packetcount = packetsPerFrame * numJobsPerThread; + carryonBufferSize = 0; + + + //check if last packet valid and calculate packet count + switch(myDetectorType){ + + + + case MOENCH: + lastpacketoffset = (((numJobsPerThread * packetsPerFrame - 1) * onePacketSize) + HEADER_SIZE_NUM_TOT_PACKETS); +#ifdef VERYDEBUG + cout <<"first packet:"<< ((((uint32_t)(*((uint32_t*)(buffer+HEADER_SIZE_NUM_TOT_PACKETS))))) & (packetIndexMask)) << endl; + cout <<"first header:"<< (((((uint32_t)(*((uint32_t*)(buffer+HEADER_SIZE_NUM_TOT_PACKETS))))) & (frameIndexMask)) >> frameIndexOffset) << endl; + cout << "last packet offset:" << lastpacketoffset << endl; + cout <<"last packet:"<< ((((uint32_t)(*((uint32_t*)(buffer+lastpacketoffset))))) & (packetIndexMask)) << endl; + cout <<"last header:"<< (((((uint32_t)(*((uint32_t*)(buffer+lastpacketoffset))))) & (frameIndexMask)) >> frameIndexOffset) << endl; +#endif + //moench last packet value is 0 + if( ((((uint32_t)(*((uint32_t*)(buffer+lastpacketoffset))))) & (packetIndexMask))){ + lastframeheader = ((((uint32_t)(*((uint32_t*)(buffer+lastpacketoffset))))) & (frameIndexMask)) >> frameIndexOffset; + carryonBufferSize += onePacketSize; + lastpacketoffset -= onePacketSize; + --packetcount; + while (lastframeheader == (((((uint32_t)(*((uint32_t*)(buffer+lastpacketoffset))))) & (frameIndexMask)) >> frameIndexOffset)){ + carryonBufferSize += onePacketSize; + lastpacketoffset -= onePacketSize; + --packetcount; + } + memcpy(tempchar, buffer+(lastpacketoffset+onePacketSize), carryonBufferSize); +#ifdef VERYDEBUG + cout << "tempchar header:" << (((((uint32_t)(*((uint32_t*)(tempchar))))) + & (frameIndexMask)) >> frameIndexOffset) << endl; + cout <<"tempchar packet:"<< ((((uint32_t)(*((uint32_t*)(tempchar))))) + & (packetIndexMask)) << endl; +#endif + } + break; + + + + default: + if(shortFrame == -1){ + lastpacketoffset = (((numJobsPerThread * packetsPerFrame - 1) * onePacketSize) + HEADER_SIZE_NUM_TOT_PACKETS); +#ifdef VERYDEBUG + cout << "last packet offset:" << lastpacketoffset << endl; +#endif + + if((unsigned int)(packetsPerFrame -1) != ((((uint32_t)(*((uint32_t*)(buffer+lastpacketoffset))))+1) & (packetIndexMask))){ + memcpy(tempchar,buffer+lastpacketoffset, onePacketSize); +#ifdef VERYDEBUG + cout << "tempchar header:" << (((((uint32_t)(*((uint32_t*)(tempchar))))+1) + & (frameIndexMask)) >> frameIndexOffset) << endl; +#endif + carryonBufferSize = onePacketSize; + --packetcount; + } + } +#ifdef VERYDEBUG + cout << "header:" << (((((uint32_t)(*((uint32_t*)(buffer + HEADER_SIZE_NUM_TOT_PACKETS))))+1) + & (frameIndexMask)) >> frameIndexOffset) << endl; +#endif + break; + + + + + } +#ifdef VERYDEBUG + cout << "*** packetcount:" << packetcount << " carryonbuffer:" << carryonBufferSize << endl; +#endif + //write packet count and push + (*((uint16_t*)(buffer))) = packetcount; + totalListeningFrameCount += packetcount; + while(!fifo->push(buffer)); +#ifdef VERYDEBUG + cout << "*** pushed into listening fifo" << endl; +#endif + } + + sem_wait(&listensmp); + + //make sure its not exiting thread + if(killListeningThread) + pthread_exit(NULL); + } + + return OK; +} + + + + + + + + + + + + + + + +int slsReceiverUDPFunctions::startWriting(){ + int ithread = currentWriterThreadIndex; +#ifdef VERYVERBOSE + cout << ithread << "In startWriting()" <pop(wbuf); + numpackets = (uint16_t)(*((uint16_t*)wbuf)); +#ifdef VERYDEBUG + cout << ithread << " numpackets:" << dec << numpackets << endl; + cout << ithread << " *** popped from fifo " << numpackets << endl; +#endif + + + + + + + //last dummy packet + if(numpackets == 0xFFFF){ +#ifdef VERYDEBUG + cout << ithread << " **********************popped last dummy frame:" << (void*)wbuf << endl; +#endif + + //free fifo + while(!fifoFree->push(wbuf)); +#ifdef VERYDEBUG + cout << ithread << " fifo freed:" << (void*)wbuf << endl; +#endif + + + + //all threads need to close file, reset mask and exit loop + closeFile(ithread); + pthread_mutex_lock(&status_mutex); + writerthreads_mask^=(1<> frameIndexOffset); + else + tempframenum = ((((uint32_t)(*((uint32_t*)(wbuf + HEADER_SIZE_NUM_TOT_PACKETS))))& (frameIndexMask)) >> frameIndexOffset); + + if(numWriterThreads == 1) + currframenum = tempframenum; + else{ + pthread_mutex_lock(&progress_mutex); + if(tempframenum > currframenum) + currframenum = tempframenum; + pthread_mutex_unlock(&progress_mutex); + } +#ifdef VERYDEBUG + cout << ithread << " tempframenum:" << dec << tempframenum << " curframenum:" << currframenum << endl; +#endif + + + + + + //without datacompression: write datacall back, or write data, free fifo + if(!dataCompression){ + if (cbAction < DO_EVERYTHING) + rawDataReadyCallBack(currframenum, wbuf, numpackets * onePacketSize, sfilefd, guiData,pRawDataReady); + else if (numpackets > 0){ + writeToFile_withoutCompression(wbuf, numpackets); + } + //copy to gui + copyFrameToGui(wbuf + HEADER_SIZE_NUM_TOT_PACKETS); + + while(!fifoFree->push(wbuf)); +#ifdef VERYVERBOSE + cout<<"buf freed:"<<(void*)wbuf<findNextFrame(data,ndata,remainingsize)){ + np = ndata/onePacketSize; + + //cout<<"buff framnum:"<> frameIndexOffset)<newFrame(); + + //only for moench + if(commonModeSubtractionEnable){ + for(ix = xmin - 1; ix < xmax+1; ix++){ + for(iy = ymin - 1; iy < ymax+1; iy++){ + thisEvent = singlePhotonDet[ithread]->getEventType(buff, ix, iy, 0); + } + } + } + + + for(ix = xmin - 1; ix < xmax+1; ix++) + for(iy = ymin - 1; iy < ymax+1; iy++){ + thisEvent=singlePhotonDet[ithread]->getEventType(buff, ix, iy, commonModeSubtractionEnable); + if (nf>1000) { + tot=0; + tl=0; + tr=0; + bl=0; + br=0; + if (thisEvent==PHOTON_MAX) { + + iFrame=receiverdata[ithread]->getFrameNumber(buff); +#ifdef MYROOT1 + myTree[ithread]->Fill(); + //cout << "Fill in event: frmNr: " << iFrame << " ix " << ix << " iy " << iy << " type " << thisEvent << endl; +#else + pthread_mutex_lock(&write_mutex); + if((enableFileWrite) && (sfilefd)) + singlePhotonDet[ithread]->writeCluster(sfilefd); + pthread_mutex_unlock(&write_mutex); +#endif + } + } + } + + nf++; +#ifndef ALLFILE + pthread_mutex_lock(&progress_mutex); + packetsInFile += packetsPerFrame; + packetsCaught += packetsPerFrame; + totalPacketsCaught += packetsPerFrame; + if(packetsInFile >= maxPacketsPerFile) + createNewFile(); + pthread_mutex_unlock(&progress_mutex); + +#endif + if(!once){ + copyFrameToGui(buff); + once = 1; + } + } + + remainingsize -= ((buff + ndata) - data); + data = buff + ndata; + if(data > (wbuf + HEADER_SIZE_NUM_TOT_PACKETS + numpackets * onePacketSize) ) + cout <<" **************ERROR SHOULD NOT COME HERE, Error 142536!"<push(wbuf)); +#ifdef VERYVERBOSE + cout<<"buf freed:"<<(void*)wbuf< 0){ + + //for progress and packet loss calculation(new files) + if ((myDetectorType == GOTTHARD) && (shortFrame == -1)) + tempframenum = (((((uint32_t)(*((uint32_t*)(buf + HEADER_SIZE_NUM_TOT_PACKETS))))+1)& (frameIndexMask)) >> frameIndexOffset); + else + tempframenum = ((((uint32_t)(*((uint32_t*)(buf + HEADER_SIZE_NUM_TOT_PACKETS))))& (frameIndexMask)) >> frameIndexOffset); + + if(numWriterThreads == 1) + currframenum = tempframenum; + else{ + if(tempframenum > currframenum) + currframenum = tempframenum; + } +#ifdef VERYDEBUG + cout << "tempframenum:" << dec << tempframenum << " curframenum:" << currframenum << endl; +#endif + + //lock + if(numWriterThreads > 1) + pthread_mutex_lock(&write_mutex); + + + //to create new file when max reached + packetsToSave = maxPacketsPerFile - packetsInFile; + if(packetsToSave > numpackets) + packetsToSave = numpackets; + + fwrite(buf+offset, 1, packetsToSave * onePacketSize, sfilefd); + packetsInFile += packetsToSave; + packetsCaught += packetsToSave; + totalPacketsCaught += packetsToSave; + + + //new file + if(packetsInFile >= maxPacketsPerFile){ + //for packet loss + lastpacket = (((packetsToSave - 1) * onePacketSize) + offset); + if ((myDetectorType == GOTTHARD) && (shortFrame == -1)) + tempframenum = (((((uint32_t)(*((uint32_t*)(buf + lastpacket))))+1)& (frameIndexMask)) >> frameIndexOffset); + else + tempframenum = ((((uint32_t)(*((uint32_t*)(buf + lastpacket))))& (frameIndexMask)) >> frameIndexOffset); + + if(numWriterThreads == 1) + currframenum = tempframenum; + else{ + if(tempframenum > currframenum) + currframenum = tempframenum; + } +#ifdef VERYDEBUG + cout << "tempframenum:" << dec << tempframenum << " curframenum:" << currframenum << endl; +#endif + //create + createNewFile(); + } + + //unlock + if(numWriterThreads > 1) + pthread_mutex_unlock(&write_mutex); + + + offset += (packetsToSave * onePacketSize); + numpackets -= packetsToSave; + } + + } + else{ + if(numWriterThreads > 1) + pthread_mutex_lock(&write_mutex); + packetsInFile += numpackets; + packetsCaught += numpackets; + totalPacketsCaught += numpackets; + if(numWriterThreads > 1) + pthread_mutex_unlock(&write_mutex); + } + + + +} + + +#endif diff --git a/slsReceiverSoftware/slsReceiver/slsReceiverUDPFunctions.h b/slsReceiverSoftware/slsReceiver/slsReceiverUDPFunctions.h new file mode 100644 index 000000000..c1408a12a --- /dev/null +++ b/slsReceiverSoftware/slsReceiver/slsReceiverUDPFunctions.h @@ -0,0 +1,685 @@ +#ifdef SLS_RECEIVER_UDP_FUNCTIONS +#ifndef SLS_RECEIVER_UDP_FUNCTIONS_H +#define SLS_RECEIVER_UDP_FUNCTIONS_H +/********************************************//** + * @file slsReceiverUDPFunctions.h + * @short does all the functions for a receiver, set/get parameters, start/stop etc. + ***********************************************/ + + +#include "sls_receiver_defs.h" +#include "receiver_defs.h" +#include "genericSocket.h" +#include "circularFifo.h" +#include "singlePhotonDetector.h" +#include "slsReceiverData.h" +#include "moenchCommonMode.h" +#include "eigerReceiver.h" + +#ifdef MYROOT1 +#include +#include +#endif + + +#include +#include +#include +#include + + +/** + * @short does all the functions for a receiver, set/get parameters, start/stop etc. + */ + +class slsReceiverUDPFunctions : private virtual slsReceiverDefs { + +public: + /** + * Constructor + */ + slsReceiverUDPFunctions(); + + /** + * Destructor + */ + virtual ~slsReceiverUDPFunctions(); + + /** + * delete and free member parameters + */ + void deleteMembers(); + + /** + * initialize member parameters + */ + void initializeMembers(); + + /** + * Set receiver type + * @param det detector type + * Returns success or FAIL + */ + int setDetectorType(detectorType det); + + + //Frame indices and numbers caught + /** + * Returns current Frame Index Caught for an entire acquisition (including all scans) + */ + uint32_t getAcquisitionIndex(); + + /** + * Returns if acquisition started + */ + bool getAcquistionStarted(); + + /** + * Returns Frames Caught for each real time acquisition (eg. for each scan) + */ + int getFramesCaught(); + + /** + * Returns Total Frames Caught for an entire acquisition (including all scans) + */ + int getTotalFramesCaught(); + + /** + * Returns the frame index at start of each real time acquisition (eg. for each scan) + */ + uint32_t getStartFrameIndex(); + + /** + * Returns current Frame Index for each real time acquisition (eg. for each scan) + */ + uint32_t getFrameIndex(); + + /** + * Returns if measurement started + */ + bool getMeasurementStarted(); + + /** + * Resets the Total Frames Caught + * This is how the receiver differentiates between entire acquisitions + * Returns 0 + */ + void resetTotalFramesCaught(); + + + + + //file parameters + /** + * Returns File Path + */ + char* getFilePath(); + + /** + * Set File Path + * @param c file path + */ + char* setFilePath(char c[]); + + /** + * Returns File Name + */ + char* getFileName(); + + /** + * Set File Name (without frame index, file index and extension) + * @param c file name + */ + char* setFileName(char c[]); + + /** + * Returns File Index + */ + int getFileIndex(); + + /** + * Set File Index + * @param i file index + */ + int setFileIndex(int i); + + /** + * Set Frame Index Needed + * @param i frame index needed + */ + int setFrameIndexNeeded(int i); + + /** + * Set enable file write + * @param i file write enable + * Returns file write enable + */ + int setEnableFileWrite(int i); + + /** + * Enable/disable overwrite + * @param i enable + * Returns enable over write + */ + int enableOverwrite(int i); + + + +//other parameters + + /** + * Returns status of receiver: idle, running or error + */ + runStatus getStatus(); + + /** + * Set detector hostname + * @param c hostname + */ + char* setDetectorHostname(char c[]); + + /** + * Set Ethernet Interface or IP to listen to + */ + void setEthernetInterface(char* c); + + /** + * Set UDP Port Number + */ + void setUDPPortNo(int p); + + /** + * set frame number if a positive number + */ + int32_t setNumberOfFrames(int32_t fnum); + + /** + * set scan tag if its is a positive number + */ + int32_t setScanTag(int32_t stag); + + /** + * set dynamic range if its is a positive number + */ + int32_t setDynamicRange(int32_t dr); + + /** + * Set short frame + * @param i if shortframe i=1 + */ + int setShortFrame(int i); + + /** + * Set the variable to send every nth frame to gui + * or if 0,send frame only upon gui request + */ + int setNFrameToGui(int i); + + /** set acquisition period if a positive number + */ + int64_t setAcquisitionPeriod(int64_t index); + + /** get data compression, by saving only hits + */ + bool getDataCompression(); + + /** enabl data compression, by saving only hits + /returns if failed + */ + int enableDataCompression(bool enable); + + + + + + +//other functions + + /** + * Returns the buffer-current frame read by receiver + * @param c pointer to current file name + * @param raw address of pointer, pointing to current frame to send to gui + */ + void readFrame(char* c,char** raw); + + /** + * Closes all files + * @param ithr thread index + */ + void closeFile(int ithr = -1); + + /** + * Starts Receiver - starts to listen for packets + * @param message is the error message if there is an error + * Returns success + */ + int startReceiver(char message[]); + + /** + * Stops Receiver - stops listening for packets + * Returns success + */ + int stopReceiver(); + + /** set status to transmitting and + * when fifo is empty later, sets status to run_finished + */ + void startReadout(); + + +private: + /** + * Deletes all the filter objects for single photon data + */ + void deleteFilter(); + + /** + * Constructs the filter for single photon data + */ + void setupFilter(); + + /** + * set up fifo according to the new numjobsperthread + */ + void setupFifoStructure (); + + /** + * Copy frames to gui + * uses semaphore for nth frame mode + */ + void copyFrameToGui(char* startbuf); + + /** + * creates udp socket + * \returns if success or fail + */ + int createUDPSocket(); + + /** + * create listening thread + * @param destroy is true to kill all threads and start again + */ + int createListeningThreads(bool destroy = false); + + /** + * create writer threads + * @param destroy is true to kill all threads and start again + */ + int createWriterThreads(bool destroy = false); + + /** + * set thread priorities + */ + void setThreadPriorities(); + + /** + * initializes variables and creates the first file + * also does the startAcquisitionCallBack + * \returns FAIL or OK + */ + int setupWriter(); + + /** + * Creates new tree and file for compression + * @param ithr thread number + * @param iframe frame number + *\returns OK for succces or FAIL for failure + */ + int createCompressionFile(int ithr, int iframe); + + /** + * Creates new file + *\returns OK for succces or FAIL for failure + */ + int createNewFile(); + + /** + * Static function - Thread started which listens to packets. + * Called by startReceiver() + * @param this_pointer pointer to this object + */ + static void* startListeningThread(void *this_pointer); + + /** + * Static function - Thread started which writes packets to file. + * Called by startReceiver() + * @param this_pointer pointer to this object + */ + static void* startWritingThread(void *this_pointer); + + /** + * Thread started which listens to packets. + * Called by startReceiver() + * + */ + int startListening(); + + /** + * Thread started which writes packets to file. + * Called by startReceiver() + * + */ + int startWriting(); + + + /** + * Writing to file without compression + * @param buf is the address of buffer popped out of fifo + * @param numpackets is the number of packets + */ + void writeToFile_withoutCompression(char* buf,int numpackets); + + + + + /** Eiger Receiver */ + EigerReceiver *receiver; + + /** detector type */ + detectorType myDetectorType; + + /** detector hostname */ + char detHostname[MAX_STR_LENGTH]; + + /** status of receiver */ + runStatus status; + + /** UDP Socket between Receiver and Detector */ + genericSocket* udpSocket; + + /** Server UDP Port*/ + int server_port; + + /** ethernet interface or IP to listen to */ + char *eth; + + /** max packets per file **/ + int maxPacketsPerFile; + + /** File write enable */ + int enableFileWrite; + + /** File over write enable */ + int overwrite; + + /** Complete File name */ + char savefilename[MAX_STR_LENGTH]; + + /** File Name without frame index, file index and extension*/ + char fileName[MAX_STR_LENGTH]; + + /** File Path */ + char filePath[MAX_STR_LENGTH]; + + /** File Index */ + int fileIndex; + + /** scan tag */ + int scanTag; + + /** if frame index required in file name */ + int frameIndexNeeded; + + /* Acquisition started */ + bool acqStarted; + + /* Measurement started */ + bool measurementStarted; + + /** Frame index at start of each real time acquisition (eg. for each scan) */ + uint32_t startFrameIndex; + + /** Actual current frame index of each time acquisition (eg. for each scan) */ + uint32_t frameIndex; + + /** Frames Caught for each real time acquisition (eg. for each scan) */ + int packetsCaught; + + /** Total packets caught for an entire acquisition (including all scans) */ + int totalPacketsCaught; + + /** Pckets currently in current file, starts new file when it reaches max */ + int packetsInFile; + + /** Frame index at start of an entire acquisition (including all scans) */ + uint32_t startAcquisitionIndex; + + /** Actual current frame index of an entire acquisition (including all scans) */ + uint32_t acquisitionIndex; + + /** number of packets per frame*/ + int packetsPerFrame; + + /** frame index mask */ + uint32_t frameIndexMask; + + /** packet index mask */ + uint32_t packetIndexMask; + + /** frame index offset */ + int frameIndexOffset; + + /** acquisition period */ + int64_t acquisitionPeriod; + + /** frame number */ + int32_t numberOfFrames; + + /** dynamic range */ + int dynamicRange; + + /** short frames */ + int shortFrame; + + /** current frame number */ + uint32_t currframenum; + + /** Previous Frame number from buffer */ + uint32_t prevframenum; + + /** buffer size can be 1286*2 or 518 or 1286*40 */ + int bufferSize; + + /** oen buffer size */ + int onePacketSize; + + /** latest data */ + char* latestData; + + /** gui data ready */ + int guiDataReady; + + /** points to the data to send to gui */ + char* guiData; + + /** points to the filename to send to gui */ + char* guiFileName; + + /** send every nth frame to gui or only upon gui request*/ + int nFrameToGui; + + /** fifo size */ + unsigned int fifosize; + + /** number of jobs per thread for data compression */ + int numJobsPerThread; + + /** memory allocated for the buffer */ + char *mem0; + + /** datacompression - save only hits */ + bool dataCompression; + + /** circular fifo to store addresses of data read */ + CircularFifo* fifo; + + /** circular fifo to store addresses of data already written and ready to be resued*/ + CircularFifo* fifoFree; + + /** Receiver buffer */ + char *buffer; + + /** max number of writer threads */ + const static int MAX_NUM_WRITER_THREADS = 15; + + /** number of writer threads */ + int numWriterThreads; + + /** to know if listening and writer threads created properly */ + int thread_started; + + /** current writer thread index*/ + int currentWriterThreadIndex; + + /** thread listening to packets */ + pthread_t listening_thread; + + /** thread writing packets */ + pthread_t writing_thread[MAX_NUM_WRITER_THREADS]; + + /** total frame count the listening thread has listened to */ + int totalListeningFrameCount; + + /** mask showing which threads are running */ + volatile uint32_t writerthreads_mask; + + /** mask showing which threads have created files*/ + volatile uint32_t createfile_mask; + + /** OK if file created was successful */ + int ret_createfile; + + /** 0 if listening thread is idle, 1 otherwise */ + int listening_thread_running; + + /** variable used to self terminate threads waiting for semaphores */ + int killListeningThread; + + /** variable used to self terminate threads waiting for semaphores */ + int killAllWritingThreads; + + + + +//semaphores + /** semaphore to synchronize writer and guireader threads */ + sem_t smp; + /** semaphore to synchronize listener thread */ + sem_t listensmp; + /** semaphore to synchronize writer threads */ + sem_t writersmp[MAX_NUM_WRITER_THREADS]; + + +//mutex + /** guiDataReady mutex */ + pthread_mutex_t dataReadyMutex; + + /** mutex for status */ + pthread_mutex_t status_mutex; + + /** mutex for progress variable currframenum */ + pthread_mutex_t progress_mutex; + + /** mutex for writing data to file */ + pthread_mutex_t write_mutex; + + /** File Descriptor */ + FILE *sfilefd; + + //filter + singlePhotonDetector *singlePhotonDet[MAX_NUM_WRITER_THREADS]; + slsReceiverData *receiverdata[MAX_NUM_WRITER_THREADS]; + moenchCommonMode *cmSub; + bool commonModeSubtractionEnable; + +#ifdef MYROOT1 + /** Tree where the hits are stored */ + TTree *myTree[MAX_NUM_WRITER_THREADS]; + + /** File where the tree is saved */ + TFile *myFile[MAX_NUM_WRITER_THREADS]; +#endif + + + + /** + callback arguments are + filepath + filename + fileindex + data size + + return value is + 0 callback takes care of open,close,write file + 1 callback writes file, we have to open, close it + 2 we open, close, write file, callback does not do anything + + */ + int (*startAcquisitionCallBack)(char*, char*,int, int, void*); + void *pStartAcquisition; + + /** + args to acquisition finished callback + total frames caught + + */ + void (*acquisitionFinishedCallBack)(int, void*); + void *pAcquisitionFinished; + + + /** + args to raw data ready callback are + framenum + datapointer + datasize in bytes + file descriptor + guidatapointer (NULL, no data required) + */ + void (*rawDataReadyCallBack)(int, char*, int, FILE*, char*, void*); + void *pRawDataReady; + + /** The action which decides what the user and default responsibilites to save data are + * 0 raw data ready callback takes care of open,close,write file + * 1 callback writes file, we have to open, close it + * 2 we open, close, write file, callback does not do anything */ + int cbAction; + + +public: + + + /** + callback arguments are + filepath + filename + fileindex + datasize + + return value is + 0 callback takes care of open,close,wrie file + 1 callback writes file, we have to open, close it + 2 we open, close, write file, callback does not do anything + */ + void registerCallBackStartAcquisition(int (*func)(char*, char*,int, int, void*),void *arg){startAcquisitionCallBack=func; pStartAcquisition=arg;}; + + /** + callback argument is + toatal frames caught + */ + void registerCallBackAcquisitionFinished(void (*func)(int, void*),void *arg){acquisitionFinishedCallBack=func; pAcquisitionFinished=arg;}; + + /** + args to raw data ready callback are + framenum + datapointer + datasize in bytes + file descriptor + guidatapointer (NULL, no data required) + */ + void registerCallBackRawDataReady(void (*func)(int, char*, int, FILE*, char*, void*),void *arg){rawDataReadyCallBack=func; pRawDataReady=arg;}; +}; + + +#endif + +#endif diff --git a/slsReceiverSoftware/slsReceiver/slsReceiverUsers.cpp b/slsReceiverSoftware/slsReceiver/slsReceiverUsers.cpp new file mode 100644 index 000000000..ce2001721 --- /dev/null +++ b/slsReceiverSoftware/slsReceiver/slsReceiverUsers.cpp @@ -0,0 +1,43 @@ +#include "slsReceiverUsers.h" +#include "slsReceiverTCPIPInterface.h" + +slsReceiverTCPIPInterface* slsReceiverUsers::receiver(NULL); + +slsReceiverUsers::slsReceiverUsers(int argc, char *argv[], int &success) { + slsReceiverUsers::receiver=new slsReceiverTCPIPInterface(argc, argv, success); +} + +slsReceiverUsers::~slsReceiverUsers() { + delete slsReceiverUsers::receiver; +} + +void slsReceiverUsers::start() { + slsReceiverUsers::receiver->start(); +} + + +void slsReceiverUsers::closeFile(int p) { + slsReceiverUsers::receiver->closeFile(p); +} + +int64_t slsReceiverUsers::getReceiverVersion(){ + slsReceiverUsers::receiver->get_version(); +} + + +void slsReceiverUsers::registerCallBackStartAcquisition(int (*func)(char*, char*,int, int, void*),void *arg){ + slsReceiverUsers::receiver->registerCallBackStartAcquisition(func,arg); +} + + + +void slsReceiverUsers::registerCallBackAcquisitionFinished(void (*func)(int, void*),void *arg){ + slsReceiverUsers::receiver->registerCallBackAcquisitionFinished(func,arg); +} + + +void slsReceiverUsers::registerCallBackRawDataReady(void (*func)(int, char*, int, FILE*, char*, void*),void *arg){ + slsReceiverUsers::receiver->registerCallBackRawDataReady(func,arg); +} + + diff --git a/slsReceiverSoftware/slsReceiver/slsReceiverUsers.h b/slsReceiverSoftware/slsReceiver/slsReceiverUsers.h new file mode 100644 index 000000000..aab02b699 --- /dev/null +++ b/slsReceiverSoftware/slsReceiver/slsReceiverUsers.h @@ -0,0 +1,85 @@ + +#ifndef SLS_RECEIVER_USERS_H +#define SLS_RECEIVER_USERS_H + +#include +#include + +class slsReceiverTCPIPInterface; + + /** +@short Class for implementing the SLS data receiver in the users application. Callbacks can be defined for processing and/or saving data + */ +/** + + + @libdoc slsReceiverUsers is a class that can be instantiated in the users software to receive the data from the detectors. Callbacks can be defined for processing and/or saving data + + + ***********************************************/ + +class slsReceiverUsers { + +public: + /** + * Constructor + * reads config file, creates socket, assigns function table + * @param argc from command line + * @param argv from command line + * @param succecc socket creation was successfull + */ + slsReceiverUsers(int argc, char *argv[], int &success); + + + /** Destructor */ + ~slsReceiverUsers(); + + /** Close File and exits receiver server */ + void closeFile(int p); + + /** starts listening on the TCP port for client comminication */ + void start(); + + /** + get get Receiver Version + \returns id + */ + int64_t getReceiverVersion(); + + /** + + @sort register calbback for starting the acquisition + \param func callback to be called when starting the acquisition. Its arguments are filepath filename fileindex data size + + \returns 0 callback takes care of open,close,write file; 1 callback writes file, we have to open, close it; 2 we open, close, write file, callback does not do anything + + */ + + void registerCallBackStartAcquisition(int (*func)(char* filepath, char* filename,int fileindex, int datasize, void*),void *arg); + + + /** + @sort register callback for end of acquisition + \param func end of acquisition callback. Argument nf is total frames caught + \returns nothing + */ + + + void registerCallBackAcquisitionFinished(void (*func)(int nf, void*),void *arg); + + + + /** + @sort register callback to be called when data are available (to process and/or save the data). + \param func raw data ready callback. arguments are framenum datapointer datasize file descriptor guidatapointer (NULL, no data required) + \returns nothing + */ + + void registerCallBackRawDataReady(void (*func)(int framenumber, char* datapointer, int datasize, FILE* filedescriptor, char* guidatapointer, void*),void *arg); + + // made static to close thread files with ctrl+c + static slsReceiverTCPIPInterface* receiver; +}; + + +#endif