From a04ed5637faec76a8e155fdf0efc78bed41c692f Mon Sep 17 00:00:00 2001
From: Patrick Thomas <pthomas@caltech.edu>
Date: Wed, 17 May 2023 14:53:55 -0700
Subject: [PATCH 1/4] Turned the message structure into a class. Changes to
 make the printing of messages to the terminal and to the gui use the same
 variable. Changes to some formatting due to rerunning clang-format.

---
 src/dtt/filterwiz/FilterFile.cc      | 644 +++++++++++++++------------
 src/dtt/filterwiz/FilterMessage.cc   | 101 +++--
 src/dtt/filterwiz/FilterMessage.hh   |  36 +-
 src/dtt/filterwiz/FilterModule.cc    | 128 +++---
 src/dtt/filterwiz/TLGFilterWizard.cc |   2 +-
 5 files changed, 513 insertions(+), 398 deletions(-)

diff --git a/src/dtt/filterwiz/FilterFile.cc b/src/dtt/filterwiz/FilterFile.cc
index 2fda2f91..7878ff59 100644
--- a/src/dtt/filterwiz/FilterFile.cc
+++ b/src/dtt/filterwiz/FilterFile.cc
@@ -505,13 +505,14 @@ namespace filterwiz
                     const char* modulename = ( *mod ).getName( );
                     const char* sectionname = ( *mod )[ i ].getName( );
 
-                    cerr << "Error updating module " << modulename
-                         << ", section " << sectionname << endl;
-                    file_message_vec.push_back(
-                        create_message( ERROR,
-                                        "Error updating module %s, section %s",
-                                        modulename,
-                                        sectionname ) );
+                    message_t msg(
+                        ERROR,
+                        format( "Error updating module %s, section %s",
+                                modulename,
+                                sectionname ) );
+                    cerr << msg.get_fmt_str( ) << endl;
+                    file_message_vec.push_back( msg );
+
                     return false;
                 }
             }
@@ -526,9 +527,10 @@ namespace filterwiz
         // Note that the file name is the full path of the file.
         if ( !filename )
         {
-            cerr << "Illegal file name" << endl;
-            file_message_vec.push_back(
-                create_message( ERROR, "Illegal file name" ) );
+            message_t msg( ERROR, format( "Illegal file name" ) );
+            cerr << msg.get_fmt_str( ) << endl;
+            file_message_vec.push_back( msg );
+
             return false;
         }
         string oldfilename = fFilename;
@@ -537,9 +539,11 @@ namespace filterwiz
         gdsbase::mmap mfile( filename, std::ios_base::in );
         if ( !mfile )
         {
-            cerr << "Unable to open file " << filename << endl;
-            file_message_vec.push_back(
-                create_message( ERROR, "Unable to open file %s", filename ) );
+            message_t msg( ERROR,
+                           format( "Unable to open file %s", filename ) );
+            cerr << msg.get_fmt_str( ) << endl;
+            file_message_vec.push_back( msg );
+
             fFilename = oldfilename;
             return false;
         }
@@ -550,12 +554,13 @@ namespace filterwiz
         if ( stat( fFilename.c_str( ), &fStat ) )
         {
             // An error occurred getting stat.
-            cerr << "stat error, " << strerror( errno ) << endl;
-            file_message_vec.push_back(
-                create_message( ERROR,
-                                "stat error for file %s, %s",
-                                filename,
-                                strerror( errno ) ) );
+
+            message_t msg( ERROR,
+                           format( "stat error for file %s, %s",
+                                   filename,
+                                   strerror( errno ) ) );
+            cerr << msg.get_fmt_str( ) << endl;
+            file_message_vec.push_back( msg );
         }
 
         bool succ = read( (const char*)mfile.get( ), mfile.size( ), false ) ==
@@ -609,9 +614,11 @@ namespace filterwiz
              ( strncmp( beg, kMagic, strlen( kMagic ) ) != 0 ) )
         {
             clear( );
-            cerr << "Not an online filter file" << endl;
-            file_message_vec.push_back(
-                create_message( ERROR, "Not an online filter file" ) );
+
+            message_t msg( ERROR, format( "Not an online filter file" ) );
+            cerr << msg.get_fmt_str( ) << endl;
+            file_message_vec.push_back( msg );
+
             return 0;
         }
         // first look for filter module names.  Scan the entire file for lines
@@ -640,12 +647,12 @@ namespace filterwiz
                     }
                     else
                     {
-                        cerr << linenum << ": "
-                             << "Illegal file module name " << *i << endl;
-                        file_message_vec.push_back(
-                            create_message( ERROR,
-                                            "Illegal file module name %s",
-                                            i->c_str( ) ) );
+                        message_t msg( linenum,
+                                       ERROR,
+                                       format( "Illegal file module name %s",
+                                               i->c_str( ) ) );
+                        cerr << msg.get_fmt_str( ) << endl;
+                        file_message_vec.push_back( msg );
                     }
                 }
             }
@@ -700,13 +707,13 @@ namespace filterwiz
                     {
                         const char* temp = string( p, linelen ).c_str( );
 
-                        cerr << linenum << ": "
-                             << "Illegal sampling rate specification:" << endl
-                             << "  " << temp << endl;
-                        file_message_vec.push_back( create_message(
+                        message_t msg(
+                            linenum,
                             ERROR,
-                            "Illegal sampling rate specification: %s",
-                            temp ) );
+                            format( "Illegal sampling rate specification: %s",
+                                    temp ) );
+                        cerr << msg.get_fmt_str( ) << endl;
+                        file_message_vec.push_back( msg );
                     }
                 }
             }
@@ -751,26 +758,25 @@ namespace filterwiz
                         }
                         else
                         {
-                            cerr << linenum << ": "
-                                 << "Sampling rate for unknown filter module "
-                                 << tok[ 0 ] << endl;
-                            file_message_vec.push_back( create_message(
-                                ERROR,
-                                "Sampling rate for unknown filter module %s",
-                                tok[ 0 ].c_str( ) ) );
+                            message_t msg( linenum,
+                                           ERROR,
+                                           format( "Sampling rate for unknown "
+                                                   "filter module %s",
+                                                   tok[ 0 ].c_str( ) ) );
+                            cerr << msg.get_fmt_str( ) << endl;
+                            file_message_vec.push_back( msg );
                         }
                     }
                     else
                     {
                         const char* temp = string( p, linelen ).c_str( );
-
-                        cerr << linenum << ": "
-                             << "Illegal sampling rate specification:" << endl
-                             << "  " << temp << endl;
-                        file_message_vec.push_back( create_message(
+                        message_t   msg(
+                            linenum,
                             ERROR,
-                            "Illegal sampling rate specification: %s",
-                            temp ) );
+                            format( "Illegal sampling rate specification: %s",
+                                    temp ) );
+                        cerr << msg.get_fmt_str( ) << endl;
+                        file_message_vec.push_back( msg );
                     }
                 }
             }
@@ -799,13 +805,13 @@ namespace filterwiz
                 if ( ( tok.size( ) > 0 ) && ismodname( tok[ 0 ].c_str( ) ) &&
                      !find( tok[ 0 ].c_str( ) ) )
                 {
-                    cout << linenum << ": "
-                         << "Warning: Filter module " << tok[ 0 ] << " added."
-                         << endl;
-                    file_message_vec.push_back(
-                        create_message( WARNING,
-                                        "Filter module %s added",
-                                        tok[ 0 ].c_str( ) ) );
+                    message_t msg( linenum,
+                                   WARNING,
+                                   format( "Filter module %s added.",
+                                           tok[ 0 ].c_str( ) ) );
+                    cout << msg.get_fmt_str( ) << endl;
+                    file_message_vec.push_back( msg );
+
                     // Create a new module with the file's sample rate and add
                     // it to the file's module list.
                     add( tok[ 0 ].c_str( ), getFSample( ) );
@@ -818,10 +824,12 @@ namespace filterwiz
         if ( fModules.empty( ) )
         {
             clear( );
-            cerr << linenum << ": "
-                 << "No filter module specification" << endl;
-            file_message_vec.push_back(
-                create_message( ERROR, "No filter module specification" ) );
+
+            message_t msg(
+                linenum, ERROR, format( "No filter module specification" ) );
+            cerr << msg.get_fmt_str( ) << endl;
+            file_message_vec.push_back( msg );
+
             return 0;
         }
 
@@ -833,14 +841,16 @@ namespace filterwiz
             if ( i->getFSample( ) <= 1E-10 )
             {
                 i->defaultFSample( );
-                cout << linenum << ": "
-                     << "Error: Setting sampling rate of " << i->getName( )
-                     << " to be " << i->getFSample( ) << endl;
-                file_message_vec.push_back( create_message(
+
+                message_t msg(
+                    linenum,
                     ERROR,
-                    "No sample rate specified. Setting rate of %s to be %f",
-                    i->getName( ),
-                    i->getFSample( ) ) );
+                    format(
+                        "No sample rate specified. Setting rate of %s to be %f",
+                        i->getName( ),
+                        i->getFSample( ) ) );
+                cout << msg.get_fmt_str( ) << endl;
+                file_message_vec.push_back( msg );
             }
         }
 
