src31notes.dxy

00001 /* These are notes from my (itti@usc.edu) trying to cleanup the src3/
00002  source tree through the creation of a basic ModelComponent class */
00003 
00004 // //////////////////////////////////////////////////////////////////// //
00005 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2001 by the //
00006 // University of Southern California (USC) and the iLab at USC.         //
00007 // See http://iLab.usc.edu for information about this project.          //
00008 // //////////////////////////////////////////////////////////////////// //
00009 // Major portions of the iLab Neuromorphic Vision Toolkit are protected //
00010 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency //
00011 // in Visual Environments, and Applications'' by Christof Koch and      //
00012 // Laurent Itti, California Institute of Technology, 2001 (patent       //
00013 // pending; filed July 23, 2001, following provisional applications     //
00014 // No. 60/274,674 filed March 8, 2001 and 60/288,724 filed May 4, 2001).//
00015 // //////////////////////////////////////////////////////////////////// //
00016 // This file is part of the iLab Neuromorphic Vision C++ Toolkit.       //
00017 //                                                                      //
00018 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can   //
00019 // redistribute it and/or modify it under the terms of the GNU General  //
00020 // Public License as published by the Free Software Foundation; either  //
00021 // version 2 of the License, or (at your option) any later version.     //
00022 //                                                                      //
00023 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope  //
00024 // that it will be useful, but WITHOUT ANY WARRANTY; without even the   //
00025 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      //
00026 // PURPOSE.  See the GNU General Public License for more details.       //
00027 //                                                                      //
00028 // You should have received a copy of the GNU General Public License    //
00029 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write   //
00030 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,   //
00031 // Boston, MA 02111-1307 USA.                                           //
00032 // //////////////////////////////////////////////////////////////////// //
00033 //
00034 // Primary maintainer for this file: Rob Peters <rjpeters@klab.caltech.edu>
00035 // $Id: src31notes.dxy 11683 2009-09-10 22:51:55Z beobot $
00036 //
00037 
00038 
00039 // ######################################################################
00040 // ######################################################################
00041 /*! \page src31overview Changes from Revisions 3.0 to 3.1 in src3/
00042 
00043 <h1>NOTE</h1>
00044 
00045 Note that the 'src3' directory discussed below has now been renamed
00046 back to just 'src' (2005-06-12).
00047 
00048 <h1>Overview of changes in src3/ with Revision 3.1</h1>
00049 - <b>\ref src31components</b>
00050   - --><i>Towards a neural simulation environment</i>
00051 
00052 - <b>\ref src31tips</b>
00053   - --><i>Tips and frequently asked questions</i>
00054 
00055 */
00056 
00057 // ######################################################################
00058 // ######################################################################
00059 /*! \page src31components Towards a neural simulation environment
00060 
00061 
00062 Over the many years of development of this toolkit by many independent
00063 developers, several bad things have been growing to intolerable
00064 proportions:
00065 - only one executable, vision.C, had complex command-line parsing
00066   capability, although in principle many other executables could have
00067   had such capability through the OptionSet and OptionParser
00068   classes. Thus, vision.C had become the only program that could be
00069   tuned to do various things using command-line options, and as such
00070   people would keep adding new stuff into vision.C to the point that
00071   it had become an incredibly complicated mess;
00072 - many little programs were developed to test out and use new classes
00073   added to the toolkit. Typically those programs all shared
00074   substantial components (e.g., get a bottom-up visual attention model
00075   going, which meant instantiate a bunch of ChannelBase derivative
00076   objects, a VisualCortex, a Brain, etc), which was achieved through
00077   cut-and-paste from similar programs. Consequently, any core
00078   modification of the toolkit required updating of all those
00079   duplications of code.
00080 - people had a tendency to develop undocumented classes in their
00081   little corner, and the lack of doc and availability to core programs
00082   would make this unknown to other developers; thus, several
00083   almost-equivalent classes had been created for, e.g., access to a
00084   serial port and other functionality.
00085 
00086 With release 3.1 of the toolkit in early 2003, we attempted to fix
00087 those problems through the following strategy:
00088 - a mechanism was implemented to create tunable model parameters,
00089   whose values could be easily set via the command line or via config
00090   files. A set of classes (ModelParam, ModelComponent, ModelManager)
00091   was provided to ease the management of hierarchies of model
00092   components that would have such tunable params, and to automate the
00093   process of tuning those parameters via the command line or config
00094   files.
00095 - thus, vision.C was obsoleted and replaced by ezvision.C, which is a
00096   truly minimalistic program. Instead of doing all the work of parsing
00097   the command-line and deciding what to do based on the command-line
00098   options in the main() of various programs, that work was shifted
00099   main() to where it belonged in the first place: the various
00100   components of a model. The main paradigm shift, hence, was that a
00101   given model component (e.g., VisualCortex) should itself declare
00102   which of its parameters could be tuned, rather than the main() of
00103   vision.C or other executables deciding on that. With this new
00104   framework, adding a new tunable parameter to a given model component
00105   would automatically make it available to all programs that used that
00106   component, without any modification necessary on those programs'
00107   main() function.
00108 - ModelComponent was developed to be a base class for substantial
00109   computational modules of a neuromorphic model. The functionalities
00110   included in the base class (mechanisms to build hierarchies of
00111   ModelComponent objects, automatic setting of ModelParam values via
00112   the command-line, etc) would not need to be duplicated anymore as it
00113   had been the case previously.
00114 - Hopefully, documenting code and making it available to other
00115   programs should become more common in this framework too; indeed, if
00116   you wish to introduce new functionality into ezvision.C, typically
00117   you should not do so by adding code to ezvision.C itself, but rather
00118   by adding new components or new parameters to the existing
00119   components that are used by ezvision.C.
00120 
00121 Thus, the main idea behind revision 3.1 was to push as much code as
00122 possible out of main() and back to where it truly belonged in the
00123 first place, scattered across the various components of a model. See
00124 \ref modelbuilding "here" for a quick overview of how this was
00125 implemented and how to use this framework to build your new classes
00126 and models.
00127 
00128  */
00129 
00130 
00131 
00132 // ######################################################################
00133 // ######################################################################
00134 /*! \page src31tips Tips and frequently asked questions
00135 
00136 
00137 
00138 
00139 <h3>How do command-line options work?</h3>
00140 
00141 For a general introduction without which the details below may be
00142 difficult to understand, see \ref modelbuilding "here".
00143 
00144 Command-line options use a shared namespace and are all defined in
00145 ModelOptionDef.C. See \ref modelbuilding "here" for an explanation of
00146 why that is. The general behavior is as follows: only ModelParam<T>
00147 data members from ModelComponent objects may be exported as
00148 command-line options; each ModelComponent requests to the ModelManager
00149 that some or all of its ModelParam<T> data members be exported to the
00150 command-line; the ModelManager is in charge of parsing the
00151 command-line, and will set the ModelParam<T> value to the parsed
00152 command-line value for each ModelComponent that requested the
00153 corresponding command-line option. The process is entirely dynamic: if
00154 no ModelComponent requested a given option, it will not be available
00155 (and will not show up in the --help page); if parsing an option and
00156 setting the corresponding ModelParam<T> values triggers new options to
00157 be exported, they will become available immediately (see below for
00158 more detailed explanations of how to add command-line options that
00159 depend upon previously parsed command-line option values).
00160 
00161 Typically, things go as follows:
00162 
00163 - as ModelComponent derivative objects are instantiated, they
00164   instantiate any ModelParam<T> data member they may have. By default,
00165   those members remain private to the component and its derivatives
00166   (thus, they usually are in the protected section of the class
00167   definition). If the component is not registered with the
00168   ModelManager using ModelManager::registerComponent(), then the
00169   Manager will not interact with the component at all. If the
00170   component is registered, the ModelParam becomes accessible through
00171   calls to ModelComponent::setModelParamVal(),
00172   ModelComponent::setModelParamString(), etc. run on the manager
00173   object (see ModelComponent.H), since the ModelManager is a
00174   ModelComponent whose registered components are SubComponents. So,
00175   once a ModelComponent has been registered, you may not need to keep
00176   a pointer to it around, as you can modify its parameters through
00177   accesses to the ModelManager. This is the way to change ModelParam
00178   values for those parameters which ate not command-line options. See
00179   below for the parameters that will also become tunable via the
00180   command-line.
00181 
00182 - some time before the command-line is parsed, one typically calls
00183   ModelComponent::exportOptions() on the manager; this will propagate
00184   down to all its registered components and their subcomponents. When
00185   this is called, the caller, who has some meta-knowledge about what
00186   other components are available in the overall model, chooses which
00187   classes of command-line options should be exported (e.g., all
00188   options that have to do with saving results; see the OPTEXP_XXX
00189   defines in ModelOptionDef.H). Typically, in
00190   ModelComponent::exportOptions(), components decide on what they wish
00191   to export and then make appropriate calls to
00192   ModelManager::requestOption() on the manager, to actually request
00193   each option. If exportOptions() has not been called by the time the
00194   command-line is parsed, it will be called automatically with
00195   OPTEXP_ALL.
00196 
00197 - The manager keeps a list of default values for all possible options,
00198   and, for each option, a list of all the components that have
00199   requested it. When the manager is instantiated, the default values
00200   are taken from the hard-coded list in ModelOptionDef.C.  When a
00201   component requests an option for one of its ModelParam<T> members,
00202   by default the parameter value will be set to the default value from
00203   the manager.  Subsequent calls to
00204   ModelManager::setOptionValString() on the manager will change
00205   that default value as well as change the ModelParam values of all
00206   the components that have requested the option.
00207 
00208 - Thus, it does not matter whether you call
00209   ModelManager::setOptionValString() before or after your
00210   component is instantiated (if it exists, the ModelParam value will
00211   be changed immediately; if it does not exist yet, the ModelParam
00212   value will be changed when the component is instantiated and calls
00213   ModelManager::requestOption() on the manager).
00214 
00215 - Do not use ModelComponent::setModelParamVal() on the manager to
00216   change option values! This will change the values of the
00217   corresponding ModelParam members of all components currently
00218   registered with the manager, but it will not change the default
00219   option value; so any new component will still get the old default
00220   value rather than the value you have just set.
00221 
00222 - During parsing of the command-line,
00223   ModelManager::setOptionValString() is internally called onto the
00224   manager, for each parsed command-line option. This will change the
00225   default in the manager and the internal value of all the registered
00226   components, using ModelComponent::setModelParamString() on each
00227   registered component and its subcomponents. If you need to do
00228   something each time one of your ModelParam values is changed, you
00229   can overload ModelComponent::setModelParamString(). This is for
00230   example used by OrientationChannel in Channels.C (to instantiate a
00231   bunch of GarborChannels each time the number of orientations is
00232   changed) and by SaccadeControllerConfigurator in
00233   SaccadeControllers.C (to instantiate a saccade controller of
00234   appropriate type and export its command-line options each time a
00235   saccade controller type is specified). With this mechanism, you can
00236   thus create new command-line options on the basis of the values of
00237   previous command-line options. This is exactly what
00238   SaccadeControllerConfigurator is about. Compare the list of options
00239   related to saccade controllers when you type "ezvision --help" and
00240   "ezvision --sc-type=Monkey2 --help"
00241 
00242 - To debug the process, simply use "--debug" or
00243   "--save-config-to=debug.pmap" and check whether the value specified
00244   on the command-line was properly propagated down to all components
00245   that requested it. Otherwise check that you are following the
00246   sequence described here and \ref modelbuilding "there" in your
00247   model. You can also use a call to "manager.printout(std::cerr)" to
00248   print out the model hierarchy and ModelParam values.
00249 
00250 
00251 
00252 
00253 
00254 
00255 <h3>What if I want to hide options from the user except for a couple?</h3>
00256 
00257 If you need to be more specific than the general export classes
00258 defined for ModelComponent::exportOptions() with OPTEXP_XXX in
00259 ModelOptionDef.H, you will need to manually request the options using
00260 ModelComponent::doRequestOption() on your ModelComponent objects.
00261 
00262 An example of this is provided in the implementation of
00263 RadioDecoder::exportOptions() in RadioDecoder.C. Radiodecoder has an
00264 AudioGrabber subcomponent; we would like to let the users choose the
00265 device file name for the grabber, but we don't want them to change the
00266 audio recording frequency, otherwise the radio decoding will not
00267 work. So we explicitly block recursion in the call to exportOptions()
00268 at the level of the RadioDecoder, and manually export the device name
00269 option of the AudioGrabber subcomponent.
00270 
00271 Another possible approach is to make a very conservative call to
00272 ModelComponent::exportOptions(), for example, exporting nothing, and
00273 then to explicitly export some select options by calling
00274 ModelComponent::doRequestOption(), on the manager (which will propagate
00275 to all components of the model), or on some model components.
00276 
00277 
00278 
00279 
00280 
00281 
00282 <h3>How do I use my own custom option values instead of those provided
00283 in ModelOptionDef.C?</h3>
00284 
00285 There are several ways of doing that. You can change an option value
00286 using ModelManager::setOptionValString() before you parse the command
00287 line, to set a new default value. See how this is used in bmcvfigs.C
00288 for an example.
00289 
00290 Another approach is that you may want to change a bunch of default
00291 values depending on the type of derivation of an object which you will
00292 instantiate on a given run of your model. Furthermore, in such case,
00293 typically the object type initially is not known, and becomes known
00294 only while parsing the command-line. An example of that is for
00295 FrameGrabber objects; we would like to set the defaults that are most
00296 likely to work for either a V4Lgrabber or an IEEE1394grabber, but both
00297 sets of defaults differ substantially. To solve this, first, we use a
00298 FrameGrabberConfigurator to select the type of FrameGrabber derivative
00299 to use (see definition in FrameGrabber.H). Then, in
00300 FrameGrabber::exportOptions(), we instruct the ModelManager to use our
00301 current ModelParam values as option defaults, rather than the global
00302 defaults in ModelOptionDef.C; this is achieved by setting the third
00303 argument of the ModelManager::requestOption() calls to true (it is
00304 false by default). Finally, in the constructors of V4Lgrabber (see
00305 V4Lgrabber.C) and IEEE1394grabber (see IEEE1394grabber.C), we set our
00306 custom defaults. So as a V4Lgrabber or an IEEE1394grabber gets
00307 instantiated and gets a chance to exportOptions(), the correct
00308 defaults are being pushed into the ModelManager. Be careful with this,
00309 typically you would want to use this technique only if you expect to
00310 have only one object of the type in question in your model.
00311 
00312 
00313 
00314 
00315 
00316 
00317 <h3>Ok, that sounds cool, but what if I have several instances of a
00318 given object but want to have different options for each
00319 instance?</h3>
00320 
00321 In this kind of case, you typically will set the parameters that
00322 differentiate your objects by hand, and then will export by hand only
00323 those options which may be shared by your objects.
00324 
00325 An example of that is in test-stereo.C, which uses two IEEE1394grabber
00326 objects, for the left and right eyes. The first grabber is manually
00327 configured to use FrameGrabber subchannel 0 using
00328 ModelComponent::setModelParamVal(), and the second one to use
00329 subchannel 1. Clearly, it hence does not make sense for this setup to
00330 export a command-line option to set the subchannel. So instead, we
00331 export no option through the standard ModelManager::exportOptions()
00332 call. Then we only export a few options like image size and grab mode,
00333 by hand, calling ModelComponent::doRequestOption() on the
00334 manager. This will recurse and both grabbers will request the option
00335 since we have registered both with the manager, and when command-line
00336 options are parsed, they will affect both grabbers equally.
00337 
00338 
00339 
00340 
00341 
00342 
00343 <h3>How do I replace one of my regular internal parameters by a
00344 ModelParam<T>?</h3>
00345 
00346 - First, make sure than you can create a ModelParam of the type of
00347   your parameter. For that, check the list of instantiations of
00348   ModelParam<T> in InstantiateAll.H. If your parameter type is
00349   in this list, move on to the next step. Otherwise:
00350   - Enter a new instantiation in the list in InstantiateAll.H, and
00351     #include in ModelParam.C (towards top) whatever file is required to
00352     define the type you are using, so that the instantiation will work
00353     as ModelParam.C is compiled;
00354   - If operator>> and operator<< exist for your new type, move on to
00355     the next step;
00356   - If that type is an enum, create a .H file for it, and model it
00357     after the PyramidType enum in PyramidTypes.H; make sure you number
00358     your enum values and provide the xxxName() function;
00359   - We need to be able to convert to/from string for your new
00360     parameter type; to this end, edit StringConversions.H and add
00361     prototypes for convertToString() and convertFromString()
00362     specializations for your new type. Then implement those functions in
00363     StringConversions.C; look at how the other conversions were
00364     implemented and just do the same for your type.
00365   - If you are going to export your new type as a command-line option,
00366     edit ModelOptionDef.H and add a key for your new type in the
00367     ModelOptionType enum.
00368 
00369 - At this point, 'make ModelParam.o' and 'make StringConversions.o'
00370   should work.
00371 
00372 - Add the new data member in the protected section of your class that
00373   will use the parameter; your class must derive from ModelComponent
00374   or one of its derivatives. Make sure you put doxygen comments as to
00375   what the ModelParam data member does; see for example the protected
00376   section of class Brain in Brain.H.
00377 
00378 - In your constructor for your class, add an initialization for your
00379   parameter, with a default value. See the constructor in Brain.C for
00380   an example.
00381 
00382 - If you want to export your new parameter as a command-line option,
00383   you will need to implement an overload of the
00384   ModelComponent::exportOptions() function. Decide when you want to
00385   export the option, depending on how much it relies on the presence
00386   of other components in the model; look in ModelOptionDef.H at the
00387   OPTEXP_XXX defines. Typically, models that will only use your
00388   component will call exportOptions() with only OPTEXP_CORE on. Then
00389   implement exportOptions() for your new class, looking for example at
00390   the implementation for class Brain in Brain.C. Make sure your
00391   overload calls the base ModelComponent::exportOptions() at some
00392   point. Finally, create a new entry in ModelOptionDef.C for your new
00393   option. The name for your ModelParam should be chosen so that:
00394    - if it is unlikely to be used by other components, prefix it with
00395      something that has to do with your class, so that you will be
00396      sure that nobody will use the same name by mistake (e.g.,
00397      "AudioGrabberStereo" rather than "Stereo");
00398    - if you expect that several components will share the value set by
00399      your option, then use a more generic name (e.g.,
00400      "FOAradius"). Look at the top for the format of the entries in
00401      the AllModelOptions array in ModelOptionDef.C. Choose an option
00402      category for your option; this will place your option along with
00403      related options when --help is requested.
00404 
00405 - Everything should now compile and models using your class will all
00406 benefit from the presence of the new ModelParam and possible
00407 associated command-line option.
00408 
00409 
00410 
00411 
00412 
00413 
00414 <h3>How do I set the FOA radius?</h3>
00415 
00416 That's a good one. Once you have called ModelComponent::start() on
00417 your manager, you can't change option values anymore (that's to
00418 prevent people from changing, e.g., the number of orientations in an
00419 OrientationChannel while a simulation is running). But you need to
00420 start the model and load the first input image in order to get its
00421 dims and compute the FOA radius. We solve this in two ways:
00422 
00423 - the preferred way is to just use an InputFrameSeries to load your
00424   input frames (see FrameSeries.H). The InputFrameSeries will peek the
00425   dims of the first frame during start(), and set a few options that
00426   are dependent on these dims, like FOAradius, FoveaRadius, etc, if
00427   those currently are set to zero (which means that they should be set
00428   from input image dims).
00429 
00430 - or there is the manual way, but it is non-preferred. You can just
00431   use a raw Raster::ReadRGB() call to read your first frame before you
00432   call start() and after you have parsed the command-line. Then you
00433   manually compute your FOA radius, then set the option by calling
00434   setOptionValString() on the manager (you will need to convert your
00435   radius to string, and can use convertToString() from
00436   StringConversions.H to do that). Then start your model.
00437 
00438 */
00439 
Generated on Sun May 8 08:04:09 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3