new separate receiver

This commit is contained in:
Maliakal Dhanya 2014-05-21 09:59:37 +02:00
commit 8c72246ce7
59 changed files with 11792 additions and 0 deletions

View File

@ -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)

Binary file not shown.

View File

@ -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"

View File

@ -0,0 +1 @@
MySocketTCP.cxx

View File

@ -0,0 +1 @@
MySocketTCP.cxx

View File

@ -0,0 +1,53 @@
//version 1.0, base development, Ian 19/01/09
#include "MySocketTCP.h"
#include <string.h>
#include <iostream>
#include <cstdio>
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;
}

View File

@ -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

View File

@ -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 <arpa/inet.h>
#include <netdb.h>
#include <netinet/in.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <ifaddrs.h>
#endif
#include <unistd.h>
#include <string.h>
#include <iostream>
#include <math.h>
#include <errno.h>
#include <stdio.h>
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 "<<endl;
return;
}
// Set some fields in the serverAddress structure.
serverAddress.sin_family = AF_INET;
serverAddress.sin_port = htons(port_number);
serverAddress.sin_addr.s_addr = htonl(INADDR_ANY);
if (string(ip)!=string("0.0.0.0")) {
if (inet_pton(AF_INET, ip, &(serverAddress.sin_addr)))
;
else
serverAddress.sin_addr.s_addr = htonl(INADDR_ANY);
}
// reuse port
int val=1;
if (setsockopt(socketDescriptor,SOL_SOCKET,SO_REUSEADDR,&val,sizeof(int)) == -1) {
cerr << "setsockopt" << endl;
socketDescriptor=-1;
return;
}
//increase buffer size if its udp
val = SOCKET_BUFFER_SIZE;
if((p == UDP) && (setsockopt(socketDescriptor, SOL_SOCKET, SO_RCVBUF, &val, sizeof(int)) == -1))
{
cerr << "WARNING:Could not set socket receive buffer size" << endl;
//socketDescriptor=-1;
//return;
}
if(bind(socketDescriptor,(struct sockaddr *) &serverAddress,sizeof(serverAddress))<0){
cerr << "Can not bind socket "<< endl;
socketDescriptor=-1;
return;
}
if (getProtocol()==SOCK_STREAM)
listen(socketDescriptor, DEFAULT_BACKLOG);
}
/**
The destructor: disconnects and close the socket
@short the destructor
*/
~genericSocket(){ \
Disconnect();
if (socketDescriptor >= 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"<<endl;
if(file_des>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"<<endl;
switch(errno) {
case EWOULDBLOCK:
printf("ewouldblock eagain\n");
break;
case EBADF:
printf("ebadf\n");
break;
case ECONNABORTED:
printf("econnaborted\n");
break;
case EFAULT:
printf("efault\n");
break;
case EINTR:
printf("eintr\n");
break;
case EINVAL:
printf("einval\n");
break;
case EMFILE:
printf("emfile\n");
break;
case ENFILE:
printf("enfile\n");
break;
case ENOTSOCK:
printf("enotsock\n");
break;
case EOPNOTSUPP:
printf("eOPNOTSUPP\n");
break;
case ENOBUFS:
printf("ENOBUFS\n");
break;
case ENOMEM:
printf("ENOMEM\n");
break;
case ENOSR:
printf("ENOSR\n");
break;
case EPROTO:
printf("EPROTO\n");
break;
default:
printf("unknown error\n");
}
socketDescriptor=-1;
}
else{
inet_ntop(AF_INET, &(clientAddress.sin_addr), dummyClientIP, INET_ADDRSTRLEN);
#ifdef VERY_VERBOSE
cout << "client connected "<< file_des << endl;
#endif
}
}
// file_des = socketDescriptor;
#ifdef VERY_VERBOSE
cout << "fd " << file_des << endl;
#endif
} else {
if (socketDescriptor<=0)
socketDescriptor = socket(AF_INET, getProtocol(),0);
// SetTimeOut(10);
if (socketDescriptor < 0){
cerr << "Can not create socket "<<endl;
file_des = socketDescriptor;
} else {
if(connect(socketDescriptor,(struct sockaddr *) &serverAddress,sizeof(serverAddress))<0){
cerr << "Can not connect to socket "<<endl;
file_des = -1;
} else{
file_des = socketDescriptor;
}
}
}
return file_des;
}
uint16_t getPortNumber(){
return ntohs(serverAddress.sin_port);
}
int getFileDes(){return file_des;};
int getsocketDescriptor(){return socketDescriptor;};
/** @short free connection */
void Disconnect(){
if (protocol==UDP){
close(socketDescriptor);
socketDescriptor=-1;
}
else{
if(file_des>=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;i<packets_per_frame;i++){
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;
}
}
break;
default:
;
}
#ifdef VERY_VERBOSE
cout << "sent "<< total_sent << " Bytes" << endl;
#endif
if (total_sent>0)
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

Binary file not shown.

View File

@ -0,0 +1,31 @@
//version 1.0, base development ij 19/01/09
#include <iostream>
#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 :"<<sock->ReceiveDataAndKeepConnection(data,23000)<<endl;
cout<<"\tReceived :"<<sock->ReceiveData(data,32200)<<endl;
cout<<"\tReceived :"<<sock->ReceiveData(data,33300)<<endl;
cout<<"\tReceived :"<<sock->ReceiveData(data,30000)<<endl;
cout<<"\tReceived :"<<sock->ReceiveData(data,3222)<<endl;
delete sock;
return 0;
}

Binary file not shown.

View File