@@ -895,42 +905,52 @@ namespace filterwiz
                  !isnum( tok[ 8 ] ) || !isnum( tok[ 9 ] ) ||
                  !isnum( tok[ 10 ] ) || !isnum( tok[ 11 ] ) )
             {
-                cerr << linenum << ": "
-                     << "Illegal filter section:" << endl
-                     << "  " << string( p, linelen ) << endl;
-                file_message_vec.push_back(
-                    create_message( ERROR,
-                                    "Illegal filter section: '%s' [0]=%d",
-                                    string( p, linelen ).c_str( ),
-                                    *p ) );
+
+                message_t msg( linenum,
+                               ERROR,
+                               format( "Illegal filter section: '%s' [0]=%d",
+                                       string( p, linelen ).c_str( ),
+                                       *p ) );
+                cerr << msg.get_fmt_str( ) << endl;
+                file_message_vec.push_back( msg );
+
                 continue;
             }
             FilterModule* mod = find( tok[ 0 ].c_str( ) );
             if ( !mod )
             {
-                cerr << linenum << ": "
-                     << "Unknown filter module " << tok[ 0 ] << endl;
-                file_message_vec.push_back( create_message(
-                    ERROR, "Unknown filter module %s", tok[ 0 ].c_str( ) ) );
+                message_t msg(
+                    linenum,
+                    ERROR,
+                    format( "Unknown filter module %s", tok[ 0 ].c_str( ) ) );
+                cerr << msg.get_fmt_str( ) << endl;
+                file_message_vec.push_back( msg );
+
                 continue;
             }
             int index = atoi( tok[ 1 ].c_str( ) );
             if ( ( index < 0 ) || ( index >= kMaxFilterSections ) )
             {
-                cerr << linenum << ": "
-                     << "Illegal section number " << tok[ 1 ] << endl;
-                file_message_vec.push_back( create_message(
-                    ERROR, "Illegal section number %s", tok[ 1 ].c_str( ) ) );
+                message_t msg(
+                    linenum,
+                    ERROR,
+                    format( "Illegal section number %s", tok[ 1 ].c_str( ) ) );
+                cerr << msg.get_fmt_str( ) << endl;
+                file_message_vec.push_back( msg );
+
                 continue;
             }
             input_switching inpsw =
                 ( input_switching )( atoi( tok[ 2 ].c_str( ) ) / 10 );
             if ( ( inpsw != kAlwaysOn ) && ( inpsw != kZeroHistory ) )
             {
-                cerr << linenum << ": "
-                     << "Illegal input switch " << tok[ 2 ] << endl;
-                file_message_vec.push_back( create_message(
-                    ERROR, "Illegal input switch %s", tok[ 2 ].c_str( ) ) );
+                message_t msg(
+                    linenum,
+                    ERROR,
+                    format( "Illegal input switch %s", tok[ 2 ].c_str( ) ) );
+                cerr << msg.get_fmt_str( ) << endl;
+                file_message_vec.push_back( msg );
+
                 continue;
             }
             output_switching outsw =
@@ -938,10 +958,14 @@ namespace filterwiz
             if ( ( outsw != kImmediately ) && ( outsw != kRamp ) &&
                  ( outsw != kInputCrossing ) && ( outsw != kZeroCrossing ) )
             {
-                cerr << linenum << ": "
-                     << "Illegal output switch " << tok[ 2 ] << endl;
-                file_message_vec.push_back( create_message(
-                    ERROR, "Illegal output switch %s", tok[ 2 ].c_str( ) ) );
+
+                message_t msg(
+                    linenum,
+                    ERROR,
+                    format( "Illegal output switch %s", tok[ 2 ].c_str( ) ) );
+                cerr << msg.get_fmt_str( ) << endl;
+                file_message_vec.push_back( msg );
+
                 continue;
             }
             int sosnum = atoi( tok[ 3 ].c_str( ) );
@@ -956,10 +980,13 @@ namespace filterwiz
             }
             if ( ( sosnum < 1 ) || ( sosnum > kMaxFilterSOS ) )
             {
-                cerr << linenum << ": "
-                     << "Illegal SOS number " << tok[ 3 ] << endl;
-                file_message_vec.push_back( create_message(
-                    ERROR, "Illegal SOS number %s", tok[ 3 ].c_str( ) ) );
+                message_t msg(
+                    linenum,
+                    ERROR,
+                    format( "Illegal SOS number %s", tok[ 3 ].c_str( ) ) );
+                cerr << msg.get_fmt_str( ) << endl;
+                file_message_vec.push_back( msg );
+
                 continue;
             }
             double ramp = 0;
@@ -973,18 +1000,17 @@ namespace filterwiz
                 ramp = atof( tok[ 4 ].c_str( ) ) / mod->getFSample( );
                 if ( ramp <= 0 )
                 {
-                    cerr << linenum << ": "
-                         << "Illegal ramp time " << tok[ 4 ] << endl;
-                    file_message_vec.push_back( create_message(
-                        ERROR,
-                        "Module %s section %d, Illegal ramp time %s",
-                        tok[ 0 ].c_str( ),
-                        index,
-                        tok[ 4 ].c_str( ) ) );
-                    file_message_vec.push_back(
-                        create_message( ERROR,
-                                        "   Setting output switch to "
-                                        "Immediate, ramp time to 0!" ) );
+                    message_t msg( linenum,
+                                   ERROR,
+                                   format( "Module %s section %d, Illegal ramp "
+                                           "time %s. Setting output switch to "
+                                           "Immediate, ramp time to 0!",
+                                           tok[ 0 ].c_str( ),
+                                           index,
+                                           tok[ 4 ].c_str( ) ) );
+                    cerr << msg.get_fmt_str( ) << endl;
+                    file_message_vec.push_back( msg );
+
                     // Try to fix the filter by changing the output switch and
                     // ramp time.
                     outsw = kImmediately;
@@ -997,30 +1023,31 @@ namespace filterwiz
                 timeout = atof( tok[ 5 ].c_str( ) ) / mod->getFSample( );
                 if ( tolerance < 0 )
                 {
-                    cerr << linenum << ": "
-                         << "Illegal switch tolerance " << tok[ 4 ] << endl;
-                    file_message_vec.push_back( create_message(
+                    message_t msg(
+                        linenum,
                         ERROR,
-                        "Module %s section %d, Illegal switch tolerance %s",
-                        tok[ 0 ].c_str( ),
-                        index,
-                        tok[ 4 ].c_str( ) ) );
-                    file_message_vec.push_back( create_message(
-                        ERROR, "   Setting switch tolerance to 0!" ) );
+                        format( "Module %s section %d, Illegal switch "
+                                "tolerance %s. Setting switch tolerance to 0!",
+                                tok[ 0 ].c_str( ),
+                                index,
+                                tok[ 4 ].c_str( ) ) );
+                    cerr << msg.get_fmt_str( ) << endl;
+                    file_message_vec.push_back( msg );
+
                     tolerance = 0.0;
                 }
                 if ( timeout < 0 )
                 {
-                    cerr << linenum << ": "
-                         << "Illegal timeout " << tok[ 5 ] << endl;
-                    file_message_vec.push_back( create_message(
-                        ERROR,
-                        "Module %s section %d, Illegal timeout %s",
-                        tok[ 0 ].c_str( ),
-                        index,
-                        tok[ 5 ].c_str( ) ) );
-                    file_message_vec.push_back(
-                        create_message( ERROR, "   Setting timeout to 0!" ) );
+                    message_t msg( linenum,
+                                   ERROR,
+                                   format( "Module %s section %d, Illegal "
+                                           "timeout %s. Setting timeout to 0!",
+                                           tok[ 0 ].c_str( ),
+                                           index,
+                                           tok[ 5 ].c_str( ) ) );
+                    cerr << msg.get_fmt_str( ) << endl;
+                    file_message_vec.push_back( msg );
+
                     timeout = 0.0;
                 }
                 break;
@@ -1044,23 +1071,25 @@ namespace filterwiz
                 p = nextline( p, end, linelen );
                 if ( p >= end )
                 {
-                    cerr << linenum << ": "
-                         << "Not enough lines in file" << endl;
-                    file_message_vec.push_back(
-                        create_message( ERROR, "Not enough lines in file" ) );
+                    message_t msg(
+                        linenum, ERROR, format( "Not enough lines in file" ) );
+                    cerr << msg.get_fmt_str( ) << endl;
+                    file_message_vec.push_back( msg );
+
                     break;
                 }
                 tokens( p, linelen, tok, true );
             }
             if ( ( sosnum > 0 ) && ( (int)tok.size( ) != 8 + 4 * sosnum ) )
             {
-                cerr << linenum << ": "
-                     << "Not enough second order sections for " << tok[ 0 ]
-                     << endl;
-                file_message_vec.push_back(
-                    create_message( ERROR,
-                                    "Not enough second order sections for %s",
-                                    tok[ 0 ].c_str( ) ) );
+                message_t msg(
+                    linenum,
+                    ERROR,
+                    format( "Not enough second order sections for %s",
+                            tok[ 0 ].c_str( ) ) );
+                cerr << msg.get_fmt_str( ) << endl;
+                file_message_vec.push_back( msg );
+
                 continue;
             }
             bool ok = true;
