00001 00002 // //////////////////////////////////////////////////////////////////// // 00003 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2000-2002 // 00004 // by the University of Southern California (USC) and the iLab at USC. // 00005 // See http://iLab.usc.edu for information about this project. // 00006 // //////////////////////////////////////////////////////////////////// // 00007 // Major portions of the iLab Neuromorphic Vision Toolkit are protected // 00008 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency // 00009 // in Visual Environments, and Applications'' by Christof Koch and // 00010 // Laurent Itti, California Institute of Technology, 2001 (patent // 00011 // pending; application number 09/912,225 filed July 23, 2001; see // 00012 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status). // 00013 // //////////////////////////////////////////////////////////////////// // 00014 // This file is part of the iLab Neuromorphic Vision C++ Toolkit. // 00015 // // 00016 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can // 00017 // redistribute it and/or modify it under the terms of the GNU General // 00018 // Public License as published by the Free Software Foundation; either // 00019 // version 2 of the License, or (at your option) any later version. // 00020 // // 00021 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope // 00022 // that it will be useful, but WITHOUT ANY WARRANTY; without even the // 00023 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // 00024 // PURPOSE. See the GNU General Public License for more details. // 00025 // // 00026 // You should have received a copy of the GNU General Public License // 00027 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write // 00028 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, // 00029 // Boston, MA 02111-1307 USA. // 00030 // //////////////////////////////////////////////////////////////////// // 00031 // 00032 // Primary maintainer for this file: Laurent Itti <itti@usc.edu> 00033 // $Id: modelbuilding.dxy 11684 2009-09-10 22:52:30Z beobot $ 00034 // 00035 00036 00037 // ###################################################################### 00038 // ###################################################################### 00039 00040 00041 /*! \page modelbuilding Building models using the toolkit 00042 00043 <h1>Overview</h1> 00044 00045 A number of facilities are provided to allow easy creation of new 00046 models. These off-load most of the work involved in having tunable 00047 persistent parameters in your models and in being able to generate and 00048 parse command-line options in your executables. 00049 00050 To allow this, a computational model is defined as a managed 00051 collection of ModelComponent derivative objects. These objects are 00052 instantiated as a hierachical collection that varies from model to 00053 model and may also vary within one model through run-time selection of 00054 certain components or behaviors. ModelComponent provides a basic 00055 facility for building such hierarchies. In addition, it provides 00056 facilities for holding a number of ModelParam data members. These are 00057 persistent parameters, in the sense that their values can be saved to 00058 a file and later re-loaded from that file (using a ParamMap 00059 structure). ModelParam objects typically are private to a model 00060 component and the hierarchical file format used to store them ensures 00061 that no conflict between identical parameters across several 00062 components should occur. Finally, ModelComponent objects may request 00063 that some command-line option be created for some of their ModelParam 00064 members, so that the ModelParam values may be set via the 00065 command-line. Because typically those options may be shared among a 00066 variety of ModelComponents (e.g., radius of the focus of attention, or 00067 verbosity level), there is a single namespace for all the ModelParam 00068 names that may become valid command-line options (see 00069 ModelOptionDef.C). So, in order to be exportable as a command-line 00070 option, a ModelParam should have its name registered in a global list 00071 of all possible command-line options. When the command-line is parsed, 00072 all ModelParam objects with maching name will be updated to the value 00073 supplied in the command-line. 00074 00075 <h1>The bottom-up view</h1> 00076 00077 The following classes are available to implement the above 00078 functionality. 00079 00080 - ModelParamBase is a base class (that cannot be instantiated directly 00081 because it has some virtual methods) for a persistent model 00082 parameter. At the base level, such parameter is just defined by its 00083 name and the base does not yet hold any data. However, it provides 00084 an interface for name access, registration of the parameter with its 00085 parent component, and other functionality. 00086 00087 - ModelParam<T> is a template class that derives from 00088 ModelParamBase. It adds the actual parameter data as a single 00089 instance of a value of type T. When the parameter is saved to a 00090 ParamMap, it will appear as a "name value" pair in the file. 00091 00092 - ModelComponent is a base class that facilitates building hierarchies 00093 of objects that may hold ModelParam<T> parameters, that may request 00094 command-line options, and that may have other ModelComponent 00095 derivatives as sub-components. 00096 00097 - ModelManager is a class that facilitates loading/saving of 00098 ModelParam values to a config file, run-time generation of a set of 00099 command-line options that depends on which options have been 00100 requested by the particular collection of ModelComponent objects 00101 currently instantiated, parsing of the command-line options and 00102 automatic update of the ModelParam<T> contents for those parameters 00103 that have been associated with the option, and saving of config 00104 files (plus some added functionality). 00105 00106 - ModelOptionDef.C contains a global, shared list of all possible 00107 command-line options that may be used by any model in our source 00108 tree. When ModelComponent objects request an option to be added to 00109 the command-line, it must exist in this list. There are at least 00110 three reasons for having such global shared list rather than having 00111 each component fully specify all the characteristics of some 00112 command-line option it may wish to instantiate: 00113 -# it is easier to ensure that two option names will not be used 00114 in two different parts of the codebase with different meanings 00115 -# it allows several unrelated components to easily share the 00116 value specified at the command-line (both components just need 00117 to request the correct option name; in comparison, realizing 00118 that two options are equal although they have been fully 00119 defined in two different objects would require that all 00120 meta-information (name, long option name, short option name, 00121 description, valid values) match. This would make updates a 00122 nightmare (e.g., updating the description of an option that has 00123 been used by 25 differnt components defined in 25 separate 00124 source files)). 00125 -# When you wish to create a new command-line option, it would be 00126 nearly impossible to check whether a similar one does not 00127 already exist if all the definitions were spread out all over 00128 the code. 00129 00130 Below we walk through a typical use of these facilities to build and 00131 run a computational model that is composed of a run-rime selectable 00132 collection of ModelComponent derivatives. 00133 00134 <h1>The top-down view and building models</h1> 00135 00136 Typically, building a new model entails the following sequence of 00137 actions (for a fuller yet simple example, see test-audioGrab.C): 00138 00139 - start a main() function 00140 00141 \code 00142 int main(const int argc, const char **argv) 00143 { 00144 \endcode 00145 00146 - instantiate a ModelManager object. It will be in charge of managing 00147 a collection of ModelComponent objects, of loading/saving their 00148 persistent data, and of creating and parsing the command-line 00149 options depending on the requests of the current collection of 00150 components: 00151 00152 \code 00153 ModelManager manager("My cool model"); 00154 \endcode 00155 00156 - Instantiate a hierarchy of ModelComponent objects. The natural way 00157 to do that in this framework is to immediately attach the objects to 00158 a SharedPtr. Typically, each ModelComponent object will hold a 00159 number of ModelParam persistent data members. In addition, 00160 ModelComponent may request that certain command-line options be 00161 added to the command-line. This is done by calling 00162 ModelManager::requestOption(this, param) where the name of the param 00163 must correspond to one of the possible command-line option names 00164 defined in the global list in ModelOptionDef.C: 00165 00166 \code 00167 SharedPtr<MyComponent> mycomp(new MyComponent(manager)); 00168 \endcode 00169 00170 - Register the top-level components with the manager. Upon load/save 00171 of parameter files, the manager will invoke the corresponding 00172 load/save functions on all its registered components. Those 00173 functions are recursive. so that each component will invoke the same 00174 function in all of its subcomponents: 00175 00176 \code 00177 manager.registerComponent(mycomp); 00178 \endcode 00179 00180 - Once you have registered your hierarchy of components, you may 00181 optionally decide which of their internal parameters you wish to 00182 export as command-line options; you may do that in batch style using 00183 (see ModelOptionDef.H for possible values to use here): 00184 00185 \code 00186 // Note: this is optional; if you don't do this call explicitly, it 00187 // will be made automatically (exporting ALL options) just before 00188 // we start parsing the command line: 00189 manager.exportOptions(OPTEXP_ALL); 00190 \endcode 00191 00192 - In addition, if you wish to explicitly export a ModelParam from one 00193 of your components as a command-line option (assuming the component 00194 has not already done so), you can do that using 00195 ModelComponent::doRequestOption() here (this is a recursive call so 00196 that it can also turn on option export in deeply nested 00197 sub-components that you may not have direct access to): 00198 00199 \code 00200 mycomp->doRequestOption("MyParamName", true, true, true); 00201 \endcode 00202 00203 - Parse the command-line, using the ModelManager built-in mechanism. 00204 This will update the values of all the requested model options, 00205 depending on which ones are specified on the command-line. The 00206 min/max number of expected non-option arguments are passed, along 00207 with a text description of what those are, to parseCommandLine(). If 00208 an incorrect number of arguments is found, or bogus options are 00209 specified, parseCommandLine() will print a usage message and return 00210 false. There are several special command-line options that are 00211 implemented by the manager itself, including --debug, --test-mode, 00212 --load-config-from=file and --save-config-to=file. If the 00213 --load-config-from option is encountered during parsing, the config 00214 file is loaded and all ModelParam values are updated immediately. So 00215 any command-line option specified before the --load-config-file is 00216 likely to be overwritten by the values in the config file. Any 00217 command-line option specified afterwards, however, will be applied 00218 after the config file has been loaded. --save-config-to has no 00219 immediate effect. Rather, one should call manager::saveConfig() at 00220 some appropriate time (for example, after a successful run of the 00221 model), which will automatically save the config file if the option 00222 was specified, or be a no-op if the option was not 00223 specified. Finally, one last feature is that the manager may attempt 00224 to automatically load a config file named "~/.executablename" just 00225 before parsing the first option, if it was instructed to do so at 00226 construction (by default, all three of these features are on. See 00227 the ModelManager constructor for details): 00228 00229 \code 00230 if (manager.parseCommandLine(argc, argv, "<input.ppm> <output.ppm>", 00231 2, 2) == false) return(1); 00232 \endcode 00233 00234 - Get the extra non-option arguments: 00235 00236 \code 00237 int numargs = manager.numExtraArgs(); 00238 std::string infilename = manager.getExtraArg(0); 00239 std::string outfilename = manager.getExtraArg(1); 00240 \endcode 00241 00242 - If any additional configuration needs to be made now that the 00243 command-line options have been parsed, they should be made 00244 here. This may for instance include instantiation of components 00245 whose nature is defined at run-time through some command-line 00246 option. 00247 00248 - The configuration may be automatically saved if --save-config-to was 00249 specified on the command-line (the call below will be a no-op 00250 otherwise). The call below is optional, and will be made as part of 00251 start() below if it has not been made explicitly: 00252 00253 \code 00254 // Note: This call is optinal too, and if you don't make it 00255 // explicitly, it will be made from within start(): 00256 manager.saveConfig(); 00257 \endcode 00258 00259 - Start all the components through a single recursive call. Typically 00260 each component will then perform any additional setup that could not 00261 be done in its constructor because it depended on command-line or 00262 persistent parameter values: 00263 00264 \code 00265 manager.start(); 00266 \endcode 00267 00268 - Use the model and get some interesting results. Once the model has 00269 started, all functions that modify ModelParam<T> values will throw a 00270 fatal error if used, so that external people cannot mess with the 00271 guts of a ModelComponent once it has started. 00272 00273 - If you need to revert your model to its initial state (e.g., your 00274 program runs three independent simulations between the start() and 00275 stop() calls), try a: 00276 00277 \code 00278 manager.reset(); 00279 \endcode 00280 00281 to reset your model. But check that your various model components 00282 indeed do implement reset(), as reset() has been implemented only on 00283 a few components to date (since most programs run only one 00284 simulation and hence to not need any reset() capability). 00285 00286 - Once done with a simulation, proper termination of the executable 00287 starts by recursively stopping all components. 00288 00289 \code 00290 manager.stop(); 00291 \endcode 00292 00293 - We are now ready for an exit that will destroy the manager and the 00294 hierarchy of components. 00295 00296 \code 00297 return 0; 00298 } 00299 \endcode 00300 00301 */ 00302 00303 // ###################################################################### 00304 /* So things look consistent in everyone's emacs... */ 00305 /* Local Variables: */ 00306 /* indent-tabs-mode: nil */ 00307 /* End: */