DRS4 Forum
  DRS4 Discussion Forum, Page 1 of 40  Not logged in ELOG logo
ID Date Authorup Subject
  487   Thu Mar 31 19:30:26 2016 Abaz KryemadhiTrigger on the And of a positive and negative signal

I would like to be able to trigger in this fashon:  channel 0 > 0.1 and. channel 1< -0.1,  because I have a positive and a negative signal.  Can DRS4 (5) Eval board do this kind of trigger?

Thanks!

Abaz

  489   Thu Mar 31 19:44:38 2016 Abaz KryemadhiTrigger on the And of a positive and negative signal

Ok, thanks!  do you know an easy in-line inverter like mini-circuit or digikey?    Can also redesign the detector I gues to produce positive signals, just it might be easier if there was a simple inverter if you are aware of? thanks Abaz

Stefan Ritt wrote:

No. You have to use an inverter for one of your signals.

Stefan

Abaz Kryemadhi wrote:

I would like to be able to trigger in this fashon:  channel 0 > 0.1 and. channel 1< -0.1,  because I have a positive and a negative signal.  Can DRS4 (5) Eval board do this kind of trigger?

Thanks!

Abaz

 

 

  491   Thu Mar 31 20:38:05 2016 Abaz KryemadhiTrigger on the And of a positive and negative signal

Thanks, that looks just fine.

Stefan Ritt wrote:

Here is one (SI 100): https://www.picoquant.com/products/category/accessories/adapters-splitters-cables-various-accessories-for-photon-counting-setups

Abaz Kryemadhi wrote:

Ok, thanks!  do you know an easy in-line inverter like mini-circuit or digikey?    Can also redesign the detector I gues to produce positive signals, just it might be easier if there was a simple inverter if you are aware of? thanks Abaz

Stefan Ritt wrote:

No. You have to use an inverter for one of your signals.

Stefan

Abaz Kryemadhi wrote:

I would like to be able to trigger in this fashon:  channel 0 > 0.1 and. channel 1< -0.1,  because I have a positive and a negative signal.  Can DRS4 (5) Eval board do this kind of trigger?

Thanks!

Abaz

 

 

 

 

  493   Fri Apr 1 01:30:40 2016 Abaz KryemadhiTrigger on the And of a positive and negative signal

Hi Chris,

 I am looking at Sensl SiPMs as well,  can you send the part number from Coilcraft?

Thanks!

Abaz

Chris Thompson wrote:

I needed a fast pulse inverter in order to feed signals from the recent SensL SiPMs into a conventional CFD which only accepted negative signals. I got a very small ferite torridal transformer from Coilcraft and wired up to invert signals then inserted into in 50 ohm coax cable and it works fine. These things cost only a few cents each!

Abaz Kryemadhi wrote:

Thanks, that looks just fine.

Stefan Ritt wrote:

Here is one (SI 100): https://www.picoquant.com/products/category/accessories/adapters-splitters-cables-various-accessories-for-photon-counting-setups

Abaz Kryemadhi wrote:

Ok, thanks!  do you know an easy in-line inverter like mini-circuit or digikey?    Can also redesign the detector I gues to produce positive signals, just it might be easier if there was a simple inverter if you are aware of? thanks Abaz

Stefan Ritt wrote:

No. You have to use an inverter for one of your signals.

Stefan

Abaz Kryemadhi wrote:

I would like to be able to trigger in this fashon:  channel 0 > 0.1 and. channel 1< -0.1,  because I have a positive and a negative signal.  Can DRS4 (5) Eval board do this kind of trigger?

Thanks!

Abaz

 

 

 

 

 

 

  497   Sat Apr 2 17:22:34 2016 Abaz KryemadhiTrigger on the And of a positive and negative signal

Thanks again,   this is very useful,  just another question did you put any other passive elements in the circuit for inverting the signal or just simply swaped the transformer connections? 

Chris Thompson wrote:

The coilcraft part number is: JA4220-ALB. Iordered two of them and they were sent as free samples. You might want to buy some slightly bigger ones. I found them so small it was very hard to solder the coax cable to the connectors. Since I got them, I managed to damage one as they are quite fragile! In the confirmation email I got there was some contact info which may be useful for you: "For help, contact Victoria Berner at 847-516-5551  vberner@coilcraft.com "  BTW every time I use this forum I'm told that my password is not valid. Each time I reset it according to the "Lost pasword preceedure. Then I can log on again. Its quite annoying.

Abaz Kryemadhi wrote:

Hi Chris,

 I am looking at Sensl SiPMs as well,  can you send the part number from Coilcraft?

Thanks!

Abaz

Chris Thompson wrote:

I needed a fast pulse inverter in order to feed signals from the recent SensL SiPMs into a conventional CFD which only accepted negative signals. I got a very small ferite torridal transformer from Coilcraft and wired up to invert signals then inserted into in 50 ohm coax cable and it works fine. These things cost only a few cents each!

Abaz Kryemadhi wrote:

Thanks, that looks just fine.

Stefan Ritt wrote:

Here is one (SI 100): https://www.picoquant.com/products/category/accessories/adapters-splitters-cables-various-accessories-for-photon-counting-setups

Abaz Kryemadhi wrote:

Ok, thanks!  do you know an easy in-line inverter like mini-circuit or digikey?    Can also redesign the detector I gues to produce positive signals, just it might be easier if there was a simple inverter if you are aware of? thanks Abaz

Stefan Ritt wrote:

No. You have to use an inverter for one of your signals.

Stefan

Abaz Kryemadhi wrote:

I would like to be able to trigger in this fashon:  channel 0 > 0.1 and. channel 1< -0.1,  because I have a positive and a negative signal.  Can DRS4 (5) Eval board do this kind of trigger?

