LCOV - code coverage report
Current view: top level - flagging/Flagging - grpcFlagAgentDisplay.cc (source / functions) Hit Total Coverage
Test: casacpp_coverage.info Lines: 0 979 0.0 %
Date: 2024-10-12 00:35:29 Functions: 0 49 0.0 %

          Line data    Source code
       1             : //# FlagAgentDisplay.cc: This file contains the implementation of the FlagAgentDisplay class.
       2             : //#
       3             : //#  CASA - Common Astronomy Software Applications (http://casa.nrao.edu/)
       4             : //#  Copyright (C) Associated Universities, Inc. Washington DC, USA 2011, All rights reserved.
       5             : //#  Copyright (C) European Southern Observatory, 2011, All rights reserved.
       6             : //#
       7             : //#  This library is free software; you can redistribute it and/or
       8             : //#  modify it under the terms of the GNU Lesser General Public
       9             : //#  License as published by the Free software Foundation; either
      10             : //#  version 2.1 of the License, or (at your option) any later version.
      11             : //#
      12             : //#  This library is distributed in the hope that it will be useful,
      13             : //#  but WITHOUT ANY WARRANTY, without even the implied warranty of
      14             : //#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      15             : //#  Lesser General Public License for more details.
      16             : //#
      17             : //#  You should have received a copy of the GNU Lesser General Public
      18             : //#  License along with this library; if not, write to the Free Software
      19             : //#  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
      20             : //#  MA 02111-1307  USA
      21             : //# $Id: rurvashi 28 Nov 2011$
      22             : 
      23             : #include <array>
      24             : #include <thread>
      25             : #include <unistd.h>
      26             : #include <sys/types.h>
      27             : #include <sys/wait.h>
      28             : #include <casatools/Config/State.h>
      29             : 
      30             : #ifdef USE_GRPC
      31             : #include <flagging/Flagging/grpcFlagAgentDisplay.h>
      32             : #include <grpc++/grpc++.h>
      33             : #include "shutdown.grpc.pb.h"
      34             : #include "ping.grpc.pb.h"
      35             : 
      36             : using namespace casacore;
      37             : namespace casa { //# NAMESPACE CASA - BEGIN
      38             : 
      39             : constexpr int FlagAgentDisplay::TIMEOUT;
      40             : 
      41             : // https://stackoverflow.com/questions/216823/whats-the-best-way-to-trim-stdstring
      42             : // C++ is so ridiculous... trim from start (in place)
      43           0 : static inline void ltrim(std::string &s) {
      44           0 :     s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](int ch) {
      45           0 :         return !std::isspace(ch);
      46             :     }));
      47           0 : }
      48             : 
      49             : // trim from end (in place)
      50           0 : static inline void rtrim(std::string &s) {
      51           0 :     s.erase(std::find_if(s.rbegin(), s.rend(), [](int ch) {
      52           0 :         return !std::isspace(ch);
      53           0 :     }).base(), s.end());
      54           0 : }
      55             : 
      56             : // trim from both ends (in place)
      57           0 : static inline void trim(std::string &s) {
      58           0 :     ltrim(s);
      59           0 :     rtrim(s);
      60           0 : }
      61             : 
      62           0 : static bool isdir( const char *path ) {
      63             :     struct stat statbuf;
      64           0 :     int err = stat(path, &statbuf);
      65           0 :     if ( err == -1 ) return false;
      66           0 :     if ( S_ISDIR(statbuf.st_mode) ) return true;
      67           0 :     return false;
      68             : }
      69             : 
      70           0 : static std::string trim_trailing_slash( const char *str ) {
      71           0 :     char *temp = strdup(str);
      72           0 :     for ( int off = strlen(str) - 1; off >= 0; --off ) {
      73           0 :         if ( temp[off] == '/' ) temp[off] = '\0';
      74           0 :         else break;
      75             :     }
      76           0 :     std::string result = temp;
      77           0 :     free(temp);
      78           0 :     return result;
      79             : }
      80             : 
      81           0 : grpcFlagAgentState::grpcFlagAgentState( ) : userChoice_p("Continue"), userFixA1_p(""), userFixA2_p(""),
      82           0 :                                             skipScan_p(-1), skipSpw_p(-1), skipField_p(-1),
      83           0 :                                             antenna1_p(""),antenna2_p(""), input_received(false) { }
      84             : 
      85           0 : ::grpc::Status grpcFlagAgentResponse::button( ::grpc::ServerContext *context,
      86             :                                               const ::rpc::gui::ButtonEvent *req,
      87             :                                               ::google::protobuf::Empty* ) {
      88           0 :     static const auto debug = getenv("GRPC_DEBUG");
      89           0 :     if ( debug ) {
      90           0 :         std::cerr << "plotserver '" << req->name( ) << "' button event received " <<
      91           0 :             " (process " << getpid( ) << ", thread " << 
      92           0 :             std::this_thread::get_id() << ")" << std::endl;
      93           0 :         fflush(stderr);
      94             :     }
      95             : 
      96             :     // Manage buttons from: Data Plot Window
      97           0 :     if ( req->name( ) == "NextBaseline" || req->name( ) == "PrevBaseline" ||
      98           0 :          req->name( ) == "NextScan" || req->name( ) == "NextField" ||
      99           0 :          req->name( ) == "NextSpw" || req->name( ) == "StopDisplay" || req->name( ) == "Quit") {
     100           0 :         std::lock_guard<std::mutex> lock(state->set_values);
     101           0 :         state->userChoice_p = req->name( );               // set input
     102           0 :         state->input_received = true;                        // set whenever state object is modified
     103           0 :         if ( state->input_needed ) {
     104           0 :             state->input_needed = false;             // prevent setting future twice
     105           0 :             state->output.set_value(true);           // signal controlling thread that wait is over
     106             :         }
     107             : 
     108             :     // Manage buttons from: Report Plot Window
     109           0 :     } else if ( req->name( ) == "Next" || req->name( ) == "Prev" || req->name( ) == "Quit") {
     110           0 :         std::lock_guard<std::mutex> lock(state->set_values);
     111           0 :         state->userChoice_p = req->name( );               // set input
     112           0 :         state->input_received = true;                        // set whenever state object is modified
     113           0 :         if ( state->input_needed ) {
     114           0 :             state->input_needed = false;             // prevent setting future twice
     115           0 :             state->output.set_value(true);           // signal controlling thread that wait is over
     116             :         }
     117           0 :     }
     118             : 
     119           0 :     return grpc::Status::OK;
     120             : }
     121           0 : ::grpc::Status grpcFlagAgentResponse::check( ::grpc::ServerContext *context,
     122             :                                              const ::rpc::gui::CheckEvent *req,
     123             :                                              ::google::protobuf::Empty* ) {
     124           0 :     static const auto debug = getenv("GRPC_DEBUG");
     125           0 :     if ( debug ) {
     126           0 :         std::cerr << "plotserver " << req->name( ) <<
     127           0 :             " [" << req->state( ) << "] check event received " <<
     128           0 :             " (process " << getpid( ) << ", thread " << 
     129           0 :             std::this_thread::get_id() << ")" << std::endl;
     130           0 :         fflush(stderr);
     131             :     }
     132             : 
     133             :     // Manage check boxes from: Data Plot Window
     134           0 :     if ( req->name( ) == "FixAntenna1" ) {
     135           0 :         std::lock_guard<std::mutex> lock(state->set_values);
     136           0 :         state->userFixA1_p = (req->state( ) == 0) ? "" : state->antenna1_p;
     137           0 :     } else if ( req->name( ) == "FixAntenna2" ) {
     138           0 :         std::lock_guard<std::mutex> lock(state->set_values);
     139           0 :         state->userFixA2_p = (req->state( ) == 0 ) ? "" : state->antenna2_p;
     140           0 :     }
     141           0 :     return grpc::Status::OK;
     142             : }
     143           0 : ::grpc::Status grpcFlagAgentResponse::radio( ::grpc::ServerContext *context,
     144             :                                              const ::rpc::gui::RadioEvent *req,
     145             :                                              ::google::protobuf::Empty* ) {
     146           0 :     static const auto debug = getenv("GRPC_DEBUG");
     147           0 :     if ( debug ) {
     148           0 :         std::cerr << "plotserver " << req->name( ) <<
     149           0 :             " [" << req->state( ) << "] radio event received " <<
     150           0 :             " (process " << getpid( ) << ", thread " << 
     151           0 :             std::this_thread::get_id() << ")" << std::endl;
     152           0 :         fflush(stderr);
     153             :     }
     154           0 :     return grpc::Status::OK;
     155             : }
     156           0 : ::grpc::Status grpcFlagAgentResponse::linetext( ::grpc::ServerContext *context,
     157             :                                                 const ::rpc::gui::LineTextEvent *req,
     158             :                                                 ::google::protobuf::Empty* ) {
     159           0 :     static const auto debug = getenv("GRPC_DEBUG");
     160           0 :     if ( debug ) {
     161           0 :         std::cerr << "plotserver " << req->name( ) <<
     162           0 :             " [" << req->text( ) << "] linetext event received " <<
     163           0 :             " (process " << getpid( ) << ", thread " << 
     164           0 :             std::this_thread::get_id() << ")" << std::endl;
     165           0 :         fflush(stderr);
     166             :     }
     167           0 :     return grpc::Status::OK;
     168             : }
     169           0 : ::grpc::Status grpcFlagAgentResponse::slidevalue( ::grpc::ServerContext *context,
     170             :                                                   const ::rpc::gui::SlideValueEvent *req,
     171             :                                                   ::google::protobuf::Empty* ) {
     172           0 :     static const auto debug = getenv("GRPC_DEBUG");
     173           0 :     if ( debug ) {
     174           0 :         std::cerr << "plotserver " << req->name( ) <<
     175           0 :             "[" << req->value( ) << "] slidevalue event received " <<
     176           0 :             " (process " << getpid( ) << ", thread " << 
     177           0 :             std::this_thread::get_id() << ")" << std::endl;
     178           0 :         fflush(stderr);
     179             :     }
     180           0 :     return grpc::Status::OK;
     181             : }
     182           0 : ::grpc::Status grpcFlagAgentResponse::exiting( ::grpc::ServerContext *context,
     183             :                                                const ::google::protobuf::Empty*,
     184             :                                                ::google::protobuf::Empty* ) {
     185           0 :     static const auto debug = getenv("GRPC_DEBUG");
     186           0 :     if ( debug ) {
     187             :         std::cerr << "plotserver exiting event received " <<
     188           0 :             " (process " << getpid( ) << ", thread " << 
     189           0 :             std::this_thread::get_id() << ")" << std::endl;
     190           0 :         fflush(stderr);
     191             :     }
     192           0 :     return grpc::Status::OK;
     193             : }
     194           0 : ::grpc::Status grpcFlagAgentResponse::closing( ::grpc::ServerContext *context,
     195             :                                                const ::rpc::gui::ClosingEvent *req,
     196             :                                                ::google::protobuf::Empty* ){
     197           0 :     static const auto debug = getenv("GRPC_DEBUG");
     198           0 :     if ( debug ) {
     199             :         std::cerr << "plotserver closing event received " <<
     200           0 :             " (process " << getpid( ) << ", thread " << 
     201           0 :             std::this_thread::get_id() << ")" << std::endl;
     202           0 :         fflush(stderr);
     203             :     }
     204             : 
     205           0 :     std::lock_guard<std::mutex> lock(state->set_values);
     206           0 :     state->userChoice_p = "Quit";                  // user stopped GUI
     207           0 :     state->input_received = true;                    // set whenever state object is modified
     208           0 :     if ( state->input_needed ) {
     209           0 :         state->input_needed = false;         // prevent setting future twice
     210           0 :         state->output.set_value(true);               // signal controlling thread that wait is over
     211             :     }
     212           0 :     return grpc::Status::OK;
     213           0 : }
     214             : 
     215           0 : std::string FlagAgentDisplay::plotter_t::get_casaplotserver_path( ) const {
     216           0 :     static std::string python_path = casatools::get_state( ).pythonPath( );
     217             :     //*** python3 -m casaplotserver --app-path
     218           0 :     char python_cmd[python_path.size( ) + 35];
     219           0 :     sprintf( python_cmd, "%s -m casaplotserver --app-path", python_path.c_str( ) );
     220             :     std::array<char, 512> buffer;
     221           0 :     std::string result;
     222           0 :     std::unique_ptr<FILE, decltype(&pclose)> pipe(popen(python_cmd, "r"), pclose);
     223           0 :     if ( ! pipe ) return std::string( );        //*** failed to start python
     224           0 :     while ( fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr ) {
     225           0 :         result += buffer.data();
     226             :     }
     227           0 :     trim(result);
     228           0 :     if ( result.size( ) == 0 ) return std::string( );
     229           0 :     return result;
     230           0 : }
     231             : 
     232           0 : std::string FlagAgentDisplay::plotter_t::get_fifo( ) const {
     233           0 :     static const char *env_tmpdir = getenv("TMPDIR");
     234           0 :     static std::string fifo_template = trim_trailing_slash(env_tmpdir && isdir(env_tmpdir) ? env_tmpdir : P_tmpdir) + "/cps-XXXXXXXXXX";
     235           0 :     static int fifo_template_size = fifo_template.size( );
     236           0 :     char fifo_path[fifo_template_size+1];
     237           0 :     strncpy( fifo_path, fifo_template.c_str( ), fifo_template_size );
     238           0 :     fifo_path[fifo_template_size] = '\0';
     239           0 :     int fd = mkstemp(fifo_path);
     240           0 :     if ( fd == -1 ) throw std::runtime_error("mkstemp failed...");
     241           0 :     close( fd );
     242           0 :     unlink(fifo_path);
     243           0 :     mkfifo( fifo_path, 0666 );
     244           0 :     return fifo_path;
     245           0 : }
     246             : 
     247           0 : bool FlagAgentDisplay::plotter_t::start_response_manager( ) {
     248           0 :     static const auto debug = getenv("GRPC_DEBUG");
     249             :     //***
     250             :     //*** set up a default address (grpc picks port) and address buffers
     251             :     //***
     252             :     char address_buf[100];
     253           0 :     constexpr char address_template[] = "0.0.0.0:%d";
     254           0 :     snprintf(address_buf,sizeof(address_buf),address_template,0);
     255           0 :     std::string server_address(address_buf);
     256           0 :     int selected_port = 0;
     257             : 
     258             :     //***
     259             :     //*** build grpc service
     260             :     //***
     261           0 :     grpc::ServerBuilder builder;
     262             :     // Listen on the given address without any authentication mechanism.
     263           0 :     builder.AddListeningPort(server_address, grpc::InsecureServerCredentials(), &selected_port);
     264             :     // Register "service" as the instance through which we'll receive from
     265             :     // the plot server client.
     266           0 :     builder.RegisterService(response_svc.get( ));
     267             : 
     268             :     // ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
     269             :     // Launch server...
     270           0 :     response_server = builder.BuildAndStart( );
     271           0 :     if ( selected_port > 0 ) {
     272             :         // if an available port can be found, selected_port is set to a value greater than zero
     273           0 :         snprintf(address_buf,sizeof(address_buf),address_template,selected_port);
     274           0 :         response_uri = address_buf;
     275           0 :         if ( debug ) {
     276           0 :             std::cerr << "flagagentdisplay response service available at " << response_uri << std::endl;
     277           0 :             fflush(stdout);
     278             :         }
     279           0 :         return true;
     280             :     }
     281           0 :     return false;
     282           0 : }
     283             : 
     284           0 : bool FlagAgentDisplay::plotter_t::launch(std::string plotserver_path) {
     285           0 :     static const auto debug = getenv("GRPC_DEBUG");
     286             : 
     287           0 :     std::string fifo = get_fifo( );
     288           0 :     if ( fifo.size( ) == 0 ) return false;
     289             : 
     290             :     // plot server will generate events (formerly DBus signals)
     291             :     // in response to GUI operations...
     292           0 :     if ( start_response_manager( ) == false ) return false;
     293             : 
     294             :     // here we start the viewer in a very basic manner... we do not bother
     295             :     // with all of the theatrics needed to daemonize the launched process
     296             :     // (see https://stackoverflow.com/questions/17954432/creating-a-daemon-in-linux)
     297             :     // it could be that this should be done in the future, but for now we
     298             :     // will adopt the simple...
     299             : 
     300             :     // casaplotserver --server=<FIFO-or-GRPC> --event-uri=<GRPC> [ --datapath=<PATH> --casalog=<PATH> ]
     301             : 
     302           0 :     int argc = 3;
     303           0 :     int logarg = argc;    // if a log file is specfied it comes last...
     304           0 :     std::string log_path = casatools::get_state( ).logPath( );
     305           0 :     if ( log_path.size( ) > 0 ) ++argc;
     306           0 :     char **arguments = (char**) malloc(sizeof(char*) * (argc + 1));
     307             : 
     308           0 :     arguments[argc] = 0;
     309           0 :     arguments[0] = strdup(plotserver_path.c_str( ));
     310           0 :     arguments[1] = (char*) malloc(sizeof(char) * (fifo.size( ) + 12));
     311           0 :     sprintf( arguments[1], "--server=%s", fifo.c_str( ) );
     312           0 :     arguments[2] = (char*) malloc(sizeof(char) * (response_uri.size( ) + 18));
     313           0 :     sprintf( arguments[2], "--event-uri=%s", response_uri.c_str( ) );
     314           0 :     if ( log_path.size( ) > 0 ) {
     315           0 :         arguments[logarg] = (char*) malloc(sizeof(char) * (log_path.size( ) + 17));
     316           0 :         sprintf( arguments[logarg], "--logfile=%s", log_path.c_str( ) );
     317             :     }
     318             : 
     319           0 :     if ( debug ) {
     320           0 :         std::cerr << "forking plotserver process: ";
     321           0 :         for (int i=0; i < argc; ++i) std::cerr << arguments[i] << " ";
     322           0 :         std::cerr << " (process " << getpid( ) << ", thread " << 
     323           0 :             std::this_thread::get_id() << ")" << std::endl;
     324           0 :         fflush(stderr);
     325             :     }
     326           0 :     pid_t newpid = fork( );
     327             : 
     328           0 :     if ( newpid == 0 ) {
     329           0 :         if ( debug ) {
     330           0 :             std::cerr << "execing plotserver process: ";
     331           0 :             for (int i=0; i < argc; ++i) std::cerr << arguments[i] << " ";
     332           0 :             std::cerr << " (process " << getpid( ) << ", thread " << 
     333           0 :                 std::this_thread::get_id() << ")" << std::endl;
     334           0 :             fflush(stderr);
     335             :         }
     336           0 :         execvp( arguments[0], (char* const*) arguments );
     337           0 :         perror( "FlagAgentDisplay::plotter_t::launch(...) child process exec failed" );
     338           0 :         exit(1);
     339             :     }
     340             : 
     341           0 :     for ( int i=0; i < argc; ++i ) free(arguments[i]);
     342           0 :     free(arguments);
     343             : 
     344           0 :     if ( newpid == -1 ) {
     345           0 :         perror( "FlagAgentDisplay::plotter_t::launch(...) child process fork failed" );
     346           0 :         return false;
     347             :     }
     348             : 
     349             :     // perform a health check, after a delay...
     350             :     int status;
     351           0 :     sleep(2);
     352           0 :     pid_t w = waitpid( newpid, &status, WUNTRACED | WCONTINUED | WNOHANG );
     353           0 :     if ( w == -1 ){
     354           0 :         if ( debug ) {
     355             :             std::cerr << "plotserver process failed " <<
     356           0 :                 " (process " << getpid( ) << ", thread " << 
     357           0 :                 std::this_thread::get_id() << ")" << std::endl;
     358           0 :             fflush(stderr);
     359             :         }
     360             :         // waitpid failed
     361           0 :         return false;
     362           0 :     } else if ( w != 0 ) {
     363           0 :         if ( debug ) {
     364             :             std::cerr << "plotserver process died " <<
     365           0 :                 " (process " << getpid( ) << ", thread " << 
     366           0 :                 std::this_thread::get_id() << ")" << std::endl;
     367           0 :             fflush(stderr);
     368             :         }
     369             :         // process exited
     370           0 :         if ( WIFEXITED(status) ) {
     371           0 :             printf("exited, status=%d\n", WEXITSTATUS(status));
     372           0 :         } else if (WIFSIGNALED(status)) {
     373           0 :             printf("killed by signal %d\n", WTERMSIG(status));
     374           0 :         } else if (WIFSTOPPED(status)) {
     375           0 :             printf("stopped by signal %d\n", WSTOPSIG(status));
     376             :         }
     377           0 :         return false;
     378             :     }
     379             : 
     380           0 :     if ( debug ) {
     381             :         std::cerr << "fetching casaplotserver uri from " << fifo <<
     382           0 :             " (process " << getpid( ) << ", thread " << 
     383           0 :             std::this_thread::get_id() << ")" << std::endl;
     384           0 :         fflush(stderr);
     385             :     }
     386             : 
     387             :     char buffer[512];
     388           0 :     std::string uri_buffer;
     389           0 :     FILE *fp = fopen(fifo.c_str( ), "r");
     390           0 :     while ( fgets( buffer, sizeof(buffer), fp ) ) { uri_buffer = uri_buffer + buffer; }
     391           0 :     fclose(fp);
     392           0 :     trim(uri_buffer);
     393             : 
     394             :     // validate viewer uri...
     395           0 :     if ( ! std::regex_match( uri_buffer, std::regex("^([0-9]+\\.){3}[0-9]+:[0-9]+$") ) ) {
     396             :         //rework of regex required for IPv6...
     397           0 :         if ( debug ) {
     398             :             std::cerr << "bad casaplotserver uri " << uri_buffer <<
     399           0 :                 " (process " << getpid( ) << ", thread " << 
     400           0 :                 std::this_thread::get_id() << ")" << std::endl;
     401           0 :             fflush(stderr);
     402             :         }
     403           0 :         return false;
     404             :     }
     405             : 
     406           0 :     if ( debug ) {
     407             :         std::cerr << "received casaplotserver uri: " << uri_buffer <<
     408           0 :             " (process " << getpid( ) << ", thread " << 
     409           0 :             std::this_thread::get_id() << ")" << std::endl;
     410           0 :         fflush(stderr);
     411             :     }
     412             : 
     413           0 :     plot_uri = uri_buffer;
     414           0 :     pid = newpid;
     415           0 :     if ( debug ) {
     416           0 :         std::cerr << "creating plotserver stub: " << plot_uri <<
     417           0 :             " (process " << getpid( ) << ", thread " << 
     418           0 :             std::this_thread::get_id() << ")" << std::endl;
     419           0 :         fflush(stderr);
     420             :     }
     421           0 :     plot = rpc::gui::plotserver::NewStub( grpc::CreateChannel( plot_uri,
     422           0 :                                                                grpc::InsecureChannelCredentials( ) ) );
     423             : 
     424           0 :     grpc::ClientContext context;
     425           0 :     ::google::protobuf::Empty resp;
     426           0 :     ::google::protobuf::Empty msg;
     427           0 :     auto ping = casatools::rpc::Ping::NewStub( grpc::CreateChannel( plot_uri, grpc::InsecureChannelCredentials( ) ) );
     428           0 :     auto deadline = std::chrono::system_clock::now() + std::chrono::milliseconds(TIMEOUT);
     429           0 :     context.set_deadline(deadline);
     430           0 :     ::grpc::Status st = ping->now( &context, msg, &resp );
     431           0 :     bool ping_result = st.ok( );
     432           0 :     if ( debug ) {
     433             :         std::cerr << "ping result: " << (ping_result ? "OK" : "FAIL")<< 
     434           0 :             " (process " << getpid( ) << ", thread " << 
     435           0 :             std::this_thread::get_id() << ")" << std::endl;
     436           0 :         fflush(stderr);
     437             :     }
     438             :     
     439           0 :     plot_started_ = true;
     440             : 
     441           0 :     return true;
     442           0 : }
     443             : 
     444             : 
     445           0 : FlagAgentDisplay::plotter_t::plotter_t(std::shared_ptr<grpcFlagAgentState> state) :
     446           0 :         active_(false), response_svc(new grpcFlagAgentResponse(state)), plot_started_(false) {
     447           0 :     static const auto debug = getenv("GRPC_DEBUG");
     448             : 
     449           0 :     if ( debug ) {
     450             :         std::cerr << "attempting to start plotserver process " <<
     451           0 :             " (process " << getpid( ) << ", thread " << 
     452           0 :             std::this_thread::get_id() << ")" << std::endl;
     453           0 :         fflush(stderr);
     454             :     }
     455           0 :     std::string ps_path = get_casaplotserver_path( );
     456           0 :     if ( ps_path.size() > 0 ) {
     457             :         // sanity check on casaplotserver path...
     458             :         struct stat statbuf;
     459           0 :         if ( stat( ps_path.c_str( ), &statbuf ) < 0 ) {
     460             :             // file (or dir) does not exist... e.g.
     461             :             //   >>>>>>registry available at 0.0.0.0:40939
     462             :             //   stopping registry<<<<<<
     463           0 :             if ( debug ) {
     464             :                 std::cerr << "could not find casaplotserver executable " <<
     465           0 :                     " (process " << getpid( ) << ", thread " << 
     466           0 :                     std::this_thread::get_id() << ")" << std::endl;
     467           0 :                 fflush(stderr);
     468             :             }
     469             :         } else {
     470           0 :             if ( launch(ps_path) ) {
     471           0 :                 active_ = true;
     472           0 :             } else if ( debug ) {
     473             :                 std::cerr << "could not find casaplotserver executable " <<
     474           0 :                     " (process " << getpid( ) << ", thread " << 
     475           0 :                     std::this_thread::get_id() << ")" << std::endl;
     476           0 :                 fflush(stderr);
     477             :             }
     478             :         }        
     479           0 :     } else if ( debug ) {
     480             :         std::cerr << "could not find casaplotserver executable " <<
     481           0 :             " (process " << getpid( ) << ", thread " << 
     482           0 :             std::this_thread::get_id() << ")" << std::endl;
     483           0 :         fflush(stderr);
     484             :     }
     485             : 
     486           0 : }
     487             : 
     488             : 
     489           0 : FlagAgentDisplay::FlagAgentDisplay(FlagDataHandler *dh, Record config, Bool writePrivateFlagCube):
     490             :                         FlagAgentBase(dh,config,ANTENNA_PAIRS_INTERACTIVE,writePrivateFlagCube),
     491           0 :                 gui_state(new grpcFlagAgentState),
     492           0 :                         dataplotter_p(NULL),reportplotter_p(NULL), pause_p(false),
     493           0 :                         fieldId_p(-1), fieldName_p(""), scanStart_p(-1), scanEnd_p(-1), spwId_p(-1),
     494           0 :                         nPolarizations_p(1), freqList_p(Vector<Double>()),
     495           0 :                         dataDisplay_p(false), reportDisplay_p(false),reportFormat_p("screen"),
     496           0 :                         stopAndExit_p(false),/* reportReturn_p(false),*/ showBandpass_p(false)
     497             : {
     498             :         // Parse parameters and set base variables.
     499           0 :         setAgentParameters(config);
     500             :         // Request loading polarization map to FlagDataHandler
     501           0 :         flagDataHandler_p->setMapPolarizations(true);
     502             :         // Make the list of colours (these are almost all predefined ones for Qt.
     503             :         // Can add more later, based on RGB values.
     504           0 :         plotColours_p.resize(13);
     505           0 :         plotColours_p[0]="blue";
     506           0 :         plotColours_p[1]="red";
     507           0 :         plotColours_p[2]="green";
     508           0 :         plotColours_p[3]="cyan";
     509           0 :         plotColours_p[4]="darkGray";
     510           0 :         plotColours_p[5]="magenta";
     511           0 :         plotColours_p[6]="yellow";
     512           0 :         plotColours_p[7]="darkBlue";
     513           0 :         plotColours_p[8]="darkRed";
     514           0 :         plotColours_p[9]="darkGreen";
     515           0 :         plotColours_p[10]="darkCyan";
     516           0 :         plotColours_p[11]="black";
     517           0 :         plotColours_p[12]="darkMagenta";
     518             : 
     519           0 : }
     520             : 
     521           0 : bool FlagAgentDisplay::done( std::shared_ptr<FlagAgentDisplay::plotter_t> plotter ) {
     522             :     // send shutdown message to plotserver...
     523           0 :     static const auto debug = getenv("GRPC_DEBUG");
     524             : 
     525           0 :     if ( plotter && plotter->active( ) && plotter->plot_uri.size( ) > 0) {
     526           0 :         grpc::ClientContext context;
     527           0 :         ::google::protobuf::Empty req;
     528           0 :         ::google::protobuf::Empty resp;
     529           0 :         if ( debug ) {
     530             :             std::cerr << "attempting to shutdown plotserver [" <<
     531           0 :                 plotter->plot_uri << "] " << 
     532           0 :                 " (process " << getpid( ) << ", thread " << 
     533           0 :                 std::this_thread::get_id() << ")" << std::endl;
     534           0 :             fflush(stderr);
     535             :         }
     536           0 :         auto shutdown = casatools::rpc::Shutdown::NewStub( grpc::CreateChannel( plotter->plot_uri, grpc::InsecureChannelCredentials( ) ) );
     537           0 :         auto deadline = std::chrono::system_clock::now() + std::chrono::milliseconds(TIMEOUT);
     538           0 :         context.set_deadline(deadline);
     539           0 :         shutdown->now( &context, req, &resp );
     540             : 
     541             :         // wait on plotserver to exit...
     542             :         int status;
     543           0 :         pid_t w = waitpid( plotter->pid, &status, WUNTRACED | WCONTINUED );
     544           0 :         if ( w == -1 ){
     545           0 :             if ( debug ) {
     546             :                 std::cerr << "plotserver waitpid failed " <<
     547           0 :                     " (process " << getpid( ) << ", thread " << 
     548           0 :                     std::this_thread::get_id() << ")" << std::endl;
     549           0 :                 fflush(stderr);
     550             :             }
     551             :             // waitpid failed
     552           0 :             return false;
     553           0 :         } else if ( w == 0 ) {
     554           0 :             if ( debug ) {
     555             :                 std::cerr << "plotserver process not found " <<
     556           0 :                     " (process " << getpid( ) << ", thread " << 
     557           0 :                     std::this_thread::get_id() << ")" << std::endl;
     558           0 :                 fflush(stderr);
     559             :             }
     560           0 :             return false;
     561             :         } else {
     562           0 :             if ( debug ) {
     563           0 :                 std::cerr << "plotserver process (" << w << ") exited, status fetched " <<
     564           0 :                     " (process " << getpid( ) << ", thread " << 
     565           0 :                     std::this_thread::get_id() << ")" << std::endl;
     566           0 :                 fflush(stderr);
     567             :             }
     568           0 :             plotter->pid = 0;
     569           0 :             return true;
     570             :         }
     571           0 :     }
     572             : 
     573           0 :     plotter.reset( );
     574           0 :     return true;
     575             : }
     576             : 
     577           0 : int FlagAgentDisplay::create_panel( std::shared_ptr<plotter_t> plot, int parent, bool new_row ) {
     578           0 :     static const auto debug = getenv("GRPC_DEBUG");
     579           0 :         string zoomloc="";
     580           0 :         string legendloc="bottom";
     581           0 :     grpc::ClientContext context;
     582           0 :     ::rpc::gui::Id result;
     583           0 :     ::rpc::gui::NewPanel panel;
     584           0 :     panel.set_title("");
     585           0 :     panel.set_xlabel("");
     586           0 :     panel.set_ylabel("");
     587           0 :     panel.set_window_title("");
     588           0 :     *panel.mutable_size( ) = { };
     589           0 :     panel.set_legend(legendloc);
     590           0 :     panel.set_zoom(zoomloc);
     591           0 :     panel.set_with_panel(parent);
     592           0 :     panel.set_new_row(new_row);
     593           0 :     panel.set_hidden(false);
     594           0 :     if ( debug ) {
     595           0 :         std::cerr << (plot->active( ) ? "FlagAgentDisplay creating panel " : "FlagAgentDisplay create ERROR plot not active ") <<
     596           0 :             " (process " << getpid( ) << ", thread " << 
     597           0 :             std::this_thread::get_id() << ")" << std::endl;
     598           0 :         fflush(stderr);
     599             :     }
     600             : 
     601           0 :     if ( ! plot->active( ) ) return -1;
     602             : 
     603           0 :     auto deadline = std::chrono::system_clock::now() + std::chrono::milliseconds(TIMEOUT);
     604           0 :     context.set_deadline(deadline);
     605           0 :     ::grpc::Status st = plot->plot->panel(&context,panel,&result);
     606           0 :     bool stat = st.ok( );
     607           0 :     if ( debug ) {
     608           0 :         std::cerr << "panel creation " << (stat ? "SUCCEEDED " : "FAILED ") << (stat ? result.id( ) : -1) <<
     609           0 :             " (process " << getpid( ) << ", thread " << 
     610           0 :             std::this_thread::get_id() << ")" << std::endl;
     611           0 :         fflush(stderr);
     612             :     }
     613           0 :     return stat ? result.id( ) : -1;
     614           0 : }
     615             : 
     616           0 : void FlagAgentDisplay::erase( std::shared_ptr<plotter_t> plot, int panel ) {
     617           0 :     static const auto debug = getenv("GRPC_DEBUG");
     618           0 :     grpc::ClientContext context;
     619           0 :     ::google::protobuf::Empty resp;
     620           0 :     ::rpc::gui::Id id;
     621             : 
     622           0 :     if ( debug ) {
     623           0 :         std::cerr << (plot->active( ) ? "FlagAgentDisplay erase " : "FlagAgentDisplay erase ERROR plot not active ") <<
     624           0 :             " (process " << getpid( ) << ", thread " << 
     625           0 :             std::this_thread::get_id() << ")" << std::endl;
     626           0 :         fflush(stderr);
     627             :     }
     628             : 
     629           0 :     if ( ! plot->active( ) ) return;
     630             : 
     631           0 :     id.set_id(panel);
     632           0 :     auto deadline = std::chrono::system_clock::now() + std::chrono::milliseconds(TIMEOUT);
     633           0 :     context.set_deadline(deadline);
     634           0 :     plot->plot->erase(&context,id,&resp);
     635           0 : }
     636             :     
     637           0 : void FlagAgentDisplay::setlabel( std::shared_ptr<plotter_t> plot, int panel,
     638             :                                  std::string xlabel, std::string ylabel, std::string title ) {
     639           0 :     static const auto debug = getenv("GRPC_DEBUG");
     640           0 :     grpc::ClientContext context;
     641           0 :     ::google::protobuf::Empty resp;
     642           0 :     ::rpc::gui::Label label;
     643             : 
     644           0 :     if ( debug ) {
     645           0 :         std::cerr << (plot->active( ) ? "FlagAgentDisplay setlabel " : "FlagAgentDisplay setlabel ERROR plot not active ") <<
     646           0 :             " (process " << getpid( ) << ", thread " << 
     647           0 :             std::this_thread::get_id() << ")" << std::endl;
     648           0 :         fflush(stderr);
     649             :     }
     650             : 
     651           0 :     if ( ! plot->active( ) ) return;
     652             : 
     653           0 :     label.mutable_panel( )->set_id(panel);
     654           0 :     label.set_xlabel(xlabel);
     655           0 :     label.set_ylabel(ylabel);
     656           0 :     label.set_title(title);
     657           0 :     auto deadline = std::chrono::system_clock::now() + std::chrono::milliseconds(TIMEOUT);
     658           0 :     context.set_deadline(deadline);
     659           0 :     plot->plot->setlabel(&context,label,&resp);
     660           0 : }
     661             : 
     662           0 : int FlagAgentDisplay::create_dock( std::shared_ptr<plotter_t> plot, int panel, std::string xml ) {
     663           0 :     static const auto debug = getenv("GRPC_DEBUG");
     664           0 :     grpc::ClientContext context;
     665           0 :     ::rpc::gui::DockSpec spec;
     666           0 :     ::rpc::gui::Id result;
     667             : 
     668           0 :     if ( debug ) {
     669           0 :         std::cerr << (plot->active( ) ? "FlagAgentDisplay create_dock " : "FlagAgentDisplay create_dock ERROR plot not active ") <<
     670           0 :             " (process " << getpid( ) << ", thread " << 
     671           0 :             std::this_thread::get_id() << ")" << std::endl;
     672           0 :         fflush(stderr);
     673             :     }
     674             : 
     675           0 :     if ( ! plot->active( ) ) return -1;
     676             : 
     677           0 :     spec.set_file_or_xml(xml);
     678           0 :     spec.set_loc("bottom");
     679           0 :     spec.add_dockable("top");
     680           0 :     spec.mutable_panel( )->set_id(panel);
     681           0 :     auto deadline = std::chrono::system_clock::now() + std::chrono::milliseconds(TIMEOUT);
     682           0 :     context.set_deadline(deadline);
     683           0 :     plot->plot->loaddock(&context,spec,&result);
     684           0 :     return result.id( );
     685           0 : }
     686             : 
     687           0 : int FlagAgentDisplay::raster( std::shared_ptr<plotter_t> plot, int panel, const std::vector<float> &data, ssize_t sizex, ssize_t sizey ) {
     688           0 :     static const auto debug = getenv("GRPC_DEBUG");
     689           0 :     grpc::ClientContext context;
     690           0 :     ::rpc::gui::Id result;
     691           0 :     ::rpc::gui::NewRaster raster;
     692             : 
     693           0 :     if ( debug ) {
     694           0 :         std::cerr << (plot->active( ) ? "FlagAgentDisplay raster " : "FlagAgentDisplay raster ERROR plot not active ") <<
     695           0 :             " (process " << getpid( ) << ", thread " << 
     696           0 :             std::this_thread::get_id() << ")" << std::endl;
     697           0 :         fflush(stderr);
     698             :     }
     699             : 
     700           0 :     if ( ! plot->active( ) ) return -1;
     701             : 
     702           0 :     raster.mutable_panel( )->set_id(panel);
     703           0 :     *raster.mutable_matrix( ) = { data.begin( ), data.end( ) };
     704           0 :     raster.set_sizex(sizex);
     705           0 :     raster.set_sizey(sizey);
     706           0 :     raster.set_colormap("Hot Metal 1");
     707             : 
     708           0 :     auto deadline = std::chrono::system_clock::now() + std::chrono::milliseconds(TIMEOUT);
     709           0 :     context.set_deadline(deadline);
     710           0 :     plot->plot->raster(&context,raster,&result);
     711           0 :     return result.id( );
     712           0 : }    
     713             : 
     714           0 : int FlagAgentDisplay::line( std::shared_ptr<plotter_t> plot, int panel, const std::vector<float> &xdata, const std::vector<float> &ydata, std::string color, std::string label ) {
     715           0 :     static const auto debug = getenv("GRPC_DEBUG");
     716           0 :     grpc::ClientContext context;
     717           0 :     ::rpc::gui::Id result;
     718           0 :     ::rpc::gui::NewLine line;
     719             : 
     720           0 :     if ( debug ) {
     721           0 :         std::cerr << (plot->active( ) ? "FlagAgentDisplay line " : "FlagAgentDisplay line ERROR plot not active ") <<
     722           0 :             " (process " << getpid( ) << ", thread " << 
     723           0 :             std::this_thread::get_id() << ")" << std::endl;
     724           0 :         fflush(stderr);
     725             :     }
     726             : 
     727           0 :     if ( ! plot->active( ) ) return -1;
     728             : 
     729           0 :     line.mutable_panel( )->set_id(panel);
     730           0 :     *line.mutable_x( ) = { xdata.begin( ), xdata.end( ) };
     731           0 :     *line.mutable_y( ) = { ydata.begin( ), ydata.end( ) };
     732           0 :     line.set_color(color);
     733           0 :     line.set_label(label);
     734           0 :     auto deadline = std::chrono::system_clock::now() + std::chrono::milliseconds(TIMEOUT);
     735           0 :     context.set_deadline(deadline);
     736           0 :     plot->plot->line(&context,line,&result);
     737           0 :     return result.id( );
     738           0 : }
     739             : 
     740           0 : int FlagAgentDisplay::scatter( std::shared_ptr<plotter_t> plot, int panel, const std::vector<float> &xdata,
     741             :                                const std::vector<float> &ydata, std::string color, std::string label,
     742             :                                std::string symbol, int symbol_size, int dot_size ) {
     743           0 :     static const auto debug = getenv("GRPC_DEBUG");
     744           0 :     grpc::ClientContext context;
     745           0 :     ::rpc::gui::Id result;
     746           0 :     ::rpc::gui::NewScatter scatter;
     747             : 
     748           0 :     if ( debug ) {
     749           0 :         std::cerr << (plot->active( ) ? "FlagAgentDisplay scatter " : "FlagAgentDisplay scatter ERROR plot not active ") <<
     750           0 :             " (process " << getpid( ) << ", thread " << 
     751           0 :             std::this_thread::get_id() << ")" << std::endl;
     752           0 :         fflush(stderr);
     753             :     }
     754             : 
     755           0 :     if ( ! plot->active( ) ) return -1;
     756             : 
     757           0 :     scatter.mutable_panel( )->set_id(panel);
     758           0 :     *scatter.mutable_x( ) = { xdata.begin( ), xdata.end( ) };
     759           0 :     *scatter.mutable_y( ) = { ydata.begin( ), ydata.end( ) };
     760           0 :     scatter.set_color(color);
     761           0 :     scatter.set_label(label);
     762           0 :     scatter.set_symbol(symbol);
     763           0 :     scatter.set_symbol_size(symbol_size);
     764           0 :     scatter.set_dot_size(dot_size);
     765           0 :     auto deadline = std::chrono::system_clock::now() + std::chrono::milliseconds(TIMEOUT);
     766           0 :     context.set_deadline(deadline);
     767           0 :     plot->plot->scatter(&context,scatter,&result);
     768           0 :     return result.id( );
     769           0 : }
     770             : 
     771           0 : FlagAgentDisplay::~FlagAgentDisplay()
     772             : {
     773           0 :     static const auto debug = getenv("GRPC_DEBUG");
     774           0 :     if ( debug ) {
     775             :         std::cerr << "FlagAgentDisplay dtor " <<
     776           0 :             " (process " << getpid( ) << ", thread " << 
     777           0 :             std::this_thread::get_id() << ")" << std::endl;
     778           0 :         fflush(stderr);
     779             :     }
     780             : 
     781             :         // Compiler automagically calls FlagAgentBase::~FlagAgentBase()
     782           0 :         if ( dataplotter_p != NULL ) {
     783           0 :         done(dataplotter_p);
     784           0 :         dataplotter_p=NULL;
     785             :     }
     786           0 :         if ( reportplotter_p != NULL ) {
     787           0 :         done(reportplotter_p);
     788           0 :         reportplotter_p=NULL;
     789             :     }
     790           0 : }
     791             : 
     792           0 : void FlagAgentDisplay::setAgentParameters(Record config)
     793             : {
     794           0 :         logger_p->origin(LogOrigin(agentName_p,__FUNCTION__,WHERE));
     795             :         int exists;
     796             : 
     797           0 :         exists = config.fieldNumber ("pause");
     798           0 :         if (exists >= 0)
     799             :         {
     800           0 :                 if( config.type(exists) != TpBool )
     801             :                 {
     802           0 :                         throw( AipsError ( "Parameter 'pause' must be of type 'bool'" ) );
     803             :                 }
     804             : 
     805           0 :                 pause_p = config.asBool("pause");
     806             :         }
     807             :         else
     808             :         {
     809           0 :                 pause_p = true;
     810             :         }
     811             : 
     812           0 :         *logger_p << LogIO::NORMAL << " pause is " << pause_p << LogIO::POST;
     813             : 
     814           0 :         exists = config.fieldNumber ("datadisplay");
     815           0 :         if (exists >= 0)
     816             :         {
     817           0 :                 if( config.type(exists) != TpBool )
     818             :                 {
     819           0 :                         throw( AipsError ( "Parameter 'datadisplay' must be of type 'bool'" ) );
     820             :                 }
     821             : 
     822           0 :                 dataDisplay_p = config.asBool("datadisplay");
     823             :         }
     824             :         else
     825             :         {
     826           0 :                 dataDisplay_p = false;
     827             :         }
     828             : 
     829           0 :         *logger_p << LogIO::NORMAL << " datadisplay is " << dataDisplay_p << LogIO::POST;
     830             : 
     831           0 :         exists = config.fieldNumber ("reportdisplay");
     832           0 :         if (exists >= 0)
     833             :         {
     834           0 :                 if( config.type(exists) != TpBool )
     835             :                 {
     836           0 :                         throw( AipsError ( "Parameter 'reportdisplay' must be of type 'bool'" ) );
     837             :                 }
     838             : 
     839           0 :                 reportDisplay_p = config.asBool("reportdisplay");
     840             :         }
     841             :         else
     842             :         {
     843           0 :                 reportDisplay_p = false;
     844             :         }
     845             : 
     846           0 :         *logger_p << LogIO::NORMAL << " reportdisplay is " << reportDisplay_p << LogIO::POST;
     847             : 
     848             : 
     849           0 :         exists = config.fieldNumber ("format");
     850           0 :         if (exists >= 0)
     851             :         {
     852           0 :                 if( config.type(exists) != TpString )
     853             :                 {
     854           0 :                         throw( AipsError ( "Parameter 'format' must be of type 'bool'" ) );
     855             :                 }
     856             : 
     857           0 :                 reportFormat_p = config.asString("format");
     858           0 :                 if( reportFormat_p != "screen" && reportFormat_p != "file")
     859             :                 {
     860           0 :                         throw( AipsError( "Unsupported report format : " + reportFormat_p + ". Supported formats are 'screen' and 'file'") );
     861             :                 }
     862             :         }
     863             :         else
     864             :         {
     865           0 :                 reportFormat_p = String("screen");
     866             :         }
     867             : 
     868           0 :         *logger_p << LogIO::NORMAL << " format is " << reportFormat_p << LogIO::POST;
     869             : 
     870           0 : }
     871             : 
     872             : 
     873             : void
     874           0 : FlagAgentDisplay::preProcessBuffer(const vi::VisBuffer2 &visBuffer)
     875             : {
     876             : 
     877           0 :         getChunkInfo(visBuffer);
     878             : 
     879           0 :         return;
     880             : }
     881             : 
     882             : 
     883             : void
     884           0 : FlagAgentDisplay::iterateAntennaPairsInteractive(antennaPairMap *antennaPairMap_ptr)
     885             : {
     886           0 :         logger_p->origin(LogOrigin(agentName_p,__FUNCTION__,WHERE));
     887             :         // Check if the visibility expression is suitable for this spw
     888           0 :         if (!checkVisExpression(flagDataHandler_p->getPolarizationMap())) return;
     889             : 
     890             :         // Iterate through antenna pair map
     891           0 :         std::pair<Int,Int> antennaPair;
     892           0 :         antennaPairMapIterator myAntennaPairMapIterator;
     893           0 :         bool stepback=false;
     894           0 :         for (myAntennaPairMapIterator=antennaPairMap_ptr->begin(); myAntennaPairMapIterator != antennaPairMap_ptr->end(); ++myAntennaPairMapIterator)
     895             :         {
     896             : 
     897             :                 // Check whether to skip the rest of this chunk or not
     898           0 :                 if(gui_state->skipSpw_p != -1)
     899             :                 {
     900           0 :                         if(gui_state->skipSpw_p == spwId_p) {dataDisplay_p=false;} // Skip the rest of this SPW
     901             :                         else {
     902           0 :                 std::lock_guard<std::mutex> lock(gui_state->set_values);
     903           0 :                 gui_state->skipSpw_p = -1;
     904           0 :                 dataDisplay_p=true;
     905           0 :             } // Reached next SPW. Reset state
     906             :                 }
     907           0 :                 if(gui_state->skipField_p != -1)
     908             :                 {
     909           0 :                         if(gui_state->skipField_p == fieldId_p) {dataDisplay_p=false;} // Skip the rest of this Field
     910             :                         else {
     911           0 :                 std::lock_guard<std::mutex> lock(gui_state->set_values);
     912           0 :                 gui_state->skipField_p = -1;
     913           0 :                 dataDisplay_p=true;
     914           0 :             } // Reached next Field. Reset state
     915             :                 }
     916           0 :                 if(gui_state->skipScan_p != -1)
     917             :                 {
     918           0 :                         if(gui_state->skipScan_p == scanEnd_p) {dataDisplay_p=false;} // Skip the rest of this Scan
     919             :                         else {
     920           0 :                 std::lock_guard<std::mutex> lock(gui_state->set_values);
     921           0 :                 gui_state->skipScan_p = -1;
     922           0 :                 dataDisplay_p=true;
     923           0 :             } // Reached next Scan. Reset state
     924             :                 }
     925             : 
     926             : 
     927             :                 // Display this baseline
     928           0 :                 if(dataDisplay_p)
     929             :                 {
     930             : 
     931             :                         // If choice from previous plot was to go backwards in baseline.
     932           0 :                         if(stepback)
     933             :                         {
     934             :                                 // Go to previous baseline (decrement by 2)
     935           0 :                                 if( myAntennaPairMapIterator != antennaPairMap_ptr->begin() )
     936           0 :                                         -- myAntennaPairMapIterator;
     937           0 :                                 if( myAntennaPairMapIterator != antennaPairMap_ptr->begin() )
     938           0 :                                         -- myAntennaPairMapIterator;
     939             : 
     940             :                                 // If antenna constraints exist, keep going back until first match is found.
     941             :                                 // If not found, stay on current baseline (continue)
     942           0 :                                 if( gui_state->userFixA1_p != "" || gui_state->userFixA2_p != "" )
     943             :                                 {
     944           0 :                                         antennaPairMapIterator tempIterator;
     945           0 :                                         bool found=false;
     946           0 :                                         for(tempIterator = myAntennaPairMapIterator; tempIterator != antennaPairMap_ptr->begin() ; --tempIterator )
     947             :                                         {
     948           0 :                                                 if( ! skipBaseline(tempIterator->first) ) {found=true; break;}
     949             :                                         }
     950           0 :                                         if(found) // Jump to this antenna pair
     951             :                                         {
     952           0 :                                                 myAntennaPairMapIterator = tempIterator;
     953             :                                         }
     954             :                                         else
     955             :                                         {
     956           0 :                                                 *logger_p << "No Previous baseline in this chunk with Ant1 : "
     957           0 :                                                                 << ( (gui_state->userFixA1_p != "") ? gui_state->userFixA1_p : "any" )
     958             :                                                                 << "  and Ant2 : "
     959           0 :                                                                 << ( (gui_state->userFixA2_p != "") ? gui_state->userFixA2_p : "any" )
     960           0 :                                                                 << LogIO::POST;
     961             : 
     962             :                                                 // Stay on current baseline
     963           0 :                                                 if( myAntennaPairMapIterator != antennaPairMap_ptr->end() )
     964           0 :                                                         ++myAntennaPairMapIterator;
     965             :                                         }
     966             :                                 }
     967             : 
     968             :                                 // Reset state
     969           0 :                                 stepback=false;
     970             :                         }
     971             : 
     972             :                         // Get antenna pair from map
     973           0 :                         antennaPair = myAntennaPairMapIterator->first;
     974             : 
     975             :                         // Check whether or not to display this baseline (for going in the forward direction)
     976           0 :                         if( skipBaseline(antennaPair) ) continue;
     977             : 
     978             :                         // Process antenna pair
     979           0 :                         processAntennaPair(antennaPair.first,antennaPair.second);
     980             : 
     981             :                         // If Plot window is visible, and, if asked for, get and react to user-choices.
     982           0 :                         if(pause_p==true)
     983             :                         {
     984             : 
     985             :                                 // Wait for User Input
     986           0 :                                 getUserInput( ); // Fills in userChoice_p. userfix
     987             : 
     988             :                                 // React to user-input
     989           0 :                                 if(gui_state->userChoice_p=="Quit")
     990             :                                 {
     991           0 :                                         dataDisplay_p = false;
     992           0 :                                         stopAndExit_p = true;
     993           0 :                                         *logger_p << "Exiting flagger" << LogIO::POST;
     994           0 :                                         if ( dataplotter_p != NULL ) {
     995           0 :                         done(dataplotter_p);
     996           0 :                         dataplotter_p=NULL;
     997             :                     }
     998           0 :                                         flagDataHandler_p->stopIteration();
     999           0 :                                         return ;
    1000             :                                 }
    1001           0 :                                 else if(gui_state->userChoice_p=="StopDisplay")
    1002             :                                 {
    1003           0 :                                         dataDisplay_p = false;
    1004           0 :                                         *logger_p << "Stopping display. Continuing flagging." << LogIO::POST;
    1005           0 :                                         if ( dataplotter_p != NULL ) {
    1006           0 :                         done(dataplotter_p);
    1007           0 :                         dataplotter_p=NULL;
    1008             :                     }
    1009             :                                 }
    1010           0 :                                 else if(gui_state->userChoice_p=="PrevBaseline")
    1011             :                                 {
    1012           0 :                                         if( myAntennaPairMapIterator==antennaPairMap_ptr->begin() )
    1013           0 :                                                 *logger_p << "Already on first baseline..." << LogIO::POST;
    1014           0 :                                         stepback=true;
    1015             :                                 }
    1016           0 :                                 else if(gui_state->userChoice_p=="NextScan")
    1017             :                                 {
    1018             :                                         //*logger_p << "Next Scan " << LogIO::POST;
    1019           0 :                     std::lock_guard<std::mutex> lock(gui_state->set_values);
    1020           0 :                                         gui_state->skipScan_p = scanEnd_p;
    1021           0 :                                 }
    1022           0 :                                 else if(gui_state->userChoice_p=="NextSpw")
    1023             :                                 {
    1024             :                                         //*logger_p << "Next SPW " << LogIO::POST;
    1025           0 :                     std::lock_guard<std::mutex> lock(gui_state->set_values);
    1026           0 :                                         gui_state->skipSpw_p = spwId_p;
    1027           0 :                                 }
    1028           0 :                                 else if(gui_state->userChoice_p=="NextField")
    1029             :                                 {
    1030             :                                         //*logger_p << "Next Field " << LogIO::POST;
    1031           0 :                     std::lock_guard<std::mutex> lock(gui_state->set_values);
    1032           0 :                                         gui_state->skipField_p = fieldId_p;
    1033           0 :                                 }
    1034           0 :                                 else if(gui_state->userChoice_p=="Continue")
    1035             :                                 {
    1036             :                                         //*logger_p << "Next chunk " << LogIO::POST; // Right now, a chunk is one baseline !
    1037           0 :                                         return;
    1038             :                                 }
    1039             : 
    1040             :                         }// end if pause=true
    1041             : 
    1042             :                 }// if dataDisplay_p
    1043             : 
    1044             :         }// end antennaMapIterator
    1045             : 
    1046           0 :         return;
    1047             : }// end iterateAntennaPairsInteractive
    1048             : 
    1049             : 
    1050             : Bool
    1051           0 : FlagAgentDisplay::skipBaseline(std::pair<Int,Int> antennaPair)
    1052             : {
    1053           0 :         std::string antenna1Name = flagDataHandler_p->antennaNames_p->operator()(antennaPair.first);
    1054           0 :         std::string antenna2Name = flagDataHandler_p->antennaNames_p->operator()(antennaPair.second);
    1055             :         //          if(userFixA2_p != "") cout << "*********** userfixa2 : " << userFixA2_p << "   thisant : " << antenna1Name << " && " << antenna2Name << LogIO::POST;
    1056           0 :         return  (  (gui_state->userFixA1_p != ""  && gui_state->userFixA1_p != antenna1Name)  ||
    1057           0 :                (gui_state->userFixA2_p != ""  && gui_state->userFixA2_p != antenna2Name) ) ;
    1058           0 : }
    1059             : 
    1060             : bool
    1061           0 : FlagAgentDisplay::computeAntennaPairFlags(const vi::VisBuffer2 &visBuffer,
    1062             :                 VisMapper &visibilities,FlagMapper &flags,Int antenna1,Int antenna2,
    1063             :                 vector<uInt> &/*rows*/)
    1064             : {
    1065           0 :         logger_p->origin(LogOrigin(agentName_p,__FUNCTION__,WHERE));
    1066             :         // Gather shapes
    1067           0 :         IPosition flagCubeShape = visibilities.shape();
    1068           0 :         uInt nChannels = flagCubeShape(0);
    1069           0 :         uInt nTimes = flagCubeShape(1);
    1070             : 
    1071             :         // Read antenna names for the current baseline
    1072           0 :         String antenna1Name = flagDataHandler_p->antennaNames_p->operator()(antenna1);
    1073           0 :         String antenna2Name = flagDataHandler_p->antennaNames_p->operator()(antenna2);
    1074           0 :         String baselineName = antenna1Name + "&&" + antenna2Name;
    1075             :     {
    1076           0 :         std::lock_guard<std::mutex> lock(gui_state->set_values);
    1077           0 :         gui_state->antenna1_p = antenna1Name;
    1078           0 :         gui_state->antenna2_p = antenna2Name;
    1079           0 :     }
    1080             : 
    1081           0 :         String scanRange = (scanStart_p!=scanEnd_p)?String::toString(scanStart_p)+"~"+String::toString(scanEnd_p) : String::toString(scanStart_p);
    1082           0 :         String spwName = String::toString(visBuffer.spectralWindows()(0));
    1083             : 
    1084             :         // Get Frequency List
    1085           0 :         freqList_p.resize(nChannels);
    1086           0 :         for(uInt ch=0;ch<nChannels;ch++) freqList_p[ch]=(Double)ch;
    1087             : 
    1088             : 
    1089             :         /*
    1090             :     // Read current Field name, SPW id, and correlation string from visBuffer Info.
    1091             :     uInt fieldId_p = visBuffer.fieldId();
    1092             :     String fieldName = visBuffer.msColumns().field().name().getColumn()[fieldId_p];
    1093             :     String spwName = String::toString(visBuffer.spectralWindow());
    1094             :     Int scanstart = visBuffer.scan()[0];
    1095             :     int scanend = visBuffer.scan()[ (visBuffer.scan().nelements())-1 ];
    1096             :     String scanRange = (scanstart!=scanend)?String::toString(scanstart)+"~"+String::toString(scanend) : String::toString(scanstart);
    1097             :          */
    1098             : 
    1099             :         // Get Polarization Maps
    1100             :         /*
    1101             :     Vector<uInt> polarizations = flags.getSelectedCorrelations();
    1102             :     nPolarizations_p = polarizations.size();
    1103             :     polarizationIndexMap *polMap = flagDataHandler_p->getPolarizationIndexMap();
    1104             :     Vector<String> corrTypes(nPolarizations_p);
    1105             :     for(uInt pol=0;pol<nPolarizations_p;pol++)
    1106             :       corrTypes[pol] = (*polMap)[polarizations[pol]];
    1107             :          */
    1108             : 
    1109             :         // Get Polarization Maps
    1110             :         // jagonzal: Migrated to new implementation of multiple expressions handling
    1111           0 :         vector<string> corrTypes = visibilities.getSelectedCorrelationStrings();
    1112           0 :         nPolarizations_p = corrTypes.size();
    1113             : 
    1114             :         ///cout << "Selected Correlations : " << polarizations << LogIO::POST;
    1115             : 
    1116             :         // Print where we are...
    1117             :         //    *logger_p << LogIO::NORMAL  << " Baseline : " << baselineName << " Field : " << fieldName_p << " Spw : " << spwName << "  nChan : " << nChannels << " nPol : " << nPolarizations_p << " nTime : " << nTimes << LogIO::POST;
    1118             : 
    1119             :         // Build the Plot Window for the first time
    1120           0 :         if(dataDisplay_p && dataplotter_p==NULL) buildDataPlotWindow();
    1121             : 
    1122             :         // Adding this block of code as a fix for CAS-4052.
    1123             :         // J.G. : If you find a better way to do this, please change this...
    1124           0 :         if(dataDisplay_p==true && dataplotter_p!=NULL)
    1125             :         {
    1126             :                 Int nrows;
    1127           0 :                 if(showBandpass_p==true) nrows=3;
    1128           0 :                 else nrows=2;
    1129             : 
    1130           0 :                 if(panels_p.size() != nPolarizations_p*nrows)
    1131             :                 {
    1132             :                         //cout << "Wrong number of panels !" << endl;
    1133           0 :                         done(dataplotter_p);
    1134           0 :                         dataplotter_p = NULL;
    1135           0 :                         buildDataPlotWindow();
    1136             :                 }
    1137             :         }
    1138             : 
    1139             :         // Initialize Plot Arrays and other vars
    1140           0 :         Float runningsum=0, runningflag=0,runningpreflag=0;
    1141           0 :         Vector<Float> vecflagdat(0), vecdispdat(0);
    1142           0 :         Vector<Float> origspectrum(0), flagspectrum(0), precountspec(0), countspec(0);
    1143           0 :         if(dataDisplay_p)
    1144             :         {
    1145           0 :                 vecflagdat.resize(nChannels * nTimes); vecdispdat.resize(nChannels * nTimes);
    1146           0 :                 origspectrum.resize(nChannels); flagspectrum.resize(nChannels);
    1147           0 :                 precountspec.resize(nChannels); countspec.resize(nChannels);
    1148             :         }
    1149             : 
    1150           0 :         if(dataDisplay_p)
    1151             :         {
    1152             :                 // Make and send plots for each polarization
    1153           0 :                 for(int pl=0;pl<(int) nPolarizations_p;pl++)  // Start Correlation Loop
    1154             :                 {
    1155           0 :                         runningsum=0; runningflag=0;  runningpreflag=0;
    1156           0 :                         origspectrum=0.0; flagspectrum=0.0; precountspec=0.0; countspec=0.0;
    1157           0 :                         for(int ch=0;ch<(int) nChannels;ch++)  // Start Channel Loop
    1158             :                         {
    1159           0 :                                 for(uInt tm=0;tm<nTimes;tm++)  // Start Time Loop
    1160             :                                 {
    1161             :                                         // UUU FOR TEST ONLY -- Later, enable additional ManualFlagAgent in the tFlagAgentDisplay
    1162             :                                         /////if(ch>10 && ch<20) flags.applyFlag(ch,tm);
    1163             : 
    1164           0 :                                         vecdispdat( ch*nTimes + tm ) = visibilities(pl,ch,tm) * ( ! flags.getOriginalFlags(pl,ch,tm) );
    1165           0 :                                         vecflagdat( ch*nTimes + tm ) = visibilities(pl,ch,tm) * ( ! flags.getModifiedFlags(pl,ch,tm) );
    1166             : 
    1167           0 :                                         origspectrum[ch] += visibilities(pl,ch,tm) * ( ! flags.getOriginalFlags(pl,ch,tm) );
    1168           0 :                                         flagspectrum[ch] += visibilities(pl,ch,tm) * ( ! flags.getModifiedFlags(pl,ch,tm) );
    1169             : 
    1170           0 :                                         precountspec[ch] += ( ! flags.getOriginalFlags(pl,ch,tm) );
    1171           0 :                                         countspec[ch] += ( ! flags.getModifiedFlags(pl,ch,tm) );
    1172             : 
    1173           0 :                                         runningsum += visibilities(pl,ch,tm);
    1174           0 :                                         runningflag += (Float)(flags.getModifiedFlags(pl,ch,tm));
    1175           0 :                                         runningpreflag += (Float)(flags.getOriginalFlags(pl,ch,tm));
    1176             : 
    1177             :                                 }// End Time Loop
    1178             :                         }//End Channel Loop
    1179             : 
    1180             :                         // Make the Labels
    1181           0 :                         stringstream ostr1,ostr2;
    1182           0 :                         ostr1 << "(" << fieldId_p << ") " << fieldName_p << "  [scan:" << scanRange << "]\n[spw:" << spwName << "] " << baselineName << "  ( " << corrTypes[pl] << " )";
    1183           0 :                         ostr2 << fixed;
    1184           0 :                         ostr2.precision(1);
    1185           0 :                         ostr2 << " flag:" << 100 * runningflag/(nChannels*nTimes) << "% (pre-flag:" << 100 * runningpreflag/(nChannels*nTimes) << "%)";
    1186             : 
    1187             :                         //*logger_p << "[" << corrTypes[pl] << "]:" << 100 * runningflag/(nChannels*nTimes) << "%(" << 100 * runningpreflag/(nChannels*nTimes) << "%) ";
    1188             : 
    1189             :                         // Make the Before/After Raster Plots
    1190           0 :                         DisplayRaster(nChannels,nTimes,vecdispdat,panels_p[pl]);
    1191           0 :             setlabel( dataplotter_p, panels_p[pl], " ", pl?" ":"Time", ostr1.str() );
    1192           0 :                         DisplayRaster(nChannels,nTimes,vecflagdat,panels_p[pl+nPolarizations_p]);
    1193           0 :             setlabel( dataplotter_p, panels_p[pl+nPolarizations_p], "Frequency", pl?" ":"Time", ostr2.str() );
    1194             : 
    1195           0 :                         if(showBandpass_p==true)
    1196             :                         {
    1197             : 
    1198             :                                 // Make the Before/After bandpass plots
    1199           0 :                                 for(uInt ch=0;ch<nChannels;ch++)
    1200             :                                 {
    1201           0 :                                         if(precountspec[ch]==0) {origspectrum[ch]=0.0; precountspec[ch]=1.0;}
    1202           0 :                                         if(countspec[ch]==0) {flagspectrum[ch]=0.0; countspec[ch]=1.0;}
    1203             :                                 }
    1204             : 
    1205           0 :                                 origspectrum = (origspectrum/precountspec);
    1206           0 :                                 flagspectrum = (flagspectrum/countspec);
    1207           0 :                                 AlwaysAssert( freqList_p.nelements()==nChannels , AipsError);
    1208             : 
    1209           0 :                                 DisplayLine( nChannels, freqList_p, origspectrum, String("before:")+String(corrTypes[pl]),
    1210           0 :                              String("red"), false, panels_p[pl+(2*nPolarizations_p)] );
    1211           0 :                                 DisplayScatter( nChannels, freqList_p, flagspectrum, String("after:")+String(corrTypes[pl]),
    1212           0 :                                 String("blue"), true, panels_p[pl+(2*nPolarizations_p)] );
    1213             : 
    1214             :                                 //// TODO : Can I query the tfcrop agent for a "view" to overlay here.
    1215             :                                 // If available, get a plot from the agents
    1216             :                                 /*
    1217             :                   for (uInt fmeth=0; fmeth<flagmethods.nelements(); fmeth++)
    1218             :                   {
    1219             :                   if(flagmethods[fmeth]->getMonitorSpectrum(flagspectrum,pl,bs))
    1220             :                   {
    1221             :                   //                flagspectrum = log10(flagspectrum);
    1222             :                   DisplayLine(nChannels, freqlist_p, flagspectrum, flagmethods[fmeth]->methodName(), 
    1223             :                   String("green"), true, panels_p[pl+(2*nPolarizations_p)].getInt());
    1224             :                   }
    1225             :                   }
    1226             :                                  */
    1227             :                         }// end of if (showBandPass_p)
    1228             : 
    1229           0 :                 }//End Correlation Loop
    1230             : 
    1231             :                 //*logger_p << LogIO::POST;
    1232             : 
    1233             :         }// end if dataDisplay_p
    1234             : 
    1235           0 :         return false;
    1236           0 : }// end computeAntennaPairFlags
    1237             : 
    1238             : //----------------------------------------------------------------------------------------------------------
    1239             : 
    1240             : void
    1241           0 : FlagAgentDisplay::getChunkInfo(const vi::VisBuffer2 &visBuffer)
    1242             : {
    1243           0 :         logger_p->origin(LogOrigin(agentName_p,__FUNCTION__,WHERE));
    1244             :         // Read current Field name, SPW id, and scan info.
    1245           0 :         fieldId_p = visBuffer.fieldId()(0);
    1246           0 :         fieldName_p = flagDataHandler_p->fieldNames_p->operator()(fieldId_p);
    1247           0 :         spwId_p = visBuffer.spectralWindows()(0);
    1248           0 :         scanStart_p = visBuffer.scan()[0];
    1249           0 :         scanEnd_p = visBuffer.scan()[ (visBuffer.scan().nelements())-1 ];
    1250             : 
    1251           0 :         *logger_p << LogIO::NORMAL << "FlagAgentDisplay::" << __FUNCTION__ << " Field : " << fieldId_p << " , " << fieldName_p << " Spw : " << spwId_p << " Scan : " << scanStart_p << " : " << scanEnd_p << LogIO::POST;
    1252           0 : }
    1253             : 
    1254             : //----------------------------------------------------------------------------------------------------------
    1255             : 
    1256             : FlagReport
    1257           0 : FlagAgentDisplay::getReport()
    1258             : {
    1259           0 :         logger_p->origin(LogOrigin(agentName_p,__FUNCTION__,WHERE));
    1260             : 
    1261             :         //       FlagReport dispRep("plot",agentName_p);
    1262             : 
    1263             :         // Make empty list
    1264           0 :         FlagReport dispRep("list");
    1265             : 
    1266             :         /*
    1267             : 
    1268             :        // Make sample arrays/vectors
    1269             :        Int N=10;
    1270             :        Array<Float> sample( IPosition(2, N, N) );
    1271             :        sample = 0.0;
    1272             :        sample( IPosition(2,N/2,N/2)) = 1.0;
    1273             :        Vector<Float> xdata( N ), ydata( N ), error ( N );
    1274             :        for(Int i=0;i<N;i++) {xdata[i]=i;}
    1275             :        ydata = 1.0;
    1276             : 
    1277             :        // (1) Make a raster plot. Only one set of data is allowed here.
    1278             :        FlagReport subRep0 = FlagReport("plotraster",agentName_p,"example raster", "xaxis", "yaxis");
    1279             :        subRep0.addData(sample); // add 2D data
    1280             : 
    1281             :        // Add this raster FlagReport to the list.
    1282             :        dispRep.addReport( subRep0 ); 
    1283             : 
    1284             :        // (2) Make a line plot. Can give multiple lines to overlay on the same panel.
    1285             :        FlagReport subRep1 = FlagReport("plotpoints",agentName_p,"example line", "xaxis", "yaxis");
    1286             :        subRep1.addData("line", xdata,ydata,"",Vector<Float>(),"line 1"); // add first set of line data
    1287             :        ydata[N/2]=2.0;
    1288             :        subRep1.addData("scatter", xdata,ydata,"",Vector<Float>(),"scatter 2"); // add second set of line data to overlay
    1289             : 
    1290             :        // Add this line FlagReport to the list
    1291             :        dispRep.addReport( subRep1 ); 
    1292             : 
    1293             :        // (3) Make an overlay of a line with errorbar, scatter with errorbar, and scatter with circle
    1294             :        FlagReport subRep2 = FlagReport("plotpoints",agentName_p,"example line", "xaxis", "yaxis");
    1295             :        for(Int i=0;i<N;i++) {error[i]=i;}
    1296             :        subRep2.addData("line", xdata,ydata,"bar",error,"line+bar"); // add first set of line data, with errorbars
    1297             :        for(Int i=0;i<N;i++) {xdata[i] += 0.3; error[i]=i; ydata[i]+=2.0;}
    1298             :        subRep2.addData("scatter", xdata, ydata,"bar",error,"scatter+bar"); // add second set of scatter data to overlay, with error bars
    1299             :        for(Int i=0;i<N;i++) {xdata[i] += 0.3; error[i]=i*10; ydata[i]+=2.0;}
    1300             :        subRep2.addData("scatter", xdata, ydata,"circle",error,"scatter+circle"); // add third set, scatter data with circles.
    1301             : 
    1302             :        // Add this line FlagReport to the list
    1303             :        dispRep.addReport( subRep2 ); 
    1304             : 
    1305             :        if( ! dispRep.verifyFields() )
    1306             :          cout << "Problem ! " << endl;
    1307             : 
    1308             : 
    1309             :          */
    1310             : 
    1311           0 :         return dispRep;
    1312             : }// end of getReport()
    1313             : 
    1314             : //----------------------------------------------------------------------------------------------------------
    1315             : // Go through the list of reports and make plots
    1316             : Bool
    1317           0 : FlagAgentDisplay::displayReports(FlagReport &combinedReport)
    1318             : {
    1319           0 :         logger_p->origin(LogOrigin(agentName_p,__FUNCTION__,WHERE));
    1320             : 
    1321           0 :         if(reportDisplay_p && !stopAndExit_p)
    1322             :         {
    1323           0 :                 Int nReports = combinedReport.nReport();
    1324             : 
    1325           0 :                 if( dataplotter_p != NULL ) {
    1326           0 :             done(dataplotter_p);
    1327           0 :             dataplotter_p = NULL;
    1328             :         }
    1329           0 :                 if(nReports>0 && reportplotter_p==NULL) buildReportPlotWindow();
    1330             : 
    1331           0 :                 Bool stepback=false;
    1332             : 
    1333           0 :                 for (Int reportid=0; reportid<nReports; reportid++)
    1334             :                 {
    1335           0 :                         String agentName, title, xlabel, ylabel;
    1336           0 :                         FlagReport oneRep;
    1337             : 
    1338           0 :                         if(stepback==true)
    1339             :                         {
    1340             :                                 // Go back until a valid one is found.
    1341           0 :                                 Int previd=-1;
    1342           0 :                                 for( Int rep=reportid-1; rep>=0; --rep)
    1343             :                                 {
    1344           0 :                                         Bool valid = combinedReport.accessReport(rep,oneRep);
    1345           0 :                                         if(valid)
    1346             :                                         {
    1347           0 :                                                 String type = oneRep.reportType();
    1348           0 :                                                 if( type=="plotraster" || type=="plotpoints" )
    1349             :                                                 {
    1350           0 :                                                         previd=rep; break;
    1351             :                                                 }
    1352           0 :                                         }
    1353             :                                 }
    1354             : 
    1355           0 :                                 if(previd==-1)
    1356             :                                 {
    1357           0 :                                         *logger_p << "Already on first plot" << LogIO::POST;
    1358           0 :                                         reportid=0;
    1359             :                                 }
    1360             :                                 else
    1361             :                                 {
    1362           0 :                                         reportid = previd;
    1363             :                                 }
    1364             : 
    1365           0 :                                 stepback=false;
    1366             :                         }
    1367             : 
    1368             : 
    1369           0 :                         Bool valid = combinedReport.accessReport(reportid,oneRep);
    1370           0 :                         if(valid)
    1371             :                         {
    1372           0 :                                 oneRep.get( RecordFieldId("name") , agentName );
    1373           0 :                                 String type = oneRep.reportType();
    1374             : 
    1375           0 :                                 if( type=="plotraster" || type=="plotpoints" )
    1376             :                                 {
    1377             : 
    1378           0 :                                         *logger_p << reportid << " : " << type << " with " << oneRep.nData() << " layer(s) " << " from " << agentName << LogIO::POST;
    1379             : 
    1380           0 :                                         if( type == "plotraster" )
    1381             :                                         {
    1382           0 :                                                 oneRep.get( RecordFieldId("title") , title );
    1383           0 :                                                 oneRep.get( RecordFieldId("xlabel") , xlabel );
    1384           0 :                                                 oneRep.get( RecordFieldId("ylabel") , ylabel );
    1385             : 
    1386           0 :                                                 Array<Float> data;
    1387           0 :                                                 oneRep.get( RecordFieldId("data"+String::toString(0)) , data );
    1388             : 
    1389           0 :                         std::vector<float> flatdata(data.begin(),data.end());
    1390             : 
    1391           0 :                         erase( reportplotter_p, report_panels_p[0] );
    1392           0 :                         raster( reportplotter_p, report_panels_p[0], flatdata, data.shape()[0], data.shape()[1] );
    1393           0 :                         setlabel( reportplotter_p, report_panels_p[0], xlabel, ylabel, title );
    1394             : 
    1395           0 :                                         }
    1396           0 :                                         else if( type == "plotpoints")
    1397             :                                         {
    1398           0 :                                                 oneRep.get( RecordFieldId("title") , title );
    1399           0 :                                                 oneRep.get( RecordFieldId("xlabel") , xlabel );
    1400           0 :                                                 oneRep.get( RecordFieldId("ylabel") , ylabel );
    1401             : 
    1402           0 :                         erase( reportplotter_p, report_panels_p[0] );
    1403             : 
    1404           0 :                                                 Int ndata = oneRep.nData();
    1405           0 :                                                 for(Int datid=0;datid<ndata;datid++)
    1406             :                                                 {
    1407           0 :                                                         Vector<Float> xdata,ydata,error;
    1408           0 :                                                         String legendlabel,plottype="line",errortype="";
    1409           0 :                                                         oneRep.get( RecordFieldId("xdata"+String::toString(datid)) , xdata );
    1410           0 :                                                         oneRep.get( RecordFieldId("ydata"+String::toString(datid)) , ydata );
    1411           0 :                                                         oneRep.get( RecordFieldId("label"+String::toString(datid)) , legendlabel );
    1412           0 :                                                         oneRep.get( RecordFieldId("plottype"+String::toString(datid)) , plottype );
    1413             : 
    1414             :                                                         ///reportplotter_p->line(dbus::af(xdata), dbus::af(ydata),(datid%2)?String("red"):String("blue"),legendlabel, report_panels_p[0].getInt());
    1415             : 
    1416           0 :                                                         if ( oneRep.isDefined( "error"+String::toString(datid)  ) )
    1417             :                                                         {
    1418           0 :                                                                 oneRep.get( RecordFieldId("error"+String::toString(datid)) , error );
    1419           0 :                                                                 oneRep.get( RecordFieldId("errortype"+String::toString(datid)) , errortype );
    1420             :                                                         }
    1421             : 
    1422           0 :                                                         DisplayLineScatterError(reportplotter_p , plottype, xdata, ydata, errortype, error, legendlabel, plotColours_p[datid%plotColours_p.nelements()], report_panels_p[0] );
    1423             :                                                         /// (datid%2)?String("red"):String("blue")
    1424           0 :                                                 }// end of for datid
    1425             : 
    1426           0 :                         setlabel( reportplotter_p, report_panels_p[0], xlabel, ylabel, title );
    1427             : 
    1428             :                                         }// end of plotpoints
    1429             :                                         else
    1430             :                                         {
    1431           0 :                                                 *logger_p << "NO Display for : " << reportid << " : " << agentName << LogIO::POST;
    1432             :                                         }
    1433             : 
    1434           0 :                                         getReportUserInput();
    1435             : 
    1436             :                                         // React to user-input
    1437           0 :                                         if(gui_state->userChoice_p=="Quit")
    1438             :                                         {
    1439           0 :                                                 dataDisplay_p = false;
    1440           0 :                                                 stopAndExit_p = true;
    1441             :                                                 //*logger_p << "Exiting flagger" << LogIO::POST;
    1442           0 :                                                 if( reportplotter_p != NULL ) {
    1443           0 :                             done(reportplotter_p);
    1444           0 :                             reportplotter_p = NULL;
    1445             :                         }
    1446           0 :                                                 return true;
    1447             :                                         }
    1448           0 :                                         else if(gui_state->userChoice_p=="Prev")
    1449             :                                         {
    1450             :                                                 //*logger_p << "Prev Plot" << LogIO::POST;
    1451           0 :                                                 if( reportid==0 )
    1452           0 :                                                         *logger_p << "Already on first plot..." << LogIO::POST;
    1453             :                                                 else
    1454           0 :                                                         --reportid;
    1455           0 :                                                 stepback=true;
    1456             :                                         }
    1457           0 :                                         else if(gui_state->userChoice_p=="Continue" || gui_state->userChoice_p=="Next")
    1458             :                                         {
    1459             :                                                 //*logger_p << "Next Plot " << LogIO::POST;
    1460           0 :                                                 if( reportid==nReports-1 )
    1461             :                                                 {
    1462           0 :                                                         *logger_p << "Already on last plot..." << LogIO::POST;
    1463           0 :                                                         --reportid;
    1464             :                                                 }
    1465             :                                         }
    1466             : 
    1467             :                                 }// if valid plot type
    1468             :                                 else
    1469             :                                 {
    1470             :                                         //*logger_p  <<  "No plot for Report : " << reportid << LogIO::POST;
    1471           0 :                                         *logger_p << reportid << " : No plot for report from " << agentName << LogIO::POST;
    1472             : 
    1473             :                                 }
    1474           0 :                         }// if valid plot record.
    1475             :                         else
    1476             :                         {
    1477           0 :                                 *logger_p << LogIO::WARN <<  "Invalid Plot Record for : " << reportid << LogIO::POST;
    1478             :                         }
    1479             : 
    1480           0 :                 }// end of for-report-in-combinedReport
    1481             : 
    1482           0 :         }// end of reportDisplay_p==true
    1483             :         else
    1484             :         {
    1485           0 :                 *logger_p << "Report Displays are turned OFF " << LogIO::POST;
    1486             :         }
    1487           0 :         return true;
    1488             : } // end of displayReports()
    1489             : 
    1490             : /***********************************************************************/
    1491             : /******************     Plot Functions      ******************************/
    1492             : /***********************************************************************/
    1493             : 
    1494             : // Note : By default, only two rows of plots are created.
    1495             : // The third row, for bandpass plots (before and after) are turned off
    1496             : // by the private variable 'showBandPass_p'. This can be later
    1497             : // enabled when we get per-chunk 'extra info' displays/reports from
    1498             : // the agents. Right now, it's redundant info, and takes up too much
    1499             : // space on small laptop screens.
    1500           0 : Bool FlagAgentDisplay::buildDataPlotWindow()
    1501             : {
    1502             : 
    1503           0 :         setDataLayout();
    1504           0 :         AlwaysAssert( dock_xml_p != NULL , AipsError );
    1505             : 
    1506           0 :         dataplotter_p.reset(new plotter_t(gui_state));
    1507             : 
    1508             :         Int nrows;
    1509           0 :         if(showBandpass_p==true) nrows=3;
    1510           0 :         else nrows=2;
    1511           0 :         panels_p.resize(nPolarizations_p*nrows);
    1512           0 :         string zoomloc="";
    1513           0 :         string legendloc="bottom";
    1514             : 
    1515             :     // First row : Data with no flags
    1516           0 :     panels_p[0] = create_panel(dataplotter_p,0,false);
    1517             : 
    1518           0 :         if(nPolarizations_p>1)
    1519             :         {
    1520           0 :                 for(Int i=1;i<(int) nPolarizations_p;i++)
    1521             :                 {
    1522           0 :             panels_p[i] = create_panel(dataplotter_p,panels_p[i-1],false);
    1523             :                 }
    1524             :         }
    1525             : 
    1526             : 
    1527             :         // Second row : Data with flags
    1528           0 :         panels_p[nPolarizations_p] = create_panel(dataplotter_p,panels_p[0],true);
    1529           0 :         if(nPolarizations_p>1)
    1530             :         {
    1531           0 :                 for(int i=static_cast<int>(nPolarizations_p)+1;i<2*static_cast<int>(nPolarizations_p);i++)
    1532             :                 {
    1533           0 :                         panels_p[i] = create_panel(dataplotter_p,panels_p[i-1],false);
    1534             :                 }
    1535             :         }
    1536             : 
    1537             :         // Third row : Average Bandpass
    1538           0 :         if(showBandpass_p==true)
    1539             :         {
    1540           0 :                 panels_p[2*nPolarizations_p] = create_panel(dataplotter_p,panels_p[0],true);
    1541             : 
    1542           0 :                 if(nPolarizations_p>1)
    1543             :                 {
    1544           0 :                         for(int i=2* static_cast<int>(nPolarizations_p)+1;i<3*static_cast<int>(nPolarizations_p);i++)
    1545             :                         {
    1546           0 :                                 panels_p[i] = create_panel(dataplotter_p,panels_p[i-1],false);
    1547             :                         }
    1548             :                 }
    1549             :         }// if showbandpass
    1550             : 
    1551             :         /*
    1552             :     // Misc panel
    1553             :     panels_p[8] = dataplotter_p->panel( "BandPass", "Frequency", "Amp", "",
    1554             :     std::vector<int>( ),legendloc,zoomloc, panels_p[3].getInt(),false,false);
    1555             : 
    1556             :     // Dummy panel
    1557             :     panels_p[9] = dataplotter_p->panel( "---", "----", "---", "",
    1558             :     std::vector<int>( ),legendloc,zoomloc, panels_p[7].getInt(),false,false);
    1559             :          */
    1560             : 
    1561           0 :     create_dock(dataplotter_p, panels_p[0],dock_xml_p);
    1562           0 :         return true;
    1563             : 
    1564           0 : }// end buildDataPlotWindow
    1565             : 
    1566             : 
    1567           0 : Bool FlagAgentDisplay::buildReportPlotWindow()
    1568             : {
    1569             : 
    1570           0 :         setReportLayout();
    1571           0 :         AlwaysAssert( report_dock_xml_p != NULL , AipsError );
    1572             : 
    1573           0 :         reportplotter_p.reset(new plotter_t(gui_state));
    1574             : 
    1575           0 :         report_panels_p.resize(1);
    1576           0 :         string zoomloc="";
    1577           0 :         string legendloc="bottom";
    1578           0 :     report_panels_p[0] = create_panel(reportplotter_p,0,false);
    1579             : 
    1580           0 :     create_dock( reportplotter_p, report_panels_p[0], report_dock_xml_p );
    1581           0 :         return true;
    1582             : 
    1583           0 : }// end buildReportPlotWindow
    1584             : 
    1585             : 
    1586             : 
    1587           0 : void FlagAgentDisplay::getUserInput( ) {
    1588             : 
    1589           0 :     static const auto debug = getenv("GRPC_DEBUG");
    1590           0 :     if ( debug ) {
    1591           0 :         std::cerr << ( active( ) ? 
    1592             :                        "FlagAgentDisplay getUserInput " : 
    1593             :                        "FlagAgentDisplay getUserInput ERROR no active GUIs " ) <<
    1594           0 :             " (process " << getpid( ) << ", thread " << 
    1595           0 :             std::this_thread::get_id() << ")" << std::endl;
    1596           0 :         fflush(stderr);
    1597             :     }
    1598             : 
    1599           0 :     if ( ! active( ) ) return;
    1600             : 
    1601           0 :     if ( gui_state->input_received ) {
    1602             :         // GUI input received while this thread was preoccupied...
    1603           0 :         std::lock_guard<std::mutex> lock(gui_state->set_values);
    1604           0 :         gui_state->input_received = false;
    1605           0 :         return;
    1606           0 :     } else  {
    1607           0 :         std::lock_guard<std::mutex> lock(gui_state->set_values);
    1608           0 :         gui_state->userChoice_p = "Continue";
    1609           0 :         gui_state->output = std::promise<bool>( );
    1610           0 :         gui_state->input_needed = true;
    1611           0 :     }
    1612             : 
    1613           0 :     auto fut = gui_state->output.get_future();
    1614           0 :     fut.get( );
    1615             :     {
    1616           0 :         std::lock_guard<std::mutex> lock(gui_state->set_values);
    1617           0 :         gui_state->input_received = false;
    1618           0 :     }
    1619           0 : }
    1620             : 
    1621             : 
    1622             : 
    1623           0 : void FlagAgentDisplay :: getReportUserInput() {
    1624             : 
    1625           0 :     static const auto debug = getenv("GRPC_DEBUG");
    1626           0 :     if ( debug ) {
    1627           0 :         std::cerr << ( active( ) ? 
    1628             :                        "FlagAgentDisplay getReportUserInput " : 
    1629             :                        "FlagAgentDisplay getReportUserInput ERROR no active GUIs " ) <<
    1630           0 :             " (process " << getpid( ) << ", thread " << 
    1631           0 :             std::this_thread::get_id() << ")" << std::endl;
    1632           0 :         fflush(stderr);
    1633             :     }
    1634             : 
    1635           0 :     if ( ! active( ) ) return;
    1636             : 
    1637           0 :     if ( gui_state->input_received ) {
    1638             :         // GUI input received while this thread was preoccupied...
    1639           0 :         std::lock_guard<std::mutex> lock(gui_state->set_values);
    1640           0 :         gui_state->input_received = false;
    1641           0 :         return;
    1642           0 :     } else  {
    1643           0 :         std::lock_guard<std::mutex> lock(gui_state->set_values);
    1644           0 :         gui_state->userChoice_p = "Continue";
    1645           0 :         gui_state->output = std::promise<bool>( );
    1646           0 :         gui_state->input_needed = true;
    1647           0 :     }
    1648             : 
    1649           0 :     auto fut = gui_state->output.get_future();
    1650           0 :     fut.get( );
    1651           0 : }
    1652             : 
    1653             : 
    1654             : //////////////////////////////////////////////////////////////////////////////////////////////////////
    1655             : //////   Plot functions
    1656             : //////////////////////////////////////////////////////////////////////////////////////////////////////
    1657             : 
    1658           0 : void FlagAgentDisplay::DisplayRaster(Int xdim, Int ydim, Vector<Float> &data, int frame)
    1659             : {
    1660           0 :         if(data.nelements() != (uInt) xdim*ydim)
    1661             :         {
    1662           0 :                 logger_p->origin(LogOrigin(agentName_p,__FUNCTION__,WHERE));
    1663           0 :                 *logger_p << LogIO::WARN << "Error in data XY dimensions. Not plotting" << LogIO::POST;
    1664           0 :                 return;
    1665             :         }
    1666             :         //    cout << "panel id : " << frame << endl;
    1667             : 
    1668             :         // dataplotter_p->release( panel_p.getInt( ) );
    1669           0 :     erase( dataplotter_p, frame );
    1670             : 
    1671             :         //      dataplotter_p->line(x, y, "blue", "time", panel_p.getInt() );
    1672           0 :         raster( dataplotter_p, frame, std::vector<float>(data.begin(),data.end()), xdim, ydim );
    1673             : }
    1674             : 
    1675             : //////////////////////////////////////////////////////////////////////////////////////////////////////
    1676           0 : void FlagAgentDisplay::DisplayLine(Int /*xdim*/, Vector<Double> &xdata, Vector<Float> &ydata, String label, String color, Bool hold, int frame)
    1677             : {
    1678           0 :         if(xdata.nelements() != ydata.nelements())
    1679             :         {
    1680           0 :                 logger_p->origin(LogOrigin(agentName_p,__FUNCTION__,WHERE));
    1681           0 :                 *logger_p << LogIO::WARN << "X and Y plot data have different sizes. Not plotting " << LogIO::POST;
    1682           0 :                 return;
    1683             :         }
    1684           0 :         if( hold==false ) erase( dataplotter_p, frame );
    1685           0 :         line( dataplotter_p, frame, std::vector<float>(xdata.begin(),xdata.end()), std::vector<float>(ydata.begin(),ydata.end()), color, label );
    1686             : }
    1687             : //////////////////////////////////////////////////////////////////////////////////////////////////////
    1688             : 
    1689           0 : void FlagAgentDisplay::DisplayScatter(Int /*xdim*/, Vector<Double> &xdata, Vector<Float> &ydata, String label, String color, Bool hold, int frame)
    1690             : {
    1691           0 :         if(xdata.nelements() != ydata.nelements())
    1692             :         {
    1693           0 :                 logger_p->origin(LogOrigin(agentName_p,__FUNCTION__,WHERE));
    1694           0 :                 *logger_p << LogIO::WARN << "X and Y plot data have different sizes. Not plotting " << LogIO::POST;
    1695           0 :                 return;
    1696             :         }
    1697           0 :         if( hold==false ) erase( dataplotter_p, frame );
    1698           0 :         scatter( dataplotter_p, frame, std::vector<float>(xdata.begin(),xdata.end()),
    1699           0 :              std::vector<float>(ydata.begin(),ydata.end()), color, label, "dot", 1, 4 );
    1700             : }
    1701             : //////////////////////////////////////////////////////////////////////////////////////////////////////
    1702             : 
    1703             : // Display scatter dots, with optional vertical error-bars, or circles or text labels, or all together.
    1704             : // Send in vectors of size 0 for radii and pointlabels and error to disable them.
    1705           0 : void FlagAgentDisplay::DisplayLineScatterError(std::shared_ptr<FlagAgentDisplay::plotter_t> plotter, String &plottype, Vector<Float> &xdata, Vector<Float> &ydata, String &errortype, Vector<Float> &error, String label, String color, int frame)
    1706             : {
    1707             :         // Check X and Y shapes
    1708           0 :         if(xdata.nelements() != ydata.nelements())
    1709             :         {
    1710           0 :                 logger_p->origin(LogOrigin(agentName_p,__FUNCTION__,WHERE));
    1711           0 :                 *logger_p << LogIO::WARN << "X, Y plot data have different sizes. Not plotting." << LogIO::POST;
    1712           0 :                 return;
    1713             :         }
    1714             : 
    1715           0 :         if(plottype==String("scatter"))
    1716             :         {
    1717             :                 // Scatter-plot of X and Y
    1718           0 :                 scatter( plotter, frame, std::vector<float>(xdata.begin(),xdata.end()),
    1719           0 :                  std::vector<float>(ydata.begin(),ydata.end()),color,label,"dot",1,4 );
    1720             :         }
    1721           0 :         else if (plottype==String("line"))
    1722             :         {
    1723             :                 // Line plot of X and Y
    1724           0 :                 line( plotter, frame, std::vector<float>(xdata.begin(),xdata.end()),
    1725           0 :               std::vector<float>(ydata.begin(),ydata.end()),color,label );
    1726             :         }
    1727             :         else
    1728             :         {
    1729           0 :                 return;
    1730             :         }
    1731             : 
    1732             :         // Check Error shape ( if not zero, must match xdata,ydata)
    1733           0 :         if(error.nelements()>0)
    1734             :         {
    1735           0 :                 if(error.nelements()!=xdata.nelements())
    1736             :                 {
    1737           0 :                         logger_p->origin(LogOrigin(agentName_p,__FUNCTION__,WHERE));
    1738           0 :                         *logger_p << LogIO::WARN << "Number of Error elements is different from data. Not plotting." << LogIO::POST;
    1739           0 :                         return;
    1740             :                 }
    1741             : 
    1742           0 :                 if(errortype == "bar")
    1743             :                 {
    1744           0 :                         Vector<Double>pointerror(2);
    1745           0 :                         Vector<Double>xval(2);
    1746           0 :                         for ( Int onepoint=0; onepoint<(Int) error.nelements(); onepoint++)
    1747             :                         {
    1748           0 :                                 xval[0]=xdata[onepoint];
    1749           0 :                                 xval[1]=xdata[onepoint];
    1750           0 :                                 pointerror[0]=ydata[onepoint] + error[onepoint];
    1751           0 :                                 pointerror[1]=ydata[onepoint] - error[onepoint];
    1752           0 :                                 line( plotter, frame, std::vector<float>(xval.begin(),xval.end()),
    1753           0 :                       std::vector<float>(pointerror.begin(),pointerror.end()), color,"" );
    1754             :                         }
    1755           0 :                 }
    1756           0 :                 else if(errortype == "separator")
    1757             :                 {
    1758           0 :                         Vector<Double>pointerror(2);
    1759           0 :                         Vector<Double>xval(2);
    1760           0 :                         for ( Int onepoint=0; onepoint<(Int) error.nelements(); onepoint++)
    1761             :                         {
    1762           0 :                                 xval[0]=xdata[onepoint];
    1763           0 :                                 xval[1]=xdata[onepoint];
    1764           0 :                                 pointerror[0]=ydata[onepoint] + error[onepoint];
    1765           0 :                                 pointerror[1]=0;
    1766           0 :                                 line( plotter, frame, std::vector<float>(xval.begin(),xval.end()),
    1767           0 :                       std::vector<float>(pointerror.begin(),pointerror.end()),"black","" );
    1768             :                         }
    1769           0 :                 }
    1770           0 :                 else if(errortype == "circle")
    1771             :                 {
    1772             :                         // Check Circle shape ( if not zero, must match xdata,ydata)
    1773           0 :                         Vector<Double>xval(1),yval(1);
    1774           0 :                         for ( Int onepoint=0; onepoint<(Int) error.nelements(); onepoint++)
    1775             :                         {
    1776           0 :                                 xval[0]=xdata[onepoint];
    1777           0 :                                 yval[0]=ydata[onepoint];
    1778             :                                 // function signature should allow a float for the error bar
    1779           0 :                                 scatter( plotter, frame, std::vector<float>(xval.begin(),xval.end()),
    1780           0 :                          std::vector<float>(yval.begin(),yval.end()), color, "", "ellipse",
    1781           0 :                          static_cast<Int>(error[onepoint]), 4 );
    1782             :                                 // Note : I think this plots the centre point too. If so, it's a repeat....
    1783             :                         }
    1784           0 :                 }
    1785             :                 else
    1786             :                 {
    1787           0 :                         logger_p->origin(LogOrigin(agentName_p,__FUNCTION__,WHERE));
    1788           0 :                         *logger_p << LogIO::WARN << "Unknown error-plot type. Not plotting." << LogIO::POST;
    1789             :                 }
    1790             :         }// if error
    1791             : 
    1792             :         // Do a similar thing for labels.
    1793             :         // NOTE : Cannot plot point-labels or text strings yet.
    1794             : 
    1795             : }
    1796             : //////////////////////////////////////////////////////////////////////////////////////////////////////
    1797             : 
    1798             : 
    1799             : 
    1800             : //////////////////////////////////////////////////////////////////////////////////////////////////////
    1801             : //////////////////////     GUI Layout Functions
    1802             : //////////////////////////////////////////////////////////////////////////////////////////////////////
    1803             : 
    1804             : 
    1805           0 : Bool FlagAgentDisplay :: setDataLayout()
    1806             : {
    1807             : 
    1808           0 :         dock_xml_p = "\
    1809             : <?xml version=\"1.0\" encoding=\"UTF-8\"?>\
    1810             : <ui version=\"4.0\">\
    1811             :  <class>dock01</class>\
    1812             :  <widget class=\"QDockWidget\" name=\"dock01\">\
    1813             :   <property name=\"geometry\">\
    1814             :    <rect>\
    1815             :     <x>0</x>\
    1816             :     <y>0</y>\
    1817             :     <width>770</width>\
    1818             :     <height>120</height>\
    1819             :    </rect>\
    1820             :   </property>\
    1821             :   <property name=\"sizePolicy\">\
    1822             :    <sizepolicy hsizetype=\"Preferred\" vsizetype=\"Preferred\">\
    1823             :     <horstretch>0</horstretch>\
    1824             :     <verstretch>0</verstretch>\
    1825             :    </sizepolicy>\
    1826             :   </property>\
    1827             :   <property name=\"minimumSize\">\
    1828             :    <size>\
    1829             :     <width>770</width>\
    1830             :     <height>87</height>\
    1831             :    </size>\
    1832             :   </property>\
    1833             :   <property name=\"windowTitle\">\
    1834             :    <string/>\
    1835             :   </property>\
    1836             :   <widget class=\"QWidget\" name=\"dockWidgetContents\">\
    1837             :    <layout class=\"QGridLayout\" name=\"gridLayout_2\">\
    1838             :     <item row=\"0\" column=\"0\">\
    1839             :      <layout class=\"QGridLayout\" name=\"gridLayout\">\
    1840             :       <item row=\"0\" column=\"0\">\
    1841             :        <widget class=\"QPushButton\" name=\"PrevBaseline\">\
    1842             :         <property name=\"text\">\
    1843             :          <string>Prev Baseline</string>\
    1844             :         </property>\
    1845             :        </widget>\
    1846             :       </item>\
    1847             :       <item row=\"0\" column=\"1\">\
    1848             :        <widget class=\"QPushButton\" name=\"NextBaseline\">\
    1849             :         <property name=\"text\">\
    1850             :          <string>Next Baseline</string>\
    1851             :         </property>\
    1852             :        </widget>\
    1853             :       </item>\
    1854             :       <item row=\"0\" column=\"2\">\
    1855             :        <layout class=\"QVBoxLayout\" name=\"verticalLayout\">\
    1856             :         <property name=\"spacing\">\
    1857             :          <number>0</number>\
    1858             :         </property>\
    1859             :         <property name=\"sizeConstraint\">\
    1860             :          <enum>QLayout::SetMinimumSize</enum>\
    1861             :         </property>\
    1862             :         <item>\
    1863             :          <widget class=\"QCheckBox\" name=\"FixAntenna1\">\
    1864             :           <property name=\"text\">\
    1865             :            <string>Fix Antenna1</string>\
    1866             :           </property>\
    1867             :          </widget>\
    1868             :         </item>\
    1869             :         <item>\
    1870             :          <widget class=\"QCheckBox\" name=\"FixAntenna2\">\
    1871             :           <property name=\"text\">\
    1872             :            <string>Fix Antenna2</string>\
    1873             :           </property>\
    1874             :          </widget>\
    1875             :         </item>\
    1876             :        </layout>\
    1877             :       </item>\
    1878             :       <item row=\"0\" column=\"3\">\
    1879             :        <widget class=\"QPushButton\" name=\"NextSpw\">\
    1880             :         <property name=\"text\">\
    1881             :          <string>Next SPW</string>\
    1882             :         </property>\
    1883             :        </widget>\
    1884             :       </item>\
    1885             :       <item row=\"0\" column=\"4\">\
    1886             :        <widget class=\"QPushButton\" name=\"NextScan\">\
    1887             :         <property name=\"text\">\
    1888             :          <string>Next Scan</string>\
    1889             :         </property>\
    1890             :        </widget>\
    1891             :       </item>\
    1892             :       <item row=\"0\" column=\"5\">\
    1893             :        <widget class=\"QPushButton\" name=\"NextField\">\
    1894             :         <property name=\"text\">\
    1895             :          <string>Next Field</string>\
    1896             :         </property>\
    1897             :        </widget>\
    1898             :       </item>\
    1899             :       <item row=\"0\" column=\"6\">\
    1900             :        <widget class=\"QPushButton\" name=\"StopDisplay\">\
    1901             :         <property name=\"text\">\
    1902             :          <string>Stop Display</string>\
    1903             :         </property>\
    1904             :        </widget>\
    1905             :       </item>\
    1906             :       <item row=\"0\" column=\"7\">\
    1907             :        <widget class=\"QPushButton\" name=\"Quit\">\
    1908             :         <property name=\"text\">\
    1909             :          <string>Quit</string>\
    1910             :         </property>\
    1911             :        </widget>\
    1912             :       </item>\
    1913             :      </layout>\
    1914             :     </item>\
    1915             :    </layout>\
    1916             :   </widget>\
    1917             :  </widget>\
    1918             :  <resources/>\
    1919             :  <connections/>\
    1920             : </ui>\
    1921             : ";
    1922             : 
    1923           0 :         return true;
    1924             : 
    1925             : }// end of SetLayout
    1926             : 
    1927             : 
    1928           0 : Bool FlagAgentDisplay :: setReportLayout()
    1929             : {
    1930             : 
    1931           0 :         report_dock_xml_p = "\
    1932             : <?xml version=\"1.0\" encoding=\"UTF-8\"?>\
    1933             : <ui version=\"4.0\">\
    1934             :  <class>dock01</class>\
    1935             :  <widget class=\"QDockWidget\" name=\"dock01\">\
    1936             :   <property name=\"geometry\">\
    1937             :    <rect>\
    1938             :     <x>0</x>\
    1939             :     <y>0</y>\
    1940             :     <width>320</width>\
    1941             :     <height>80</height>\
    1942             :    </rect>\
    1943             :   </property>\
    1944             :   <property name=\"sizePolicy\">\
    1945             :    <sizepolicy hsizetype=\"Preferred\" vsizetype=\"Preferred\">\
    1946             :     <horstretch>0</horstretch>\
    1947             :     <verstretch>0</verstretch>\
    1948             :    </sizepolicy>\
    1949             :   </property>\
    1950             :   <property name=\"minimumSize\">\
    1951             :    <size>\
    1952             :     <width>320</width>\
    1953             :     <height>80</height>\
    1954             :    </size>\
    1955             :   </property>\
    1956             :   <property name=\"windowTitle\">\
    1957             :    <string/>\
    1958             :   </property>\
    1959             :   <widget class=\"QWidget\" name=\"dockWidgetContents\">\
    1960             :    <property name=\"enabled\">\
    1961             :     <bool>true</bool>\
    1962             :    </property>\
    1963             :    <property name=\"sizePolicy\">\
    1964             :     <sizepolicy hsizetype=\"Preferred\" vsizetype=\"Preferred\">\
    1965             :      <horstretch>0</horstretch>\
    1966             :      <verstretch>0</verstretch>\
    1967             :     </sizepolicy>\
    1968             :    </property>\
    1969             :    <layout class=\"QGridLayout\" name=\"gridLayout\">\
    1970             :     <item row=\"0\" column=\"0\">\
    1971             :      <layout class=\"QHBoxLayout\" name=\"horizontalLayout\">\
    1972             :       <item>\
    1973             :        <widget class=\"QPushButton\" name=\"Prev\">\
    1974             :         <property name=\"text\">\
    1975             :          <string>Prev</string>\
    1976             :         </property>\
    1977             :        </widget>\
    1978             :       </item>\
    1979             :       <item>\
    1980             :        <widget class=\"QPushButton\" name=\"Next\">\
    1981             :         <property name=\"text\">\
    1982             :          <string>Next</string>\
    1983             :         </property>\
    1984             :        </widget>\
    1985             :       </item>\
    1986             :       <item>\
    1987             :        <widget class=\"QPushButton\" name=\"Quit\">\
    1988             :         <property name=\"text\">\
    1989             :          <string>Quit</string>\
    1990             :         </property>\
    1991             :        </widget>\
    1992             :       </item>\
    1993             :      </layout>\
    1994             :     </item>\
    1995             :    </layout>\
    1996             :   </widget>\
    1997             :  </widget>\
    1998             :  <resources/>\
    1999             :  <connections/>\
    2000             : </ui>\
    2001             : ";
    2002             : 
    2003           0 :         return true;
    2004             : 
    2005             : }
    2006             : 
    2007             : #endif // USE_GRPC
    2008             : 
    2009             : } //# NAMESPACE CASA - END
    2010             : 
    2011             : 

Generated by: LCOV version 1.16