GTK: Displaying Query Data - show_data, write_minmax, file_add

Cogent Tools Demo and Tutorials: Version 4.0
Prev | Chapter 14. History Functions | Next

# 14.7. GTK: Displaying Query Data - `show_data`, `write_minmax`, `file_add`

The `show_data` function reads a `hsoutput*.dat` file, which contains interpolated query output from the Cascade Historian, retrieved by the `InterpolatorSettings`.`get_data` method. This function modifies the data slightly as necessary, puts it into the text widget, and sets up the `histoutputpl.dat` data file for gnuplot.

       /*--------------------------------------------------------------------
        * Function:    show_data
        * Returns:     t or nil
        * Description: Shows interpolated query results from the Cascade Historian
        *              in the text widget.  Sets up a single file (hsoutputpl.dat)
        *              that contains the content of all existing hsoutput files.
        *              This is necessary because gnuplot must read from a single file.
        *              Uses file_add() to do the actual reading and writing of the files.
        *------------------------------------------------------------------*/
       function show_data(txt_wgt, int_set, button, datalist, minmaxlist)
       {
         local start_time, tsk, infile, line, string_list, line_ret;
         local title_string, x_list, y_list;
         local f1, f2, f3, f4;

         x_list = car(datalist);
         y_list = cadr(datalist);
         midnite = find_midnite();

         if (int_set.fn == "NoInterpolator"  || int_set.fn == "Periodic")
           {
             x_is_time = t;
             title_string = "Query results: \n     Time             Y History\n";
           }
         else
           {
             x_is_time = nil;
             title_string = "Query results: \nX-hist / Y-hist\n";
           }

         midnite = find_midnite();
         txt_wgt.freeze();
         txt_wgt.backward_delete(txt_wgt.get_length());
         txt_wgt.insert(FONT, nil, nil, title_string, -1);

         if(int_set.dbflag == "NONE")
           infile = open("/tmp/cogentdemo/hsoutput.dat", "r");
         if(int_set.dbflag == "DB")
           infile = open("/tmp/cogentdemo/hsoutput2.dat", "r");
         if(int_set.dbflag == "DBP")
           infile = open("/tmp/cogentdemo/hsoutput3.dat", "r");
         if (infile)
           {
             line = nil;
             while(line != _eof_)
               {
                 line = read_line(infile);
                 if (line != "Unexpected end of file")
                   {
                     if ((strstr(line,"#") != -1))
                       {
                         txt_wgt.insert(FONT, nil, nil, line, -1);
                         read_line(infile);
                         read_line(infile);
                       }

If the first character in the first line of output is "`#`", this means there was no data available. If this is the case, the `.get_data` method will have printed two dummy data lines into the `hsoutputpl.dat` file. These two lines must be read now, so that they will not get inserted into the text widget by the rest of this function. Hence we put in two extra Gamma `read_line` calls.

                     else
                       {
                         string_list = string_split(line, " ", 2);
                         if (int_set.fn == "NoInterpolator"
                             || int_set.fn == "Periodic")
                           line_ret = string(number(car(string_list)) - midnite,
                                             " ", cadr(string_list),"\n");

Valid data in the `hsoutputpl.dat` file comes in two space-separated columns of numbers. If the numbers in the first column are time values (created using `NoInterpolator` or `Periodic` for the interpolator), this function recalculates each value to the number of seconds after midnight. This makes the data easier to read, and makes a better display in the plot.

                         else
                           line_ret = string(number(car(string_list)),
                                             " ", cadr(string_list),"\n");
                         txt_wgt.insert(FONT, nil, nil, line_ret, -1);
                       }
                   }
               }
             close(infile);

             if(x_list && y_list && minmaxlist != nil)
               {
                 if (x_is_time)
                   {
                     x_min = caar(minmaxlist);
                     x_max = cadar(minmaxlist);
                   }
                 else
                   {
                     x_min = floor(caar(minmaxlist));
                     x_max = ceil(cadar(minmaxlist));
                   }
                 y_min = floor(caadr(minmaxlist));
                 y_max = ceil(car(cdadr(minmaxlist))) + 1;
                 int_set.misc_info = string("x_min = ", x_min, "\n",
                                            "x_max = ", x_max, "\n",
                                            "y_min = ", y_min, "\n",
                                            "y_max = ", y_max, "\n");
                 write_minmax(int_set.misc_info);
               }
           }
         txt_wgt.thaw();

Having calculated the minimums and maximums, we put the information into one long string, for gnuplot to read, and write it to the `plhistsetup.dat` setup file, using the `write_minmax` function.

Next we need to create the output file for gnuplot. This code concatenates all the existing `hsoutput*.dat` files in order. These files were each created by the `show_data` function itself, and now it needs to compile the data from all existing files to include data for deadband queries.

         if(is_file("/tmp/cogentdemo/hsoutput.dat"))
           f1 = open("/tmp/cogentdemo/hsoutput.dat", "r");
         if(is_file("/tmp/cogentdemo/hsoutput2.dat"))
           f2 = open("/tmp/cogentdemo/hsoutput2.dat", "r");
         if(is_file("/tmp/cogentdemo/hsoutput3.dat"))
           f3 = open("/tmp/cogentdemo/hsoutput3.dat", "r");
         f4 = open("/tmp/cogentdemo/hsoutputpl.dat", "w");

         if(f1)
           {
             file_add(f1, f4);
             if(f2)
               file_add(f2, f4);
             else
               /* Put in a spacer line so gnuplot starts a new plot. */
               writec(f4, "999 999\n\n\n");
             if(f3)
               file_add(f3, f4);
           }

         close(f4);
       }

The gnuplot program can show multiple plots, if properly configured, as long as the data for each plot is separated by two newlines. However we might want to show one, two, or three plots, depending on the chosen Deadband options. To keep the code as simple as possible, and still cover all 7 possible ways that the plots could be displayed, we simply add the data for each plot to one final output file (`hsoutput.dat`), using the `file_add` function. The only drawback is that gnuplot can't handle extra empty spaces in its data file. There must be two and only two newlines separating each data set. So, to show plots one and three without plot two, we created a filler plot made of a bogus line of data (`"999 999"`) followed by the right number of spaces. The bogus data is way outside any possible plot range, and thus the plot never appears.

       /*--------------------------------------------------------------------
        * Function:    write_minmax
        * Returns:     t or nil
        * Description: Writes a string to the plhistsetup.dat file containing
        *              four lines, each line assigning a value for an X or Y axis
        *              minimum or maximum variable, which are used by gnuplot.
        *------------------------------------------------------------------*/
       function write_minmax(minmax_string)
       {
         local fp = open("/tmp/cogentdemo/plhistsetup.dat", "a", nil);
         writec(fp, minmax_string);
         close(fp);
       }

       /*--------------------------------------------------------------------
        * Function:    file_add
        * Returns:     t or nil
        * Description: Adds content from a file previously opened for reading
        *              (inptr) to a file previously opened for writing (outptr).
        *              Adds extra newlines, which gnuplot uses to mark the beginning
        *              of a new index file.  Called only by show_data().
        *------------------------------------------------------------------*/
       function file_add(inptr, outptr)
       {
         local line;
         while(line != _eof_)
           {
             line = read_line(inptr);
             if (line != "Unexpected end of file")
               writec(outptr, string(line, "\n"));
           }
         writec(outptr, "\n\n");
         close(inptr);
       }

Prev | Home | Next
GTK: Sending Queries - `send_query`, `.get_data` | Up | GTK: Configuring gnuplot

Copyright 1995-2002 by Cogent Real-Time Systems, Inc.