@@ -1071,13 +1100,14 @@ namespace filterwiz
             }
             if ( !ok )
             {
-                cerr << linenum << ": "
-                     << "Filter coefficients for " << tok[ 0 ]
-                     << " are not all numbers" << endl;
-                file_message_vec.push_back( create_message(
+                message_t msg(
+                    linenum,
                     ERROR,
-                    "Filter coefficients for %s are not all numbers",
-                    tok[ 0 ].c_str( ) ) );
+                    format( "Filter coefficients for %s are not all numbers",
+                            tok[ 0 ].c_str( ) ) );
+                cerr << msg.get_fmt_str( ) << endl;
+                file_message_vec.push_back( msg );
+
                 continue;
             }
             // Finally we have a valid filter section!
@@ -1222,35 +1252,33 @@ namespace filterwiz
                     }
                     else if ( !mod )
                     {
-                        cerr << linenum << ": "
-                             << "Design for unknown filter module " << tok[ 0 ]
-                             << endl;
-                        file_message_vec.push_back( create_message(
+                        message_t msg(
+                            linenum,
                             ERROR,
-                            "Design for unknown filter module %s",
-                            tok[ 0 ].c_str( ) ) );
+                            format( "Design for unknown filter module %s",
+                                    tok[ 0 ].c_str( ) ) );
+                        cerr << msg.get_fmt_str( ) << endl;
+                        file_message_vec.push_back( msg );
                     }
                     else
                     {
-                        cerr << linenum << ": "
-                             << "Illegal section number " << tok[ 0 ] << "/"
-                             << tok[ 1 ] << endl;
-                        file_message_vec.push_back(
-                            create_message( ERROR,
-                                            "Illegal section number %s/%s",
-                                            tok[ 0 ].c_str( ),
-                                            tok[ 1 ].c_str( ) ) );
+                        message_t msg( linenum,
+                                       ERROR,
+                                       format( "Illegal section number %s/%s",
+                                               tok[ 0 ].c_str( ),
+                                               tok[ 1 ].c_str( ) ) );
+                        cerr << msg.get_fmt_str( ) << endl;
+                        file_message_vec.push_back( msg );
                     }
                 }
                 else
                 {
-                    cerr << linenum << ": "
-                         << "Illegal design specification:" << endl
-                         << "  " << string( p, linelen ) << endl;
-                    file_message_vec.push_back(
-                        create_message( ERROR,
-                                        "Illegal design specification: %s",
-                                        string( p, linelen ).c_str( ) ) );
+                    message_t msg( linenum,
+                                   ERROR,
+                                   format( "Illegal design specification: %s",
+                                           string( p, linelen ).c_str( ) ) );
+                    cerr << msg.get_fmt_str( ) << endl;
+                    file_message_vec.push_back( msg );
                 }
             }
         }
@@ -1321,9 +1349,12 @@ namespace filterwiz
         {
             if ( errmsg )
                 sprintf( errmsg, "Unable to open file %s", filename );
-            cerr << "Unable to open file " << filename << endl;
-            file_message_vec.push_back(
-                create_message( ERROR, "Unable to open file %s", filename ) );
+
+            message_t msg( ERROR,
+                           format( "Unable to open file %s", filename ) );
+            cerr << msg.get_fmt_str( ) << endl;
+            file_message_vec.push_back( msg );
+
             return false;
         }
         int   size = 0;
@@ -1340,12 +1371,14 @@ namespace filterwiz
                 if ( errmsg )
                     strcpy( errmsg,
                             "Memory exhausted attempting to write file" );
-                cerr << "Memory exhausted attempting to write file" << filename
-                     << endl;
-                file_message_vec.push_back( create_message(
+
+                message_t msg(
                     ERROR,
-                    "Memory exhausted attempting to write file %s",
-                    filename ) );
+                    format( "Memory exhausted attempting to write file %s",
+                            filename ) );
+                cerr << msg.get_fmt_str( ) << endl;
+                file_message_vec.push_back( msg );
+
                 return ( false );
             }
             // Assuming we got the memory we requested, attempt to fill the
@@ -1544,16 +1577,19 @@ namespace filterwiz
                 if ( !sect.designEmpty( ) )
                 {
                     //--- iirorder suppresses zeroes at fNy ... we don't want
-                    //this int order = iirorder (sect.filter().get());
+                    // this int order = iirorder (sect.filter().get());
                     int order = iirsoscount( sect.filter( ).get( ) );
                     if ( order < 0 )
                     {
-                        cerr << "Not an IIR filter" << endl;
-                        file_message_vec.push_back( create_message(
+                        message_t msg(
                             ERROR,
-                            "Module %s, section %s - Not an IIR filter.",
-                            mod->getName( ),
-                            sect.getName( ) ) );
+                            format(
+                                "Module %s, section %s - Not an IIR filter.",
+                                mod->getName( ),
+                                sect.getName( ) ) );
+                        cerr << msg.get_fmt_str( ) << endl;
+                        file_message_vec.push_back( msg );
+
                         continue;
                     }
                     //--- Reserve space for zeroes.
@@ -1567,14 +1603,16 @@ namespace filterwiz
 
                     if ( !iir2z( sect.filter( ).get( ), nba, coeff, "o" ) )
                     {
-                        cerr << "Unable to obtain online filter coefficients"
-                             << endl;
-                        file_message_vec.push_back(
-                            create_message( ERROR,
-                                            "Module %s, section %s - Unable to "
-                                            "obtain online filter coefficients",
-                                            mod->getName( ),
-                                            sect.getName( ) ) );
+
+                        message_t msg(
+                            ERROR,
+                            format( "Module %s, section %s - Unable to "
+                                    "obtain online filter coefficients",
+                                    mod->getName( ),
+                                    sect.getName( ) ) );
+                        cerr << msg.get_fmt_str( ) << endl;
+                        file_message_vec.push_back( msg );
+
                         delete[] coeff;
                         continue;
                     }
@@ -1600,14 +1638,16 @@ namespace filterwiz
                            ( sosnum < 1 ) ) ||
                          ( sosnum > kMaxFilterSOS ) )
                     {
-                        cerr << "Invalid number of SOSs " << sosnum << endl;
-                        file_message_vec.push_back(
-                            create_message( ERROR,
-                                            "Module %s, section %s - Invalid "
-                                            "number of SOS (%d)",
-                                            mod->getName( ),
-                                            sect.getName( ),
-                                            sosnum ) );
+                        message_t msg(
+                            ERROR,
+                            format( "Module %s, section %s - Invalid "
+                                    "number of SOS (%d)",
+                                    mod->getName( ),
+                                    sect.getName( ),
+                                    sosnum ) );
+                        cerr << msg.get_fmt_str( ) << endl;
+                        file_message_vec.push_back( msg );
+
                         delete[] coeff;
                         continue; // Don't write the filter section.
                     }
@@ -1713,23 +1753,26 @@ namespace filterwiz
                 if ( coeffs[ 0 ] != 0 || coeffs[ 1 ] != 0 || coeffs[ 2 ] != 0 ||
                      coeffs[ 3 ] != 0 )
                 {
-                    file_message_vec.push_back( create_message(
-                        WARNING,
-                        "SOS was corrected to 'empty' in filter %d module %s",
-                        section,
-                        mod.getName( ) ) );
+                    message_t msg( WARNING,
+                                   format( "SOS was corrected to 'empty' in "
+                                           "filter %d module %s",
+                                           section,
+                                           mod.getName( ) ) );
+                    file_message_vec.push_back( msg );
                 }
                 return false;
             }
 
             if ( sos_list.size( ) > 1 )
             {
-                file_message_vec.push_back(
-                    create_message( WARNING,
-                                    "2 SOSs were produced from one "
-                                    "input when correcting filter %d module %s",
-                                    section,
-                                    mod.getName( ) ) );
+                message_t msg(
+                    WARNING,
+                    format( "2 SOSs were produced from one "
+                            "input when correcting filter %d module %s",
+                            section,
+                            mod.getName( ) ) );
+                file_message_vec.push_back( msg );
+
                 poles_ok = false;
             }
 
