ModelComponent.H

Go to the documentation of this file.
00001 /*!@file Component/ModelComponent.H base class for parameterized model components */
00002 
00003 // //////////////////////////////////////////////////////////////////// //
00004 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2000-2003   //
00005 // by the University of Southern California (USC) and the iLab at USC.  //
00006 // See http://iLab.usc.edu for information about this project.          //
00007 // //////////////////////////////////////////////////////////////////// //
00008 // Major portions of the iLab Neuromorphic Vision Toolkit are protected //
00009 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency //
00010 // in Visual Environments, and Applications'' by Christof Koch and      //
00011 // Laurent Itti, California Institute of Technology, 2001 (patent       //
00012 // pending; application number 09/912,225 filed July 23, 2001; see      //
00013 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status).     //
00014 // //////////////////////////////////////////////////////////////////// //
00015 // This file is part of the iLab Neuromorphic Vision C++ Toolkit.       //
00016 //                                                                      //
00017 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can   //
00018 // redistribute it and/or modify it under the terms of the GNU General  //
00019 // Public License as published by the Free Software Foundation; either  //
00020 // version 2 of the License, or (at your option) any later version.     //
00021 //                                                                      //
00022 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope  //
00023 // that it will be useful, but WITHOUT ANY WARRANTY; without even the   //
00024 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      //
00025 // PURPOSE.  See the GNU General Public License for more details.       //
00026 //                                                                      //
00027 // You should have received a copy of the GNU General Public License    //
00028 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write   //
00029 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,   //
00030 // Boston, MA 02111-1307 USA.                                           //
00031 // //////////////////////////////////////////////////////////////////// //
00032 //
00033 // Primary maintainer for this file: Laurent Itti <itti@usc.edu>
00034 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/Component/ModelComponent.H $
00035 // $Id: ModelComponent.H 11019 2009-03-11 20:57:11Z itti $
00036 //
00037 
00038 #ifndef MODELCOMPONENT_H_DEFINED
00039 #define MODELCOMPONENT_H_DEFINED
00040 
00041 #include "Component/ParamClient.H"
00042 #include "Component/ModelParamBase.H"
00043 #include "Util/Types.H"
00044 #include "Util/log.H"
00045 #include "nub/object.h"
00046 #include "nub/ref.h"
00047 #include "rutz/shared_ptr.h"
00048 
00049 #include <iosfwd>
00050 #include <string>
00051 
00052 //! A convenience function for making a rutz::shared_ptr out of a raw pointer.
00053 template <class T>
00054 inline nub::ref<T> makeSharedComp(T* t) { return nub::ref<T>(t); }
00055 
00056 class ParamMap;
00057 class OptionManager;
00058 
00059 //! Type for bitwise-or'ed combinations of ModelComponent flags
00060 typedef int ModelFlag;
00061 
00062 //! placeholder for "no flags"
00063 const ModelFlag MC_NO_FLAGS = 0;
00064 
00065 //! do operations recursively on subcomponents
00066 const ModelFlag MC_RECURSE = (1 << 0);
00067 
00068 //! ignore missing param values, if possible (not all ops allow this flag)
00069 const ModelFlag MC_IGNORE_MISSING = (1 << 1);
00070 
00071 //! Provide some information about howto save() things
00072 /*! Base class is empty, but derivations of ModelComponent, like, for
00073   example SimModule and derivatives, may use a derivation of
00074   ModelComponentSaveInfo which actually contains some info: */
00075 class ModelComponentSaveInfo {
00076 public:
00077   //! Default constructor
00078   ModelComponentSaveInfo() { }
00079 
00080   //! Virtual destructor to ensure safe destruction of derived objects
00081   virtual ~ModelComponentSaveInfo() { }
00082 };
00083 
00084 //! Base class for parameterized model components
00085 /*! The goal is to provide a unified interface by which tunable
00086   parameters can be set, read, or exported as command-line options or
00087   in parameter maps or files, so that executables using a variable
00088   collection of model components can easily be built and configured
00089   using command-line options and config files. To this end,
00090   ModelComponent provides a set of facilities that allow it to hold a
00091   number of ModelParamBase data members. A ModelComponent also holds a
00092   list of sub-components that are ModelComponent as well, and many of
00093   the ModelComponent functions will first apply to the component
00094   itself, then recursively to its subcomponents. The ModelParamBase
00095   are the tunable parameters that are persistent and may be associated
00096   with a command-line option; see ModelParam.H for details. A
00097   ModelComponent is attached to a OptionManager that will handle
00098   option parsing and ModelParamBase load/save. A ModelComponent may
00099   request its master to associate some of its ModelParamBase data
00100   members with command-line options. Command-line option definitions
00101   are typically given in one master file per source directory
00102   (e.g. Devices/DeviceOpts.C, Media/MediaOpts.C, Neuro/NeuroOpts.C),
00103   although some components may also define private command-line
00104   options internally in their own .C files. Command-line parsing will
00105   set the value of ALL ModelParamBase objects in all ModelComponent
00106   objects and their subcomponents that have requested the option to
00107   the value specified on the command line. So this mechanism should be
00108   used sparingly, for parameters that may be used across a variety of
00109   models and a variety of ModelComponent derivatives.
00110 
00111   There is one trick to be aware of with respect to the basic
00112   operation and setup of ModelComponent. For speed reasons, we want
00113   our ModelParam parameters to be true data members, so that we can
00114   access them as efficiently as normal data members (rather than
00115   having to first look them up by name). On the other hand, the
00116   ModelComponent must also be able to produce a list of all its
00117   ModelParam members, so that they can be saved to a ParamMap. To
00118   resolve this, ModelComponent both holds each ModelParam as a regular
00119   data member, and a list of pointers to all its ModelParam
00120   members. In addition, this list keeps track of which model params
00121   are affiliated with command-line options, as well as which should
00122   actually be exported on the command-line. This list is automatically
00123   maintained when the ModelParam objects are constructed and
00124   destroyed, so that the user does not have to worry about it. */
00125 class ModelComponent : public ParamClient, public virtual nub::object
00126 {
00127 public:
00128   // ######################################################################
00129   /*! @name Constructors and Destructors */
00130   //@{
00131 
00132   //! Constructor
00133   /*! Typically, in the constructor you should perform all
00134     initializations that are independent of the values of your
00135     ModelParam data members. Since the command-line usually has not
00136     been parsed yet at the time you construct your various
00137     ModelComponent objects, however, the start() function below is
00138     provided to allow you to perform additional initializations after
00139     the command-line has been parsed and the ModelParam data members
00140     have been configured.
00141     @param mgr our option manager; see OptionManager.H
00142     @param descrName a human-readable descriptive name
00143     @param tagname a computer-oriented unique name (used for storage in ParamMap)
00144     @param crealm the realm in which this component lives, used for partitioning
00145       the SimEvent space into possibly distinct realms. */
00146   ModelComponent(OptionManager& mgr, const std::string& descrName,
00147                  const std::string& tagName,
00148                  const std::string& crealm = "World");
00149 
00150   //! Constructor overload without an OptionManager
00151   /*! In this case, you must call setManager() before using any other
00152       functions. In fact, if you aren't ModelManager, you probably
00153       shouldn't be using this constructor! (ModelManager needs it due
00154       to an implementation quirk related to multiple inheritance). */
00155   ModelComponent(const std::string& descrName,
00156                  const std::string& tagName,
00157                  const std::string& crealm = "World");
00158 
00159   //! Virtual destructor ensures proper destruction of derived classes
00160   virtual ~ModelComponent();
00161 
00162   //! Start the component
00163   /*! This will start the component by triggering the following
00164     sequence of actions:
00165         - Check if we are already started and emit a fatal error if so
00166         - Call start1() that may be overloaded by derived classes
00167         - Call start() on all our subcomponents
00168         - Call start2() that may be overloaded by derived classes
00169         - Switch us to "started" state, in which modifying our ModelParam
00170           values externally is forbidden
00171 
00172     Derived classes should overload start1() and start2() as a way to
00173     get the component started, once the command-line options and
00174     config files have been parsed and all the ModelParam objects have
00175     been configured. Default no-op implementations are provided for
00176     start1() and start2(), so if you don't need to do anything to
00177     start your component, you don't need to implement start1() and
00178     start2(). Because this is a recursive call on our sub-components,
00179     typically you only need to call it once on your root
00180     ModelComponent (probably ModelManager) to get your entire
00181     hierarchy of ModelComponent objects started. */
00182   void start();
00183 
00184   //! Did we already get a call to start()?
00185   bool started() const;
00186 
00187   //! Stop the component
00188   /*! This will stop the component by triggering the following
00189     sequence of actions:
00190         - Check if we are already started and emit a fatal error if not
00191         - Call stop1() that may be overloaded by derived classes
00192         - Call stop() on all our subcomponents
00193         - Call stop2() that may be overloaded by derived classes
00194         - Switch us out of "started" state, so that modifying our ModelParam
00195           values externally is allowed
00196 
00197     Derived classes should overload stop1() and stop2() as a way to
00198     get the component stopped, once the command-line options and
00199     config files have been parsed and all the ModelParam and objects
00200     have been configured. Default no-op implementations are provided
00201     for stop1() and stop2(), so if you don't need to do anything to
00202     stop your component, you don't need to implement stop1() and
00203     stop2(). Because this is a recursive call on our sub-component,
00204     typically you only need to call it once on your root
00205     ModelComponent (probably ModelManager) to get the entire hierarchy
00206     of ModelComponent objects stopped. */
00207   void stop();
00208 
00209   //! Signify that our ModelManager just got destroyed
00210   /*! This should not be called manually, but will be called from
00211       within our parent ModelComponent's destructor. It will ensure
00212       that we do not try to unregister with our ModelManager if the
00213       manager is destroyed before us. */
00214   void managerDestroyed();
00215 
00216   //! Get our manager.
00217   OptionManager& getManager() const;
00218   //@}
00219 
00220   // ######################################################################
00221   /*! @name Name functions */
00222   //@{
00223 
00224   //! Get a human-readable descriptive name for this component.
00225   /*! This is NOT intended to be a name for programmatic use (such as
00226       for indexing into associative arrays). It is not necessarily
00227       unique on a per-object basis; it's possible that all objects of
00228       the same class return the same descriptiveName(). */
00229   std::string descriptiveName() const;
00230 
00231   //! Change this component's descriptive name.
00232   void setDescriptiveName(const std::string& name);
00233 
00234   //! Get a programmer-usable tag name for this object.
00235   /*! This is intended to be unique among component objects, so that
00236       this string could be used for associate-array indexing, for
00237       example. */
00238   std::string tagName() const;
00239 
00240   //! Change this component's tag name.
00241   void setTagName(const std::string& name);
00242 
00243   //! Get the realm
00244   std::string realm() const;
00245 
00246   //! Set the realm
00247   /*! This will throw a fatal exception if the component is in started
00248       state. This is a recursive call which will propagate to all
00249       subcomponents. */
00250   void setRealm(const std::string& crealm);
00251 
00252   //@}
00253 
00254   // ######################################################################
00255   /*! @name Sub-Component management functions */
00256   //@{
00257 
00258   //! Get this component's parent ModelComponent, or NULL if it has no parent.
00259   /*! Internally, each component stores a weak smart pointer to its
00260       parent, while the parent stores a strong smart pointer to the
00261       child. This avoids unbreakable reference-counting cycles, but
00262       still lets us traverse the parent-child in both directions
00263       component tree using getParent() and subComponent(). */
00264   ModelComponent* getParent() const;
00265 
00266   //! Get this component's root parent (the parent of all parents in our tree)
00267   /*! If this component has no parent, then getRootObject() returns a
00268       pointer to this component itself. */
00269   ModelComponent* getRootObject();
00270 
00271   //! Get this component's root parent (the parent of all parents in our tree)
00272   /*! If this component has no parent, then getRootObject() returns a
00273       pointer to this component itself. */
00274   const ModelComponent* getRootObject() const;
00275 
00276   //! Add a subcomponent to our internal list; return its index
00277   /*! NOTE that by default this will set the realm of the subcomponent (and its subs) to our realm */
00278   uint addSubComponent(const nub::ref<ModelComponent>& subc, const bool propagate_realm = true);
00279 
00280   //! Remove a subcomponent from our internal list, by address
00281   /*! This will only remove the component from our list of registered
00282       subcomponents, but will not attempt to destroy it. If removeall
00283       is true, then all components matching subc are removed;
00284       otherwise, only the first is removed. Returns the number of
00285       subcomponents that were removed. */
00286   int removeSubComponent(const ModelComponent& subc, bool removeall = false);
00287 
00288   //! Remove a subcomponent by nub:ref.
00289   void removeSubComponent(const nub::ref<ModelComponent>& subc);
00290 
00291   //! Remove a subcomponent from our internal list, by index
00292   /*! This will only remove the component from our list of registered
00293     subcomponents, but will not attempt to destroy it. */
00294   void removeSubComponent(const uint idx);
00295 
00296   //! Remove a subcomponent from our internal list, by tagName
00297   /*! This will only remove the component from our list of registered
00298     subcomponents, but will not attempt to destroy it. */
00299   void removeSubComponent(const std::string& tagname);
00300 
00301   //! Remove all our subcomponents
00302   void removeAllSubComponents();
00303 
00304   //! Access a sub-component by index
00305   nub::ref<ModelComponent> subComponent(const uint idx) const;
00306 
00307   //! Access a sub-component by tagname
00308   /*! @param flags if containing MC_RECURSE, will look not only in our
00309     subcomponents but also recursively in their subcomponents
00310     (depth-first search)*/
00311   nub::ref<ModelComponent> subComponent(const std::string& tagname,
00312                                         const ModelFlag flags = 0) const;
00313 
00314   //! Get current number of subcomponents
00315   uint numSubComp() const;
00316 
00317   //! Return true if we have a subcomponent by that tagname
00318   /*! @param flags if containing MC_RECURSE, will look not only in our
00319     subcomponents but also recursively in their subcomponents
00320     (depth-first search)*/
00321   bool hasSubComponent(const std::string& tagname,
00322                        const ModelFlag flags = 0) const;
00323 
00324   //! Return true if we have the pointee as subcomponent
00325   /*! @param flags if containing MC_RECURSE, will look not only in our
00326     subcomponents but also recursively in their subcomponents
00327     (depth-first search)*/
00328   bool hasSubComponent(const nub::soft_ref<ModelComponent>& c,
00329                        const ModelFlag flags = 0) const;
00330 
00331   //! Show our ModelParam internals and those of our subcomponents
00332   void printout(std::ostream& s, const std::string& prefix = "") const;
00333 
00334   //! Reset a model component and propagate the request to the sub-components
00335   /*! For each ModelComponent reset should set it into the state that
00336       it was just after calling the constructor. It will depend on the
00337       component what exactly that involves.
00338 
00339       @param flags if containing MC_RECURSE, then we recursively
00340              reset() our subcomponents as well
00341 
00342       PROGRAMMER NOTE: This function is not virtual, so you should not
00343       try to override this function in your derived class; instead
00344       override reset1() and/or reset2(). In those overrides, be sure
00345       to call your base class's version of reset1() or reset2().
00346   */
00347   void reset(const ModelFlag flags);
00348 
00349   //! Save/display our current state
00350   /*! Over the course of a program run, once in a while it may be
00351     desirable to broadcast an order to all ModelComponents to save
00352     and/or display their current state or internals. This function
00353     achieves this. Like for start(), stop() and reset(), this is a
00354     usually recursive call, and derived classes should not override this
00355     function, but should instead override save1() (called before we
00356     recurse through our subcomponents) and save2() (called after we
00357     have recursed through our subcomponents). Default implementations
00358     for save1() and save2() are provided which are no-ops. */
00359   void save(const ModelComponentSaveInfo& sinfo,
00360             const ModelFlag flags = MC_RECURSE);
00361 
00362   //@}
00363 
00364   // ######################################################################
00365   /*! @name Access to tunable ModelParam's */
00366   //@{
00367 
00368   //! Export some of our ModelParam parameters as command-line-options
00369   /*! This should be called once on the model manager to decide which
00370       sets of ModelParam paremeters should become command-line
00371       options; the call will then recurse through all ModelComponent
00372       objects that have been registered with the manager. This is
00373       provided so that external meta-knowledge about what a collection
00374       of ModelComponent objects forming a computational model can be
00375       used to decide on which command-line options are relevant: for
00376       instance, if you build a model that has no OutputFrameSeries,
00377       then you will not be able to call saveResults() on your Brain or
00378       other objects, so you would not want to export command-line
00379       options that relate to which results should be saved. This is
00380       handled by the exportFlag member of each ModelOptionDef, which
00381       must match the ModelManager's current export mask (set by
00382       ModelManager::allowOptions()) in order for that option to
00383       actually be exported.
00384 
00385       HISTORICAL NOTE: It used to be that every subclass of
00386       ModelComponent would need to override exportOptions(), and
00387       explicitly request that each model param be exported. This is no
00388       longer the case -- instead, when each OModelParam is constructed
00389       in the subclass's constructor, it ends up calling
00390       registerOptionedParam() on the ModelComponent, which adds the
00391       param to our list of params, but also marks the param for
00392       command-line export whenever exportOptions() is finally
00393       called. For those rare cases where you do not want an
00394       OModelParam exported to the command-line, you can call
00395       forgetExports(), and then explicitly re-export any desired
00396       options using doRequestOption().
00397   */
00398   void exportOptions(const ModelFlag flags);
00399 
00400   //! Check for named param in this component (and possibly its subcomponents)
00401   /*! Use this to verify that a param exists before doing a
00402       getModelParamVal() or setModelParamVal(), since those functions
00403       will throw an exception if the named param is non-existent. */
00404   bool hasModelParam(const std::string& name, const ModelFlag flags = 0) const;
00405 
00406   //! Parse a parameter value given as string and set the param
00407   /*! Should not be needed in normal operation, inefficient text-based
00408       interface. In normal operation, the internals of the
00409       ModelComponent derivative will directly access the ModelParam,
00410       not external people. If you want to provide external access to
00411       your ModelParam values, you should implement a wrapper for them
00412       in your ModelComponent derivative (e.g., implement a function
00413       setSize() that will set the value of your Size ModelParam).
00414       Returns true if the ModelParam was found and set. Throws a fatal
00415       error if the ModelComponent was started, to avoid external
00416       people messing around with our ModelParam values during
00417       operation of the component.
00418 
00419       @param name the ModelParam tagname
00420       @param value the parameter value, to be parsed
00421       @param flags bitwise-or'ed combination of MC_RECURSE, MC_IGNORE_MISSING
00422 
00423       HISTORICAL NOTE: In the past, subclasses would override
00424       setModelParamString() if they needed special handling when param
00425       values changed, this is no longer the case -- instead subclasses
00426       should override paramChanged(); see additional documentation
00427       there.
00428   */
00429   void setModelParamString(const std::string& name,
00430                            const std::string& value,
00431                            const ModelFlag flags = 0);
00432 
00433   //! Set a parameter value
00434   /*! This is slow, as it will search for the ModelParam by name. If
00435       you need efficient access to ModelParam values, you should
00436       define a wrapper method in your ModelComponent derivative. In
00437       normal operation, indeed, only the methods of the ModelComponent
00438       derivative should directly access the ModelParam, not external
00439       people. Returns true if the ModelParam was found and set. Throws
00440       a fatal error if the ModelComponent was started, to avoid
00441       external people messing around with our ModelParam values during
00442       operation of the component.
00443 
00444       This function will set the param value for ALL matching model
00445       params found in us (and in our subcomponents, if flags contains
00446       MC_RECURSE).
00447 
00448       If the parameter is not found in us (or in any of our
00449       subcomponents, if flags contains MC_RECURSE), this function will
00450       not return (will abort or throw an exception) -- to avoid such
00451       an error, call hasModelParam() first to check that the
00452       particular param exists.
00453 
00454       @param name the ModelParam tagname
00455       @param val the parameter value
00456       @param flags bitwise-or'ed combination MC_RECURSE, MC_IGNORE_MISSING */
00457   template <class T> inline
00458   void setModelParamVal(const std::string& name, const T& val,
00459                         const ModelFlag flags = 0);
00460 
00461   //! Auxiliary implementation function for setModelParamVal()
00462   void setModelParamValAux(const std::string& name,
00463                            const RefHolder& val,
00464                            const ModelFlag flags);
00465 
00466   //! Get a parameter value
00467   /*! Because the parameter may exist both in us and in several of our
00468       subcomponents, we will stop and return the value of the first
00469       instance encountered, searching first in us, then recursively in
00470       our subcomponents (depth-first search, if flags contains
00471       MC_RECURSE), in the order in which they were added.
00472 
00473       If the parameter is not found in us (or in any of our
00474       subcomponents, if flags contains MC_RECURSE), this function will
00475       not return (will abort or throw an exception) -- to avoid such
00476       an error, call hasModelParam() first to check that the
00477       particular param exists.
00478 
00479       It is ok to call this on a started ModelComponent. */
00480   std::string getModelParamString(const std::string& name,
00481                                   const ModelFlag flags = 0) const;
00482 
00483   //! Get a parameter value
00484   /*! This is slow, as it will search for the ModelParam by name. If
00485       you need efficient access to ModelParam values, you should
00486       define a wrapper method in your ModelComponent derivative. In
00487       normal operation, indeed, only the methods of the ModelComponent
00488       derivative should directly access the ModelParam, not external
00489       people. Because the parameter may exist both in us and in
00490       several of our subcomponents, we will stop and return the value
00491       of the first instance encountered, searching first in us, then
00492       recursively in our subcomponents (depth-first search, if flags
00493       contains MC_RECURSE), in the order in which they were added.
00494 
00495       If the parameter is not found in us (or in any of our
00496       subcomponents, if flags contains MC_RECURSE), this function will
00497       not return (will abort or throw an exception) -- to avoid such
00498       an error, call hasModelParam() first to check that the
00499       particular param exists.
00500 
00501       It is ok to call this on a started ModelComponent. */
00502   template <class T> inline
00503   T getModelParamVal(const std::string& name, const ModelFlag flags = 0) const;
00504 
00505   //! Auxiliary implementation function for getModelParamVal()
00506   void getModelParamValAux(const std::string& name,
00507                            RefHolder& val,
00508                            const ModelFlag flags) const;
00509 
00510   //! External request that one of our ModelParam becomes an option
00511   /*! This is to allow external callers to selectively decide that
00512     some of our internal ModelParam parameters should be exported as
00513     command-line options. If recurse is true, will look for the
00514     ModelParam in all our subcomponents, and will link all matching
00515     ModelParam in us and our subcomponents to the option (so that if a
00516     command-line value is provided, it will affect all matching
00517     ModelParam objects in us and all our subcomponents). Will return
00518     false (and generate a warning message if warn is true) if we (or
00519     our subcomponents if recurse is true) don't have a ModelParam of
00520     the specified name. Will generate a fatal error if we have the
00521     ModelParam but no known command-line option exists for that name
00522     in ModelOptionDefs.C. Returns true if the ModelParam was found and
00523     added as a command-line option. Throws a fatal error is we are
00524     started. */
00525   bool doRequestOption(const ModelOptionDef* opt, const bool useMyVal = false,
00526                        const bool recurse = true, const bool warn = true);
00527 
00528   //! External request that we hide a command-line option
00529   /*! In some rare cases (see, e.g., VisualCortexConfigurator), we
00530       want to create a component but avoid exporting some of its
00531       ModelParam members as command-line options. Use with caution,
00532       since the ModelParam still looks and feels like an option, just
00533       the ModelManager will ignore it. This must be called immediately
00534       after construction of the ModelComponent and before
00535       exportOptions() is called (either explicitly or automatically
00536       when the command-line is parsed). Throws a fatal error if
00537       exportOptions() has already been called, we don't have the
00538       option, or we are started. */
00539   void hideOption(const ModelOptionDef* opt);
00540 
00541   //! Return the number of params that we have
00542   size_t getNumModelParams() const;
00543 
00544   //! Get non-const access to the i'th model parameter
00545   const ModelParamBase* getModelParam(size_t i) const;
00546 
00547   //! Get non-const access to the i'th model parameter
00548   ModelParamBase* getModelParam(size_t i);
00549 
00550   //@}
00551 
00552   // ######################################################################
00553   /*! @name ParamMap-based configuration functions */
00554   //@{
00555 
00556   //! Read params from the ParamMap
00557   /*! Throws a fatal error is we are started.
00558       @param noerr will not generate an error message if some of our
00559              parameters do not exist in ParamMap */
00560   void readParamsFrom(const ParamMap& pmap, const bool noerr = true);
00561 
00562   //! Write params to the ParamMap
00563   /*! Prints out a warning message if we are started. */
00564   void writeParamsTo(ParamMap& pmap) const;
00565 
00566   //@}
00567 
00568   // ######################################################################
00569   /*! @name ParamClient interface */
00570   //@{
00571 
00572   //! our parameters will register with us upon construction
00573   /*! override of ParamClient's pure virtual function */
00574   virtual void registerParam(ModelParamBase* mp);
00575 
00576   //! Our parameters will register with us upon construction
00577   /*! @param flags Pass USE_MY_VAL here if you want the current value
00578       of the model param to be taken as the new default value,
00579       otherwise pass 0 for flags. */
00580   virtual void registerOptionedParam(OptionedModelParam* mp,
00581                                      const ParamFlag flags);
00582 
00583   //! our parameters will un-register with us upon destruction
00584   /*! override of ParamClient's pure virtual function */
00585   virtual void unregisterParam(const ModelParamBase* mp);
00586 
00587   //! Called whenever a ModelParamBase has its value changed
00588   /*! Subclasses of ModelComponent should override this function if
00589       they need to do any internal reconfiguration when their
00590       parameters change value (whether due to a command-line option,
00591       or a setModelParamString(), or a readParamsFrom()). See
00592       OrientationChannel::paramChanged() in
00593       Channels/OrientationChannel.C for an example; also see
00594       SaccadeControllerConfigurator::paramChanged() in
00595       Neuro/SaccadeControllers.C for for how to use this to select
00596       subcomponents at runtime.
00597 
00598       @param param the address of the ModelParamBase that changed;
00599              subclasses can compare this with the addresses of their
00600              model param members to figure out which is the relevant
00601              param
00602 
00603       @param valueChanged true if the value actually changed, false if
00604              the value was "set" but the new value is the same as the
00605              old value; some clients may want to avoid re-doing
00606              expensive operations if the value did not actually change
00607 
00608       @param status the subclass that implements paramChanged() should
00609              set *status to CHANGE_REJECTED if it wishes to reject a
00610              particular parameter change; the caller of paramChanged()
00611              is expected to set *status to CHANGE_ACCEPTED prior to
00612              calling paramChanged(), so the implentation of
00613              paramChanged() does not need to set *status
00614              CHANGE_ACCEPTED if it wishes to allow the change since
00615              that will already be the default status
00616 
00617       HISTORICAL NOTE: In the past, subclasses would override
00618       setModelParamString() for this same purpose, but in the new
00619       setup, setModelParamString() is NOT virtual and hence should not
00620       be (cannot be) overridden by subclasses. This setup is cleaner
00621       (and potentially more efficient) because subclasses don't have
00622       to compare string names to figure out which param changed;
00623       instead they are passed the address of the param
00624       itself. Furthermore, the new setup is more robust, since we can
00625       handle param value changes that come from any source (e.g.,
00626       setModelParamVal(), or ModelParamBase::setValString(), or
00627       OModelParam::setVal()), and not just those that come through
00628       setModelParamString().
00629   */
00630   virtual void paramChanged(ModelParamBase* param,
00631                             const bool valueChanged,
00632                             ParamClient::ChangeStatus* status);
00633 
00634   //! Clear our list of command-line options to be exported
00635   void forgetExports();
00636 
00637   //@}
00638 
00639 protected:
00640   //! Set our manager.
00641   void setManager(OptionManager& mgr);
00642 
00643   //! Check if our options have already been exported.
00644   bool hasBeenExported() const;
00645 
00646   //! This is called from within start() before the subcomponents start
00647   virtual void start1();
00648 
00649   //! This is called from within start() after the subcomponents have started
00650   virtual void start2();
00651 
00652   //! This is called from within stop() before the subcomponents stop
00653   virtual void stop1();
00654 
00655   //! This is called from within stop() after the subcomponents have stopped
00656   virtual void stop2();
00657 
00658   //! This is called from within reset() before the subcomponents are reset
00659   virtual void reset1();
00660 
00661   //! This is called from within reset() after the subcomponents are reset
00662   virtual void reset2();
00663 
00664   //! This is called from within save() before the subcomponents save
00665   virtual void save1(const ModelComponentSaveInfo& sinfo);
00666 
00667   //! This is called from within save() after the subcomponents have saved
00668   virtual void save2(const ModelComponentSaveInfo& sinfo);
00669 
00670   //! Default constructor without arguments. DO NOT USE!
00671   /*! This constructor exists only so that we don't have to explicitly
00672     call the parameterized ModelComponent constructor in each and
00673     every object that has a ModelComponent virtual base somewhere in
00674     its inheritance hierarchy. This constructor, however, will leave
00675     the object uninitialized and you must call init() before you can
00676     use the object. Here is what you should do when building an
00677     inheritance hierarchy that has ModelComponent as virtual base: 1)
00678     in the constructor of the class that virtually derives from
00679     ModelComponent, call init(). See for example Channels/ChannelBase;
00680     2) in classes that concretely derive from the latter one, just
00681     construct as usual; see for example Channels/SingleChannel,
00682     Channels/BlueChannel, etc. */
00683   ModelComponent();
00684 
00685   //! Make sure you call this if you have used the default constructor
00686   void init(OptionManager& mgr, const std::string& descrName,
00687             const std::string& tagName, const std::string& crealm = "World");
00688 
00689 private:
00690   class Impl;
00691   Impl* const rep;
00692 };
00693 
00694 // ######################################################################
00695 // #################### INLINED METHODS:
00696 // ######################################################################
00697 
00698 template <class T> inline
00699 void ModelComponent::setModelParamVal(const std::string& name,
00700                                       const T& val,
00701                                       const ModelFlag flags)
00702 {
00703   TRefHolder<const T> ref(val);
00704   return setModelParamValAux(name, ref, flags);
00705 }
00706 
00707 // ######################################################################
00708 template <class T> inline
00709 T ModelComponent::getModelParamVal(const std::string& name,
00710                                    const ModelFlag flags) const
00711 {
00712   T val;
00713   TRefHolder<T> ref(val);
00714   getModelParamValAux(name, ref, flags);
00715   return val;
00716 }
00717 
00718 #endif
00719 
00720 // ######################################################################
00721 /* So things look consistent in everyone's emacs... */
00722 /* Local Variables: */
00723 /* indent-tabs-mode: nil */
00724 /* End: */
Generated on Sun May 8 08:04:42 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3