@ -0,0 +1,40 @@
//version 1.0, base development ij 19/01/09
#include <iostream>
#include "MySocketTCP.h"
using namespace std;
int main(int argc, char *argv[]){
if(argc!=2){
cout<<"Usage: send ip_addess/hostName"<<endl;
return 1;
}
cout<<"rec function must be first called."<<endl;
char ip_address[200];
sprintf(ip_address,"%s",argv[1]);
unsigned short int portnum = 1952;
char data[50000];
int length=50000;
MySocketTCP* sock = new MySocketTCP(ip_address,portnum);
cout<<"\tSending :"<<sock->SendDataAndKeepConnection(data,2000)<<endl;
cout<<"\tSending :"<<sock->SendData(data,2200)<<endl;
cout<<"\tSending :"<<sock->SendData(data,1200)<<endl;
cout<<"\tSending :"<<sock->SendData(data,25000)<<endl;
cout<<"\tSending :"<<sock->SendData(data,222)<<endl;
delete sock;
return 0;
}

View File

@ -0,0 +1,261 @@
/* CircularFifo.h
* Not any company's property but Public-Domain
* Do with source-code as you will. No requirement to keep this
* header if need to use it/change it/ or do whatever with it
*
* Note that there is No guarantee that this code will work
* and I take no responsibility for this code and any problems you
* might get if using it. The code is highly platform dependent!
*
* Code & platform dependent issues with it was originally
* published at http://www.kjellkod.cc/threadsafecircularqueue
* 2009-11-02
* @author Kjell Hedstr<EFBFBD>m, hedstrom@kjellkod.cc */
#ifndef CIRCULARFIFO_H_
#define CIRCULARFIFO_H_
//#include "sls_receiver_defs.h"
#include <semaphore.h>
#include <vector>
#include <iostream>
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<typename Element>
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 <Element*> array;
volatile unsigned int head; // output index
unsigned int Capacity;
sem_t free_mutex;
unsigned int increment(unsigned int idx_) const;
};
template<typename Element>
int CircularFifo<Element>::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<typename Element>
bool CircularFifo<Element>::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<typename Element>
bool CircularFifo<Element>::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<typename Element>
bool CircularFifo<Element>::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<typename Element>
bool CircularFifo<Element>::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<typename Element>
unsigned int CircularFifo<Element>::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 <vector>
using namespace std;
template<typename Element>
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 <Element*> array;
unsigned int Capacity;
std::atomic<unsigned int> tail; // input index
std::atomic<unsigned int> head; // output index
unsigned int increment(unsigned int idx_) const;
};
template<typename Element>
bool CircularFifo<Element>::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<typename Element>
bool CircularFifo<Element>::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<typename Element>
bool CircularFifo<Element>::wasEmpty() const
{
return (head.load() == tail.load());
}
template<typename Element>
bool CircularFifo<Element>::wasFull() const
{
const auto nextTail = increment(tail.load());
return (nextTail == head.load());
}
template<typename Element>
bool CircularFifo<Element>::isLockFree() const
{
return (tail.is_lock_free() && head.is_lock_free());
}
template<typename Element>
unsigned int CircularFifo<Element>::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 */

View File

@ -0,0 +1,72 @@
#ifndef RECEIVER_DEFS_H
#define RECEIVER_DEFS_H
#include "sls_receiver_defs.h"
#include <stdint.h>
#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

View File

@ -0,0 +1,118 @@
#ifndef SLS_RECEIVER_DEFS_H
#define SLS_RECEIVER_DEFS_H
#ifdef __CINT__
#define MYROOT
#define __cplusplus
#endif
#include <stdint.h>
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
;

View File

@ -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 */

View File

@ -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
//

View File

@ -0,0 +1,11 @@
//#define SVNPATH ""
#define SVNURL ""
//#define SVNREPPATH ""
#define SVNREPUUID ""
//#define SVNREV ""
//#define SVNKIND ""
//#define SVNSCHED ""
#define SVNAUTH ""
#define SVNREV ""
#define SVNDATE ""
//

View File