@@ -1740,18 +1783,20 @@ namespace filterwiz
                  coeffs[ 3 ] != corrected_sos.B2( ) )
             {
                 poles_ok = false;
-                file_message_vec.push_back( create_message(
+                message_t msg(
                     WARNING,
-                    "filter %d module %s had at least one pole with\n"
-                    "  a low frequency. Poles with frequency less than "
-                    "10^(-6)\n"
-                    "  as fraction of sample frequency will suffer from low "
-                    "precision.\n"
-                    "%s",
-                    section,
-                    mod.getName( ),
-                    correct_on_load ? "  The pole(s) were corrected.\n"
-                                    : "" ) );
+                    format( "filter %d module %s had at least one pole with\n"
+                            "  a low frequency. Poles with frequency less than "
+                            "10^(-6)\n"
+                            "  as fraction of sample frequency will suffer "
+                            "from low "
+                            "precision.\n"
+                            "%s",
+                            section,
+                            mod.getName( ),
+                            correct_on_load ? "  The pole(s) were corrected.\n"
+                                            : "" ) );
+                file_message_vec.push_back( msg );
 
                 //            don't actually write out the "corrected" values.
                 //            We are just going to produce warnings. coeffs[0] =
@@ -1764,12 +1809,13 @@ namespace filterwiz
         catch ( const std::exception& e )
         {
             std::exception_ptr p = std::current_exception( );
-            file_message_vec.push_back(
-                create_message( ERROR,
-                                "error in SOS in filter %d of mod %s: %s",
-                                section,
-                                mod.getName( ),
-                                e.what( ) ) );
+
+            message_t msg( ERROR,
+                           format( "error in SOS in filter %d of mod %s: %s",
+                                   section,
+                                   mod.getName( ),
+                                   e.what( ) ) );
+            file_message_vec.push_back( msg );
             poles_ok = false;
         }
 
@@ -2005,27 +2051,37 @@ namespace filterwiz
     // # ETMX_R0_S_ACT 8 notch(1,10,30) 12 3.0 0.0 notch_1
     //
     // Note the following: + module_name must be listed in the MODULES section
-    // at the 			 head of the filter file.  If it doesn't exist, the filter
+    // at the 			 head of the filter file.  If it doesn't exist,
+    // the filter
     //			 definition is ignored.
     //		       + section_number is in the range 0-9
     //		       + design_string must be a valid string containing no
-    //spaces.
+    // spaces.
     //		       + switching is a two digit integer consisting of
     //			 (input switching + output switching), where input
-    //switching 			 is one of: 			    10 - Input is always applied to filter 			    20 - Input
-    //switch will switch with output switch 			 output switching is one of: 			    1 -
-    //Immediate - switch off as soon as commanded 			    2 - Ramp - ramp over time
-    //specified in ramp_time 			    3 - Input crossing - output will switch when the
-    //filter 				input and output are within a given value of each other
+    // switching 			 is one of: 			    10 -
+    // Input is always applied to filter 20 - Input switch will switch with
+    // output switch output
+    // switching is one of: 			    1 - Immediate - switch off
+    // as soon as commanded 			    2 - Ramp - ramp over time
+    // specified in ramp_time 			    3 - Input crossing - output
+    // will switch when the
+    // filter 				input and output are within a given
+    // value of each other
     //   				(value is in ramp_time field)
     //			    4 - Zero crossing - output switch when input crosses
-    //zero.
-    //		       + ramp_time can be a time (which is multiplied by sampling rate
-    //to 			 obtain ramp cycles) or a floating point value for input crossing
+    // zero.
+    //		       + ramp_time can be a time (which is multiplied by
+    // sampling rate
+    // to 			 obtain ramp cycles) or a floating point value
+    // for input crossing
     //		       + timeout_time - time in seconds. If the output switching
-    //isn't 			 met in this time, the output will switch anyway.
-    //		       + section_name - Filter section name used in EPICS displays
-    //of 			 the standard filter module.  No whitespace allowed.
+    // isn't 			 met in this time, the output will switch
+    // anyway.
+    //		       + section_name - Filter section name used in EPICS
+    // displays
+    // of 			 the standard filter module.  No whitespace
+    // allowed.
     //
     // These functions are part of the FilterFile class because the merge needs
     // to be done on a filter file that's already been read. Return 0 if
@@ -2106,11 +2162,10 @@ namespace filterwiz
                 // The first token has to be a "#"
                 if ( !ishash( tok[ 0 ] ) )
                 {
-                    merge_message_vec.push_back(
-                        create_message( ERROR,
-                                        linenum,
-                                        "Line %d: Must start with '#'",
-                                        linenumber ) );
+                    message_t msg(
+                        linenumber, ERROR, format( "Must start with '#'" ) );
+                    merge_message_vec.push_back( msg );
+
                     invalid = 1;
                 }
 
@@ -2119,23 +2174,23 @@ namespace filterwiz
                 if ( !ismodname( tok[ 1 ] ) ||
                      !( module = find( tok[ 1 ].c_str( ) ) ) )
                 {
-                    merge_message_vec.push_back( create_message(
-                        ERROR,
-                        linenum,
-                        "Line %d: Invalid module name %s or module not found",
-                        linenumber,
-                        tok[ 1 ].c_str( ) ) );
+                    message_t msg( linenumber,
+                                   ERROR,
+                                   format( "Invalid module name %s or "
+                                           "module not found",
+                                           tok[ 1 ].c_str( ) ) );
+                    merge_message_vec.push_back( msg );
+
                     invalid = 1;
                 }
 
                 // The third token needs to be a section number, range 0-9
                 if ( !isintnum( tok[ 2 ] ) )
                 {
-                    merge_message_vec.push_back(
-                        create_message( ERROR,
-                                        linenum,
-                                        "Line %d: Invalid section number",
-                                        linenumber ) );
+                    message_t msg(
+                        linenumber, ERROR, format( "Invalid section number" ) );
+                    merge_message_vec.push_back( msg );
+
                     invalid = 1;
                 }
                 else
@@ -2143,12 +2198,12 @@ namespace filterwiz
                     section_number = atoi( tok[ 2 ].c_str( ) );
                     if ( section_number < 0 || section_number > 9 )
                     {
-                        merge_message_vec.push_back( create_message(
-                            ERROR,
-                            linenum,
-                            "Line %d: Invalid section number %d",
-                            linenumber,
-                            section_number ) );
+                        message_t msg( linenumber,
+                                       ERROR,
+                                       format( "Invalid section number %d",
+                                               section_number ) );
+                        merge_message_vec.push_back( msg );
+
                         invalid = 1;
                     }
                 }
@@ -2156,11 +2211,11 @@ namespace filterwiz
                 // Fifth token is a switching parameter.  Needs to be an int.
                 if ( !isintnum( tok[ 4 ] ) )
                 {
-                    merge_message_vec.push_back(
-                        create_message( ERROR,
-                                        linenum,
-                                        "Line %d: Invalid switching parameter",
-                                        linenumber ) );
+                    message_t msg( linenumber,
+                                   ERROR,
+                                   format( "Invalid switching parameter" ) );
+                    merge_message_vec.push_back( msg );
+
                     invalid = 1;
                 }
                 else
@@ -2169,12 +2224,13 @@ namespace filterwiz
                         ( input_switching )( atoi( tok[ 4 ].c_str( ) ) / 10 );
                     if ( ( inpsw != kAlwaysOn ) && ( inpsw != kZeroHistory ) )
                     {
-                        merge_message_vec.push_back(
-                            create_message( ERROR,
-                                            linenum,
-                                            "Line %d: Invalid input switch %d",
-                                            linenumber,
-                                            atoi( tok[ 4 ].c_str( ) ) / 10 ) );
+                        message_t msg(
+                            linenumber,
+                            ERROR,
+                            format( "Invalid input switch %d",
+                                    atoi( tok[ 4 ].c_str( ) ) / 10 ) );
+                        merge_message_vec.push_back( msg );
+
                         invalid = 1;
                     }
                     outsw =
@@ -2183,12 +2239,14 @@ namespace filterwiz
                          ( outsw != kInputCrossing ) &&
                          ( outsw != kZeroCrossing ) )
                     {
-                        merge_message_vec.push_back(
-                            create_message( ERROR,
-                                            linenum,
-                                            "Line %d: Invalid output switch %d",
-                                            linenumber,
-                                            atoi( tok[ 4 ].c_str( ) ) % 10 ) );
+
+                        message_t msg(
+                            linenumber,
+                            ERROR,
+                            format( "Invalid output switch %d",
+                                    atoi( tok[ 4 ].c_str( ) ) % 10 ) );
+                        merge_message_vec.push_back( msg );
+
                         invalid = 1;
                     }
                 }
