### 24.8 Examples

The following example programs demonstrate the use of ntuples in managing a large dataset. The first program creates a set of 10,000 simulated “events”, each with 3 associated values (x,y,z). These are generated from a Gaussian distribution with unit variance, for demonstration purposes, and written to the ntuple file `test.dat`.

    #include <gsl/gsl_ntuple.h>
    #include <gsl/gsl_rng.h>
    #include <gsl/gsl_randist.h>

    struct data
    {
      double x;
      double y;
      double z;
    };

    int
    main (void)
    {
      const gsl_rng_type * T;
      gsl_rng * r;

      struct data ntuple_row;
      int i;

      gsl_ntuple *ntuple
        = gsl_ntuple_create ("test.dat", &ntuple_row,
                             sizeof (ntuple_row));

      gsl_rng_env_setup ();

      T = gsl_rng_default;
      r = gsl_rng_alloc (T);

      for (i = 0; i < 10000; i++)
        {
          ntuple_row.x = gsl_ran_ugaussian (r);
          ntuple_row.y = gsl_ran_ugaussian (r);
          ntuple_row.z = gsl_ran_ugaussian (r);

          gsl_ntuple_write (ntuple);
        }

      gsl_ntuple_close (ntuple);
      gsl_rng_free (r);

      return 0;
    }

The next program analyses the ntuple data in the file `test.dat`. The analysis procedure is to compute the squared-magnitude of each event, E^2=x^2+y^2+z^2, and select only those which exceed a lower limit of 1.5. The selected events are then histogrammed using their E^2 values.

    #include <math.h>
    #include <gsl/gsl_ntuple.h>
    #include <gsl/gsl_histogram.h>

    struct data
    {
      double x;
      double y;
      double z;
    };

    int sel_func (void *ntuple_data, void *params);
    double val_func (void *ntuple_data, void *params);

    int
    main (void)
    {
      struct data ntuple_row;

      gsl_ntuple *ntuple
        = gsl_ntuple_open ("test.dat", &ntuple_row,
                           sizeof (ntuple_row));
      double lower = 1.5;

      gsl_ntuple_select_fn S;
      gsl_ntuple_value_fn V;

      gsl_histogram *h = gsl_histogram_alloc (100);
      gsl_histogram_set_ranges_uniform(h, 0.0, 10.0);

      S.function = &sel_func;
      S.params = &lower;

      V.function = &val_func;
      V.params = 0;

      gsl_ntuple_project (h, ntuple, &V, &S);
      gsl_histogram_fprintf (stdout, h, "%f", "%f");
      gsl_histogram_free (h);
      gsl_ntuple_close (ntuple);

      return 0;
    }

    int
    sel_func (void *ntuple_data, void *params)
    {
      struct data * data = (struct data *) ntuple_data;
      double x, y, z, E2, scale;
      scale = *(double *) params;

      x = data->x;
      y = data->y;
      z = data->z;

      E2 = x * x + y * y + z * z;

      return E2 > scale;
    }

    double
    val_func (void *ntuple_data, void *params)
    {
      (void)(params); /* avoid unused parameter warning */
      struct data * data = (struct data *) ntuple_data;
      double x, y, z;

      x = data->x;
      y = data->y;
      z = data->z;

      return x * x + y * y + z * z;
    }

The following plot shows the distribution of the selected events. Note the cut-off at the lower bound.