Thanks!

Abaz

 

 

 

 

 

 

 

 

  499   Sun Apr 3 22:34:28 2016 Abaz KryemadhiTrigger on the And of a positive and negative signal

Thanks, great!

Chris Thompson wrote:

No there are no other components. I put a photo of the inverter with its cables SMA and one end, BNC at the other. You can see it is very small. I glued the inverter to a piece of thin plywood, and fixed the cables to it before attempting to solder them to the pads on the ferite bead support

Abaz Kryemadhi wrote:

Thanks again,   this is very useful,  just another question did you put any other passive elements in the circuit for inverting the signal or just simply swaped the transformer connections? 

Chris Thompson wrote:

The coilcraft part number is: JA4220-ALB. Iordered two of them and they were sent as free samples. You might want to buy some slightly bigger ones. I found them so small it was very hard to solder the coax cable to the connectors. Since I got them, I managed to damage one as they are quite fragile! In the confirmation email I got there was some contact info which may be useful for you: "For help, contact Victoria Berner at 847-516-5551  vberner@coilcraft.com "  BTW every time I use this forum I'm told that my password is not valid. Each time I reset it according to the "Lost pasword preceedure. Then I can log on again. Its quite annoying.

Abaz Kryemadhi wrote:

Hi Chris,

 I am looking at Sensl SiPMs as well,  can you send the part number from Coilcraft?

Thanks!

Abaz

Chris Thompson wrote:

I needed a fast pulse inverter in order to feed signals from the recent SensL SiPMs into a conventional CFD which only accepted negative signals. I got a very small ferite torridal transformer from Coilcraft and wired up to invert signals then inserted into in 50 ohm coax cable and it works fine. These things cost only a few cents each!

Abaz Kryemadhi wrote:

Thanks, that looks just fine.

Stefan Ritt wrote:

Here is one (SI 100): https://www.picoquant.com/products/category/accessories/adapters-splitters-cables-various-accessories-for-photon-counting-setups

Abaz Kryemadhi wrote:

Ok, thanks!  do you know an easy in-line inverter like mini-circuit or digikey?    Can also redesign the detector I gues to produce positive signals, just it might be easier if there was a simple inverter if you are aware of? thanks Abaz

Stefan Ritt wrote:

No. You have to use an inverter for one of your signals.

Stefan

Abaz Kryemadhi wrote:

I would like to be able to trigger in this fashon:  channel 0 > 0.1 and. channel 1< -0.1,  because I have a positive and a negative signal.  Can DRS4 (5) Eval board do this kind of trigger?

Thanks!

Abaz

 

 

 

 

 

 

 

 

 

 

  517   Wed Apr 27 20:04:12 2016 Abaz KryemadhiBest settings for time measurements

I am studing some pulses that are about 200-300 ns wide and a rise time of few ns,    which settings would be best for coincidence time measurements?

In some preliminary work I found for 700 MegaS the time measurement is better without time calibration (in -0.05 to 1V) rather than with time calibration in -0.5 to 0.5,  my pulses are about 60 mV.   Is it expected that always with time calibration time accuracy would be better or depends?   

Also I use this code snippet to find time for channel 1 and the same idea for chan. 2.

// find peak in channel 1 above threshold
      for (i=0 ; i<1022 ; i++)
         if (waveform[0][i] < threshold1 && waveform[0][i+1] >= threshold1) {
            tt1 = (threshold1-waveform[0][i])/(waveform[0][i+1]-waveform[0][i])*(time[0][i+1]-time[0][i])+time[0][i];
            break;
         }

 

Thanks!

Abaz

  727   Tue Jan 29 14:43:44 2019 Abaz KryemadhiROOT Macro for data acquired with the newest software

Hello,

Is there a root macro for decoding binary data acquired with the newest software for single board or multi-boards daisy chained?

Cheers,

Abaz

  747   Fri Mar 8 19:35:11 2019 Abaz KryemadhiROOT Macro for newest software

The older root macro did not work for me for data acquired with the newest software.

so for the newest software and multiple boards, I modified the read_binary.cpp into read_binary.C for those who like to use the root macro, see the attachment.  

 

Attachment 1: read_binary.C
/*
 
   Name:           read_binary.C
   Created by:     Stefan Ritt <stefan.ritt@psi.ch>
   Date:           July 30th, 2014
   Modified By:    Abaz Kryemadhi
   Date:           March 7th, 2019
 
   Purpose:        Example program under ROOT to read a binary data file written 
                   by the DRSOsc program. Decode time and voltages from waveforms 
                   and display them as a graph. Put values into a ROOT Tree for 
                   further analysis.
 
                   To run it, do:
 
                   - Crate a file test.dat via the "Save" button in DRSOsc
                   - start ROOT (type root)
                   root [0] .L read_binary.C+
                   root [1] decode("test.dat");
 
*/
 

#include <fcntl.h>
#include <unistd.h>
#include <math.h>


#include <string.h>
#include <stdio.h>
#include "TFile.h"
#include "TTree.h"
#include "TString.h"
#include "TGraph.h"
#include "TCanvas.h"
#include "Getline.h"
#include "TAxis.h"

typedef struct {
   char           tag[3];
   char           version;
} FHEADER;

typedef struct {
   char           time_header[4];
} THEADER;

typedef struct {
   char           bn[2];
   unsigned short board_serial_number;
} BHEADER;

typedef struct {
   char           event_header[4];
   unsigned int   event_serial_number;
   unsigned short year;
   unsigned short month;
   unsigned short day;
   unsigned short hour;
   unsigned short minute;
   unsigned short second;
   unsigned short millisecond;
   unsigned short range;
} EHEADER;