@@ -2213,11 +2271,11 @@ namespace filterwiz
                         timeout_time = 0.0;
                         if ( ramp_time <= 0 )
                         {
-                            merge_message_vec.push_back( create_message(
-                                ERROR,
-                                linenum,
-                                "Line %d: Ramp time must be greater than 0.",
-                                linenumber ) );
+                            message_t msg( linenumber,
+                                           ERROR,
+                                           format( "Ramp time must be "
+                                                   "greater than 0." ) );
+                            merge_message_vec.push_back( msg );
                             invalid = 1;
                         }
                         break;
@@ -2230,20 +2288,22 @@ namespace filterwiz
                         timeout_time = atof( tok[ 6 ].c_str( ) );
                         if ( tolerance < 0 )
                         {
-                            merge_message_vec.push_back( create_message(
-                                ERROR,
-                                linenum,
-                                "Line %d: Tolerance must be greater than 0.",
-                                linenumber ) );
+                            message_t msg( linenumber,
+                                           ERROR,
+                                           format( "Tolerance must be "
+                                                   "greater than 0." ) );
+                            merge_message_vec.push_back( msg );
+
                             invalid = 1;
                         }
                         if ( timeout_time < 0 )
                         {
-                            merge_message_vec.push_back( create_message(
+                            message_t msg(
+                                linenumber,
                                 ERROR,
-                                linenum,
-                                "Line %d: Timeout must be greater than 0.",
-                                linenumber ) );
+                                format( "Timeout must be greater than 0." ) );
+                            merge_message_vec.push_back( msg );
+
                             invalid = 1;
                         }
                         break;
@@ -2271,11 +2331,13 @@ namespace filterwiz
 
                     if ( !( section->update( ) ) )
                     {
-                        merge_message_vec.push_back( create_message(
+                        message_t msg(
                             ERROR,
-                            linenum,
-                            "Creation of filter failed from design = %s\n",
-                            section->getDesign( ) ) );
+                            format(
+                                "Creation of filter failed from design = %s\n",
+                                section->getDesign( ) ) );
+                        merge_message_vec.push_back( msg );
+
                         invalid = 1;
                     }
                     else
diff --git a/src/dtt/filterwiz/FilterMessage.cc b/src/dtt/filterwiz/FilterMessage.cc
index 3e9427e3..5daaa002 100644
--- a/src/dtt/filterwiz/FilterMessage.cc
+++ b/src/dtt/filterwiz/FilterMessage.cc
@@ -1,9 +1,25 @@
-#include "FilterMessage.hh"
 #include <cstdarg>
 #include <algorithm>
 #include <iostream>
 #include <functional>
 
+#include "FilterMessage.hh"
+
+std::string
+format( const char* format, ... )
+{
+    char    buffer[ 1024 ];
+    va_list argp;
+
+    // Textbook case of handling variable arguments being passed to another
+    // function that takes variable arguments.
+    va_start( argp, format );
+    vsnprintf( buffer, sizeof( buffer ), format, argp );
+    va_end( argp );
+
+    return std::string( buffer );
+}
+
 std::string
 message_level_to_string( message_level_t level )
 {
@@ -18,49 +34,47 @@ message_level_to_string( message_level_t level )
     }
 }
 
-message_t
-create_message( message_level_t level, const char* msg, ... )
+message_t::message_t( message_level_t level, std::string text )
 {
-    char    mbuf[ 1024 ];
-    char    msgbuf[ 1024 ];
-    va_list argp;
-
-    // Textbook case of handling variable arguments being passed to another
-    // function that takes variable arguments.
-    va_start( argp, msg );
-    vsprintf( msgbuf, msg, argp );
-    va_end( argp );
+    this->has_line_number = false;
 
-    message_t message;
-    message.level = level;
-    message.text = message_level_to_string( level ) + std::string( ": " ) +
-        std::string( msgbuf );
-
-    return message;
+    this->level = level;
+    this->text = text;
 }
 
-message_t
-create_message( message_level_t level, int line_num, const char* msg, ... )
+message_t::message_t( int line_number, message_level_t level, std::string text )
 {
-    char    mbuf[ 1024 ];
-    char    msgbuf[ 1024 ];
-    va_list argp;
+    this->has_line_number = true;
+    this->line_number = line_number;
 
-    // Textbook case of handling variable arguments being passed to another
-    // function that takes variable arguments.
-    va_start( argp, msg );
-    vsnprintf( msgbuf, sizeof( msgbuf ), msg, argp );
-    va_end( argp );
+    this->level = level;
+    this->text = text;
+}
 
-    // Create a string from the msgbuf to add to the message vector
-    snprintf( mbuf, sizeof( mbuf ), "line %d: %s", line_num, msgbuf );
+std::string
+message_t::get_fmt_str( ) const
+{
+    char fmt_str[ 1024 ];
 
-    message_t message;
-    message.level = level;
-    message.text = message_level_to_string( level ) + std::string( ": " ) +
-        std::string( mbuf );
+    if ( this->has_line_number )
+    {
+        snprintf( fmt_str,
+                  sizeof( fmt_str ),
+                  "%i: %s: %s",
+                  this->line_number,
+                  message_level_to_string( this->level ).c_str( ),
+                  this->text.c_str( ) );
+    }
+    else
+    {
+        snprintf( fmt_str,
+                  sizeof( fmt_str ),
+                  "%s: %s",
+                  message_level_to_string( this->level ).c_str( ),
+                  this->text.c_str( ) );
+    }
 
-    return message;
+    return std::string( fmt_str );
 }
 
 std::vector< message_t >
@@ -68,17 +82,22 @@ message_vec_filter_level( std::vector< message_t > message_vec,
                           message_level_t          level )
 {
     std::vector< message_t > filtered_message_vec;
-    std::copy_if( message_vec.begin( ),
-                  message_vec.end( ),
-                  std::back_inserter( filtered_message_vec ),
-                  [ level ]( message_t m ) { return m.level == level; } );
+
+    std::copy_if(
+        message_vec.begin( ),
+        message_vec.end( ),
+        std::back_inserter( filtered_message_vec ),
+        [ level ]( message_t m ) { return m.get_level( ) == level; } );
+
     return filtered_message_vec;
 }
 
 void
 print_message_vec( std::vector< message_t > message_vec )
 {
-    auto print = []( const message_t& m ) { std::cout << m.text << std::endl; };
+    auto print = []( const message_t& m ) {
+        std::cout << m.get_fmt_str( ) << std::endl;
+    };
 
     std::for_each( message_vec.cbegin( ), message_vec.cend( ), print );
 }
@@ -91,7 +110,7 @@ message_vec_to_string_vec( std::vector< message_t > message_vec )
     std::transform( message_vec.begin( ),
                     message_vec.end( ),
                     std::back_inserter( string_vec ),
-                    std::mem_fn( &message_t::text ) );
+                    std::mem_fn( &message_t::get_fmt_str ) );
 
     return string_vec;
 }
diff --git a/src/dtt/filterwiz/FilterMessage.hh b/src/dtt/filterwiz/FilterMessage.hh
index 521d83f4..225922c8 100644
--- a/src/dtt/filterwiz/FilterMessage.hh
+++ b/src/dtt/filterwiz/FilterMessage.hh
@@ -4,24 +4,44 @@
 #include <string>
 #include <vector>
 
+std::string format( const char*, ... );
+
 enum message_level_t
 {
     WARNING,
     ERROR
 };
 
-struct message_t
+std::string message_level_to_string( );
+
+class message_t
 {
-    message_level_t level;
-    std::string     text;
-};
+public:
+    message_t( message_level_t, std::string );
+
+    message_t( int, message_level_t, std::string );
 
-std::string message_level_to_string( message_level_t level );
+    message_level_t
+    get_level( )
+    {
+        return this->level;
+    }
 
-message_t create_message( message_level_t level, const char* msg, ... );
+    std::string
+    get_text( )
+    {
+        return this->text;
+    }
 
-message_t
-create_message( message_level_t level, int line_num, const char* msg, ... );
+    std::string get_fmt_str( ) const;
+
+private:
+    message_level_t level;
+    std::string     text;
+
+    bool has_line_number;
+    int  line_number;
+};
 
 std::vector< message_t >
 message_vec_filter_level( std::vector< message_t > message_vec,
diff --git a/src/dtt/filterwiz/FilterModule.cc b/src/dtt/filterwiz/FilterModule.cc
index d851ef81..a77779f9 100644
--- a/src/dtt/filterwiz/FilterModule.cc
+++ b/src/dtt/filterwiz/FilterModule.cc
@@ -175,12 +175,14 @@ namespace filterwiz
                          << fSect[ i ].getName( ) << ", creating one: " << s
                          << endl;
 
-                    message_vec->push_back( create_message(
+                    message_t msg(
                         WARNING,
-                        "Module %s section %d: Missing design string, "
-                        "a new string will be generated.",
-                        getName( ),
-                        i ) );
+                        format( "Module %s section %d: Missing design string, "
+                                "a new string will be generated.",
+                                getName( ),
+                                i ) );
+                    cerr << msg.get_fmt_str( ) << endl;
+                    message_vec->push_back( msg );
 
                     fSect[ i ].setDesign( s );
                 }