@ -0,0 +1,130 @@
#ifndef MOVINGSTAT_H
#define MOVINGSTAT_H
#include <math.h>
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<n) Add(x);
else Push(x);
}
/** adds the element to the accumulated average and standard deviation
\param x value to add
*/
inline void Add(double x) {
m_n++;
if (m_n == 1)
{
m_newM = x;
m_newM2 = x*x;
} else {
m_newM = m_newM + x;
m_newM2 = m_newM2 + x*x;
}
}
inline void Push(double x)
{
/** adds the element to the accumulated average and squared mean, while subtracting the current value of the average and squared average
\param x value to push
*/
if (m_n == 0)
{
m_newM = x;
m_newM2 = x*x;
m_n++;
} else {
m_newM = m_newM + x - m_newM/m_n;
m_newM2 = m_newM2 + x*x - m_newM2/m_n;
}
}
/** returns the current number of elements of the moving average
\returns returns the current number of elements of the moving average
*/
int NumDataValues() const
{
return m_n;
}
/** returns the mean, 0 if no elements are inside
\returns returns the mean
*/
inline double Mean() const
{
return (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

View File

@ -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;
};

View File

@ -0,0 +1,89 @@
#ifndef CHIPTESTDATA_H
#define CHIPTESTDATA_H
#include "slsDetectorData.h"
class chiptestBoardData : public slsDetectorData<uint16_t> {
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<uint16_t>(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; /**<number of ADC read out */
const int offSize; /**< offset at the beginning of the frame (depends on the pattern) */
int iframe; /**< frame number (calculated in software! not in the data)*/
};
#endif

View File

@ -0,0 +1,82 @@
#ifndef COMMONMODESUBTRACTION_H
#define COMMONMODESUBTRACTION_H
#include "MovingStat.h"
class commonModeSubtraction {
/** @short class to calculate the common mode of the pedestals based on an approximated moving average*/
public:
/** constructor
\param nn number of samples for the moving average to calculate the average common mode
\param iroi number of regions on which one can calculate the common mode separately. Defaults to 1 i.e. whole detector
*/
commonModeSubtraction(int nn=1000, int iroi=1) : cmStat(NULL), cmPed(NULL), nCm(NULL), nROI(iroi) {cmStat=new MovingStat[nROI]; for (int i=0; i<nROI; i++) cmStat[i].SetN(nn); cmPed=new double[nROI]; nCm=new double[nROI];};
/** destructor - deletes the moving average(s) and the sum of pedestals calculator(s) */
virtual ~commonModeSubtraction() {delete [] cmStat; delete [] cmPed; delete [] nCm;};
/** clears the moving average and the sum of pedestals calculation - virtual func*/
virtual void Clear(){
for (int i=0; i<nROI; i++) {
cmStat[i].Clear();
nCm[i]=0;
cmPed[i]=0;
}};
/** adds the average of pedestals to the moving average and reinitializes the calculation of the sum of pedestals for all ROIs. - virtual func*/
virtual void newFrame(){
for (int i=0; i<nROI; i++) {
if (nCm[i]>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 && isc<nROI) {
cmPed[0]+=val;
nCm[0]++;//}
};
/** gets the common mode i.e. the difference between the current average sum of pedestals mode and the average pedestal -- virtual func must be overloaded to define the regions of interest
\param ix pixel x coordinate
\param iy pixel y coordinate
\return the difference between the current average sum of pedestals and the average pedestal
*/
virtual double getCommonMode(int ix=0, int iy=0) {
(void) ix; (void) iy;
if (nCm[0]>0) return cmPed[0]/nCm[0]-cmStat[0].Mean();
return 0;};
protected:
MovingStat *cmStat; /**<array of moving average of the pedestal average per region of interest */
double *cmPed; /**< array storing the sum of pedestals per region of interest */
double *nCm; /**< array storing the number of pixels currently contributing to the pedestals */
const int nROI; /**< constant parameter for number of regions on which the common mode should be calculated separately e.g. supercolumns */
};
#endif

View File

@ -0,0 +1,31 @@
{
//.L moenchReadData.C
TFile *fout;
THStack *hs2N;
fout=new TFile("/scratch/outfile.root","RECREATE");
hs2N=moenchReadData("/data/moench_xbox_20140113/MoTarget_45kV_0_8mA_12us_120V_cds_g4_f00000%04d000_0.raw","dum",0,20,1500,-500,2500,1,0.,1,159,1,159, 0,1);
hs2N->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();
}

View File

@ -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

View File

@ -0,0 +1,527 @@
#include "energyCalibration.h"
#ifdef __CINT
#define MYROOT
#endif
#ifdef MYROOT
#include <TMath.h>
#include <TH1F.h>
#include <TH2F.h>
#include <TGraphErrors.h>
#endif
#include <iostream>
#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<n; i++) {
k=0;
for (j=0; j<n; j++) {
if(*(x+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 (l<m) {
x=a[k] ;
i=l ;
j=m ;
do {
while (a[i]<x) i++ ;
while (x<a[j]) j-- ;
if (i<=j) {
ELEM_SWAP(a[i],a[j]) ;
i++ ; j-- ;
}
} while (i<=j) ;
if (j<k) l=i ;
if (k<i) m=j ;
}
return a[k] ;
}
#ifdef MYROOT
Double_t energyCalibrationFunctions::spectrum(Double_t *x, Double_t *par) {
return gaussChargeSharing(x,par);
}
Double_t energyCalibrationFunctions::spectrumPixel(Double_t *x, Double_t *par) {
return gaussChargeSharingPixel(x,par);
}
Double_t energyCalibrationFunctions::scurve(Double_t *x, Double_t *par) {
return erfFunctionChargeSharing(x,par);
}
Double_t energyCalibrationFunctions::scurveFluo(Double_t *x, Double_t *par) {
return erfFuncFluo(x,par);
}
#endif
energyCalibration::energyCalibration() :
#ifdef MYROOT
fit_min(-1),
fit_max(-1),
bg_offset(-1),
bg_slope(-1),
flex(-1),
noise(-1),
ampl(-1),
cs_slope(-1),
fscurve(NULL),
fspectrum(NULL),
#endif
funcs(NULL),
plot_flag(1), // fit parameters output to screen
cs_flag(1)
{
#ifdef MYROOT
funcs=new energyCalibrationFunctions();
fscurve=new TF1("fscurve",funcs,&energyCalibrationFunctions::scurve,0,1000,6,"energyCalibrationFunctions","scurve");
fscurve->SetParNames("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; ib<h1->GetXaxis()->GetNbins(); ib++) {
for (int ich=0; ich<nch; ich++) {
x[ich]=h2->GetBinContent(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; ib<h1->GetYaxis()->GetNbins(); ib++) {
for (int ich=0; ich<nch; ich++) {
x[ich]=h2->GetBinContent(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<nscan; ien++) {
h=h1[ien];
if (integral)
fitSCurve(h,mypar,emypar);
else
fitSpectrum(h,mypar,emypar);
fl[ien]=mypar[2];
efl[ien]=emypar[2];
}
return linearCalibration(nscan,en,een,fl,efl,gain,off, egain, eoff);
}
#endif
Fit data is empty

View File

@ -0,0 +1,452 @@
#ifndef ENERGYCALIBRATION_H
#define ENERGYCALIBRATION_H
#ifdef __CINT__
#define MYROOT
#endif
#ifdef G__ROOT
#define MYROOT
#endif
#ifdef __MAKECINT__
#define MYROOT
#endif
#ifdef ROOT_VERSION
#define MYROOT
#endif
#define MYROOT
#ifdef MYROOT
#include <TROOT.h>
#include <TF1.h>
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

View File

@ -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");
}

View File

@ -0,0 +1,228 @@
#define MYROOT
#include <TH2F.h>
#include <TSpectrum.h>
#include <TH1D.h>
#include <TFile.h>
#include <TList.h>
#include <TPolyMarker.h>
#include <THStack.h>
#include <TF1.h>
#include <TGraphErrors.h>
#include <iostream>
#include <energyCalibration.h>
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; ix<npx-1; ix++) {
for (int iy=1; iy<npy-1; iy++) {
// cout << ix << " " << iy << " " << ibin << endl;
ibin=ix*npy+iy;
px=h2->ProjectionX("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; ip<np; ip++) {
// cout << ip << " " << peakX[ip] << " " << peakY[ip] << endl;
enCal->setFitRange(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; ix<npx; ix++) {
for (int iy=0; iy<npy; iy++) {
cout << ix << " " << iy << " " << ibin << endl;
ibin=ix*npy+iy;
px=h2->ProjectionX("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;
}

View File

@ -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<uint16_t> {
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<uint16_t>(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<ypixels; ++ix)
for(iy=0; iy<xpixels; ++iy)
dMask[ix][iy] = 0x0;
for(ix=0; ix<ypixels; ++ix){
if(ix == (ypixels/2)){
offset += initial_offset;//2
offset++;
}
for(iy=0; iy<xpixels; ++iy){
dMap[ix][iy] = offset;
offset++;
}
}
setDataMap(dMap);
setDataMask(dMask);
};
/**
Returns the frame number for the given dataset.
\param buff pointer to the dataset
\returns frame number
*/
int getFrameNumber(char *buff){
int np=(*(int*)buff);
//gotthards frame header must be incremented
++np;
//packet index should be 1 or 2
return ((np&FRAMEMASK)>>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<uint16_t>::getValue(data, ix, iy);
else
return slsDetectorData<uint16_t>::getValue(data, ix, iy)-xtalk*slsDetectorData<uint16_t>::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; /**<output buffer crosstalk correction parameter */
const static int xpixels = 1280;
const static int ypixels = 1;
const static int npackets = 2;
const static int buffersize = 1286;
};
#endif

View File

@ -0,0 +1,127 @@
#ifndef GOTTHARDSHORTMODULEDATA_H
#define GOTTHARDSHORTMODULEDATA_H
#include "slsReceiverData.h"
class gotthardShortModuleData : public slsReceiverData<uint16_t> {
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<uint16_t>(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<ypixels; ++ix)
for(iy=0; iy<xpixels; ++iy)
dMask[ix][iy] = 0x0;
for(ix=0; ix<ypixels; ++ix)
for(iy=0; iy<xpixels; ++iy){
dMap[ix][iy] = offset;
offset++;
}
setDataMap(dMap);
setDataMask(dMask);
};
/**
Returns the frame number for the given dataset.
\param buff pointer to the dataset
\returns frame number
*/
int getFrameNumber(char *buff){
return (*(int*)buff);
};
/**
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){
return 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<uint16_t>::getValue(data, ix, iy);
else
return slsDetectorData<uint16_t>::getValue(data, ix, iy)-xtalk*slsDetectorData<uint16_t>::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; /**<output buffer crosstalk correction parameter */
const static int xpixels = 256;
const static int ypixels = 1;
const static int npackets = 1;
const static int buffersize = 518;
};
#endif

View File

@ -0,0 +1,156 @@
#ifndef JUNGFRAU02DATA_H
#define JUNGFRAU02DATA_H
#include "chiptestBoardData.h"
class jungfrau02Data : public chiptestBoardData {
public:
/**
Implements the chiptestBoardData structure for the jungfrau02 prototype
(48x48 pixels, ADC2 for analog output, 2 more ADCs used for readout of digital bits, pixel offset configurable.)
\param c crosstalk parameter for the output buffer
*/
jungfrau02Data(int nadc, int offset, double c=0): chiptestBoardData(48, 48, nadc, offset),
xtalk(c) {
uint16_t **dMask;
int **dMap;
dMask=new uint16_t*[48];
dMap=new int*[48];
for (int i = 0; i < 48; i++) {
dMap[i] = new int[48];
dMask[i] = new uint16_t[48];
}
for (int iy=0; iy<48; iy++) {
for (int ix=0; ix<48; ix++) {
dMap[ix][iy]=offset+(iy*48+ix)*nAdc;//dMap[iy][ix]=offset+(iy*48+ix)*nAdc;
// cout << ix << " " << iy << " " << dMap[ix][iy] << endl;
}
}
cout << (0,0) << " " << dMap[0][0] << endl;
cout << (47,47) << " " << dMap[47][47] << endl;
for (int ix=0; ix<48; ix++) {
for (int iy=0; iy<48; iy++)
dMask[iy][ix]=0x0;
setDataMap(dMap);
setDataMask(dMask);
}
};
/**
Returns the value of the selected channel for the given dataset. Since the ADC is only 14bit wide, only bit 0-13 are occupied. If the gain bits are read out, they are returned in bit 14-15.
\param data pointer to the dataset (including headers etc)
\param ix pixel number in the x direction
\param iy pixel number in the y direction
\returns data for the selected channel, with inversion if required
*/
virtual uint16_t getChannel(char *data, int ix, int iy=0) {
uint16_t m=0, d=0;
if (ix>=0 && ix<nx && iy>=0 && iy<ny && dataMap[iy][ix]>=0 && dataMap[iy][ix]<dataSize) {
m=dataMask[iy][ix];
d=*(((uint16_t*)(data))+dataMap[iy][ix]);
// cout << ix << " " << iy << " " << (uint16_t*)data << " " << ((uint16_t*)(data))+dataMap[iy][ix] << " " << d << endl;
if (nAdc==3) {
//cout << "Gain bit!" << endl;
if (*((uint16_t*)(data)+dataMap[iy][ix]+2)>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 << " " <<iy << endl;
uint16_t d=getChannel(data, ix, iy);
// cout << d << " " << (d&0x3fff) << endl;
if (xtalk==0 || ix==0)
return (double)(getChannel(data, ix, iy)&0x3fff);
else
return (double)(getChannel(data, ix, iy)&0x3fff)-xtalk* (double)(getChannel(data, ix, iy)&0x3fff);
};
/**
returns the gain bit value, i.e. returns 0 if(GB0==0 && GB1==0), returns 1 if(GB0==1 && GB1==0), returns 3 if(GB0==1 && GB1==1), if it returns 2 -> 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; /**<output buffer crosstalk correction parameter */
};
#endif

View File

@ -0,0 +1,264 @@
#include <TH1D.h>
#include <TH2D.h>
#include <TPad.h>
#include <TDirectory.h>
#include <TEntryList.h>
#include <TFile.h>
#include <TMath.h>
#include <TTree.h>
#include <TChain.h>
#include <THStack.h>
#include <TCanvas.h>
#include <stdio.h>
//#include <deque>
//#include <list>
//#include <queue>
#include <fstream>
#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 <TCanvas.h>
#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<uint16_t> *filter=new singlePhotonDetector<uint16_t>(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; ix<xmax+1; ix++)
for (iy=ymin-1; iy<ymax+1; iy++) {
thisEvent=filter->getEventType(buff, ix, iy,0);
}
}
}
// cout << "new frame " << endl;
for (ix=xmin-1; ix<xmax+1; ix++)
for (iy=ymin-1; iy<ymax+1; iy++) {
// cout << ix << " " << iy << endl;
thisEvent=filter->getEventType(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;
}

View File

@ -0,0 +1,137 @@
#ifndef MOENCH02MODULEDATA_H
#define MOENCH02MODULEDATA_H
#include "slsReceiverData.h"
class moench02ModuleData : public slsReceiverData<uint16_t> {
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<uint16_t>(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 << " " <<iy << endl;
if (xtalk==0 || ix%40==0)
return slsDetectorData<uint16_t>::getValue(data, ix, iy);
else
return slsDetectorData<uint16_t>::getValue(data, ix, iy)-xtalk*slsDetectorData<uint16_t>::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; /**<output buffer crosstalk correction parameter */
};
#endif

View File

@ -0,0 +1,45 @@
#ifndef MOENCHCOMMONMODE_H
#define MOENCHCOMMONMODE_H
#include "commonModeSubtraction.h"
class moenchCommonMode : public commonModeSubtraction {
/** @short class to calculate the common mode noise for moench02 i.e. on 4 supercolumns separately */
public:
/** constructor - initalizes a commonModeSubtraction with 4 different regions of interest
\param nn number of samples for the moving average
*/
moenchCommonMode(int nn=1000) : commonModeSubtraction(nn,4){} ;
/** add value to common mode as a function of the pixel value, subdividing the region of interest in the 4 supercolumns of 40 columns each;
\param val value to add to the common mode
\param ix pixel coordinate in the x direction
\param iy pixel coordinate in the y direction
*/
virtual void addToCommonMode(double val, int ix=0, int iy=0) {
(void) iy;
int isc=ix/40;
if (isc>=0 && isc<nROI) {
cmPed[isc]+=val;
nCm[isc]++;
}
};
/**returns common mode value as a function of the pixel value, subdividing the region of interest in the 4 supercolumns of 40 columns each;
\param ix pixel coordinate in the x direction
\param iy pixel coordinate in the y direction
\returns common mode value
*/
virtual double getCommonMode(int ix=0, int iy=0) {
(void) iy;
int isc=ix/40;
if (isc>=0 && isc<nROI) {
if (nCm[isc]>0) return cmPed[isc]/nCm[isc]-cmStat[isc].Mean();
}
return 0;
};
};
#endif

View File

@ -0,0 +1,244 @@
#include <TH1D.h>
#include <TH2D.h>
#include <TPad.h>
#include <TDirectory.h>
#include <TEntryList.h>
#include <TFile.h>
#include <TMath.h>
#include <TTree.h>
#include <TChain.h>
#include <THStack.h>
#include <TCanvas.h>
#include <stdio.h>
#include <deque>
#include <list>
#include <queue>
#include <fstream>
#include "RunningStat.h"
#include "MovingStat.h"
#include "moench02ModuleData.h"
#include <TThread.h>
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; irun<runmax; irun++) {
sprintf(fname,fformat,irun);
//cout << "process file " << fname; // cout.flush();
filebin.open((const char *)(fname), ios::in | ios::binary);
while ((buff=decoder->readNextFrame(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 (nf<nbg || dum==0)
stat[iy][ix].Calc(sign*decoder->getChannel(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();
}

View File

@ -0,0 +1,236 @@
#include <TH1D.h>
#include <TH2D.h>
#include <TPad.h>
#include <TDirectory.h>
#include <TEntryList.h>
#include <TFile.h>
#include <TMath.h>
#include <TTree.h>
#include <TChain.h>
#include <THStack.h>
#include <TCanvas.h>
#include <stdio.h>
//#include <deque>
//#include <list>
//#include <queue>
#include <fstream>
#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 <TCanvas.h>
#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<uint16_t> *filter=new singlePhotonDetector<uint16_t>(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; 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; ix<xmax+1; ix++)
for (iy=ymin-1; iy<ymax+1; iy++) {
thisEvent=filter->getEventType(buff, ix, iy,0);
}
}
}
// cout << "new frame " << endl;
for (ix=xmin-1; ix<xmax+1; ix++)
for (iy=ymin-1; iy<ymax+1; iy++) {
// cout << ix << " " << iy << endl;
thisEvent=filter->getEventType(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;
}

View File

@ -0,0 +1,52 @@
#include <TFile.h>
#include <TThread.h>
#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();
}
}

View File

@ -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

View File

@ -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
*/

View File

@ -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
}

View File

@ -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 <TTree.h>
#endif
#include <iostream>
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 dataType>
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<dataType> *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; i<ny; i++) {
stat[i]=new pedestalSubtraction[nx];
stat[i]->SetNPedestals(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; i<ny; i++) delete [] stat[i]; delete [] stat;};
/** resets the pedestalSubtraction array and the commonModeSubtraction */
void newDataSet(){iframe=-1; for (int iy=0; iy<ny; iy++) for (int ix=0; ix<nx; ix++) stat[iy][ix].Clear(); if (cmSub) cmSub->Clear(); };
/** resets the eventMask to undefined and the commonModeSubtraction */
void newFrame(){iframe++; for (int iy=0; iy<ny; iy++) for (int ix=0; ix<nx; ix++) eventMask[iy][ix]=UNDEFINED_EVENT; if (cmSub) cmSub->newFrame();};
/** 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<nx && iy>=0 && iy<ny) {
// cout << ix << " " << iy << " " << val << endl;
stat[iy][ix].addToPedestal(val);
if (cmSub && det->isGood(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<nx && iy>=0 && iy<ny) if (cmSub && cm>0) 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<nx && iy>=0 && iy<ny) return stat[iy][ix].getPedestalRMS();else return -1;};
/** sets/gets number of rms threshold to detect photons
\param n number of sigma to be set (0 or negative gets)
\returns actual number of sigma parameter
*/
double setNSigma(double n=-1){if (n>0) 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 (iframe<nDark) {
if (cm==0) {
// cout << "=" << endl;
addToPedestal(det->getValue(data, ix, iy),ix,iy);
cluster->set_data(dataSign*(det->getValue(data, ix, iy)-getPedestal(ix,iy,cm)), 0,0 );
// cout << "=" << endl;
}
return UNDEFINED_EVENT;
}
// if (eventMask[iy][ix]==UNDEFINED) {
eventMask[iy][ix]=PEDESTAL;
cluster->x=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)<ny && (ix+ic)>=0 && (ix+ic)<nx) {
cluster->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; ix<nx; ix++) for (iy=0; iy<ny; iy++) stat[iy][ix].SetNPedestals(i); return stat[0][0].SetNPedestals();};
/** returns value for cluster element in relative coordinates
\param ic x coordinate (center is (0,0))
\param ir y coordinate (center is (0,0))
\returns cluster element
*/
double getClusterElement(int ic, int ir=0){return cluster->get_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<dataType> *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

View File

@ -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

View File

@ -0,0 +1,251 @@
#ifndef SLSDETECTORDATA_H
#define SLSDETECTORDATA_H
#include <inttypes.h>
#include <iostream>
#include <fstream>
using namespace std;
template <class dataType>
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<nx; j++)
dataROIMask[i][j]=1;
}
setDataMap(dMap);
setDataMask(dMask);
setDataROIMask(dROI);
};
virtual ~slsDetectorData() {
for(int i = 0; i < ny; i++) {
delete [] dataMap[i];
delete [] dataMask[i];
delete [] dataROIMask[i];
}
delete [] dataMap;
delete [] dataMask;
delete [] dataROIMask;
}
/**
defines the data map (as offset) - no error checking if datasize and offsets are compatible!
\param dMap array of size nx*ny storing the pointers to the data in the dataset (as offset). If NULL (default),the data are arranged as if read out row by row (dataMap[iy][ix]=(iy*nx+ix)*sizeof(dataType);)
*/
void setDataMap(int **dMap=NULL) {
if (dMap==NULL) {
for (int iy=0; iy<ny; iy++)
for (int ix=0; ix<nx; ix++)
dataMap[iy][ix]=(iy*nx+ix)*sizeof(dataType);
} else {
for (int iy=0; iy<ny; iy++)
for (int ix=0; ix<nx; ix++)
dataMap[iy][ix]=dMap[iy][ix];
}
};
/**
defines the data mask i.e. the polarity of the data
\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)
*/
void setDataMask(dataType **dMask=NULL){
if (dMask!=NULL) {
for (int iy=0; iy<ny; iy++)
for (int ix=0; ix<nx; ix++)
dataMask[iy][ix]=dMask[iy][ix];
} else {
for (int iy=0; iy<ny; iy++)
for (int ix=0; ix<nx; ix++)
dataMask[iy][ix]=0;
}
};
/**
defines the region of interest and/or the bad channels mask
\param dROI Array of size nx*ny. The lements are 1s if the channel is good or in the ROI, 0 is bad or out of the ROI. NULL (default) means all 1s.
*/
void setDataROIMask(int **dROI=NULL){
if (dROI!=NULL) {
for (int iy=0; iy<ny; iy++)
for (int ix=0; ix<nx; ix++)
dataROIMask[iy][ix]=dROI[iy][ix];
} else {
for (int iy=0; iy<ny; iy++)
for (int ix=0; ix<nx; ix++)
dataROIMask[iy][ix]=1;
}
};
/**
Define bad channel or roi mask for a single channel
\param ix channel x coordinate
\param iy channel y coordinate (1 for strips)
\param i 1 if pixel is good (or in the roi), 0 if bad
\returns 1 if pixel is good, 0 if it's bad, -1 if pixel is out of range
*/
int setGood(int ix, int iy, int i=1) { if (ix>=0 && ix<nx && iy>=0 && iy<ny) dataROIMask[iy][ix]=i; return isGood(ix,iy);};
/**
Define bad channel or roi mask for a single channel
\param ix channel x coordinate
\param iy channel y coordinate (1 for strips)
\returns 1 if pixel is good, 0 if it's bad, -1 if pixel is out of range
*/
int isGood(int ix, int iy) { if (ix>=0 && ix<nx && iy>=0 && iy<ny) return dataROIMask[iy][ix]; else return -1;};
/**
Returns detector size in x,y
\param npx reference to number of channels in x
\param npy reference to number of channels in y (will be 1 for strips)
\returns total number of channels
*/
int getDetectorSize(int &npx, int &npy){npx=nx; npy=ny; return nx*ny;};
/** Returns the size of the data frame */
int getDataSize() {return dataSize;};
/** changes the size of the data frame */
int setDataSize(int d) {dataSize=d; return dataSize;};
/**
Returns the value of the selected channel for the given dataset. Virtual function, can be overloaded.
\param data pointer to the dataset (including headers etc)
\param ix pixel number in the x direction
\param iy pixel number in the y direction
\returns data for the selected channel, with inversion if required
*/
virtual dataType getChannel(char *data, int ix, int iy=0) {
dataType m=0, d=0;
if (ix>=0 && ix<nx && iy>=0 && iy<ny && dataMap[iy][ix]>=0 && dataMap[iy][ix]<dataSize) {
m=dataMask[iy][ix];
d=*((dataType*)(data+dataMap[iy][ix]));
}
return d^m;
};
/**
Returns the value of the selected channel for the given dataset as double.
\param data pointer to the dataset (including headers etc)
\param ix pixel number in the x direction
\param iy pixel number in the y direction
\returns data for the selected channel, with inversion if required as double
*/
virtual double getValue(char *data, int ix, int iy=0) {return (double)getChannel(data, ix, iy);};
/**
Returns the frame number for the given dataset. Purely virtual func.
\param buff pointer to the dataset
\returns frame number
*/
virtual int getFrameNumber(char *buff)=0;
/**
Returns the packet number for the given dataset. purely virtual func
\param buff pointer to the dataset
\returns packet number number
virtual int getPacketNumber(char *buff)=0;
*/
/**
Loops over a memory slot until a complete frame is found (i.e. all packets 0 to nPackets, same frame number). purely virtual func
\param data pointer to the memory to be analyzed
\param ndata reference to the amount of data found for the frame, in case the frame is incomplete at the end of the memory slot
\param dsize size of the memory slot to be analyzed
\returns pointer to the beginning of the last good frame (might be incomplete if ndata smaller than dataSize), or NULL if no frame is found
*/
virtual char *findNextFrame(char *data, int &ndata, int dsize)=0;
/**
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 begin of the last good frame, NULL if no frame is found or last frame is incomplete
*/
virtual char *readNextFrame(ifstream &filebin)=0;
protected:
const int nx; /**< Number of pixels in the x direction */
const int ny; /**< Number of pixels in the y direction */
int dataSize; /**<size of the data constituting one frame */
int **dataMap; /**< Array of size nx*ny storing the pointers to the data in the dataset (as offset)*/
dataType **dataMask; /**< 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) */
int **dataROIMask; /**< Array of size nx*ny 1 if channel is good (or in the ROI), 0 if bad channel (or out of ROI) */
};
#endif

View File

@ -0,0 +1,171 @@
#ifndef SLSRECEIVERDATA_H
#define SLSRECEIVERDATA_H
#include "slsDetectorData.h"
template <class dataType>
class slsReceiverData : public slsDetectorData<dataType> {
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<dataType>(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 (np<nPackets) {
if (np>0)
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; ip<np; ip++)
memcpy(data+ip*packetSize,retval+ip*packetSize,packetSize);
}
} else if (np>nPackets) {
cout << "*******too many packets!!!!!!!!!!" << endl;
delete [] data;
return NULL;
} else {
// cout << "." << endl;;
np++;
}
}
}
delete [] data;
return NULL;
};
private:
const int nPackets; /**<number of UDP packets constituting one frame */
const int packetSize; /**< size of a udp packet */
};
#endif

View File

@ -0,0 +1,51 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<?fileVersion 4.0.0?>
<cproject storage_type_id="org.eclipse.cdt.core.XmlProjectDescriptionStorage">
<storageModule moduleId="org.eclipse.cdt.core.settings">
<cconfiguration id="0.1592123610">
<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="0.1592123610" moduleId="org.eclipse.cdt.core.settings" name="Default">
<externalSettings/>
<extensions>
<extension id="org.eclipse.cdt.core.VCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
</extensions>
</storageModule>
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
<configuration buildProperties="" description="" id="0.1592123610" name="Default" parent="org.eclipse.cdt.build.core.prefbase.cfg">
<folderInfo id="0.1592123610." name="/" resourcePath="">
<toolChain id="org.eclipse.cdt.build.core.prefbase.toolchain.2043853512" name="No ToolChain" resourceTypeBasedDiscovery="false" superClass="org.eclipse.cdt.build.core.prefbase.toolchain">
<targetPlatform id="org.eclipse.cdt.build.core.prefbase.toolchain.2043853512.1428560959" name=""/>
<builder id="org.eclipse.cdt.build.core.settings.default.builder.1228246701" keepEnvironmentInBuildfile="false" managedBuildOn="false" name="Gnu Make Builder" superClass="org.eclipse.cdt.build.core.settings.default.builder"/>
<tool id="org.eclipse.cdt.build.core.settings.holder.libs.891716849" name="holder for library settings" superClass="org.eclipse.cdt.build.core.settings.holder.libs"/>
<tool id="org.eclipse.cdt.build.core.settings.holder.1775606856" name="Assembly" superClass="org.eclipse.cdt.build.core.settings.holder">
<inputType id="org.eclipse.cdt.build.core.settings.holder.inType.98773194" languageId="org.eclipse.cdt.core.assembly" languageName="Assembly" sourceContentType="org.eclipse.cdt.core.asmSource" superClass="org.eclipse.cdt.build.core.settings.holder.inType"/>
</tool>
<tool id="org.eclipse.cdt.build.core.settings.holder.41809089" name="GNU C++" superClass="org.eclipse.cdt.build.core.settings.holder">
<inputType id="org.eclipse.cdt.build.core.settings.holder.inType.817253715" languageId="org.eclipse.cdt.core.g++" languageName="GNU C++" sourceContentType="org.eclipse.cdt.core.cxxSource,org.eclipse.cdt.core.cxxHeader" superClass="org.eclipse.cdt.build.core.settings.holder.inType"/>
</tool>
<tool id="org.eclipse.cdt.build.core.settings.holder.1467561536" name="GNU C" superClass="org.eclipse.cdt.build.core.settings.holder">
<inputType id="org.eclipse.cdt.build.core.settings.holder.inType.210475521" languageId="org.eclipse.cdt.core.gcc" languageName="GNU C" sourceContentType="org.eclipse.cdt.core.cSource,org.eclipse.cdt.core.cHeader" superClass="org.eclipse.cdt.build.core.settings.holder.inType"/>
</tool>
</toolChain>
</folderInfo>
</configuration>
</storageModule>
<storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
</cconfiguration>
</storageModule>
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
<project id="slsReceiver.null.670781774" name="slsReceiver"/>
</storageModule>
<storageModule moduleId="scannerConfiguration">
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
<scannerConfigBuildInfo instanceId="0.1592123610">
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
</scannerConfigBuildInfo>
</storageModule>
<storageModule moduleId="org.eclipse.cdt.core.LanguageSettingsProviders"/>
</cproject>

View File

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>Receiver</name>
<comment></comment>
<projects>
<project>newMythenSoftware</project>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.cdt.managedbuilder.core.genmakebuilder</name>
<triggers>clean,full,incremental,</triggers>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder</name>
<triggers>full,incremental,</triggers>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.cdt.core.cnature</nature>
<nature>org.eclipse.cdt.core.ccnature</nature>
<nature>org.eclipse.cdt.managedbuilder.core.managedBuildNature</nature>
<nature>org.eclipse.cdt.managedbuilder.core.ScannerConfigNature</nature>
</natures>
</projectDescription>

View File

@ -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

View File

@ -0,0 +1,195 @@
/**
* @file RestHelper.h
* @author Leonardo Sala <leonardo.sala@psi.ch>
* @date Tue Mar 25 09:28:19 2014
*
* @brief
*
*
*/
#include <Poco/Net/HTTPClientSession.h>
#include <Poco/Net/HTTPRequest.h>
#include <Poco/Net/HTTPResponse.h>
#include <Poco/StreamCopier.h>
#include <Poco/Path.h>
#include <Poco/URI.h>
#include <Poco/Exception.h>
#include <Poco/Timespan.h>
#include "JsonBox/Value.h"
#include <iostream>
#include <string>
#include <exception>
/// 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(n<N_CONNECTION_TRIES){
try {
if (request_body == "")
session->sendRequest( (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;
}
};

View File

@ -0,0 +1,254 @@
/*
* eigerReceiver.cpp
*
* Created on: Mar 11, 2014
* Author: billich
*/
#include <iostream>
#include <string>
#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 " <<status);
return(status);
}
char *setFileName(const char c[]) {
DEBUG("setFileName() called with " << c <<".");
scan_config.fileName = c;
return(this->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();
}

View File

@ -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 */

View File

@ -0,0 +1,99 @@
/*
* eigerReceiver.cpp
*
* Created on: Mar 11, 2014
* Author: billich
*/
#include <iostream>
#include <string>
#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();
}

View File

@ -0,0 +1,97 @@
/*
* eigerReceiverTest.cpp
*
* Created on: Mar 11, 2014
* Author: billich
*/
#include <iostream>
#include <string>
#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 <<prefix<< "start EigerReceiver tests" << endl;
EigerReceiver *receiver = EigerReceiver::create();
int status = receiver->getStatus();
char *c0 = receiver->getDetectorHostname();
if (c0 == NULL) {
cout <<prefix<< "getDetectorHostname() returned NULL, as expected before initialization." << endl;
}
delete[] c0;
cout <<prefix<< "initialize 4 times - only the second should work" << endl;
receiver->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 <<prefix<< "got detector hostname " << c6 << " after initialization;" <<endl<<endl;
delete[] c6;
cout <<prefix<< "try get*() methods before set*() - expect default values" <<endl;
char *c1 = receiver->getFileName();
cout <<prefix<< "got file name <" << c1 <<">." << endl;
delete[] c1;
char *c2 = receiver->getFilePath();
cout <<prefix<< "got path name <" << c2 <<">." << endl;
delete[]c2;
int range = receiver->getDynamicRange();
cout <<prefix<< "got dynamic range " << range << endl;
int tag = receiver->getScanTag();
cout <<prefix<< "got scan tag " << tag << endl;
cout << endl;
char *c3 = receiver->setFileName( "some_other_name");
cout <<prefix<< "got file name <" << c3 << "> after setting to <some_other_name>" << endl << endl;
delete[] c3;
char *c4 = receiver->setFilePath( "some_other_path");
cout <<prefix<< "got file path <" << c4 << "> after setting to <some_other_path>" << endl << endl;
delete[] c4;
range = receiver->setDynamicRange(8);
cout <<prefix<< "got dynamic range " << range << " after setting it to 8." << endl << endl;
tag = receiver->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();
}

View File

@ -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 <iostream>
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;
}

File diff suppressed because it is too large Load Diff

View File

@ -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

File diff suppressed because it is too large Load Diff

View File

@ -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 <TTree.h>
#include <TFile.h>
#endif
#include <string.h>
#include <pthread.h>
#include <stdio.h>
#include <semaphore.h>
/**
* @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<char>* fifo;
/** circular fifo to store addresses of data already written and ready to be resued*/
CircularFifo<char>* 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<uint16_t> *singlePhotonDet[MAX_NUM_WRITER_THREADS];
slsReceiverData<uint16_t> *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

View File

@ -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);
}

View File

@ -0,0 +1,85 @@
#ifndef SLS_RECEIVER_USERS_H
#define SLS_RECEIVER_USERS_H
#include <stdio.h>
#include <stdint.h>
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