Tutorials Step 2: First Super-K Code Example (C++ version)

A First Super-K Code Example

Here is a first Super-K program example. It’s in C++.  Most of the Super-K software is written in Fortran, but it has been slowly transitioning towards C++ over the years.

All this program does is to take a raw Super-K data file, and dump to the screen a list of events; for each event, it then loops through the ID PMT hits and writes to the screen: hit number, cable number, charge, time.


Hopefully by now you have done the setup steps.  If you don’t have your .tcshrc set up yet (and you really should, and you should be running tcsh), you’ll need to type the following before doing this example (on the Duke machines).  See the setup steps for the corresponding commands on the Kamioka machines.  For future, tutorials, this part will be assumed to already be done.

setenv PROJECT /var/phy/project/hep/neutrino
source $PROJECT/soft-CentOS8/updateEnv/env.csh
setenv TUTEXAMPLES /disk/usr2/jalbert/tutorial-example-files

Files for this example

Copy the following files from


into your tutorials subdirectory of your work directory (or anywhere in your work directory you want, really):

  • example1c.cc: contains the source code for the program
  • fort_fopen.F
  • example1c.sh: A shell script to launch the example1c program
  • GNUmakefile: used to compile the program
  • fort_fopen.F: A Fortran wrapper program to allow us to make calls to some Fortran programs from C++.

First, before doing anything else, take a look at example1c.cc, and see if you can follow generally what it’s doing. We put numerous comments in it (labeled by a “//” at the beginning of the line) which we hope will help somewhat.

  • Before the main program starts, we load some header files, and declares some functions from Fortran so they can be called in C++.
  • After the main program begins, there’s a short check to make sure the input is correct, and it reads the input file name(s).
  • Next, it performs some initializations, options setting, etc.
  • Then, it loops over input files, and uses fort_fopen (a wrapper file for SKOPENF (a routine in the SK libraries)) to open a file.
  • Then, it loops over events in the file, and uses skcread (the C++ compatible version of SKREAD (another SK routine)) to read each event. What “reading an event” means: SKREAD copies information (after a bit of processing) from the ZBS banks of the files into some data structures, defined in the header files.  These structs correspond to the FORTRAN common blocks used in the Fortran version of the code.  After the read of the event, you can access the event’s information via variables in these structs. For instance, after the read, the skq_ struct is filled with charge information, and skq_.nqisk contains the number of ID hits in the event, and the skq_.qisk[] array contains the charge values for each PMT of the event.  The full lists of these structs and variables are in the header files.
  • For each event, it prints the run number, subrun number and event number. Then, for each event, it loops over the hits in the event, and writes to the screen: hit number, cable number (same as tube number), charge (in photoelectrons), and time (in nanoseconds). In the loop:
           for (int ihit = 0; ihit != skq_.nqisk; ihit++)
             cablenum = skchnl_.ihcab[ihit];
             std::cout << ihit+1 << "\t" <<                     // hit number
                          skchnl_.ihcab[ihit] << "\t" <<        // hit cable #
                          skq_.qisk[cablenum-1] << "\t" <<      // hit charge
                          skt_.tisk[cablenum-1] << std::endl;   // hit time
           } // end loop over hits

    ihit is the hit number, skchnl_.ihcab[ihit] is the tube number, and qisk and tisk are the charge and time, respectively, for that tube.  Note that we use one less than the cable number in our array index.  This is because C++ arrays start at 0, while Fortran arrays start at 1.

  • When it reaches the end of the events in a file, it starts the next file, if there is another file; otherwise, it stops.

Note that this program will be run with one or more arguments the command line.  That’s what the whole argc and argv business is about.  Thus, the program will read whatever file you tell it to read when you start it.  If you input multiple files (one after another), it will read them in order.

Take a look at example1c.sh.  This is a shell script.  The commands here are similar to what you’d type in on the command line (though there are some added comments).  You can see that this script will modify the LD_LIBRARY_PATH environment variable, and then run the example1c executable with one argument.  You will likely be using a lot of shell scripts in the future, but shell scripts are mostly for executing code in an organized way or file manipulation, so we won’t get into any fancy syntax there.  Note that your .tcshrc file is technically a shell script too!

Finally, look at the GNUmakefile. This is a file which contains information for compiling and linking the program. Needed libraries and includes are linked against automatically using information specifed in $(SKOFL_ROOT)/config.gmk. The instructions for compiling this example are in there.  Don’t worry too much about the details of GNUmakefiles right now.

Running this example

  • Compile the program by doing
    make example1c

    This compiles and links the source code (example1c.cc) according to the GNUmakefile instructions. The resulting executable (called example1c, compiled programs traditionally don’t have file extensions in linux) is created in your working directory.

  • Next you should be able to run the executable using the script, with
     ./example1c filename

    where the filename argument is the SK data file you want to run on. For this test, I suggest you do

    ./example1c.sh $TUTEXAMPLES/rfm_run060960.000096.tqr.zbs

    This file is a nearly unprocessed raw data file, without any reconstructed information and all triggers.

  • Look at the output. You might want to “pipe into less” to see it more slowly:
    ./example1c.sh $TUTEXAMPLES/rfm_run060960.000096.tqr.zbs | less

    and hit the space bar for paging output, “b” to go back.

  • Try seeing what you get by modifying the source code (say, adding a cout (writes to screen) statement), recompiling and rerunning.

Now you’ve gotten to see some code that reads SK data, compiled it into an executable, and used that to read some data.  Then, you played around with the code to get a better feel for it.

The next example will be to make some histograms.

Back to the tutorials top page