@@ -199,13 +201,14 @@ namespace filterwiz
                 {
                     ok = false;
 
-                    message_vec->push_back( create_message(
+                    message_t msg(
                         ERROR,
-                        "Filter module %s section %d: Failed to create "
-                        "filter from design string %s",
-                        getName( ),
-                        i,
-                        fSect[ i ].getDesign( ) ) );
+                        format( "Filter module %s section %d: Failed to create "
+                                "filter from design string %s",
+                                getName( ),
+                                i,
+                                fSect[ i ].getDesign( ) ) );
+                    message_vec->push_back( msg );
                 }
             }
             // get filter from coefficients
@@ -232,16 +235,18 @@ namespace filterwiz
                         {
                             if ( zero[ k ].Real( ) > 0 )
                             {
-                                message_t message = create_message(
-                                    WARNING,
-                                    "Module %s section %d has a zero in the "
-                                    "right half s-plane\n"
-                                    "at (%f, %f) rad/s.\n",
-                                    getName( ),
-                                    i,
-                                    zero[ k ].Real( ),
-                                    zero[ k ].Imag( ) );
-                                message_vec->push_back( message );
+                                message_t msg =
+                                    message_t( WARNING,
+                                               format( "Module %s section %d "
+                                                       "has a zero in the "
+                                                       "right half s-plane\n"
+                                                       "at (%f, %f) rad/s.\n",
+                                                       getName( ),
+                                                       i,
+                                                       zero[ k ].Real( ),
+                                                       zero[ k ].Imag( ) ) );
+                                cerr << msg.get_fmt_str( ) << endl;
+                                message_vec->push_back( msg );
                             }
                         }
                         delete[] zero;
@@ -251,13 +256,14 @@ namespace filterwiz
                     {
                         ok = false;
 
-                        message_vec->push_back( create_message(
+                        message_t msg(
                             ERROR,
-                            "Filter module %s section %d: Failed to create "
-                            "filter from coefficients.",
-                            getName( ),
-                            i ) );
-
+                            format(
+                                "Filter module %s section %d: Failed to create "
+                                "filter from coefficients.",
+                                getName( ),
+                                i ) );
+                        message_vec->push_back( msg );
                         break;
                     }
                 }
@@ -272,21 +278,23 @@ namespace filterwiz
                 {
                     if ( noDesign )
                     {
-                        message_vec->push_back( create_message(
-                            WARNING,
-                            "Module %s section %d: Missing design string, a "
-                            "new string will be generated.",
-                            getName( ),
-                            i ) );
+                        message_t msg( WARNING,
+                                       format( "Module %s section %d: Missing "
+                                               "design string, a "
+                                               "new string will be generated.",
+                                               getName( ),
+                                               i ) );
+                        message_vec->push_back( msg );
                     }
                     else
                     {
-                        message_vec->push_back(
-                            create_message( ERROR,
-                                            "Module %s section %d: Mismatch "
-                                            "between design and coefficients.",
-                                            getName( ),
-                                            i ) );
+                        message_t msg(
+                            ERROR,
+                            format( "Module %s section %d: Mismatch "
+                                    "between design and coefficients.",
+                                    getName( ),
+                                    i ) );
+                        message_vec->push_back( msg );
                     }
                 }
             }
@@ -323,14 +331,18 @@ namespace filterwiz
                                 // Should also issue a warning!
                                 fSect[ j ].setDesign( "" );
                                 fSect[ j ].filter( ).reset( );
-                                message_vec->push_back( create_message(
+
+                                message_t msg(
                                     WARNING,
-                                    "Module %s section %d: Could not create an "
-                                    "design string that produces the filter "
-                                    "exactly.\n"
-                                    "  Design string is left blank\n",
-                                    getName( ),
-                                    i ) );
+                                    format( "Module %s section %d: Could not "
+                                            "create an "
+                                            "design string that produces the "
+                                            "filter "
+                                            "exactly.\n"
+                                            "  Design string is left blank\n",
+                                            getName( ),
+                                            i ) );
+                                message_vec->push_back( msg );
                             }
                         }
                     }
@@ -376,12 +388,13 @@ namespace filterwiz
                          << fSect[ i ].getName( ) << ", creating one: " << s
                          << endl;
 
-                    message_vec->push_back( create_message(
+                    message_t msg(
                         WARNING,
-                        "Module %s section %d: Missing design string, "
-                        "a new string will be generated.",
-                        getName( ),
-                        i ) );
+                        format( "Module %s section %d: Missing design string, "
+                                "a new string will be generated.",
+                                getName( ),
+                                i ) );
+                    message_vec->push_back( msg );
 
                     fSect[ i ].setDesign( s );
                 }
@@ -399,13 +412,14 @@ namespace filterwiz
                 catch ( ... )
                 {
                     ok = false;
-                    message_vec->push_back( create_message(
+                    message_t msg(
                         ERROR,
-                        "Filter module %s section %d: Failed to create "
-                        "filter from design string %s",
-                        getName( ),
-                        i,
-                        fSect[ i ].getDesign( ) ) );
+                        format( "Filter module %s section %d: Failed to create "
+                                "filter from design string %s",
+                                getName( ),
+                                i,
+                                fSect[ i ].getDesign( ) ) );
+                    message_vec->push_back( msg );
                 }
             }
 
diff --git a/src/dtt/filterwiz/TLGFilterWizard.cc b/src/dtt/filterwiz/TLGFilterWizard.cc
index 6255fa52..614cc537 100644
--- a/src/dtt/filterwiz/TLGFilterWizard.cc
+++ b/src/dtt/filterwiz/TLGFilterWizard.cc
@@ -4186,7 +4186,7 @@ namespace filterwiz
         }
 
         //--------------------------------  The button layout was set here,
-        //but.. delete fButtonLayout; fButtonLayout =
+        // but.. delete fButtonLayout; fButtonLayout =
         //      new TGLayoutHints (kLHintsExpandX | kLHintsTop, 15, 15, 10, 6);
         return num + nstd;
     }
-- 
GitLab


From 1829820dfd4122fd895477b88c46227e8ce6c3fb Mon Sep 17 00:00:00 2001
From: Patrick Thomas <pthomas@caltech.edu>
Date: Wed, 17 May 2023 16:44:43 -0700
Subject: [PATCH 2/4] Fixes to the Python bindings and tests to match the
 changes in the error handling data structure.

---
 src/python/foton/filterfile_pybind.cc |  4 +--
 src/python/foton/foton_unit_test.py   | 48 +++++++++++++--------------
 src/python/foton/pyfilterfile_test.py | 20 +++++------
 3 files changed, 36 insertions(+), 36 deletions(-)