typedef struct {
   char           tc[2];
   unsigned short trigger_cell;
} TCHEADER;

typedef struct {
   char           c[1];
   char           cn[3];
} CHEADER;

/*-----------------------------------------------------------------------------*/

//int main(int argc, const char * argv[])
void decode(char *filename) {

   FHEADER  fh;
   THEADER  th;
   BHEADER  bh;
   EHEADER  eh;
   TCHEADER tch;
   CHEADER  ch;
   
   unsigned int scaler;
   unsigned short voltage[1024];
   double waveform[16][4][1024], time[16][4][1024];
   float bin_width[16][4][1024];
   int i, j, b, chn, n, chn_index, n_boards;
   double t1, t2, dt;
   //char filename[256];
   char rootfile[256];
   int ndt;
   double threshold, sumdt, sumdt2;
   double sum, baseline, max,amplitude1,amplitude2, amplitude3,amplitude4;
   
   // open the binary waveform file
   FILE *f = fopen(filename, "rb");
   if (f == NULL) {
      printf("Cannot find file \'%s\'\n", filename);
      return;
   }
   
   
    //open the root file
   strcpy(rootfile, filename);
   if (strchr(rootfile, '.'))
      *strchr(rootfile, '.') = 0;
   strcat(rootfile, ".root");
   TFile *outfile = new TFile(rootfile, "RECREATE");
   
   // define the rec tree
   TTree *rec = new TTree("rec","rec");
   rec->Branch("t1", time[0][0]     ,"t1[1024]/D");  
   rec->Branch("t2", time[0][1]     ,"t2[1024]/D");  
   rec->Branch("t3", time[0][2]     ,"t3[1024]/D");  
   rec->Branch("t4", time[0][3]     ,"t4[1024]/D");  
   rec->Branch("w1", waveform[0][0] ,"w1[1024]/D");
   rec->Branch("w2", waveform[0][1] ,"w2[1024]/D");
   rec->Branch("w3", waveform[0][2] ,"w3[1024]/D");
   rec->Branch("w4", waveform[0][3] ,"w4[1024]/D");
   rec->Branch("amplitude1", &amplitude1,"amplitude1/D");
   rec->Branch("amplitude2", &amplitude2,"amplitude2/D");
   rec->Branch("amplitude3", &amplitude3,"amplitude3/D");
   rec->Branch("amplitude4", &amplitude4,"amplitude4/D");
   // create canvas
   TCanvas *c1 = new TCanvas();
   
   // create graph
   TGraph *g = new TGraph(1024, (double *)time[0][0], (double *)waveform[0][0]);


   // read file header
   fread(&fh, sizeof(fh), 1, f);
   if (fh.tag[0] != 'D' || fh.tag[1] != 'R' || fh.tag[2] != 'S') {
      printf("Found invalid file header in file \'%s\', aborting.\n", filename);
      return;
   }
   
   if (fh.version != '2') {
      printf("Found invalid file version \'%c\' in file \'%s\', should be \'2\', aborting.\n", fh.version, filename);
      return;
   }

   // read time header
   fread(&th, sizeof(th), 1, f);
   if (memcmp(th.time_header, "TIME", 4) != 0) {
      printf("Invalid time header in file \'%s\', aborting.\n", filename);
      return;
   }

   for (b = 0 ; ; b++) {
      // read board header
      fread(&bh, sizeof(bh), 1, f);
      if (memcmp(bh.bn, "B#", 2) != 0) {
         // probably event header found
         fseek(f, -4, SEEK_CUR);
         break;
      }
      
      printf("Found data for board #%d\n", bh.board_serial_number);
      
      // read time bin widths
      memset(bin_width[b], sizeof(bin_width[0]), 0);
      for (chn=0 ; chn<5 ; chn++) {
         fread(&ch, sizeof(ch), 1, f);
         if (ch.c[0] != 'C') {
            // event header found
            fseek(f, -4, SEEK_CUR);
            break;
         }
         i = ch.cn[2] - '0' - 1;
         printf("Found timing calibration for channel #%d\n", i+1);
         fread(&bin_width[b][i][0], sizeof(float), 1024, f);
         // fix for 2048 bin mode: double channel
         if (bin_width[b][i][1023] > 10 || bin_width[b][i][1023] < 0.01) {
            for (j=0 ; j<512 ; j++)
               bin_width[b][i][j+512] = bin_width[b][i][j];
         }
      }
   }
   n_boards = b;
   
   // initialize statistics
   ndt = 0;
   sumdt = sumdt2 = 0;
   
   // loop over all events in the data file
   for (n=0 ; ; n++) {
      // read event header
      i = (int)fread(&eh, sizeof(eh), 1, f);
      if (i < 1)
         break;
      
      printf("Found event #%d %d %d\n", eh.event_serial_number, eh.second, eh.millisecond);
      
      // loop over all boards in data file
      for (b=0 ; b<n_boards ; b++) {
         
         // read board header
         fread(&bh, sizeof(bh), 1, f);
         if (memcmp(bh.bn, "B#", 2) != 0) {
            printf("Invalid board header in file \'%s\', aborting.\n", filename);
            return;
         }
         
         // read trigger cell
         fread(&tch, sizeof(tch), 1, f);
         if (memcmp(tch.tc, "T#", 2) != 0) {
            printf("Invalid trigger cell header in file \'%s\', aborting.\n", filename);
            return;
         }

         if (n_boards > 1)
            printf("Found data for board #%d\n", bh.board_serial_number);
         
         // reach channel data
         for (chn=0 ; chn<4 ; chn++) {
            
            // read channel header
            fread(&ch, sizeof(ch), 1, f);
            if (ch.c[0] != 'C') {
               // event header found
               fseek(f, -4, SEEK_CUR);
               break;
            }
            chn_index = ch.cn[2] - '0' - 1;
            fread(&scaler, sizeof(int), 1, f);
            fread(voltage, sizeof(short), 1024, f);
            
            for (i=0 ; i<1024 ; i++) {
               // convert data to volts
               waveform[b][chn_index][i] = (voltage[i] / 65536. + eh.range/1000.0 - 0.5);
               
               // calculate time for this cell
               for (j=0,time[b][chn_index][i]=0 ; j<i ; j++)
                  time[b][chn_index][i] += bin_width[b][chn_index][(j+tch.trigger_cell) % 1024];
            }
         }
         
         // align cell #0 of all channels
         t1 = time[b][0][(1024-tch.trigger_cell) % 1024];
         for (chn=1 ; chn<4 ; chn++) {
            t2 = time[b][chn][(1024-tch.trigger_cell) % 1024];
            dt = t1 - t2;
            for (i=0 ; i<1024 ; i++)
               time[b][chn][i] += dt;
         }
         
         t1 = t2 = 0;
         threshold = 0.3;
         
         // find peak in channel 1 above threshold
         for (i=0 ; i<1022 ; i++)
            if (waveform[b][0][i] < threshold && waveform[b][0][i+1] >= threshold) {
               t1 = (threshold-waveform[b][0][i])/(waveform[b][0][i+1]-waveform[b][0][i])*(time[b][0][i+1]-time[b][0][i])+time[b][0][i];
               break;
            }
         
         // find peak in channel 2 above threshold
         for (i=0 ; i<1022 ; i++)
            if (waveform[b][1][i] < threshold && waveform[b][1][i+1] >= threshold) {
               t2 = (threshold-waveform[b][1][i])/(waveform[b][1][i+1]-waveform[b][1][i])*(time[b][1][i+1]-time[b][1][i])+time[b][1][i];
               break;
            }
         
         // calculate distance of peaks with statistics
         if (t1 > 0 && t2 > 0) {
            ndt++;
            dt = t2 - t1;
            sumdt += dt;
            sumdt2 += dt*dt;
         }
     //Find baseline for channel 3 to get amplitude for ch3 
     sum=0.0;
      for (i=0 ; i<10; i++) {
         sum+=waveform[0][2][i];
       } 
       baseline=sum/10;
     //Find amplitude for channel 3 (this is example channel )
     max=-10000.0;
      for (i=0 ; i<1022; i++) {
         if (waveform[b][2][i]>max) {
            max=waveform[b][2][i];
       } 
      }
       amplitude3=max;
     // fill root tree
      rec->Fill();

  //Uncomment the following to see couple waveforms of voltage vs time
  /*   
      // fill graph
      for (i=0 ; i<1024 ; i++)
         g->SetPoint(i, time[b][2][i], waveform[b][2][i]);
      
      // draw graph and wait for user click
... 20 more lines ...
  557   Thu Nov 10 04:41:24 2016 Abhishek RajputBreak Statements in DRS4 Binary to ROOT Macro

Hello,

I recently modified the binary to ROOT convertor written by Stefan (https://midas.psi.ch/elogs/DRS4+Forum/361) so it can decode data taken with any channel or set of channels  on the DRS4. In the process of testing this modifed version for data taken on all 4 channels, I encountered problems with decoding some of the event data. More specifically, upon hitting a certain event in some channel, the histograms for that channel would no longer be filled and the histograms for subsequent channels would not be filled with any event at all. 

After considerable bug hunting, I discovered the source of this problem was due to the break statement in the following code extract from the ROOT to binary macro:

 for (n=0 ; n<5 ; n++) {
      // read event header
      i = fread(&eh, sizeof(eh), 1, f);
      if (i < 1)
         break;

For some events apparently, the event header fails to be read properly (fread line returns 0 in this case). Moreover, when I used the feof and ferror functions on a particular file I was testing, the feof function returned a value of 1.

So my questions deal with two scenarios.

Firstly, in the event of an fread error, is a break statement is necessary? Is it not possible to skip the voltage data for those events whose event header fails to be read properly? Or is it the case that when some "corrupted" event header is encountered, all waveform data subsequent to that event is likewise corrupted? If the former is the case, is it advisable to replace the break condition with an fseek line that advances the position indicator of the stream by an additional 2052*n_channels + 32 bytes (in accordance with the binary file specifications of page 25 on the DRS4 manual) so that the next set of voltage data can be read? 

Secondly, in the case of an end of file error, does there exist any possible solution? Or is such an error an indication of a faulty drs4 channel or corrupted binary file? 

Any help with the aforementioned issues would be greatly appreciated.

 

Abhishek

 

  560   Thu Nov 10 19:24:52 2016 Abhishek RajputBreak Statements in DRS4 Binary to ROOT Macro

Hello,

I am wondering why the code should be changed to i < sizeof(eh), since doesn't fread(&eh,sizeof(eh),1,f) return 1 in this scenario? I've confirmed with a cout statement that this is the case, so this break condition will therefore always trigger as sizeof(eh) is 32 bytes. 

Either way, I believe I figured out my problem. In my revised version of your code, I had two nested loops, the outer one being a loop over the channels and the inner one being a loop over the events. However, I really should have been doing the reverse considering the binary structure of the file.  Otherwise, the end of the file will be reached for only a single iteration of the channel loop if I choose to loop through all the events in the data file.

Once I modified the code to have the outer loop be over all the events and the inner one be over all the channels, I no longer suffered from breaks in the loops. 

Many thanks for your assistance. 

Abhishek 

Stefan Ritt wrote:

Hi,

fread() returns the number of bytes read and zero (I believe) if there is an end of file. So this break statement is a simple end-of-file test. There might be other erros such as hard disk failures, but these are extremely rare. 

If course the file should not end in the middle of an event header. If it does, it means the file is corrupted and truncated, and we should not continue to read that file, that's why there is the break. The internal file is just a series of bytes, it does not know about the event header, so there will be no "error" if we have for example a missing event header but a voltage array. To be correct, the code should actually read

for (n=0 ; n<5 ; n++) {
      // read event header
      i = fread(&eh, sizeof(eh), 1, f);
      if (i < sizeof(eh))
         break;

Hope this helps,

Stefan

Abhishek Rajput wrote:

Hello,

I recently modified the binary to ROOT convertor written by Stefan (https://midas.psi.ch/elogs/DRS4+Forum/361) so it can decode data taken with any channel or set of channels  on the DRS4. In the process of testing this modifed version for data taken on all 4 channels, I encountered problems with decoding some of the event data. More specifically, upon hitting a certain event in some channel, the histograms for that channel would no longer be filled and the histograms for subsequent channels would not be filled with any event at all. 

After considerable bug hunting, I discovered the source of this problem was due to the break statement in the following code extract from the ROOT to binary macro:

 for (n=0 ; n<5 ; n++) {
      // read event header
      i = fread(&eh, sizeof(eh), 1, f);
      if (i < 1)
         break;

For some events apparently, the event header fails to be read properly (fread line returns 0 in this case). Moreover, when I used the feof and ferror functions on a particular file I was testing, the feof function returned a value of 1.

So my questions deal with two scenarios.

Firstly, in the event of an fread error, is a break statement is necessary? Is it not possible to skip the voltage data for those events whose event header fails to be read properly? Or is it the case that when some "corrupted" event header is encountered, all waveform data subsequent to that event is likewise corrupted? If the former is the case, is it advisable to replace the break condition with an fseek line that advances the position indicator of the stream by an additional 2052*n_channels + 32 bytes (in accordance with the binary file specifications of page 25 on the DRS4 manual) so that the next set of voltage data can be read? 

Secondly, in the case of an end of file error, does there exist any possible solution? Or is such an error an indication of a faulty drs4 channel or corrupted binary file? 

Any help with the aforementioned issues would be greatly appreciated.

 

Abhishek

 

 

 

  566   Wed Nov 23 08:17:23 2016 Abhishek RajputPotential Incorrect Timing Calibration for DRS4 Data

Hello,

I was running through a particular binary file containing data taken on all 4 channels of the DRS4 and printing out the value of the first time sample for each channel (per event). While doing so, I noticed that some of these times were negative. For this dataset, channel 1 was chosen as the reference channel (which is the default setup in Stefan's DRS4 macro).  From my understanding, the calibration procedure delineated in the DRS4 manual and shown in the code below is supposed to sync the timing of each channel relative to sample 0. However, this does not appear to be the case for when I print out the time value of the first sample, I notice that only channel 1's 0th sample is set to 0. The first sample for the other channels is nonzero (and most often negative). 

Even more strange is when I test another 4-channel dataset with the same code, this issue does not appear. More specifically, the first time sample on each waveform on all channels is set to 0, as should be the case.

My question is therefore whether or not the timing calibration varies from dataset to dataset. My initial thought was that this should not be the case, but I have two different data sets taken on the same set of channels which give different timing calibration results. Are there any circumstances under which this behavior can happen? 

for (ch=0 ; ch<5 ; ch++) {
         i = fread(hdr, sizeof(hdr), 1, f);
         if (i < 1)
            break;
         if (hdr[0] != 'C') {
            // event header found
            fseek(f, -4, SEEK_CUR);
            break;      
         }
         chn_index = hdr[3] - '0' - 1;
         fread(voltage, sizeof(short), 1024, f);
         
         for (i=0 ; i<1024 ; i++) {
            // convert data to volts
            waveform[chn_index][i] = (voltage[i] / 65536. - 0.5);
            
            // calculate time for this cell
            for (j=0,time[chn_index][i]=0 ; j<i ; j++)
              time[chn_index][i] += bin_width[chn_index][(j+eh.trigger_cell) % 1024];            
         }
      }
    
      // align cell #0 of all channels
      t1 = time[0][(1024-eh.trigger_cell) % 1024];
      for (ch=1 ; ch<4 ; ch++) {
         t2 = time[ch][(1024-eh.trigger_cell) % 1024];
         dt = t1 - t2;
         for (i=0 ; i<1024 ; i++)
            time[ch][i] += dt;
      }
  573   Tue Nov 29 23:19:06 2016 Abhishek RajputPotential Incorrect Timing Calibration for DRS4 Data

Hello Stefan,

Thank you for the excellent explanation and diagram. This part of the code is now much clearer to me.

My other questions pertain to the "trigger cell". Firstly, what precisely does this mean? Moreover, how does the "trigger cell" relate to the trigger time delay we can set in the DRS4 application? This is causing some confusion for me, because regardless of where you set the trigger time delay on the DRS4 application, there are still points on the waveform that are saved prior to the moment in time when a pulse exceeds some voltage threshold we set in the application. I get the impression that "trigger delay" and "trigger cell" are unrelated concepts, so any clarification you can provide would be greatly appreciated.

Abhishek

Stefan Ritt wrote:

The code in the macro is correct. The misconception lies in the definition what "sample 0" means. Please view the attached picture. This is simplified case with a DRS chip with only 8 cells (instead of 1024). There are two events (blue and red). In the first event, the chip is stopped at trigger cell (tc) 2, in the second case at 5. Since the readout starts with the trigger cell, the first readout sample in the first event belongs to cell #2, the next one to cell #3 and so on. In the second (red) case, the first sample belongs to cell #5, the second to cell #6 and so on. "Aligning cells 0" now means that the physical cell 0 (not the readout sample) is aligned for each channel. In the first event, the 7th readout sample will have the same time in all channels, in the second event the fourth readout cells will have the same time. This is because physical cell #0 is always at different places inside the readout array.

Stefan

Abhishek Rajput wrote:

Hello,

I was running through a particular binary file containing data taken on all 4 channels of the DRS4 and printing out the value of the first time sample for each channel (per event). While doing so, I noticed that some of these times were negative. For this dataset, channel 1 was chosen as the reference channel (which is the default setup in Stefan's DRS4 macro).  From my understanding, the calibration procedure delineated in the DRS4 manual and shown in the code below is supposed to sync the timing of each channel relative to sample 0. However, this does not appear to be the case for when I print out the time value of the first sample, I notice that only channel 1's 0th sample is set to 0. The first sample for the other channels is nonzero (and most often negative). 

Even more strange is when I test another 4-channel dataset with the same code, this issue does not appear. More specifically, the first time sample on each waveform on all channels is set to 0, as should be the case.

My question is therefore whether or not the timing calibration varies from dataset to dataset. My initial thought was that this should not be the case, but I have two different data sets taken on the same set of channels which give different timing calibration results. Are there any circumstances under which this behavior can happen? 

for (ch=0 ; ch<5 ; ch++) {
         i = fread(hdr, sizeof(hdr), 1, f);
         if (i < 1)
            break;
         if (hdr[0] != 'C') {
            // event header found
            fseek(f, -4, SEEK_CUR);
            break;      
         }
         chn_index = hdr[3] - '0' - 1;
         fread(voltage, sizeof(short), 1024, f);
         
         for (i=0 ; i<1024 ; i++) {
            // convert data to volts
            waveform[chn_index][i] = (voltage[i] / 65536. - 0.5);
            
            // calculate time for this cell
            for (j=0,time[chn_index][i]=0 ; j<i ; j++)
              time[chn_index][i] += bin_width[chn_index][(j+eh.trigger_cell) % 1024];            
         }
      }
    
      // align cell #0 of all channels
      t1 = time[0][(1024-eh.trigger_cell) % 1024];
      for (ch=1 ; ch<4 ; ch++) {
         t2 = time[ch][(1024-eh.trigger_cell) % 1024];
         dt = t1 - t2;
         for (i=0 ; i<1024 ; i++)
            time[ch][i] += dt;
      }

 

 

  580   Fri Dec 9 04:17:46 2016 Abhishek RajputPotential Incorrect Timing Calibration for DRS4 Data

Hello Stefan,

Many thanks for the explanations. You've cleared my confusion in this matter.  

Abhishek Rajput

Stefan Ritt wrote:

The inverter chain in the DRS4 is continously running in a ring. Once you get a trigger, it is stopped. This happens in any of the 1024 cells. The last cell which sampled a signal plus ne is called "trigger cell". In the previous diagram in event #1, the last cell sampling was "1", so the trigger cell is "2". In event 2 (red case), the trigger cell is 5. If you would run like this, you see only the part of the waveform BEFORE your trigger (since the DRS4 is continously sampling and is stopped with the trigger). In order to see the full peak of your waveform, you can apply some external trigger to shift the trigger position to the right. This is done in the FPGA reading out the DRS4 chip. If your peak is let's say 20 ns wide, and you delay your trigger by 30 ns, you see the peak plus 10 ns right of the peak.

Stefan

Abhishek Rajput wrote:

Hello Stefan,

Thank you for the excellent explanation and diagram. This part of the code is now much clearer to me.

My other questions pertain to the "trigger cell". Firstly, what precisely does this mean? Moreover, how does the "trigger cell" relate to the trigger time delay we can set in the DRS4 application? This is causing some confusion for me, because regardless of where you set the trigger time delay on the DRS4 application, there are still points on the waveform that are saved prior to the moment in time when a pulse exceeds some voltage threshold we set in the application. I get the impression that "trigger delay" and "trigger cell" are unrelated concepts, so any clarification you can provide would be greatly appreciated.

Abhishek

 

  783   Mon Mar 23 15:03:28 2020 Ajay KrishnamurthyUSB trigger issue

Hello,

I had forgotten to disable the turn off the power to the USB drive on Windows and DRS4 stopped triggering. Now, we are all on quarantine and I am unable to reset the board to normal function. Are there any commands to reset the board remotely. I tried all of the default Windows based solutions such as disable USB port etc., but I am unable to do this. Only thing that has worked in the past is manually replugging the USB but I do not have the option to do that currently. Please help.

Thanks,

Ajay 

  292   Tue Sep 10 10:31:30 2013 Akira OkumuraUSB connection stops
Hello the DRS4 team,

I and some of my colleagues are using DRS4 evaluation boards (ver. 3) for the R&D of the Cherenkov Telescope Array project. During 
our PMT measurements, we have encountered a problem which is probably related to USB connection. In fact, I cannot reproduce this 
problem with my Linux virtual machine (Scientific Linux 5 64 bit), but other colleagues from three different universities in Japan 
reported the same problem with their real machines.

=== Short Summary ===
DRSBoard::SetFrequency occasionally stops

=== Environment ===
- drs-3.0.0
- Scientific Linux 5.5 (32 bit)
- lib-usb-devel-0.1.12-5.1.i386

=== Steps to Reproduce the Problem ===
1. Compile the attached file drs_simple.cpp with drs-3.0.0
2. Repeat the following command several times from a terminal

$ drs_simple -0.05 1000 ./outputfilename.dat true 2.

3. The above command may stop. In that case, you need to kill the command by Ctrl-C.

=== Comments ===
- Once the command stops, we cannot run the above command properly.
- If we unplug and plug the USB cable again, the command can be executed again.
- It seems that the program stops inside DRSBoard::SetFrequency

I would very appreciate it if you could give me any advise. If you need further information, please let me know.

Akira
Attachment 1: drs_simple.cpp
/********************************************************************\

  Name:         drs_simple.cpp
  Modified : Hide Katagiri
  Originally created by:   Stefan Ritt

  Contents:     Simple example application to read out a DRS4
                evaluation board

  $Id: drs_exam.cpp 13344 2009-04-28 07:34:45Z ritt@PSI.CH $

\********************************************************************/

#include <math.h>

#ifdef _MSC_VER

#include <windows.h>

#elif defined(OS_LINUX)

#define O_BINARY 0

#include <unistd.h>
#include <ctype.h>
#include <sys/ioctl.h>
#include <errno.h>

#define DIR_SEPARATOR '/'

#endif

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#include "strlcpy.h"
#include "DRS.h"

#include <fstream>
#include <iostream.h>//20130814 add tanaka

/*------------------------------------------------------------------*/

//std::cerr << "debug output 1" << std::endl;

int main(int argc, char *argv[])
{
   int i, j, nBoards;
   DRS *drs;
   DRSBoard *b;
   float time_array[1024];
   float wave_array[1][1024];// old ver. [8][1024]

std::cerr << "debug output 2" << std::endl;
   //// arguments, inirialization
   //
   float threshold=0.1;
   if (argc > 1) {
     threshold=atof(argv[1]); // in volt
   };
   //
std::cerr << "debug output 3" << std::endl;
   int nevent=10;
   if (argc > 2) {
     nevent=atoi(argv[2]); 
   };
   //
std::cerr << "debug output 4" << std::endl;
   char *fname="tmp.dat";
   if (argc > 3) {
     fname=argv[3]; 
   };
   //
std::cerr << "debug output 5" << std::endl;
   bool negative_edge=false; // true is negative
   if (argc > 3) {
     if (argv[4]=="true") {
       negative_edge=true; 
     };
   };
   //
std::cerr << "debug output 6" << std::endl;
   float freq=2.; // sampling frequency (GHz)
   if (argc > 4) {
     freq=atof(argv[5]); 
   };

std::cerr << "debug output 7" << std::endl;
   std::ofstream fout;
   fout.open(fname); // attention! file is truncated if the file fname already exists.
   if (!fout.is_open()) {
     exit(1);            
   }

std::cerr << "debug output 8" << std::endl;
   /* do initial scan */
   drs = new DRS();

std::cerr << "debug output 9" << std::endl;
   /* show any found board(s) */
   for (i=0 ; i<drs->GetNumberOfBoards() ; i++) {
      b = drs->GetBoard(i);
      printf("Found DRS4 evaluation board, serial #%d, firmware revision %d\n", 
         b->GetBoardSerialNumber(), b->GetFirmwareVersion());
   }

std::cerr << "debug output 10" << std::endl;
   /* exit if no board found */
   nBoards = drs->GetNumberOfBoards();
   if (nBoards == 0) {
      printf("No DRS4 evaluation board found\n");
      return 0;
   }

std::cerr << "debug output 11" << std::endl;
   /* continue working with first board only */
   b = drs->GetBoard(0);

std::cerr << "debug output 12" << std::endl;
   /* initialize board */
   b->Init();

std::cerr << "debug output 13" << std::endl;
   /* set sampling frequency */
   b->SetFrequency(freq, true);

std::cerr << "debug output 14" << std::endl;
   /* enable transparent mode needed for analog trigger */
   b->SetTranspMode(1);

std::cerr << "debug output 15" << std::endl;
   /* use following line to disable hardware trigger */
   //b->EnableTrigger(0, 0);

   /* use following line to enable external hardware trigger (Lemo) */
   b->EnableTrigger(1, 0);

std::cerr << "debug output 16" << std::endl;
   /* set input range to -0.5V ... +0.5V */
  // b->SetInputRange(0);
   b->SetInputRange(0.45); //does not work?

std::cerr << "debug output 17" << std::endl;
   /* use following lines to enable hardware trigger on CH1 at 250 mV positive edge */
   // b->EnableTrigger(0, 1);              // lemo off, analog trigger on
   // b->SetTriggerSource(0);              // use CH1 as source
   // b->SetTriggerLevel(0.25, false, 0);  // 0.25 V, positive edge, zero delay
   // b->SetTriggerLevel(threshold, negative_edge);  // -0.05 V, negative edge
   b->SetTriggerDelay(120);               // zero trigger delay, this places pulse in

std::cerr << "debug output 18" << std::endl;
   /* repeat nevent times */
   for (j=0 ; j<nevent ; j++) {

      /* start board (activate domino wave) */
      b->StartDomino();

//std::cerr << "debug output 19" << std::endl;
      /* wait for trigger */
      //fout << "% Start to read Event #" << j << std::endl;
      while (b->IsBusy());

//std::cerr << "debug output 20" << std::endl;      
      /* read all waveforms */
      b->TransferWaves(0, 8);

//std::cerr << "debug output 21" << std::endl;
      /* read time (X) array in ns */
      b->GetTime(0, time_array);

//std::cerr << "debug output 22" << std::endl;
      /* decode waveform (Y) array first channel in mV */
      b->GetWave(0, 0, wave_array[0]);

      /* decode waveform (Y) array second channel in mV*/
      // b->GetWave(0, 1, wave_array[1]);

      /* process waveform: add here some code to display or save waveform X=time[i], Y=wave_array[n][i] */

//std::cerr << "debug output 23" << std::endl;
      for (i=0;i<1024;i++) {
	fout << time_array[i] << " " << wave_array[0][i] << std::endl;
      }

//std::cerr << "debug output 24" << std::endl;
      /* print some progress indication */
      //fout << "% Event #" << j << " read successfully" << std::endl;
//std::cerr << "debug output 25" << std::endl;
   }

//std::cerr << "debug output 26" << std::endl;
   fout.close();
//std::cerr << "debug output 27" << std::endl;
   /* delete DRS object -> close USB connection */
   delete drs;
//std::cerr << "debug output 28" << std::endl;
}
  297   Wed Sep 25 14:42:00 2013 Akira OkumuraUSB connection stops
Hello Andrey,

Thank you for your advise. But we never terminated the program before closing and deleting the DRS object. What we did was just executing the program multiple times 
repeatedly.

Akira
  695   Wed May 9 14:07:10 2018 Alec ShacklefordWIndows Connection problem with drs507 SOLVED

Thank you for this fantastic solution. I had almost reinstalled windows 7 to see if that would solve the issue!

 

All the best,

Alec

Stefan Ritt wrote:

Dear Steven, many thanks for this information, this is very useful. I know of people having problems on Windows 10, maybe this will also help them.

Stefan

Steven Block wrote:

Hello All,

I too have been struggling with trying to get the drs4 (507) to work on my windows machine and I found it to be a problem with the libusb library. My solution is as follows and has worked on multiple PC's. I ran this solution after I first plugged in the drs4 and installed 507.

Go to http://zadig.akeo.ie/ and install the corresponding software.

After that, you will need to plug in the DRS4 to your computer. From there go to ‘Options’, and select ‘List all Devices’.

Finally, choose the DRS4 evaluation board from the list and press install driver and let it run. You should be fine after that. 

Best,

Steven

 

 

  678   Fri Apr 13 18:14:07 2018 Alessio BertiVoltage and Timing Calibration in drs_exam.cpp

Hi,

we were trying to implement an automatic way to calibrate our DRS4 both in voltage and in time (we have the V5 Evaluation Board). We started from drs_exam.cpp and tried with the following lines:

/* set input range to -0.5V ... +0.5V */

b->SetInputRange(0);

b->CalibrateVolt(NULL);
b->CalibrateTiming(NULL);

While the timing calibration seems to work (we checked with drsosc executable), the voltage calibration in our test program seems not to do the same as in drsosc when pressing the button "Execute Voltage Calibration". Specifically we think that no primary calibration, secondary calibration or spike removal is applied when calling CalibrateVolt(). It seems that the methods to perform those tasks are implemented in Osci.ccp/Osci.h, but drs_exam.cpp uses objects of the class DRS (i.e. defined in DRS.cpp and DRS.h).

Is there a way to execute the voltage calibration in drs_exam.cpp in the same way performed within drsosc?

Cheers,

Alessio

  683   Wed May 2 10:44:17 2018 Alessio BertiPeak at 0 mV in traces

Hi,

we modified drs_exam.cpp to read all 4 channels from the DRS4 and apply directly the spike removal (taken from Osci.cpp) during the acquisition phase. For test purposes, we don't save the data showing spikes and we focus on the data not having spikes (even if at the end we end up having triple and quadro spikes which are not removed by the spike removal routine, but they are rare). With this modified program we wanted to characterize the noise of the DRS4, so we took 30000 events at 5GSPS, triggering on channel 1 with a 10 MHz sine wave with 100 mV_pp (trigger level set at 10 mV), while channels 2,3 and 4 were left open without any input.

We then took a look at the data and plotted the noise histograms for channels 2,3 and 4, which you can find attached (without offset correction, named zero_peak_after_spike_removal_ch*.png). For completeness, we also attached the plot from ch1 (the sine wave). The selections in time and amplitude we applied had the goal to remove the high oscillations in amplitude occurring in the first and last samples and to discard the quadro spikes we had in the data.

We see that there is a peak at 0 mV in all histograms from all channels and scanning through the data, we saw that indeed the value 0 mV is stored many times for each event, thus originating the peak we see in the histograms. We also applied an offset correction to the data (taking the average of the first three most occuring amplitudes) of channels 2 (as an example) and the problem seems to be only partially removed.

We also noticed that this peak at 0 mV is present also when we acquired the data from the DRS4 with DRSosc saving the data in binary format.

So we had the following questions:

- why is the DRS4 saving so many times the value 0 mV (exactly 0 mV)?

- is there any way (in our case through software, preferably at acquisition time) to solve this problem?

Thank you for the help and best regards,

Alessio & Davide

 

Attachment 1: zero_peak_after_spike_removal_ch1.png
zero_peak_after_spike_removal_ch1.png
Attachment 2: zero_peak_after_spike_removal_ch2.png
zero_peak_after_spike_removal_ch2.png
Attachment 3: zero_peak_after_spike_removal_ch3.png
zero_peak_after_spike_removal_ch3.png
Attachment 4: zero_peak_after_spike_removal_ch4.png
zero_peak_after_spike_removal_ch4.png
Attachment 5: zero_peak_after_spike_removal_offset_correction_ch2.png
zero_peak_after_spike_removal_offset_correction_ch2.png
ELOG V3.1.4-80633ba