diff --git a/src/python/foton/filterfile_pybind.cc b/src/python/foton/filterfile_pybind.cc
index 1fb32eb3..482c4853 100644
--- a/src/python/foton/filterfile_pybind.cc
+++ b/src/python/foton/filterfile_pybind.cc
@@ -24,8 +24,8 @@ PYBIND11_MODULE(pyfilterfile, m) {
     .export_values();
 
   py::class_<message_t>(m, "FilterMessage")
-    .def_readwrite("level", &message_t::level)
-    .def_readwrite("text", &message_t::text);
+    .def("get_level", &message_t::get_level)
+    .def("get_fmt_str", &message_t::get_fmt_str);
 
 
   py::class_<FilterFile>(m, "FilterFile")
diff --git a/src/python/foton/foton_unit_test.py b/src/python/foton/foton_unit_test.py
index 0b6500a8..0f61f694 100644
--- a/src/python/foton/foton_unit_test.py
+++ b/src/python/foton/foton_unit_test.py
@@ -183,10 +183,10 @@ class TestFotonMethods(unittest.TestCase):
         self.file.correct_on_load = True
         self.file.write_file(tmpfile)
 
-        warnings = list(filter(lambda m: m.level == filterfile.message_level_t.WARNING, self.file.ff.getFileMessages()))
-        warnings = list(map(lambda m: m.text, warnings))
-        errors = list(filter(lambda m: m.level == filterfile.message_level_t.ERROR, self.file.ff.getFileMessages()))
-        errors = list(map(lambda m: m.text, errors))
+        warnings = list(filter(lambda m: m.get_level() == filterfile.message_level_t.WARNING, self.file.ff.getFileMessages()))
+        warnings = list(map(lambda m: m.get_fmt_str(), warnings))
+        errors = list(filter(lambda m: m.get_level() == filterfile.message_level_t.ERROR, self.file.ff.getFileMessages()))
+        errors = list(map(lambda m: m.get_fmt_str(), errors))
         print(f"warnings={warnings}")
         print(f"errors={errors}")
         self.assertNotEqual(len(warnings), 0)
@@ -203,13 +203,13 @@ class TestFotonMethods(unittest.TestCase):
         design = f'butter("LowPass",4,{f:g})'
         fd = foton.FilterDesign(design, self.section.rate)
         self.module[4].set_filterdesign(fd)
-        print(f"starting messages={[m.text for m in self.file.ff.getFileMessages()]}")
+        print(f"starting messages={[m.get_fmt_str() for m in self.file.ff.getFileMessages()]}")
         butter_txt = self.file.ff.write_string()
 
-        warnings = list(filter(lambda m: m.level == filterfile.message_level_t.WARNING, self.file.ff.getFileMessages()))
-        warnings = list(map(lambda m: m.text, warnings))
-        errors = list(filter(lambda m: m.level == filterfile.message_level_t.ERROR, self.file.ff.getFileMessages()))
-        errors = list(map(lambda m: m.text, errors))
+        warnings = list(filter(lambda m: m.get_level() == filterfile.message_level_t.WARNING, self.file.ff.getFileMessages()))
+        warnings = list(map(lambda m: m.get_fmt_str(), warnings))
+        errors = list(filter(lambda m: m.get_level() == filterfile.message_level_t.ERROR, self.file.ff.getFileMessages()))
+        errors = list(map(lambda m: m.get_fmt_str(), errors))
         print(f"warnings={warnings}")
         print(f"errors={errors}")
         self.assertTrue(warnings)
@@ -219,10 +219,10 @@ class TestFotonMethods(unittest.TestCase):
         print(f"correct_on_load={ff.ff.correct_on_load}")
         ff.ff.read_string(butter_txt)
 
-        warnings = list(filter(lambda m: m.level == filterfile.message_level_t.WARNING, ff.ff.getFileMessages()))
-        warnings = list(map(lambda m: m.text, warnings))
-        errors = list(filter(lambda m: m.level == filterfile.message_level_t.ERROR, ff.ff.getFileMessages()))
-        errors = list(map(lambda m: m.text, errors))
+        warnings = list(filter(lambda m: m.get_level() == filterfile.message_level_t.WARNING, ff.ff.getFileMessages()))
+        warnings = list(map(lambda m: m.get_fmt_str(), warnings))
+        errors = list(filter(lambda m: m.get_level() == filterfile.message_level_t.ERROR, ff.ff.getFileMessages()))
+        errors = list(map(lambda m: m.get_fmt_str(), errors))
         print(f"read warnings={warnings}")
         print(f"read errors={errors}")
         self.assertTrue(warnings)
@@ -234,7 +234,7 @@ class TestFotonMethods(unittest.TestCase):
         butter_txt2 = ff.ff.write_string()
         ff2 = foton.FilterFile()
         ff2.ff.read_string(butter_txt2)
-        errors = [m.text for m in ff2.ff.getFileMessages() if m.level == filterfile.message_level_t.ERROR]
+        errors = [m.get_fmt_str() for m in ff2.ff.getFileMessages() if m.get_level() == filterfile.message_level_t.ERROR]
         print(f"read2 errors = {errors}")
         self.assertEqual(len(errors), 0)
 
@@ -255,13 +255,13 @@ class TestFotonMethods(unittest.TestCase):
         design = f'butter("LowPass",4,{f:g})'
         fd = foton.FilterDesign(design, self.section.rate)
         self.module[4].set_filterdesign(fd)
-        print(f"starting messages={[m.text for m in self.file.ff.getFileMessages()]}")
+        print(f"starting messages={[m.get_fmt_str() for m in self.file.ff.getFileMessages()]}")
         butter_txt = self.file.ff.write_string()
 
-        warnings = list(filter(lambda m: m.level == filterfile.message_level_t.WARNING, self.file.ff.getFileMessages()))
-        warnings = list(map(lambda m: m.text, warnings))
-        errors = list(filter(lambda m: m.level == filterfile.message_level_t.ERROR, self.file.ff.getFileMessages()))
-        errors = list(map(lambda m: m.text, errors))
+        warnings = list(filter(lambda m: m.get_level() == filterfile.message_level_t.WARNING, self.file.ff.getFileMessages()))
+        warnings = list(map(lambda m: m.get_fmt_str(), warnings))
+        errors = list(filter(lambda m: m.get_level() == filterfile.message_level_t.ERROR, self.file.ff.getFileMessages()))
+        errors = list(map(lambda m: m.get_fmt_str(), errors))
         print(f"warnings c={warnings}")
         print(f"errors c={errors}")
         self.assertTrue(warnings)
@@ -272,10 +272,10 @@ class TestFotonMethods(unittest.TestCase):
         print(f"correct_on_load c={ff.ff.correct_on_load}")
         ff.ff.read_string(butter_txt)
 
-        warnings = list(filter(lambda m: m.level == filterfile.message_level_t.WARNING, ff.ff.getFileMessages()))
-        warnings = list(map(lambda m: m.text, warnings))
-        errors = list(filter(lambda m: m.level == filterfile.message_level_t.ERROR, ff.ff.getFileMessages()))
-        errors = list(map(lambda m: m.text, errors))
+        warnings = list(filter(lambda m: m.get_level() == filterfile.message_level_t.WARNING, ff.ff.getFileMessages()))
+        warnings = list(map(lambda m: m.get_fmt_str(), warnings))
+        errors = list(filter(lambda m: m.get_level() == filterfile.message_level_t.ERROR, ff.ff.getFileMessages()))
+        errors = list(map(lambda m: m.get_fmt_str(), errors))
         print(f"read warnings c={warnings}")
         print(f"read errors c={errors}")
         self.assertTrue(warnings)
@@ -288,7 +288,7 @@ class TestFotonMethods(unittest.TestCase):
         ff2 = foton.FilterFile()
         ff2.ff.correct_on_load = True
         ff2.ff.read_string(butter_txt2)
-        errors = [m.text for m in ff2.ff.getFileMessages() if m.level == filterfile.message_level_t.ERROR]
+        errors = [m.get_fmt_str() for m in ff2.ff.getFileMessages() if m.get_level() == filterfile.message_level_t.ERROR]
         print(f"read2 errors c= {errors}")
         self.assertEqual(len(errors), 0)
 
diff --git a/src/python/foton/pyfilterfile_test.py b/src/python/foton/pyfilterfile_test.py
index 07ddfa62..5c4f2ea2 100644
--- a/src/python/foton/pyfilterfile_test.py
+++ b/src/python/foton/pyfilterfile_test.py
@@ -174,10 +174,10 @@ class FilterFileTest(unittest.TestCase):
         ret_code = self.ff.merge(self.fname)
         self.assertEqual(ret_code, -1)
 
-        warnings = list(filter(lambda m: m.level == filterfile.message_level_t.WARNING, self.ff.getMergeMessages()))
-        warnings = list(map(lambda m: m.text, warnings))
-        errors = list(filter(lambda m: m.level == filterfile.message_level_t.ERROR, self.ff.getMergeMessages()))
-        errors = list(map(lambda m: m.text, errors))
+        warnings = list(filter(lambda m: m.get_level() == filterfile.message_level_t.WARNING, self.ff.getMergeMessages()))
+        warnings = list(map(lambda m: m.get_fmt_str(), warnings))
+        errors = list(filter(lambda m: m.get_level() == filterfile.message_level_t.ERROR, self.ff.getMergeMessages()))
+        errors = list(map(lambda m: m.get_fmt_str(), errors))
         print(f"merge warnings={warnings}")
         print(f"merge errors={errors}")
         self.assertFalse(warnings)
@@ -186,10 +186,10 @@ class FilterFileTest(unittest.TestCase):
     def test_errors(self):
         self.ff.read_file(self.fname)
 
-        warnings = list(filter(lambda m: m.level == filterfile.message_level_t.WARNING, self.ff.getMergeMessages()))
-        warnings = list(map(lambda m: m.text, warnings))
-        errors = list(filter(lambda m: m.level == filterfile.message_level_t.ERROR, self.ff.getMergeMessages()))
-        errors = list(map(lambda m: m.text, errors))
+        warnings = list(filter(lambda m: m.get_level() == filterfile.message_level_t.WARNING, self.ff.getMergeMessages()))
+        warnings = list(map(lambda m: m.get_fmt_str(), warnings))
+        errors = list(filter(lambda m: m.get_level() == filterfile.message_level_t.ERROR, self.ff.getMergeMessages()))
+        errors = list(map(lambda m: m.get_fmt_str(), errors))
         print(f"merge warnings={warnings}")
         print(f"merge errors={errors}")
         self.assertFalse(warnings)
@@ -220,7 +220,7 @@ class FilterFileTest(unittest.TestCase):
         ff2.correct_on_load = True
         ff2.read_string(ff_text2)
 
-        errors = [m.text for m in ff2.getFileMessages() if m.level == filterfile.message_level_t.ERROR]
+        errors = [m.get_fmt_str() for m in ff2.getFileMessages() if m.get_level() == filterfile.message_level_t.ERROR]
         print(f"col errors={errors}")
         self.assertEqual(len(errors), 1)
 
@@ -229,7 +229,7 @@ class FilterFileTest(unittest.TestCase):
         ff3.correct_on_load = False
         ff3.read_string(ff_text2)
 
-        errors = [m.text for m in ff3.getFileMessages() if m.level == filterfile.message_level_t.ERROR]
+        errors = [m.get_fmt_str() for m in ff3.getFileMessages() if m.get_level() == filterfile.message_level_t.ERROR]
         print(f"col errors={errors}")
         self.assertEqual(len(errors), 0)
 
-- 
GitLab


From b313ed15b72109e39a920f8f8f91b40745168d4e Mon Sep 17 00:00:00 2001
From: Patrick Thomas <pthomas@caltech.edu>
Date: Thu, 18 May 2023 13:04:01 -0700
Subject: [PATCH 3/4] Added more detail to the notifications about deleting
 filter modules upon saving.

---
 src/dtt/filterwiz/FilterFile.cc      |  8 +++++++-
 src/dtt/filterwiz/FilterMessage.cc   |  2 +-
 src/dtt/filterwiz/TLGFilterWizard.cc | 14 ++++++++++++--
 3 files changed, 20 insertions(+), 4 deletions(-)

diff --git a/src/dtt/filterwiz/FilterFile.cc b/src/dtt/filterwiz/FilterFile.cc
index 7878ff59..da7e3a64 100644
--- a/src/dtt/filterwiz/FilterFile.cc
+++ b/src/dtt/filterwiz/FilterFile.cc
@@ -922,7 +922,13 @@ namespace filterwiz
                 message_t msg(
                     linenum,
                     ERROR,
-                    format( "Unknown filter module %s", tok[ 0 ].c_str( ) ) );
+                    format(
+                        "%s could not be found in the # MODULES header.\nIt "
+                        "was likely removed by the RCG. Its design is not "
+                        "being loaded.\nIf this file is saved then no "
+                        "information on it (including its design\nand "
+                        "coefficients) will be present in the saved file.\n",
+                        tok[ 0 ].c_str( ) ) );
                 cerr << msg.get_fmt_str( ) << endl;
                 file_message_vec.push_back( msg );
 
diff --git a/src/dtt/filterwiz/FilterMessage.cc b/src/dtt/filterwiz/FilterMessage.cc
index 5daaa002..5e4418b8 100644
--- a/src/dtt/filterwiz/FilterMessage.cc
+++ b/src/dtt/filterwiz/FilterMessage.cc
@@ -60,7 +60,7 @@ message_t::get_fmt_str( ) const
     {
         snprintf( fmt_str,
                   sizeof( fmt_str ),
-                  "%i: %s: %s",
+                  "Line %i: %s: %s",
                   this->line_number,
                   message_level_to_string( this->level ).c_str( ),
                   this->text.c_str( ) );
diff --git a/src/dtt/filterwiz/TLGFilterWizard.cc b/src/dtt/filterwiz/TLGFilterWizard.cc
index 614cc537..5f39ffba 100644
--- a/src/dtt/filterwiz/TLGFilterWizard.cc
+++ b/src/dtt/filterwiz/TLGFilterWizard.cc
@@ -1842,12 +1842,22 @@ namespace filterwiz
         // delete filters.
         if ( !fFilterFile.emptyFileMessages( ) )
         {
+            std::string msg =
+                std::string(
+                    "There were issues encountered when this file was "
+                    "loaded.\nThese issues may include one or more filter "
+                    "modules not listed in the # MODULES header.\nAny filter "
+                    "modules not listed in the # MODULES header\nmay be "
+                    "completely removed in the saved file.\n This includes "
+                    "their design and coefficients.\nPlease check the list of "
+                    "issues encountered loading the file for this case before "
+                    "proceeding.\n" ) +
+                std::string( "\nProceed and save anyway?" );
             Int_t ret;
             new TGMsgBox( gClient->GetRoot( ),
                           fParent,
                           "Warning",
-                          "There were errors reading the file!\n*** SAVING MAY "
-                          "DELETE FILTERS! ***\nContinue?",
+                          msg.c_str( ),
                           kMBIconExclamation,
                           kMBYes | kMBNo | kMBCancel,
                           &ret );
-- 
GitLab


From 64a2f4b69fd4412d1065d5c646b5d7ccbee6e9aa Mon Sep 17 00:00:00 2001
From: Patrick Thomas <pthomas@caltech.edu>
Date: Thu, 18 May 2023 16:30:21 -0700
Subject: [PATCH 4/4] Fixed some poorly formatted comments.

---
 src/dtt/filterwiz/FilterFile.cc | 60 +++++++++++++++------------------
 1 file changed, 27 insertions(+), 33 deletions(-)

diff --git a/src/dtt/filterwiz/FilterFile.cc b/src/dtt/filterwiz/FilterFile.cc
index da7e3a64..9177f0eb 100644
--- a/src/dtt/filterwiz/FilterFile.cc
+++ b/src/dtt/filterwiz/FilterFile.cc
@@ -28,7 +28,7 @@ namespace filterwiz
 
     //////////////////////////////////////////////////////////////////////////
     //                                                                      //
-    // Parsing utilities //
+    // Parsing utilities                                                    //
     //                                                                      //
     //////////////////////////////////////////////////////////////////////////
     typedef vector< string > tokenlist;
@@ -327,7 +327,7 @@ namespace filterwiz
 
     //////////////////////////////////////////////////////////////////////////
     //                                                                      //
-    // FilterFile //
+    // FilterFile                                                           //
     //                                                                      //
     //////////////////////////////////////////////////////////////////////////
     // A FilterFile has a couple of protected members, fFilename which is a
@@ -2057,37 +2057,31 @@ namespace filterwiz
     // # ETMX_R0_S_ACT 8 notch(1,10,30) 12 3.0 0.0 notch_1
     //
     // Note the following: + module_name must be listed in the MODULES section
-    // at the 			 head of the filter file.  If it doesn't exist,
-    // the filter
-    //			 definition is ignored.
-    //		       + section_number is in the range 0-9
-    //		       + design_string must be a valid string containing no
-    // spaces.
-    //		       + switching is a two digit integer consisting of
-    //			 (input switching + output switching), where input
-    // switching 			 is one of: 			    10 -
-    // Input is always applied to filter 20 - Input switch will switch with
-    // output switch output
-    // switching is one of: 			    1 - Immediate - switch off
-    // as soon as commanded 			    2 - Ramp - ramp over time
-    // specified in ramp_time 			    3 - Input crossing - output
-    // will switch when the
-    // filter 				input and output are within a given
-    // value of each other
-    //   				(value is in ramp_time field)
-    //			    4 - Zero crossing - output switch when input crosses
-    // zero.
-    //		       + ramp_time can be a time (which is multiplied by
-    // sampling rate
-    // to 			 obtain ramp cycles) or a floating point value
-    // for input crossing
-    //		       + timeout_time - time in seconds. If the output switching
-    // isn't 			 met in this time, the output will switch
-    // anyway.
-    //		       + section_name - Filter section name used in EPICS
-    // displays
-    // of 			 the standard filter module.  No whitespace
-    // allowed.
+    // at the head of the filter file.  If it doesn't exist,
+    // the filter definition is ignored.
+    //             + section_number is in the range 0-9
+    //             + design_string must be a valid string containing no spaces.
+    //             + switching is a two digit integer consisting of
+    //               (input switching + output switching),
+    //               where input switching is one of:
+    //                                     10 - Input is always applied to filter
+    //                                     20 - Input switch will switch with output
+    //
+    //               switch output switching is one of:
+    //                                      1 - Immediate - switch off as soon as commanded
+    //                                      2 - Ramp - ramp over time specified in ramp_time
+    //                                      3 - Input crossing - output will switch when the
+    //                                          filter input and output are within a given
+    //                                          value of each other (value is in ramp_time field)
+    //                                      4 - Zero crossing - output switch when input crosses zero.
+    //             + ramp_time can be a time (which is multiplied by sampling rate
+    //               to obtain ramp cycles) or a floating point value
+    //               for input crossing
+    //             + timeout_time - time in seconds. If the output switching
+    //               isn't met in this time, the output will switch anyway.
+    //             + section_name - Filter section name used in EPICS
+    //               displays of the standard filter module.  No whitespace
+    //               allowed.
     //
     // These functions are part of the FilterFile class because the merge needs
     // to be done on a filter file that's already been read. Return 0 if
-- 
GitLab