Main Page   Namespace List   Class Hierarchy   Compound List   File List   Namespace Members   Compound Members   File Members  

neuralregionmap.c

Go to the documentation of this file.
00001 
00007 #include <utility>
00008 
00009 #include "neuralregionmap.h"
00010 #include "matriximage.h"
00011 #include "matrixadapter.h"
00012 #include "imagegrid.h"
00013 #include "ppm_draw.h"      /* Temporary; allows ppm_post_write_hook to be shared. */
00014 #include "globals.h"
00015 #include "worldviews.h"    /* Could probably be eliminated with some juggling */
00016 #include "loopspec.h"
00017 #include "stimulusparametermap.h"
00018 #include "pathspecification.h"
00019 
00020 
00021 #ifdef EXPLICIT_INSTANTIATION_FOR_STATICS
00022 template class Histo::OneDBinList<int,double>;
00023 template class Plot::HSVPixel<Plot::Pixel::FComponent,Plot::Pixel::HueComponent>;
00024 template class ExpressionParser<PointerLookup<Typeless> >;
00025 #endif 
00026 
00027 
00028 /* Workaround for apparent bug in at least egcs-1.1.2, possibly GCC 2.95 as well.
00029    Even with the workaround, .ppm file generation will not work on those
00030    compilers on Windows or DOS machines, because they will put extra linefeed or
00031    newline characters in the output stream
00032 */
00033 #if (__GNUC__ <= 2)
00034 #define BINARY_FILE_FLAGS
00035 #else
00036 #define BINARY_FILE_FLAGS ,std::ios::binary
00037 #endif    
00038 
00039 
00040 
00042 int NeuralRegionMap::ppm_post_write_hook(const char* filename ) const
00043 {
00044   const Tristate spawn       = blackboard.get_with_default("spawn_viewer",True);
00045   const bool     interactive = blackboard.get_with_default("interactive",True);
00046   
00047   if (spawn==True || (spawn==Uninitialized && interactive) ) {
00048     static int spawned_already=False;
00049     const bool     independent   = blackboard.get_with_default("ppm_spawn_independent_viewers",False);
00050     const string   remote_viewer = blackboard.get_with_default("ppm_remote_viewer",string(""));
00051     const string   image_viewer  = blackboard.get_with_default("ppm_image_viewer",string(""));
00052     const bool     remote        = blackboard.get_with_default("running_remotely",False);
00053     
00054     if (!spawned_already || independent) {
00055       const string command =
00056         (remote? remote_viewer : image_viewer) + " " +
00057         filename + " " + (remote? "" : "&");
00058 
00059       system(command.c_str());
00060       spawned_already=True;
00061     }
00062   }
00063   
00064   return 0;
00065 }
00066 
00067 
00071 void ppm_write_to_file(const string& filebase,const Plot::AARImage<>& img)
00072 {
00073   /* Create combined image and save as a PPM file */
00074   const string filename = filebase + ".ppm";
00075   {
00076     std::ofstream os(filename.c_str() BINARY_FILE_FLAGS);
00077     img.ppm_write(os,filename,(unsigned char)(255));
00078   }
00079 }
00080 
00081 
00082 /* Static variables */
00083 string NeuralRegionMap::current_region;
00084 int    NeuralRegionMap::current_width=-1;
00085 int    NeuralRegionMap::current_height=-1;
00086 int    NeuralRegionMap::current_ui=-1;
00087 int    NeuralRegionMap::current_uj=-1;
00088 string NeuralRegionMap::current_plot;
00089 int    NeuralRegionMap::plot_pe=PARENTPE;
00090 
00091 
00097 template <class OutputRectangle, class InputRectangle>
00098 inline OutputRectangle weightbounds_to_subregion(const InputRectangle& r)
00099 {
00100   const typename InputRectangle::Points p=r.corners();
00101   return OutputRectangle(-p.yl,-p.xl,-p.yh-1,-p.xh-1);
00102 }
00103 
00104 
00105 
00107 const string NeuralRegionMap::pe_extension () const {
00108   if (plot_pe==Uninitialized)
00109     return string(".pe")+String::stringrep(MyPE,String::StreamFormat(2,'0'));
00110   return string();
00111 }
00112 
00113         
00114 
00117 const string NeuralRegionMap::filenamebase(const string& plotgroup, const string& suppliedformat) const
00118 {
00119   const string defaultformat  = blackboard.lookup_map("::PlotGroup::" + plotgroup).
00120     get_with_default("filename_format",string(""));
00121   const string filenameformat = (suppliedformat != string("") ? suppliedformat : defaultformat);
00122   const string basename       = Parse(*(params.valueptr()),filenameformat.c_str()).cmds() + pe_extension();
00123   return basename;
00124 }
00125 
00126 
00127 
00137 NeuralRegionMap::RegionManagerList
00138 NeuralRegionMap::retrieve_matching_regions(const string& names_string,
00139                                            Tristate plastic,
00140                                            Tristate internal) const
00141 {
00142   StringParser sp;
00143   StringParser::arglist names;
00144   sp.parse(names_string,names);
00145   const bool all = names.empty();
00146 
00147   /* Dummy one-item list; will iterate over all items as-is instead */
00148   if (all) sp.parse(string("Dummy"),names);
00149   
00150   RegionManagerList result;
00151   for (StringParser::arglist::const_iterator a=names.begin(); a!=names.end(); a++)
00152     for (const_iterator i=begin(); i!=end(); i++) {
00153       RegionManager* item = (*i).second;
00154       if ( (all || String::non_numeric_basename_matches(*a,item->region()->name())) &&
00155            ((internal!=True  ||   item->region()->is_internal() ) &&
00156             (internal!=False || !(item->region()->is_internal())) &&
00157             (plastic!=True   ||   item->region()->is_plastic())   &&
00158             (plastic!=False  || !(item->region()->is_plastic()))))
00159         result.push_back(item);
00160     }
00161 
00162   return result;
00163 }
00164 
00165 
00166 
00168 NeuralRegionMap::RegionManagerList
00169 NeuralRegionMap::retrieve_matching_regions(const ParamMap& params,
00170                                            const string& name_of_regionlist_param,
00171                                            const bool uselimits) const
00172 {
00173   const string regionlist     = params.get_with_default(name_of_regionlist_param.c_str(),string(""));
00174   const Tristate plastic      = (uselimits? params.get_with_default("plastic",Uninitialized)  : Uninitialized);
00175   const Tristate internal     = (uselimits? params.get_with_default("internal",Uninitialized) : Uninitialized);
00176   return retrieve_matching_regions(regionlist, plastic, internal);
00177 }
00178 
00179 
00180   
00181 const bool NeuralRegionMap::gnuplot_image(const ParamMap& argparams,
00182                                           NeuralRegionManager::PlotSpec& plotspec,
00183                                           const string& filebase,
00184                                           const NeuralRegionManager::PlotSpec::MatrixTable* tempmaps,
00185                                           const SpecRegion& subregion) const
00186 {
00187   const Tristate spawn       = argparams.get_with_default("spawn_viewer",True);
00188   const bool     interactive = argparams.get_with_default("interactive",True);
00189 
00190   /* Do a full separate plot if showing interactively (clunky, but
00191   helps encapsulation for now) */
00192   if (spawn==True || (spawn==Uninitialized && interactive) )
00193     plotspec.gnuplot_image("",tempmaps,&subregion);
00194     
00195   /* Plot to get file on disk */
00196   return plotspec.gnuplot_image(filebase,tempmaps,&subregion);
00197 }
00198 
00199 
00209 const NeuralRegionMap::PlotSpecList
00210 NeuralRegionMap::retrieve_matching_plots
00211 (const PlotSpecList::const_iterator& plotsbegin,
00212  const PlotSpecList::const_iterator& plotsend,
00213  const string& names_string) const
00214 {
00215   StringParser sp;
00216   StringParser::arglist names;
00217   sp.parse(names_string,names);
00218   const bool all = names.empty();
00219 
00220   /* Dummy one-item list; will iterate over all items as-is instead */
00221   if (all) sp.parse(string("Dummy"),names);
00222   
00223   NeuralRegionManager::PlotSpecList result;
00224   for (StringParser::arglist::const_iterator a=names.begin(); a!=names.end(); a++)
00225     for (NeuralRegionManager::PlotSpecList::const_iterator i=plotsbegin; i!=plotsend; i++) {
00226       NeuralRegionManager::PlotSpec* item = *i;
00227       if (all || String::non_numeric_basename_matches(*a,item->name()))
00228         result.push_back(item);
00229     }
00230   
00231   return result;
00232 }
00233 
00234 
00235 
00236 
00237 /* This routine should be re-written to be generally valid for any bag
00238    of parameter sets, looking up the value of a list of Tristate
00239    parameters (plastic and internal, for this application) for every
00240    parameter set in the bag, and returning all sets in the bag that
00241    match.
00242 */
00243 cmdstat NeuralRegionMap::cmd_child_set( CMD_ARGS )
00244 {
00245   CMD_ARG_PARAMS(child_set);
00246 
00247   const string   parent    = arglist.next(argparams.get_with_default("parent",string("")));
00248   const string   children  = arglist.next(argparams.get_with_default("children",string("")));
00249   const Tristate plastic   = argparams.get_with_default("plastic",Uninitialized);
00250   const Tristate internal  = argparams.get_with_default("internal",Uninitialized);
00251 
00252   if (parent != "Region") {
00253     message(Msg::Error, "Only a parent of 'Region' is supported at this time");
00254     return CMD_PARAMETER_ERROR;
00255   }
00256 
00257   RegionManagerList regions = retrieve_matching_regions(children, plastic, internal);
00258   for (RegionManagerList::iterator r=regions.begin(); r!=regions.end(); r++) {
00259     StringArgs args(arglist);
00260     cmdparams_set(blackboard.lookup_map("::Region::"+(*r)->region()->name()),
00261                   args,true,true);
00262   }
00263     
00264   return CMD_NO_ERROR;
00265 }
00266 
00267  
00268 
00269 void  NeuralRegionMap::register_params_and_commands( void )
00270 {
00271   ppm_init_hook();
00272   
00273   PARAM_A(blackboard,"internal",Uninitialized,.add_lower_bound(Uninitialized),
00274           "True if a region accepts input from other regions, or False if it does not.\n"
00275           "Often used as a guard (filter) for operations on a list of regions, where if\n"
00276           "specified as True only internal regions are included, if specified False only\n"
00277           "non-internal regions are included, and if unspecified (i.e. Uninitialized) all\n"
00278           "regions are included.");
00279   
00280   PARAM_A(blackboard,"plastic",Uninitialized,.add_lower_bound(Uninitialized),
00281           "True if a region has modifiable weights, or False if it does not.\n"
00282           "Often used as a guard (filter) for operations on a list of regions, where if\n"
00283           "specified as True only plastic regions are included, if specified False only\n"
00284           "non-plastic regions are included, and if unspecified (i.e. Uninitialized) all\n"
00285           "regions are included.");
00286 
00287   CMDOBJ_DOC(plot,"init_network",this,0,"%s [<named_arguments>]* [<plotgroup>]",
00288           "Supported <named_arguments> include:\n"
00289           "<plotgroup>,"
00290           "<filename_format>,"
00291           "<save_matrices>,"
00292           "<gnuplot_plots>,"
00293           "<ppm_plots>,\n"
00294           "<ppm_separate_plots>,"
00295           "<ppm_combined_plots>,"
00296           "<ppm_interior_border>,\n"
00297           "<ppm_histograms>,"
00298           "<ppm_mainplot>.\n\n"
00299 
00300           "Generate a plot of the specified <plotgroup> of items, evaluating the\n"
00301           "<filename_format> to construct the filename (not including the extension,\n"
00302           "e.g. .ppm or .ps).  The only natively-supported <plotgroup> is:\n\n"
00303 
00304           "   Activity\n\n"
00305              
00306           "     Shows activation levels of all the units in each area (including input\n"
00307           "     areas) at the current iteration.  The areas are shown from left to right\n"
00308           "     in the activation_order (which see).   Some areas may define more than\n"
00309           "     one activity plot, e.g. at different timesteps of a recurrent algorithm;\n"
00310           "     if so those timesteps are shown in alphabetical order by name except\n"
00311           "     that Activity is at the end.  Each of the areas may have an associated\n"
00312           "     histogram relating the activity values to another map plot; these appear\n"
00313           "     beneath the associated area plot.\n\n"
00314 
00315           "The command measure_stimulus_map may be used to create other such plots,\n"
00316           "e.g. for OrientationPreference, OrientationSelectivity, OcularPreference,\n"
00317           "etc.\n\n"
00318 
00319           "From zero to several output files will be generated, depending on the values\n"
00320           "of <ppm_plots>, <gnuplot_plots>, and <save_matrices>.\n"
00321              
00322           "If <ppm_plots> is true, the plots are generated as PPM images and saved\n"
00323           "to files.  Many parameters may be set to control the graphing format for\n"
00324           "these files; unfortunately those have not yet been enumerated in a single\n"
00325           "listing.\n\n"
00326 
00327           "If <gnuplot_plots> is true, the plots are generated as PostScript 3D plots\n"
00328           "using gnuplot.  At present only limited functionality is supported with\n"
00329           "gnuplot.  In particular, only the primary dimension will be shown, e.g.\n"
00330           "activity level, without e.g. any color coding for a subplot like\n"
00331           "OrientationPreference.  Each plot is also at present a separate gnuplot\n"
00332           "image; eventually they may be combined into a single plot like the PPM\n"
00333           "plots to facilitate comparison between simultaneous activations.\n\n"
00334 
00335           "If <save_matrices> is true, the plots are generated as ASCII data files\n"
00336           "for each Strength matrix (or Color if no Strength) in a format intended\n"
00337           "to be compatible with GNU Octave, but which should be easily convertible\n"
00338           "to any other program accepting an ASCII matrix.  Read the output files\n"
00339           "(*.matrix) in an editor to see the format (and the data).  To view the\n"
00340           "image in Octave (or, probably, Matlab), you can use the Octave\n"
00341           "commands `load <filename>.matrix ; imagesc(Activity);' (where the\n"
00342           "name Activity will differ depending on the name of the matrix plotted).");
00343   blackboard.lookup_map("::cmd::plot").set_local("plotgroup",string("Activity")); /* Default */
00344 
00345   PARAM_A(blackboard.lookup_map("::cmd"),"ppm_separate_plots",False,.add_lower_bound(False),
00346           "When ppm_plots is true, whether to generate individual image plots for each\n"
00347           "region or set of weights.  At present the individual plots do not spawn\n"
00348           "viewers, regardless of the value of spawn_viewer, because of the quantity\n"
00349           "of windows that would be spawned.  Also see ppm_combined_plots.");
00350 
00351   PARAM_A(blackboard.lookup_map("::cmd"),"ppm_combined_plots",True,.add_lower_bound(False),
00352           "When ppm_plots is true, whether to generate a combined image from all the \n"
00353           "plots for each region or set of weights.  Also see ppm_separate_plots.");
00354 
00355   
00356   CMDOBJ_DOC(plot_unit,"init_network",this,0,"%s [<named_arguments>]* [<ui> <uj>]*",
00357           "Supported <named_arguments> include:\n"
00358           "<colorspec>,"
00359           "<filename_format>,"
00360           "<gnuplot_plots>,"
00361           "<plotgroup>,\n"
00362           "<ppm_border>,"
00363           "<ppm_histograms>,"
00364           "<ppm_interior_border>,\n"
00365           "<ppm_interior_outline>,"
00366           "<ppm_line_*>,"
00367           "<ppm_mainplot>,\n"
00368           "<ppm_master_scale>,"
00369           "<ppm_outline_weights>,"
00370           "<ppm_outline_width>,\n"
00371           "<ppm_page_*>,"
00372           "<ppm_plots>,"
00373           "<ppm_separate_plots>,"
00374           "<ppm_combined_plots>,\n"
00375           "<region>,"
00376           "<verbose>,"
00377           "<weight_bare>,"
00378           "<weight_fill_background>,\n"
00379           "<weight_situate>.\n"
00380           "(Plus others, in all likelihood.)\n\n"
00381              
00382           "Same as plot, but plots single-unit data, e.g. weights, rather than data\n"
00383           "from all regions.  The only <plotgroup> currently supported is Weights.  The\n"
00384           "origin is at the upper left, with <ui> counting downwards and <uj> counting\n"
00385           "to the right.\n\n"
00386              
00387           "The values of each weight are scaled using the globals ppm_weight_scale_type\n"
00388           "and ppm_weight_fixed_multiplier before plotting, even with gnuplot.  Use a\n"
00389           "type of Fixed and a multiplier of 1.0 to see the true values in gnuplot.\n"
00390           "(Or leave those parameters as they are to see how the magnitudes are being\n"
00391           "auto-scaled for the bitmap display).");
00392   blackboard.lookup_map("::cmd::plot_unit")
00393     .set_local("plotgroup",string("Weights"))
00394     .set_local("weight_situate",True)
00395     .set_local("weight_bare",False);
00396   
00397   CMDOBJ_DOC(plot_unit_range,"init_network",this,0,"%s [<named_arguments>]* [<start_r> [<start_c>  [<end_r>  [<end_c> [<ppm_neuron_skip_aff>]]]]]",
00398           "Supported <named_arguments> include:\n"
00399           "<colorspec>,"
00400           "<filename_format>,"
00401           "<gnuplot_plots>,"
00402           "<name>,"
00403           "<plotgroup>,\n"
00404           "<ppm_border>,"
00405           "<ppm_histograms>,"
00406           "<ppm_interior_border>,\n"
00407           "<ppm_interior_outline>,"
00408           "<ppm_line_*>,"
00409           "<ppm_mainplot>,\n"
00410           "<ppm_master_scale>,"
00411           "<ppm_outline_weights>,"
00412           "<ppm_outline_width>,\n"
00413           "<ppm_page_*>,"
00414           "<ppm_plots>,"
00415           "<ppm_separate_plots>,"
00416           "<ppm_combined_plots>,\n"
00417           "<region>,"
00418           "<verbose>,"
00419           "<weight_bare>,"
00420           "<weight_fill_background>,\n"
00421           "<weight_situate>.\n"
00422           "(Plus others, in all likelihood.)\n\n"
00423              
00424           "Same as plot_unit, but plots data (e.g. weights) from a rectangular range of\n"
00425           "units in a region rather than just one.\n\n"
00426              
00427           "The only <plotgroup> currently supported is Weights.  The <name> should\n"
00428           "specify which set of data of the given <plotgroup> to use, e.g. Afferent0.\n"
00429           "A glob pattern (e.g. * or Afferent*) may also be used, to plot multiple\n"
00430           "items side by side, but support for this may change to e.g. a regular\n"
00431           "expression in the future, so do not rely on it.");
00432   blackboard.lookup_map("::cmd::plot_unit_range")
00433     .set_local("plotgroup",string("Weights"))
00434     .set_local("name",string("Afferent0"))
00435     .set_local("ppm_interior_border",1.0)
00436     .set_local("weight_situate",False)
00437     .set_local("weight_bare",True)
00438     .set_local("ppm_master_scale",double(Uninitialized))
00439     .set_local("ppm_histograms",False);
00440   blackboard.lookup_map("::cmd::plot_unit_range")
00441     .lookup("ppm_interior_border").add_default_expr("");
00442 
00443   PARAM_A(blackboard.lookup_map("::cmd"),"verbose",False,.add_lower_bound(False),
00444           "If True, increases the verbosity of the output of a command.");
00445 
00446   CMDOBJ_DOC(save_snapshot,"init_network",this,0,"%s [<named_arguments>]* [<filename>]",
00447           "Supported <named_arguments> include:\n"
00448           "<filename>,<regions>,<plastic>,<internal>,<verbose>.\n\n"
00449              
00450           "Save the current state of the network weights of the specified region(s).\n"
00451           "The binary files are intended to be portable between any machines that use\n"
00452           "the IEEE floating-point format.  When the file is reloaded, load_snapshot\n"
00453           "will assume that it was saved *after* the current iteration had completed,\n"
00454           "which is true when save_snapshot is used directly on the command line or in\n"
00455           "a command file.  If saving indirectly via a hook, you should use the hooklist\n"
00456           "after_learning to be consistent with this assumption.");
00457   blackboard.lookup_map("::cmd::save_snapshot") /* Default arguments, overriding globals */
00458     .set_local("plastic",True);
00459 
00460   PARAM_A(blackboard.lookup_map("::cmd"),"reset",False,.add_lower_bound(False),
00461           "Command argument specifying that internal state maintained across command\n"
00462           "invocations should be reset to its initial value.");
00463 
00464   PARAM_A(blackboard.lookup_map("::cmd"),"horizontal",True,.add_lower_bound(False),
00465           "When printing items from a list, whether to print each on a new line (False)\n"
00466           "or on the same line (True).");
00467 
00468   PARAM_A(blackboard.lookup_map("::cmd"),"label",string(),,
00469           "Command argument: label for printed information.");
00470 
00471   CMDOBJ_DOC(map_statistics,"init_network",this,0, "%s [<named_arguments>]* [<name>]",
00472           "Supported <named_arguments> include:\n"
00473           "<regions>,<plastic>,<internal>,<verbose>,<reset>,<cumulative>,<min_max>,<kurtosis>,<horizontal>,<label>,<name>.\n\n"
00474           
00475           "Computes and displays some statistics about the named map for the given\n"
00476           "region.  The headings can be suppressed (e.g. for multiple calls in a row)\n"
00477           "by setting verbose=False.  If <reset> is true then all internal state\n"
00478           "is reset, e.g. to make an average or cumulative sum be zero again; no\n"
00479           "statistics are printed in that case.  Note that at present cumulative\n"
00480           "values are cumulative over all regions and all maps measured since\n"
00481           "the previous reset, and thus in most cases only a single map should\n"
00482           "be measured when cumulative is true.");
00483   blackboard.lookup_map("::cmd::map_statistics") /* Default arguments, overriding globals */
00484     .set_local("name",string("Activity"))
00485     .set_local("plastic",True);
00486 
00487   PARAM_A(blackboard.lookup_map("::cmd::map_statistics"),"cumulative",False,.add_lower_bound(False),
00488           "Command argument: whether to print cumulative sums or averages.");
00489 
00490   PARAM_A(blackboard.lookup_map("::cmd::map_statistics"),"kurtosis",False,.add_lower_bound(False),
00491           "Command argument: whether to print kurtosis.");
00492 
00493   PARAM_A(blackboard.lookup_map("::cmd::map_statistics"),"min_max",False,.add_lower_bound(False),
00494           "Command argument: whether to print min and max values.");
00495 
00496 
00497   CMDOBJ_DOC(backproject,"init_network",this,0,"%s [<named_arguments>]* [<name>]",
00498           "Supported <named_arguments> include: <verbose>.\n\n"
00499 
00500           "Backproject current activity back to upstream regions through the\n"
00501           "incoming connection weights.\n");
00502   blackboard.lookup_map("::cmd::backproject") /* Default arguments, overriding globals */
00503     .set_local("name",string("Activity"));
00504 
00505 #ifdef OBJ_LISSOM
00506   CMDOBJ_DOC(resp_to_residual,"init_network",this,0,"%s [<name>]",
00507         "Computes the input response to the residual of upstream activity.\n"
00508         "(use with OBJ-LISSOM)");
00509 
00510   CMDOBJ_DOC(train_obj_weights,"init_network",this,0,"%s [<name>]",
00511         "Modifies weights in OBJ-LISSOM.  Should call backproject and resp_to_residual\n"
00512         "just before calling this command.");
00513 
00514   CMDOBJ_DOC(randomize_lat_wts,"init_network",this,0,"%s [<name>]",
00515         "Replace all of the lateral weights with random values, as a test of\n"
00516         "OBJ-LISSOM.\n\n");
00517 #endif /* OBJ_LISSOM */
00518 
00519   CMDOBJ_DOC(kill_connections,"init_network",this,0, "%s [<named_arguments>]*",
00520           "Supported <named_arguments> include:\n"
00521           "<regions>,<plastic>,<internal>,<verbose>.\n\n"
00522           
00523           "Prunes connections in each specified region (defaulting to all plastic\n"
00524           "regions) if they are at or below the values of their corresponding\n"
00525           "inh_death, exc_death, etc.");
00526   blackboard.lookup_map("::cmd::kill_connections") /* Default arguments, overriding globals */
00527     .set_local("plastic",True);
00528   
00529   CMDOBJ_DEFINE_CATCHUP(this,0,child_set,
00530           "%s [<constraints>]* <parent> <children> [<path>=<value>]*",
00531                         
00532           "This command is the same as the general set command, except that it\n"
00533           "can be limited to a subset of paths representing the children of a given\n"
00534           "set of parameters.  It can do so without specifying the actual names of\n"
00535           "those children, which may not be known ahead of time or easily enumerable.\n"
00536           "It is also a handy way to apply a set of a parameters to an enumerated\n"
00537           "subset of children.\n\n"
00538              
00539           "At present the only <parent> supported is 'Region', and thus the <children>\n"
00540           "are also <regions>.  For Region the supported <constraints> include:\n"
00541           "<plastic>,<internal>.\n\n"
00542           
00543           "The given list of names of <children> of the parameter set <parent>\n"
00544           "(which may be '' to specify all children) is first subjected to the\n"
00545           "given constraints, if any, to determine a list of regions.  (See the\n"
00546           "<plastic> and <internal> parameters for more information.)  The given\n"
00547           "parameters are then set to the given values in every child in that\n"
00548           "list.  The <path>s are relative to each child; a parameter name\n"
00549           "usually suffices.  Example:\n\n"
00550           
00551           "  child_set plastic=True Region '' colorspec=Grayscale");
00552   blackboard.lookup_map("::cmd::child_set") /* Default arguments, overriding globals */
00553     .set_local("verbose",True);
00554           
00555   PARAM_A(blackboard.lookup_map("::cmd"),"children",string(""),,
00556           "Command argument for a list of the names of children, e.g. of a set of\n"
00557           "parameters.  Specified names may omit trailing digits, which will select\n"
00558           "all items matching up to the digits, in the order of their creation.  \n"
00559           "(E.g. 'Eye' will match 'Eye0', 'Eye1', etc.)");
00560   
00561   CMDOBJ_DOC(define_plot,"init_network",this,0,"%s [<named_arguments>]* [<strength_map> [<color_map> [<confidence_map>]]]",
00562           "Supported <named_arguments> include:\n"
00563           "<plotgroup>,<name>,<regions>,<filename_format>,<plastic>,<internal>.\n\n"
00564           
00565           "Define a new plot for use with the plot command.\n\n"
00566           
00567           "The <name> of this plot defaults to the name of the first non-empty map\n"
00568           "name specified; this default value can be overridden with an explicit\n"
00569           "<name> if desired.  The <plotgroup> in turn defaults to the <name>, and\n"
00570           "it too can be overridden (e.g. to combine multiple plots into a single\n"
00571           "<plotgroup>).  If the <plotgroup> (whether specified or deduced) does not\n"
00572           "already exist, it is created, in which case you might also want to specify\n"
00573           "a <filename_format> to override the default format (which is constructed\n"
00574           "from the filebase, iteration number, presentation number, and <plotgroup>).\n\n"
00575           
00576           "The <*_map> parameters specify the name of a registered map, e.g. Activity,\n"
00577           "or '' if none is desired for that quantity.  The <strength_map> is usually\n"
00578           "the primary dimension, and is colored according to the <color_map> (if\n"
00579           "present).  (Note that <color_map> is not a computer-graphics-style\n"
00580           "colormap, i.e. a mapping from a value into a color; rather it is a matrix\n"
00581           "of values to use for the Hue component of the image.)  The strength of the\n"
00582           "colors will be determined by the <confidence_map>.  The specific colors\n"
00583           "used can be determined by setting appropriate parameters in\n"
00584           "PlotGroup::<plotgroup>::*; see the plot command for more details.\n\n"
00585           
00586           "The plot is defined for all regions by default, but an explicit list of\n"
00587           "regions may be supplied as the <regions> parameter.  This list (or the\n"
00588           "default of all regions) is further limited to plastic or non-plastic\n"
00589           "regions if <plastic> is True or False, and/or to internal or external\n"
00590           "regions only (regions which can or cannot accept input from other\n"
00591           "regions) if <internal>is True or False.\n\n"
00592           
00593           "Once the plot has been defined, you may obtain a plot via\n"
00594           "'plot <plotgroup>'.");
00595   PARAM_A(blackboard.lookup_map("::cmd"),"regions",string(""),,
00596           "Command argument for a list of the names of neural regions, in order.  If\n"
00597           "empty, all regions will be used, in the order they were defined.  Specified\n"
00598           "names may omit trailing digits, which will select all regions matching up to\n"
00599           "the digits, in the order of their creation.  (E.g. 'Eye' will match 'Eye0',\n"
00600           "'Eye1', etc.)");
00601   
00602   CMDOBJ_DOC(measure_stimulus_map,"init_network",this,0,
00603           "%s [<named_arguments>]* <presentation-command> [<dimension_spec>]*",
00604           "Supported <named_arguments> include:\n"
00605           "<regions>, <plastic>, and <internal> (as well as any of the\n"
00606           "<named_arguments> from the <dimension_spec>, below, which if specified\n"
00607           "here apply as defaults for all dimensions.)\n\n"
00608 
00609           "Computes maps of preferences for specified input patterns.  To measure the\n"
00610           "data required, this command calls the <presentation-command> multiple times,\n"
00611           "systematically varying the specified parameters (and thus the input patterns)\n"
00612           "and recording the responses of each unit in each region.  The\n"
00613           "<presentation-command> is typically input_present_object or a variant, but\n"
00614           "may be any valid command.\n\n"
00615              
00616           "A <dimension_spec> has the form:\n"
00617           "\"[<named_arguments>]* [<name> [<divisions>]]\",\n"
00618           "where any of the following <named_arguments> may be used:\n"
00619           "<cyclic>, <discrete_inputs>, <divisions>, <measure_distribution>,\n"
00620           "<name>, <num_bins>, <register>, <valuegenerator>,\n"
00621           "<varname>, and <weighted_average>.\n\n"
00622 
00623           "Each <dimension_spec> specifies one dimension of input variance, e.g.\n"
00624           "orientation or spatial frequency, of which an arbitrary number can be\n"
00625           "supplied.  All possible combinations of all values of each dimension\n"
00626           "will be tested, and the set of parameter values which generated the\n"
00627           "maximum response will be stored. From these stored peak values the maps\n"
00628           "will be constructed, using one of a variety of methods determined by the\n"
00629           "<named_arguments> for the dimension (which see).\n\n"
00630 
00631           "For each dimension, a global Param_Float parameter ranging from 0.0 to\n"
00632           "1.0 must be defined before this call, using the same <name> as this\n"
00633           "dimension (although if desired a different name for this parameter may\n"
00634           "be specified as <varname>).  By default, the full range of possible\n"
00635           "values for this parameter from 0.0 to 1.0 will be divided into\n"
00636           "<divisions> equally-spaced portions, and inputs will be presented\n"
00637           "with parameter values set to the boundaries of these divisions.\n\n"
00638 
00639           "The <presentation-command> will generally compute the actual input\n"
00640           "parameter values as a function of the normalized value of each dimension.\n"
00641           "E.g., an orientation might be computed from the dimension named Orientation\n"
00642           "as theta=2*PI*Orientation.  This uniformly normalized approach was taken to\n"
00643           "ensure that the underlying map computation is independent of the scale\n"
00644           "and type of transformation, which makes it possible to use the same\n"
00645           "algorithm for both linear and non-linear or discontinuous transformations.\n\n"
00646              
00647           "Responses are computed and stored for each region specified in <regions>,\n"
00648           "which is all regions by default.  By default, the list of regions (whether\n"
00649           "default or specified) is limited to those with modifiable connections (to\n"
00650           "avoid wasting computation time); this default may be overridden by supplying\n"
00651           "Uninitialized for <plastic>.  The list of regions may also be limited to\n"
00652           "internal regions only by supplying True for <internal>.\n\n"
00653 
00654           "When this command completes, maps for each specified region\n"
00655           "and for each dimension for which <register> is true are computed and\n"
00656           "registered under the names \"<name>Preference\" and (if\n"
00657           "<measure_distribution> is true) \"<name>Selectivity\".  For instance,\n"
00658           "if <name> is 'Orientation', maps will be created with the names\n"
00659           "'OrientationPreference' and (possibly) 'OrientationSelectivity' for\n"
00660           "each specified region.  The Selectivity maps range from 0 to 1.0, i.e.\n"
00661           "no selectivity (response was the same to all parameter values) to\n"
00662           "complete selectivity (neuron responded to only one parameter value).\n"
00663           "The method used to calculate the selectivity depends on whether the\n"
00664           "dimension is <cyclic>; see <weighted_average> for more details.\n\n"
00665 
00666           "Once the maps are registered, they may then be plotted by calling\n"
00667           "define_plot using these names, and then plot.  For instance, the maps\n"
00668           "created for the dimension named 'Orientation' can be plotted using:\n"
00669 
00670           "define_plot plastic=True plotgroup=OrMap '' OrientationPreference\n"
00671           "define_plot plastic=True plotgroup=OrMap    OrientationSelectivity\n"
00672           "plot OrMap");
00673   PARAM_A(blackboard.lookup_map("::cmd::measure_stimulus_map"),"discrete_inputs",True,.add_lower_bound(False),
00674           "Truncate the value for this parameter to be one of the discrete values 0 to\n"
00675           "<num_bins>.  This can be useful when generating random or continuous values, to\n"
00676           "ensure that the value of stimulus parameter corresponds precisely to the bin in\n"
00677           "which its response will later be placed for measurement purposes.  Usually set\n"
00678           "to True, but there may be some circumstance in which this is undesirable.");
00679   PARAM_A(blackboard.lookup_map("::cmd"),"divisions",1,.add_lower_bound(0),
00680           "The number of divisions to use for a dimension, e.g. for measure_stimulus_map.\n"
00681           "If the dimension is cyclic, this value is the same as the number of actual\n"
00682           "stimulus presentations that will be used; otherwise the number of presentations\n"
00683           "is one more than the number of divisions because of the boundary condition at\n"
00684           "1.0. The higher the number of divisions, the better the sampling, but the more\n"
00685           "presentations (and therefore time) will be required.");
00686   PARAM_A(blackboard.lookup_map("::cmd::measure_stimulus_map"),"measure_distribution",True,.add_lower_bound(False),
00687           "When measuring a preference map, whether to store a distribution of the\n"
00688           "maximal responses for the different values for this dimension, or just the\n"
00689           "single set of parameters that caused the peak response for this unit.\n"
00690           "Computing and storing the full distribution does not generally take much\n"
00691           "computation time, but it does take memory. The distribution is required\n"
00692           "for calculating selectivity and for <weighted_average> map computation\n"
00693           "types.");
00694   PARAM_A(blackboard.lookup_map("::cmd"),"num_bins",0,.add_lower_bound(-1),
00695           "When measure_distribution is true in measure_stimulus_map, how many\n"
00696           "distinct values of the parameter to keep track of, i.e. the number of\n"
00697           "bins to use in the histogram.  Higher values give more precision, but\n"
00698           "take more memory and slightly more time.  The default is the total number\n"
00699           "of presentations, which for the default equally-spaced parameter values\n"
00700           "provides exactly enough precision to represent all of the information\n"
00701           "that can be obtained.  For non-evenly-spaced parameter values (e.g. using\n"
00702           "a Random <valuegenerator>), increasing num_bins from this default may be\n"
00703           "appropriate.  In such cases, unless num_bins is quite large, you will\n"
00704           "probably want to enable discrete_inputs.");
00705   PARAM_A(blackboard.lookup_map("::cmd::measure_stimulus_map"),"register",True,.add_lower_bound(False),
00706           "For a dimension specified when measuring a preference map, whether to compute\n"
00707           "and register a map showing the preferences for that dimension.  (Often\n"
00708           "dimensions will be included just to ensure good coverage of possible stimuli,\n"
00709           "without each one necessarily being useful to graph.)");
00710   PARAM_A(blackboard.lookup_map("::cmd::measure_stimulus_map"),"selectivity_scale",1.0,,
00711           "Multiplier applied to the selectivity before it is returned as a map.  This\n"
00712           "defaults to 1.0, but can be set to other values to simplify the use of\n"
00713           "selectivity as part of combined plots; the scaling should leave the typical\n"
00714           "or useful values for selectivity in the range 0 to 1.0.");
00715   PARAM_A(blackboard.lookup_map("::cmd::measure_stimulus_map"),"weighted_average",False,.add_lower_bound(False),
00716           "If maximum response distribution information is available\n"
00717           "(measure_distribution is True), compute preference map from a weighted\n"
00718           "average of the values of each bin in the distribution, rather than simply\n"
00719           "using the actual value of the parameter for which response was maximal (the\n"
00720           "default, discrete method).  Such a computation will generally produce much\n"
00721           "more precise maps using fewer test stimuli than the discrete method.\n"
00722           "However, weighted_average methods generally require uniform sampling, as\n"
00723           "described below, which is not always desirable.\n\n"
00724 
00725           "Because of differences in how the averaging needs to be done near the\n"
00726           "borders of the parameter range, different methods are used depending on\n"
00727           "whether the parameter (dimension) is cyclic or not.  If this dimension is\n"
00728           "non-cyclic (cyclic=False), the weighted_average is computed as the center\n"
00729           "of gravity of the distribution, i.e. the arithmetic mean of the product of\n"
00730           "each bin's value and its bin number, over the total value of the bins.  The\n"
00731           "selectivity is then computed from the value of the bin with the largest\n"
00732           "value, divided by the total value of all of the bins; it is then scaled to\n"
00733           "range from 0.0 (no differences between bins) to 1.0 (only a single bin is\n"
00734           "nonzero).\n\n"
00735 
00736           "If this dimension is cyclic, the preference is computed as the direction of\n"
00737           "a vector sum.  The vectors in the sum have as their length the maximum\n"
00738           "response at each of the num_bins possible values, with their direction\n"
00739           "determined by the bin number (on a scale 0..1.0 transformed into 0..2*PI).\n"
00740           "The selectivity is then the length of the vector sum; it is zero if all bins\n"
00741           "have equal values, and 1.0 if only one bin has a nonzero value.\n\n"
00742 
00743           "For measurements at evenly-spaced intervals over the full range of possible\n"
00744           "parameter values, weighted_averages are a good measure of the underlying\n"
00745           "continuous-valued parameter preference, assuming that neurons are tuned\n"
00746           "broadly enough (and/or sampled finely enough) that they respond to at least\n"
00747           "two of the tested parameter values.  This method will not usually give good\n"
00748           "results when those criteria are not met, i.e. if the sampling is too sparse,\n"
00749           "not at evenly-spaced intervals, or does not cover the full range of possible\n"
00750           "values.  Thus a weighted_average measurement should not ordinarily use a\n"
00751           "random <valuegenerator>, and will probably not be useful with other\n"
00752           "ValueGenerator types either.  If using a ValueGenerator with a\n"
00753           "weighted_average; be sure to check that all of the possible num_bins values\n"
00754           "are equally represented in the set of testing stimuli, e.g. by setting\n"
00755           "display=True in the <presentation_command>.");
00756   PARAM_A(blackboard.lookup_map("::cmd::measure_stimulus_map"),"valuegenerator",string(""),,
00757           "Usually each stimulus dimension will just increase uniformly and monotonically\n"
00758           "from 0 to 1.0, in which case this parameter is not needed.  However, if you\n"
00759           "prefer random values to avoid sampling biases, or perhaps want some other\n"
00760           "distribution, you can specify any ValueGenerator (see input_define_generator)\n"
00761           "here instead.  For instance, to use a random value each time, use\n"
00762           "'Random 0.5 0.5'.  See also num_bins; for random distributions you will\n"
00763           "probably want more than the default num_bins in the plot.");
00764   PARAM_A(blackboard.lookup_map("::cmd::measure_stimulus_map"),"varname",string(""),,
00765           "Usually a variable with the same name as this dimension will be set to the\n"
00766           "value of the dimension's parameter at each iteration.  If you have defined\n"
00767           "a different variable name and want to use it instead, specify its name here.\n"
00768           "Note that the variable must still be a Param_Float ranging from 0 to 1.0\n"
00769           "as for the default case.\n\n"
00770 
00771           /* Might want to relax this limitation, or otherwise clean up how the parameter
00772              value is communicated to the <presentation_command>. */
00773           "Note that at present the parameter (whether default or specified explicitly\n"
00774           "here) must be in the global namespace, because the variable values are\n"
00775           "updated by setting the parameter in that namespace to make it available\n"
00776           "to the <presentation_command>.");
00777   blackboard.lookup_map("::cmd::measure_stimulus_map") /* Default arguments, overriding globals */
00778     .set_local("plastic",True);
00779 
00780   /* Set up default filename formats */
00781   PARAM_A(blackboard,"filename_format",string(""),,
00782           "String expression for a filename to use for a generated file.  It will\n"
00783           "be evaluated before each use, and may thus contain references to other\n"
00784           "parameters.  Ordinarily, the global value be \"\", which means that\n"
00785           "the value set for the appropriate PlotGroup (<plotgroup>) will be\n"
00786           "used.  Alternatively, you can force all plots to have the same filename_format\n"
00787           "(presumably one using multiple string substitutions) by defining this\n"
00788           "parameter at the root level.");
00789 
00790   PARAM_A(blackboard,"default_filename_format",
00791           string("${filebase}.${06iteration}p${03presentation}.${current_region}${?current_region,_}${current_plot}"),,
00792           "The filename_format used for new PlotGroups (see define_plot and\n"
00793           "define_plotgroup).  Also useful to override one defined for a particular\n"
00794           "type of plot, by supplying filename_format=$${default_filename_format} when\n"
00795           "calling a command.");
00796   
00797 
00798   /* Declare a ParamMap for each plot group so that we can set the
00799      default filenames.  New plotgroups can be defined dynamically, but
00800      for now we pre-set these default filenames here for
00801      compatibility.  Eventually specific ones like
00802      OrientationPreference and OcularPreference should move to a
00803      command file that collects that data. */
00804   blackboard.new_child("PlotGroup", true); /* Create branch in tree for PlotGroups */
00805   define_plotgroup("Activity"             ,"${filebase}.${06iteration}.${03current_object_angle}p${01presentation}");
00806   define_plotgroup("Weights"              ,"${filebase}.${06iteration}.wts.${03current_ui}_${03current_uj}");
00807   define_plotgroup("OrientationPreference","${filebase}.${06iteration}.or");
00808   define_plotgroup("OcularPreference"     ,"${filebase}.${06iteration}.od");
00809   define_plotgroup("WeightsMap"           ,"${filebase}.${06iteration}.aff_map${input_current_eye}");
00810   define_plotgroup("Backprojection"       ,"${filebase}.${06iteration}.bp.p${01presentation}");
00811 
00812   /* Not usually true PlotGroups, but useful places to store parameters nonetheless*/
00813   define_plotgroup("Histogram"); 
00814   define_plotgroup("SavedState"           ,"${filebase}.${06iteration}.wts");
00815 
00816   
00817   /* Declare parameters specific to Regions */
00818   ParameterMap<>& regionparams = *dynamic_cast< ParameterMap<>* >(params.valueptr());
00819   
00820   PARAM_A(regionparams,"activation_order",string("Eye Ganglia LGN Primary Secondary Association Frontal"),,
00821           "List of each neural region in the order in which they should be activated\n"
00822           "when new input is computed.  Also determines activity plot order.  If empty,\n"
00823           "all regions will be activated or plotted, in the order they were defined.");
00824 
00825   PARAM_A(regionparams,"connection_order",string("Afferent AfferentExcitatory AfferentInhibitory Lateral LateralExcitatory LateralInhibitory Efferent EfferentExcitatory EfferentInhibitory Feedback FeedbackExcitatory FeedbackInhibitory"),,
00826           "List of each type of connection in the order in which they should be plotted\n"
00827           "by plot_unit.  If empty, all connections will be plotted, in the order they\n"
00828           "were defined.");
00829 
00830   PARAM_A(regionparams,"ppm_weight_fixed_multiplier",500.0,.add_lower_bound(0.0),
00831           "Amount by which to multiply weight values to get luminance value for\n"
00832           "plots, when ppm_weight_scale_type=PPM_WtScale_Fixed.");
00833 
00834   PARAM_A(regionparams,"ppm_weight_fixed_offset",0.0,,
00835           "Amount which to add to weight values to get luminance value for\n"
00836           "plots, when ppm_weight_scale_type=PPM_WtScale_Fixed.");
00837 
00838   PARAM_A(regionparams,"colorspec",string("RYW"),,
00839           "Specification for a color lookup function to use for a plot of a single\n"
00840           "dimension.  The function returns a color when given a single quantity in\n"
00841           "the range 0.0 to 1.0, here called a level.\n\n"
00842 
00843           "The <colorspec> can be one of the named colormaps below, or it can specify\n"
00844           "a list of characters corresponding to colors between which to interpolate.\n"
00845           "(Interpolation is performed linearly in RGB space.)  Available colors include:\n\n"
00846         
00847           "  R Red\n"
00848           "  Y Yellow\n"
00849           "  G Green\n"
00850           "  C Cyan\n"
00851           "  B Blue\n"
00852           "  M Magenta\n"
00853           "  K Black\n"
00854           "  W White\n\n"
00855 
00856           "Use a lowercase letter to indicate that a color should use half intensity.\n"
00857           "For instance, a <colorspec> of 'KgYW' would map the level range 0.0->1.0\n"
00858           "to the color range black->dark green->yellow->white, with smooth\n"
00859           "interpolation between the specified colors.\n\n"
00860 
00861           
00862           "Predefined named <colorspec>s include:\n\n"
00863           
00864           "Cold\n"
00865           "  Bright cool colors based on blue and cyan.  Same as KBCW, or WBC for\n"
00866           "  ppm_paper_based_colors.\n\n"
00867           
00868           "Cool\n"
00869           "  Cool colors based on blue and cyan.  Same as KBC, or WbBC for\n"
00870           "  ppm_paper_based_colors.\n\n"
00871 
00872           "Warm\n"
00873           "  Warm colors based on red and yellow.  Same as KRY, or WrRY for\n"
00874           "  ppm_paper_based_colors.\n\n"
00875             
00876           "Hot\n"
00877           "  Bright warm colors based on red and yellow.  Useful for emphasizing\n" 
00878           "  peak values, particularly on video terminals.  Same as KRYW, or WRY for\n"
00879           "  ppm_paper_based_colors.  \n\n\n" 
00880 
00881           
00882           "CoolWarm\n"
00883           "  Uses a Cool <colorspec> for negative excursions from the middle of the\n"
00884           "  range, and a Warm <colorspec> for positive excursions.  Useful for\n"
00885           "  highlighting changes in either direction relative to a prevailing\n"
00886           "  background level of 0.5.  For paper_based_colors, blob outlines are\n"
00887           "  somewhat jagged because of the sharp transition from the colors to white.\n"
00888           "  Same as CBKRY, or CBbWrRY for ppm_paper_based_colors.\n\n"
00889             
00890           "ColdHot\n"
00891           "  Uses a Cold <colorspec> for negative excursions from the middle of the\n"
00892           "  range, and a Hot <colorspec> for positive excursions.  Useful for\n"
00893           "  highlighting changes in either direction relative to a prevailing\n"
00894           "  background level of 0.5.  For ppm_paper_based_colors==False, the extremes\n"
00895           "  are both white, which can be confusing unless the underlying\n"
00896           "  parameter is cyclic.  Same as WCBKRYW, or CBWRY for ppm_paper_based_colors.\n\n"
00897 
00898           "BlueRed\n"
00899           "  Uses blue colors for negative excursions from the middle of the\n"   
00900           "  range, and red colors for positive excursions.  Useful for\n"
00901           "  highlighting changes in either direction relative to a prevailing\n"
00902           "  background level.  Same as BKR, or BWR for ppm_paper_based_colors.\n\n\n"
00903 
00904 
00905           "In addition to the above named abbreviations for interpolated colormaps,\n"
00906           "several other specific types based on the hue, saturation, and value are\n"
00907           "available:\n\n"
00908           
00909           "Hue [saturation [value]]\n"
00910           "  Useful for plotting cyclic quantities, such as orientation.\n"
00911           "  The hue is computed from the level, and is combined with the given fixed\n"
00912           "  saturation and value (default '1.0 1.0') to determine the color.  The hue\n"
00913           "  wraps around at each end of the range (e.g. red->yellow->green->blue->magenta\n"
00914           "  ->red), and thus is usually appropriate only when the quantity plotted has\n"
00915           "  that same property.  For the defaults, nearly identical to RYGCBMR.\n\n"
00916 
00917           "Saturation [hue [value]]\n"
00918           "  Usually SpecifiedHue is used instead of specifying this type directly.\n"
00919           "  The saturation is computed from the level, and is combined with the given\n"
00920           "  fixed hue and value (default '0.0 1.0') to determine the color.\n\n"
00921 
00922           "Value [hue [saturation]]\n"
00923           "  Usually Grayscale is used instead of specifying this type directly.\n"
00924           "  The value is computed from the level, and is combined with the given fixed\n"
00925           "  hue and saturation (default '0.0 0.0') to determine the color.  The defaults\n"
00926           "  result in a range of grayscale values from black to white; the optional\n"
00927           "  arguments allow other colors to be used instead of gray.\n"
00928           "  For the defaults, nearly identical to KW.\n\n"
00929 
00930           "Grayscale [hue [saturation]]\n"
00931           "  Useful for monochrome displays or printers, or to show photographs.\n"
00932           "  Same as Value but the scale is flipped when ppm_paper_based_colors=True.\n"
00933           "  This makes the most-active areas show up with the intensity that is most\n"
00934           "  visible for the given medium (video or paper).  For the defaults, nearly\n"
00935           "  identical to KW, or WK for ppm_paper_based_colors.\n\n"
00936 
00937           "SpecifiedHue [hue [confidence]]\n"
00938           "  Useful for color-coding a plot with a specific hue visible on the default\n"
00939           "  background. For paper_based_colors=False, same as ValueColorLookup;\n"
00940           "  the confidence is used as the saturation.  Such a plot works well for\n"
00941           "  showing color on a black background.  For paper_based_colors==True,\n"
00942           "  returns the specified hue masked by the specified confidence, such\n"
00943           "  that low values produce white, and high values produce black for low\n"
00944           "  confidences and the specified hue for high confidences.  Such a plot\n"
00945           "  is good for showing colors on light backgrounds.\n\n"
00946 
00947           "MapSpecifiesHue [nameofhuemap [nameofconfidencemap]]\n"
00948           "  Neural-region-specific variant of SpecifiedHue where these colorspec\n"
00949           "  arguments specify not the actual hue and confidence, but the names of\n"
00950           "  registered maps (as in define_plot) in which to look up the hue and\n"
00951           "  confidence when plotting.  This colorspec can be used by plot_unit or\n"
00952           "  plot_unit_range to colorize a plot based on some property of a unit;\n"
00953           "  it is not supported in other contexts.  Examples:\n"
00954           "  Region::Eye0::Afferent0::colorspec='MapSpecifiesHue OrientationPreference OrientationSelectivity'\n"
00955           "  Region::Ganglia*::Afferent*::colorspec='MapSpecifiesHue OrientationPreference OrientationSelectivity\n\n"
00956           
00957           "SpecifiedColor [hue [saturation [value]]]\n"
00958           "  Used to turn off color ranges, e.g. for a plot whose shape is more\n"
00959           "  important than the intensity of each pixel, such as a histogram.  Ignores\n"
00960           "  the level, and always returns the single given fixed color.  The default\n"
00961           "  color is a medium gray: '0.0 0.0 0.5'.  For the defaults, nearly identical\n"
00962           "  to 'w'.");
00963 
00964 #define PARAM_ARO(bboard,name_str,initial_value,options,doc)\
00965 PARAM_A(bboard,name_str,initial_value,options,doc);\
00966 bboard.lookup(name_str).add_setfn(new setfnobj2_read_only_param_setfn2())
00967 
00968   PARAM_ARO(regionparams,"type",string(),,
00969           "Reports the type of this region.");
00970 
00971   PARAM_A(regionparams,"height",0,.add_lower_bound(0),
00972           "Reports the number of units in each column of a region.");
00973   
00974   PARAM_A(regionparams,"width",0,.add_lower_bound(0),
00975           "Reports the number of units in each row of a region.");
00976 
00977   PARAM_A(regionparams,"xoffset",0.5,,
00978           "Reports the horizontal position of the origin of this region.");
00979 
00980   PARAM_A(regionparams,"yoffset",0.5,,
00981           "Reports the vertical position of the origin of this region.");
00982 
00983 
00984   PARAM_A(regionparams,"histo_name",string("OrientationPreference"),,
00985           "When computing a histogram, the name of the map to use when determining the\n"
00986           "bin to which a given unit belongs.  At present, the Strength::name for the\n"
00987           "plot which a given histogram accompanies is used for the bin value.");
00988 
00989   PARAM_A(regionparams,"histo_colorspec",string("Hue"),,
00990           "Same as colorspec but specific to histogram plots.  If this parameter is\n"
00991           "not an empty string, its value is used instead of the value of colorspec\n"
00992           "for a histogram.  (Without it, it would be difficult to set the colorspec\n"
00993           "default for all histograms.)");
00994 
00995   PARAM_A(regionparams,"num_bins",36,.add_lower_bound(0),
00996           "Number of bins to use in histogram plots.");
00997 
00998   PARAM_A(blackboard,"cyclic",True,.add_lower_bound(False).add_upper_bound(True),
00999           "Whether this range or quantity is cyclic, i.e. has upper and lower bounds\n"
01000           "that are identical (like orientation or hue).  Being (or not being) cyclic\n"
01001           "is usually most important when we must obtain a number within a specified\n"
01002           "range, when given one that may fall outside of it.  If the range is cyclic,\n"
01003           "the values will wrap around to get a result in range; otherwise they will be\n"
01004           "cropped at the ends of the range.  It can also affect whether bounds are\n"
01005           "considered exclusive (appropriate for cyclic ranges) or inclusive\n"
01006           "(appropriate for non-cyclic ranges).");
01007 
01008   PARAM_A(regionparams,"range_end",0.25,.add_lower_bound(0),
01009           "Upper bound of a 1-dimensional range, e.g. for histogram values.");
01010 
01011   PARAM_A(regionparams,"reference",string(),,
01012           "In general, the name of an object to use as a reference.  For a map plot,\n"
01013           "the name of a map (in the form region::mapname) to subtract from the current\n"
01014           "Strength map before plotting.");
01015 
01016   PARAM_A(regionparams,"vertical",False,.add_lower_bound(False).add_upper_bound(True),
01017           "Determines the orientation of some types of plots, e.g. histograms.  If true,\n"
01018           "the image is oriented with the long direction vertically.");
01019 
01020   PARAM_A(regionparams,"aspect_ratio",0.25,.add_lower_bound(0),
01021           "Determines the aspect ratio for some types of plots, e.g. histograms.  For a\n"
01022           "histogram, the aspect ratio is the ratio between the number of bins and the\n"
01023           "length of the representation to use for the bin fullnesses.");
01024 
01025 
01026   PARAM_A(blackboard,"name",string(""),,
01027           "A name, as a string.  This parameter is used as an argument for commands\n"
01028           "and for e.g. specifying a name for some part of a Region.");
01029 
01030   PARAM_A(blackboard,"value_offset",0.0,,
01031           "Offset for a strength or value, e.g. an activity level, as opposed to a\n"
01032           "size_scale.  See also value_scale.");
01033 
01034   PARAM_A(blackboard,"value_scale",1.0,,
01035           "Scale for a strength or value, e.g. an activity level, as opposed to a\n"
01036           "size_scale.  See also value_offset.");
01037 
01038   PARAM_A(blackboard,"size_scale",1.0,.add_lower_bound(0.0),
01039           "Scale intended to specify distance or size across the surface of a map,\n"
01040           "as opposed to a value_scale.  Most uses of this parameter are overridden\n"
01041           "by ppm_master_scale, which see.\n");
01042 
01043   PARAM_A(blackboard,"start_c",-1,.add_lower_bound(-1),
01044           "Number of the column in which to start analysis or plotting.\n"
01045           "See also start_r,end_c,end_r; negative values on any of these\n"
01046           "mean to include all available units.");
01047   
01048   PARAM_A(blackboard,"start_r",-1,.add_lower_bound(-1),
01049           "Number of the row in which to start analysis or plotting.\n"
01050           "See also start_c,end_c,end_r; negative values on any of these\n"
01051           "mean to include all available units.");
01052 
01053   PARAM_A(blackboard,"end_c",-1,.add_lower_bound(-1),
01054           "Number of the first column not to include in analysis or plotting.\n"
01055           "See also start_c,start_r,end_r; negative values on any of these\n"
01056           "mean to include all available units.");
01057   
01058   PARAM_A(blackboard,"end_r",-1,.add_lower_bound(-1),
01059           "Number of the first row not to include in analysis or plotting.\n"
01060           "See also start_c,start_r,end_c; negative values on any of these\n"
01061           "mean to include all available units.");
01062 
01063   PARAM_II(PARAM_INT,reversed_color_order,&Plot::HSVPixel<>::reversed_color_order,False,True,
01064           "The hue in HSV-based colors normally goes red->yellow->green->purple->red\n"
01065           "as the numeric hue goes from 0 to 1.0.  Some code and publications use the\n"
01066           "reverse order (red->purple->green->yellow->red), and if you want to match\n"
01067           "them, set this parameter to True.");
01068   
01069   // Should clean up these two parameters a bit -- e.g. define them only in 
01070   // the parameter list for cmd_plot?
01071   blackboard.define_param(DECLARE_PARAM(PARAM_INT,"current_ui",true,&current_ui));
01072   params_define_doc("current_ui",
01073           "Read-only parameter which reports the unit currently being examined;\n"
01074           "see current_region for more details.");
01075   SETFN_DEFINE2(current_ui,read_only_param_setfn2);
01076  
01077   blackboard.define_param(DECLARE_PARAM(PARAM_INT,"current_uj",true,&current_uj));
01078   params_define_doc("current_uj",
01079           "Read-only parameter which reports the unit currently being examined;\n"
01080           "see current_region for more details.");
01081   SETFN_DEFINE2(current_uj,read_only_param_setfn2);
01082 
01083   blackboard.define_param(DECLARE_PARAM(PARAM_INT,"current_height",true,&current_height));
01084   params_define_doc("current_height",
01085           "Read-only parameter which reports the height of the region currently being\n"
01086           "examined; see current_region for more details.");
01087   SETFN_DEFINE2(current_height,read_only_param_setfn2);
01088 
01089   blackboard.define_param(DECLARE_PARAM(PARAM_INT,"current_width",true,&current_width));
01090   params_define_doc("current_width",
01091           "Read-only parameter which reports the width of the region currently being\n"
01092           "examined; see current_region for more details.");
01093   SETFN_DEFINE2(current_width,read_only_param_setfn2);
01094 
01095   blackboard.define_param(DECLARE_PARAM(PARAM_USTRING,"current_region",true,&current_region));
01096   params_define_doc("current_region",
01097           "Read-only parameter which reports the region currently being examined, e.g.\n"
01098           "in weight plots or weight analysis.  The current_* parameters can be useful\n"
01099           "for e.g. constructing filenames.  At present, their value is only guaranteed\n"
01100           "to be defined during a call to the plot_unit, save_snapshot, and load_snapshot\n"
01101           "commands, and only the relevant ones for each command are updated.  When\n"
01102           "not defined, they have clearly undefined values, usually -1 or ''.");
01103   SETFN_DEFINE2(current_region,read_only_param_setfn2);
01104 
01105   blackboard.define_param(DECLARE_PARAM(PARAM_USTRING,"current_plot",true,&current_plot));
01106   params_define_doc("current_plot",
01107           "Read-only parameter which reports the name of the plot currently being\n"
01108           "constructed, if any; see current_region for more details.  The name is\n"
01109           "the name of the current PlotGroup except while constructing a specific\n"
01110           "plot, in which case it is the name of that particular plot.");
01111   SETFN_DEFINE2(current_plot,read_only_param_setfn2);
01112 
01113 
01114   /* Legacy multiprocessor support */
01115   PARAM_I(PARAM_INT,   plot_pe,Uninitialized,NPES-1,
01116           "PE which plots data, e.g. for the plot command.  By default only a single\n"
01117           "PE plots the data, but when debugging on multiple-PE machines, sometimes\n"
01118           "it is helpful to get plots from every PE (if plot_pe == Uninitialized)\n"
01119           "or just a different PE than usual.  This can help e.g. verify that\n"
01120           "each PE has identical copies of global arrays.");
01121 }
01122 
01123 
01124 
01125 /* Might be better using a cmd::activate::regions parameter instead of
01126    Regions::activation_order.  */
01127 void NeuralRegionMap::activate(bool learn, bool settle, bool activatefn, bool verbose) const
01128 {
01129   /* Might want to cache the result of this call, though the time taken is probably minimal. 
01130      (Caching would just need a setfn for the activation_order parameter to update this value.) */
01131   RegionManagerList regions = retrieve_matching_regions(*params,"activation_order",false);
01132 
01133   /* Activate each region in order specified */
01134   for (RegionManagerList::iterator r=regions.begin(); r!=regions.end(); r++) {
01135     message((verbose? Msg::Notify : Msg::Verbose), "Activating " + (*r)->region()->name());
01136     (*r)->region()->activate(learn,settle,activatefn);
01137   }
01138 }
01139 
01140 
01141 
01143 cmdstat NeuralRegionMap::cmd_plot_unit( CMD_ARGS )
01144 {
01145   CMD_ARG_PARAMS(plot_unit);
01146 
01147   const string plotgroup        = argparams.get_with_default("plotgroup",string("Weights"));
01148   const string default_region   = argparams.get_with_default("default_region",string(""));
01149   const string specified_region = argparams.get_with_default("region",string(""));
01150   const string regionname       = (specified_region!=""? specified_region : default_region);
01151   
01152   const NeuralRegionManager* rm = lookup_internal_region(regionname);
01153   if (!rm) return CMD_PARAMETER_ERROR;
01154 
01155   if (plotgroup!="Weights")
01156     message(Msg::Warning, "The plot_unit command only supports a <plotgroup> of Weights.");
01157   
01158   /* Create one image per unit */
01159   int beenthrough=false;
01160   bool statusok=true;
01161   for (; (!arglist.empty()||!beenthrough); ) {
01162     define_globals(rm,Uninitialized,Uninitialized,plotgroup);
01163     const bool numargsisodd=arglist.oneremaining();
01164     const int  ui=arglist.next(rm->default_ui());
01165     const int  uj=arglist.next(rm->default_uj());
01166     
01167     /* Construct and save image */
01168     if (numargsisodd) {
01169       message(Msg::Error, "Wrong number of arguments to plot_unit");
01170       return CMD_PARAMETER_ERROR;
01171     }
01172     define_globals(rm,ui,uj,plotgroup);
01173     
01174     // Multiprocessor note:
01175     /*
01176       Assumes that all weights will be available to all units, which
01177       requires NeuralRegion::get_weights to fetch them from the
01178       appropriate PE if need be.
01179     */
01180     if (plot_pe==Uninitialized || MyPE==plot_pe) {
01181       message(Msg::Notify, "Plotting weights for " +
01182               rm->region()->name() + " unit (" +
01183               String::stringrep(ui) + "," +
01184               String::stringrep(uj) + ")");
01185 
01186       const bool newstatus = plot_write_unit(argparams, rm, ui, uj);
01187       if (!newstatus) statusok=false;
01188     }
01189     
01190     beenthrough=true;
01191   }
01192   define_globals();
01193   
01194   CMD_ARG_ASSERT_EMPTY;
01195   return (statusok ? CMD_NO_ERROR : CMD_PARAMETER_ERROR);
01196 }
01197 
01198 
01199 
01200 
01203 const NeuralRegionManager* NeuralRegionMap::lookup_region(const string& name) const
01204 {
01205   const NeuralRegionManager* rm = getptr(name);
01206 
01207   if (!rm) {
01208     message(Msg::Error, "Region '" + name + "' not found");
01209     return 0;
01210   }
01211   return rm;
01212 }
01213 
01214 
01215 
01218 const NeuralRegionManager* NeuralRegionMap::lookup_internal_region(const string& name) const
01219 {
01220   const NeuralRegionManager* rm = lookup_region(name);
01221 
01222   if (rm && !rm->internalregion()) {
01223     message(Msg::Error, "Region '" + name + "' has no weights");
01224     return 0;
01225   }
01226   return rm;
01227 }
01228 
01229 
01230 
01232 cmdstat NeuralRegionMap::cmd_plot_unit_range( CMD_ARGS )
01233 {
01234   CMD_ARG_PARAMS(plot_unit_range);
01235 
01236   const string plotitem       = argparams.get_with_default("name",string(""));
01237   const string default_region = argparams.get_with_default("default_region",string(""));
01238   const string specified_region=argparams.get_with_default("region",string(""));
01239   const string regionname     = (specified_region!=""? specified_region : default_region);
01240   const bool   verbose        = argparams.get_with_default("verbose",True);
01241   int          ui_start       = arglist.next(argparams.get_with_default("start_r", -1));
01242   int          uj_start       = arglist.next(argparams.get_with_default("start_c", -1));
01243   int          ui_end         = arglist.next(argparams.get_with_default("end_r",   -1));
01244   int          uj_end         = arglist.next(argparams.get_with_default("end_c",   -1));
01245   int          step           = arglist.next(argparams.get_with_default("ppm_neuron_skip_aff",1));
01246   
01247   const NeuralRegionManager* rm = lookup_internal_region(regionname);
01248   if (!rm) return false;
01249 
01250   const int nrows = rm->region()->nrows();
01251   const int ncols = rm->region()->ncols();
01252 
01253   if (ui_start<0) ui_start=0;  if (ui_end<0) ui_end = nrows;
01254   if (uj_start<0) uj_start=0;  if (uj_end<0) uj_end = ncols;
01255   if (step<1)     step=1;
01256 
01257   ui_start = Generic::crop(0,nrows,ui_start);
01258   ui_end   = Generic::crop(0,nrows,ui_end);
01259   uj_start = Generic::crop(0,nrows,uj_start);
01260   uj_end   = Generic::crop(0,nrows,uj_end);
01261 
01262   /* Update global that might be used in filenames; should probably be eliminated */
01263   WorldViews::set_current_eye(String::numeric_extension<int>(plotitem));
01264 
01265   message((verbose? Msg::Notify : Msg::Verbose), "Plotting " + rm->region()->name() + "::" + plotitem);
01266 
01267   const bool status = plot_write_unit_range(argparams,rm,plotitem,ui_start,uj_start,ui_end,uj_end,step);
01268   define_globals();
01269   
01270   CMD_ARG_ASSERT_EMPTY;
01271   return (status ? CMD_NO_ERROR : CMD_PARAMETER_ERROR);
01272 }
01273 
01274 
01275 
01277 cmdstat NeuralRegionMap::cmd_plot( CMD_ARGS )
01278 {
01279   CMD_ARG_PARAMS(plot);
01280 
01281   if (plot_pe!=Uninitialized && MyPE!=plot_pe)
01282     return true;
01283   
01284   /* Construct each subimage, zero or more for each NeuralRegion */
01285   ImagePListList imagelists;
01286 
01287   const string   plotgroup_     = arglist.next(argparams.get_with_default("plotgroup",string("")));
01288   const string   plotgroup      = (plotgroup_!=""? plotgroup_ : argparams.get_with_default("plotgroup",string("Activity")));
01289   const string   suppliedformat = argparams.get_with_default("filename_format",string(""));
01290   const bool     verbose        = argparams.get_with_default("verbose",True);
01291   const bool     save_matrices  = argparams.get_with_default("save_matrices",False);
01292   const bool     gnuplot_plots  = argparams.get_with_default("gnuplot_plots",False);
01293   const bool     ppm_plots      = argparams.get_with_default("ppm_plots",True);
01294   const bool     separate_plots = argparams.get_with_default("ppm_separate_plots",True);
01295   const bool     combined_plots = argparams.get_with_default("ppm_combined_plots",True);
01296   const bool     histograms     = argparams.get_with_default("ppm_histograms",True);
01297   const bool     mainplot       = argparams.get_with_default("ppm_mainplot",True);
01298   const double   master_scale   = argparams.get_with_default("ppm_master_scale", double(Uninitialized));
01299 
01300   const double   interior_b     = argparams.get_with_default("ppm_interior_border",1.0);
01301   const int      interior_border= (interior_b>=0? int(interior_b) : std::max(2,int(-interior_b*min_of_max_dimensions())));
01302   const Color    pagecolor      = lookup_param(argparams,    "ppm_page", Color());
01303   bool status=true;
01304 
01305   SpecRegion maxregion          = max_subregion();
01306 
01307   RegionManagerList regions     = retrieve_matching_regions(*params,"activation_order",false);
01308   
01309 
01310   /* Plot each region in the activation_order */
01311   for (RegionManagerList::iterator r=regions.begin(); r!=regions.end(); r++) {
01312     NeuralRegionManager* rm = (*r);
01313     
01314     for (NeuralRegionManager::PlotSpecList::const_iterator pi=rm->plotspeclist_begin(plotgroup);
01315          pi!=rm->plotspeclist_end(plotgroup); pi++) {
01316 
01317       define_globals(rm,Uninitialized,Uninitialized,(*pi)->name());
01318         
01319       /* Register the specified reference map, if any.  Only accepts a
01320          restricted format at present: "region::mapname", and creates
01321          a map named __StrengthReference for PlotSpecification to use. */
01322       const string   ref_path_name  = (*pi)->lookup_param("Strength::reference",string());
01323       NeuralRegionManager::PlotSpec::MatrixTable tempmaps;
01324 
01325       message((verbose? Msg::Notify : Msg::Verbose), "Plotting " + (*pi)->objectname() + "::" + (*pi)->name() +
01326               (ref_path_name=="" ? string() : " relative to " + ref_path_name));
01327 
01328       if (ref_path_name!="") {
01329         const PathSpecification referencepath(ref_path_name);
01330         const NeuralRegionManager* ref_rm  = getptr(referencepath.first());
01331         const NeuralRegion::MapBaseType* ref_map =
01332           (!ref_rm? 0 : ref_rm->region()->table().getptr(referencepath.last()));
01333         if (referencepath.all().size()!=2 || !ref_map)
01334           message(Msg::Error, "Invalid reference path: " + ref_path_name);
01335         else {
01336           typedef mat::MatrixInterfaceAdapter<NeuralRegion::MapBaseType> MatAdapter;
01337           tempmaps.set("__StrengthReference",new MatAdapter(*ref_map));
01338         }
01339       }
01340       
01341       if (gnuplot_plots) {
01342         if (!gnuplot_image(argparams,**pi,filenamebase(plotgroup,suppliedformat),&tempmaps,
01343                            lookup_subregion((**pi).param_map(),SpecRegion())))
01344           status=false;
01345       }
01346       
01347       if (save_matrices) {
01348         const SpecRegion& region = lookup_subregion((**pi).param_map(),SpecRegion());
01349         if (!((*pi)->save_matrix(filenamebase(plotgroup,suppliedformat),&tempmaps,
01350                                  &region)))
01351           status=false;
01352       }
01353       
01354       /*
01355         Compute and save an image as a ppm file.  The first PE computes and saves 
01356         the entire image; this could be improved by making each PE responsible for
01357         part of the image or for an activity or input panel, etc., but the speedup
01358         is probably minimal since I imagine the process is IO-bound.
01359       */
01360       if (ppm_plots) {
01361         /* Holder for a set of related images (main plot, histogram, etc.) */
01362         ImagePList* li = new ImagePList;
01363 
01364         /* Add main plot */
01365         if (mainplot) {
01366           Plot::AARImage<>* img = (*pi)->bitmap_image(master_scale,&maxregion,&tempmaps);
01367           if (img) {
01368             if (combined_plots) li->push_back(img);
01369             if (separate_plots) ppm_write_to_file(filenamebase(plotgroup,suppliedformat),*img);
01370           }
01371         }
01372         
01373         /* Add histogram(s) */
01374         if (histograms) {
01375           Plot::AARImage<>* histoimg =
01376             (*pi)->bitmap_histogram(master_scale,blackboard.lookup_map("::PlotGroup::Histogram"),&maxregion,&tempmaps);
01377           if (histoimg) {
01378             if (combined_plots) li->push_back(histoimg);
01379             if (separate_plots) ppm_write_to_file(filenamebase(plotgroup,suppliedformat)+"_Histogram",*histoimg);
01380           }
01381         }
01382 
01383         /* If anything was plotted, add it to the image grid */
01384         if (li->empty())
01385           delete li;
01386         else
01387           imagelists.push_back(li);
01388       }
01389     }
01390   }
01391 
01392   define_globals(0,Uninitialized,Uninitialized,plotgroup);
01393   if (ppm_plots && combined_plots)
01394     status = ppmgrid_write(filenamebase(plotgroup,suppliedformat),
01395                            imagelists,interior_border,pagecolor);
01396   Generic::nested_delete_contents(imagelists);
01397   define_globals();
01398   
01399   CMD_ARG_ASSERT_EMPTY;  
01400   return (status ? CMD_NO_ERROR : CMD_PARAMETER_ERROR);
01401 }
01402 
01403 
01404 
01407 const bool NeuralRegionMap::add_maps_for_unit(NeuralRegionManager::PlotSpec::MatrixTable& tempmaps,
01408                                               const NeuralRegionManager& rm,
01409                                               const NeuralRegionManager::PlotSpec& plotspec,
01410                                               const int ui, const int uj) const
01411 {
01412   const string   ref_path_name  = plotspec.lookup_param("Strength::reference",string());
01413   if (!rm.add_maps_for_unit(tempmaps,plotspec,ui,uj))
01414     return false;
01415   
01416   /* Register the specified reference map, if any.  Only accepts a
01417      restricted format at present: "region::mapname", and creates
01418      a map named __StrengthReference for PlotSpecification to use. */
01419   if (ref_path_name!="") {
01420     const PathSpecification referencepath(ref_path_name);
01421     const NeuralRegionManager* ref_rm = getptr(referencepath.first());
01422     if (referencepath.all().size()!=2 || !ref_rm) {
01423       message(Msg::Error, "Invalid reference path: " + ref_path_name);
01424       return false;
01425     }
01426     else
01427       return ref_rm->add_maps_for_unit(tempmaps,referencepath.last(),
01428                                        "__StrengthReference",plotspec,ui,uj);
01429   }
01430   
01431   return true;
01432 }
01433 
01434 
01445 const string NeuralRegionMap::overriding_colorspec
01446 (const NeuralRegionManager* rm, int ui, int uj, const string colorspec) const
01447 {
01448   typedef const NeuralRegion::MapBaseType* mapptr;
01449   StringParser sp;
01450   StringArgs   specargs(sp, colorspec);
01451   const bool   override_colorspec = (specargs.next(string(""))=="MapSpecifiesHue");
01452   const mapptr colorizingmap      = !override_colorspec? 0 : rm->region()->table().getptr(specargs.next(string("")));
01453   const mapptr confidencizingmap  = !override_colorspec? 0 : rm->region()->table().getptr(specargs.next(string("")));
01454   return
01455     (!override_colorspec? "" :
01456      ("SpecifiedHue" +
01457       (!colorizingmap?     "" : " " + String::stringrep(mat::elem(*colorizingmap,ui,uj))) +
01458       (!confidencizingmap? "" : " " + String::stringrep(mat::elem(*confidencizingmap,ui,uj)))));
01459 }
01460 
01461 
01462 
01463 const bool NeuralRegionMap::plot_write_unit
01464 (const ParamMap& argparams, const NeuralRegionManager* rm, 
01465  const int ui, const int uj) const
01466 {
01467   /* Construct each subimage, zero or more for each NeuralRegion */
01468   ImagePListList imagelists;
01469   
01470   const string   plotgroup      = argparams.get_with_default("plotgroup",string(""));
01471   const string   suppliedformat = argparams.get_with_default("filename_format",string(""));
01472   const bool     verbose        = argparams.get_with_default("verbose",True);
01473   const bool     situate        = argparams.get_with_default("weight_situate",True);
01474   const bool     gnuplot_plots  = argparams.get_with_default("gnuplot_plots",False);
01475   const bool     ppm_plots      = argparams.get_with_default("ppm_plots",True);
01476   const bool     separate_plots = argparams.get_with_default("ppm_separate_plots",True);
01477   const bool     combined_plots = argparams.get_with_default("ppm_combined_plots",True);
01478   const bool     histograms     = argparams.get_with_default("ppm_histograms",True);
01479   const bool     mainplot       = argparams.get_with_default("ppm_mainplot",True);
01480   const double   master_scale   = argparams.get_with_default("ppm_master_scale", double(Uninitialized));
01481 
01482   const double   interior_b     = argparams.get_with_default("ppm_interior_border",1.0);
01483   const int      interior_border= (interior_b>=0? int(interior_b) : std::max(2,int(-interior_b*min_of_max_dimensions())));
01484   const Color    pagecolor      = lookup_param(argparams, "ppm_page", Color());
01485   bool status=true;
01486   
01487   PlotSpecList plots = retrieve_matching_plots
01488     (rm->plotspeclist_begin(plotgroup), rm->plotspeclist_end(plotgroup),
01489      params->get_with_default("connection_order",string("")));
01490 
01491   for (PlotSpecList::const_iterator pi=plots.begin(); pi!=plots.end(); pi++) {
01492     define_globals(rm,ui,uj,(*pi)->name()); /* Ensure current_* are available for e.g. filename_format */
01493     
01494     /* Parameters specific to this type of plot, or that we otherwise must handle */
01495     const bool     draw_outline   = (*pi)->lookup_param("ppm_outline_weights", False);
01496     const int      outline_width  = (*pi)->lookup_param("ppm_outline_width", 1);
01497     const string   ref_path_name  = (*pi)->lookup_param("Strength::reference",string());
01498     const string   colorspec      = (*pi)->lookup_param("colorspec",string());
01499     
01500     /* Get maps to plot, or abort if this is an invalid unit */
01501     NeuralRegionManager::PlotSpec::MatrixTable tempmaps;
01502     if (!add_maps_for_unit(tempmaps,*rm,**pi,ui,uj)) {
01503       define_globals();
01504       return false;
01505     }
01506 
01507     message((verbose? Msg::Notify : Msg::Verbose), "Plotting " + rm->internalregion()->name() + "::" + (*pi)->name() +
01508             (ref_path_name=="" ? string() : " relative to " + ref_path_name));
01509 
01510 
01511     if (gnuplot_plots) {
01512       if (unit_gnuplot(argparams,**pi,filenamebase(plotgroup,suppliedformat),&tempmaps,
01513                        rm->internalregion()->weights((*pi)->name(),ui,uj).bounds(),situate))
01514         status=false;
01515     }
01516     
01517     if (ppm_plots) {
01518       ImagePList* li = new ImagePList;
01519       unit_bitmap(master_scale,*li,**pi,&tempmaps,
01520                   rm->internalregion()->weights((*pi)->name(),ui,uj).bounds(),
01521                   pagecolor,draw_outline,outline_width,situate,mainplot,
01522                   separate_plots,combined_plots,
01523                   filenamebase(plotgroup,suppliedformat),histograms,
01524                   -1,false,overriding_colorspec(rm,ui,uj,colorspec));
01525 
01526       /* If anything was plotted, add it to the image grid */
01527       if (li->empty())
01528         delete li;
01529       else
01530         imagelists.push_back(li);
01531     }
01532   }
01533 
01534   define_globals(rm,ui,uj,plotgroup);
01535   if (ppm_plots && combined_plots)
01536     status = ppmgrid_write(filenamebase(plotgroup,suppliedformat),
01537                            imagelists,interior_border,pagecolor);
01538   Generic::nested_delete_contents(imagelists);
01539 
01540   define_globals();
01541   return status;
01542 }
01543 
01544 
01545 
01546 const bool NeuralRegionMap::plot_write_unit_range
01547 (const ParamMap& argparams, const NeuralRegionManager* rm, 
01548  const string& plotitem, int ui_start, int uj_start, int ui_end, int uj_end, int step) const
01549 {
01550 
01552 #if (NPES>1)
01553   if (NPEs>1) {
01554     message(Msg::Error, "plot_write_unit_range is not supported on multi-PE systems");
01555     return false;
01556   }
01557 #endif
01558   
01559   /* Construct each subimage, zero or more for each NeuralRegion */
01560   ImagePListList imagelists;
01561 
01562   const string   plotgroup      = argparams.get_with_default("plotgroup",string(""));
01563   const bool     ppm_plots      = argparams.get_with_default("ppm_plots",True);
01564   const bool     separate_plots = argparams.get_with_default("ppm_separate_plots",True);
01565   const bool     combined_plots = argparams.get_with_default("ppm_combined_plots",True);
01566   const bool     situate        = argparams.get_with_default("weight_situate", False);
01567   const bool     bare           = argparams.get_with_default("weight_bare", True);
01568   const bool     fill_bg        = argparams.get_with_default("weight_fill_background", False);
01569   const bool     showinterior   = argparams.get_with_default("ppm_interior_outline", False);
01570   const Color    pagecolor      = lookup_param(argparams, (!showinterior && !fill_bg? "ppm_line" : "ppm_page"), Color());
01571   const bool     histograms     = argparams.get_with_default("ppm_histograms",True);
01572   const bool     mainplot       = argparams.get_with_default("ppm_mainplot",True);
01573   const double   master_scale   = argparams.get_with_default("ppm_master_scale", double(Uninitialized));
01574   const string   suppliedformat = argparams.get_with_default("filename_format",string(""));
01575   const double   interior_b     = argparams.get_with_default("ppm_interior_border",1.0);
01576   const int      interior_border= (interior_b>=0? int(interior_b) : std::max(2,int(-interior_b*min_of_max_dimensions())));
01577 
01578   /* Plot each unit */
01579   for   (int ui=ui_start; ui<ui_end; ui+=step) {
01580     ImagePList* li = new ImagePList;
01581     for (int uj=uj_start; uj<uj_end; uj+=step) {
01582       for (NeuralRegionManager::PlotSpecList::const_iterator pi=rm->plotspeclist_begin(plotgroup);
01583            pi!=rm->plotspeclist_end(plotgroup); pi++)
01584         if (String::glob_match(plotitem,(*pi)->name())) {
01585           define_globals(rm,ui,uj,(*pi)->name());
01586 
01587           /* Get maps to plot, or abort if this is an invalid unit */
01588           NeuralRegionManager::PlotSpec::MatrixTable tempmaps;
01589           if (!add_maps_for_unit(tempmaps,*rm,**pi,ui,uj))
01590             return false;
01591 
01592           /* Parameters specific to this type of plot, or that we otherwise must handle */
01593           const bool     draw_outline   = (bare? False : (*pi)->lookup_param("ppm_outline_weights", False));
01594           const int      outline_width  = (bare? 0     : (*pi)->lookup_param("ppm_outline_width", 1));
01595           const int      border_width   = (bare? 0     : (*pi)->lookup_param("ppm_border", 1));
01596           const string   colorspec      = (*pi)->lookup_param("colorspec",string());
01597 
01598           /* Plot the unit */
01599           if (ppm_plots)
01600             unit_bitmap(master_scale,*li,**pi,&tempmaps,
01601                         rm->internalregion()->weights((*pi)->name(),ui,uj).bounds(),
01602                         pagecolor,draw_outline,outline_width,situate,
01603                         mainplot,separate_plots,combined_plots,
01604                         filenamebase(plotgroup,suppliedformat),
01605                         histograms,border_width,fill_bg,
01606                         overriding_colorspec(rm,ui,uj,colorspec));
01607         }
01608     }
01609 
01610     /* If anything was plotted, add it to the image grid */
01611     if (li->empty())
01612       delete li;
01613     else
01614       imagelists.push_back(li);
01615   }
01616 
01617   define_globals(rm,Uninitialized,Uninitialized,plotgroup);
01618   bool status=true;
01619   if (ppm_plots && combined_plots)
01620     status = ppmgrid_write(filenamebase(plotgroup+"Map",suppliedformat),
01621                            imagelists,interior_border,pagecolor,false);
01622   Generic::nested_delete_contents(imagelists);
01623 
01624   return status;
01625 }
01626 
01627 
01628 
01630 bool NeuralRegionMap::unit_gnuplot(const ParamMap& argparams,
01631                                    NeuralRegionManager::PlotSpec& plotspec,
01632                                    const string& filebase,                         
01633                                    const NeuralRegionManager::PlotSpec::MatrixTable* tempmaps,
01634                                    const InternalNeuralRegion::WeightBounds& bounds,
01635                                    bool situate) const
01636 {
01637   SpecRegion region = (situate? lookup_subregion(plotspec.param_map(),SpecRegion()) : 
01638                        weightbounds_to_subregion<SpecRegion>(bounds.aarectangle()));
01639   return gnuplot_image(argparams,plotspec,filebase,tempmaps,region);
01640 }
01641 
01642 
01643 
01644 
01646 bool NeuralRegionMap::unit_bitmap(const double master_scale, ImagePList& imagelist,
01647                                   const NeuralRegionManager::PlotSpec& plotspec,
01648                                   const NeuralRegionManager::PlotSpec::MatrixTable* tempmaps,
01649                                   const InternalNeuralRegion::WeightBounds& bounds,
01650                                   const Color& pagecolor,
01651                                   bool draw_outline, int  outline_width,
01652                                   bool situate, bool mainplot, bool separate_plots,
01653                                   bool combined_plots, const string& filebase,
01654                                   bool histograms, int  border_width, bool fill_bg,
01655                                   const string& overriding_colorspec) const
01656 {
01657   SpecRegion maxregion = max_subregion();
01658   SpecRegion region = (situate? lookup_subregion(plotspec.param_map(),SpecRegion()) : 
01659                        weightbounds_to_subregion<SpecRegion>(bounds.aarectangle()));
01660 
01661   /* Add main plot */
01662   if (mainplot) {
01663     Plot::MatrixImage<>* img = plotspec.bitmap_image(master_scale,&maxregion,tempmaps,&region,border_width,overriding_colorspec);
01664     if (!img) return false;
01665     
01666     /* Outline the weights, if needed */
01667     if (draw_outline || fill_bg) {
01668       InternalNeuralRegion::WeightBounds* wtbounds = bounds.clone();
01669       if (!region.isinfinite())
01670         wtbounds->translate(int(region.corners().yl),int(region.corners().xl));
01671       if (fill_bg)
01672         img->outline_boundary(*wtbounds,outline_width,pagecolor,fill_bg);
01673       else
01674         img->outline_boundary(*wtbounds,outline_width);
01675       delete wtbounds;
01676     }
01677     
01678     /* Add this image to the grid */
01679     if (combined_plots) imagelist.push_back(img);
01680     if (separate_plots) ppm_write_to_file(filebase,*img);
01681   }
01682   
01683   /* Add histogram(s) */
01684   if (histograms) {
01685     Plot::AARImage<>* histoimg =
01686       plotspec.bitmap_histogram(master_scale,blackboard.lookup_map("::PlotGroup::Histogram"),&maxregion,tempmaps);
01687     if (histoimg) {
01688       if (combined_plots) imagelist.push_back(histoimg);
01689       if (separate_plots) ppm_write_to_file(filebase+"_Histogram",*histoimg);
01690     }
01691   }
01692   
01693   return true;
01694 }
01695 
01696 
01697 
01699 const bool NeuralRegionMap::ppmgrid_write(const string& filebase,
01700                                           const ImagePListList& imagelists, int interior_border,
01701                                           const Color& pagecolor, bool column_major) const
01702 {
01703   /* Skip empty plot */
01704   if (imagelists.empty()) {
01705     message(Msg::Warning, "Skipping empty image");
01706     return false;
01707   }
01708   
01709   /* Create combined image and save as a PPM file */
01710   typedef MatrixType<Plot::AARImage<>* >::rectangular MatrixOfImagePointers;
01711   const MatrixOfImagePointers moi =
01712     mat::matrix_from_nested_containers
01713     <MatrixOfImagePointers,ImagePList>(imagelists,column_major);
01714 
01715   const string filename = filebase + ".ppm";
01716   {
01717     Plot::ImagePointerGrid<> img(moi,interior_border,interior_border,pagecolor);
01718     std::ofstream os(filename.c_str() BINARY_FILE_FLAGS);
01719     img.ppm_write(os,filename,(unsigned char)(255));
01720   }
01721   ppm_post_write_hook( filename.c_str() );
01722   
01723   return true;
01724 }
01725 
01726 
01727 
01732 bool NeuralRegionMap::define_plotgroup(const string plotgroup, const string filename_format)
01733 {
01734   const string    format         = (filename_format!=""? filename_format :
01735                                     blackboard.get_with_default("default_filename_format",string("file")));
01736   BlackboardType& plotgroups     = blackboard.lookup_map("::PlotGroup");
01737   BlackboardType& plotgroupparams= plotgroups.lookup_map(plotgroup,false);
01738   const bool      alreadyexists  = (&plotgroupparams != &plotgroups);;
01739   BlackboardType* paramsptr      = (alreadyexists ? &plotgroupparams :
01740                                     plotgroups.new_child(plotgroup,true));
01741 
01742   if (filename_format!="" || !alreadyexists)
01743     paramsptr->set_local("filename_format",format);
01744 
01745   return !alreadyexists;
01746 }
01747 
01748 
01750 cmdstat NeuralRegionMap::cmd_define_plot( CMD_ARGS )
01751 {
01752   CMD_ARG_PARAMS(define_plot);
01753   bool status=true;
01754   const string strength       = arglist.next(string(""));
01755   const string color          = arglist.next(string(""));
01756   const string confidence     = arglist.next(string(""));
01757   
01758   const string specified_name = argparams.get_with_default("name",string(""));
01759   const string name           = (specified_name!=""? specified_name :
01760                                  (strength!=""?       strength :
01761                                   (color!=""?          color : confidence)));
01762 
01763   const string specified_type = argparams.get_with_default("plotgroup",string(""));
01764   const string plotgroup      = (specified_type!="" ? specified_type : name);
01765   const string format         = argparams.get_with_default("filename_format",string(""));
01766 
01767   /* The name is required */
01768   if (name=="") {
01769     message(Msg::Error, "Skipping plot definition; no name was specified");
01770     return CMD_PARAMETER_ERROR;
01771   }
01772   
01773   /* Create a set of parameters for the <plotgroup> if none exists */
01774   define_plotgroup(plotgroup,format);
01775   
01776   /* Define plot for each region in order specified */
01777   RegionManagerList regions = retrieve_matching_regions(argparams);
01778   for (RegionManagerList::iterator r=regions.begin(); r!=regions.end(); r++)
01779     (*r)->define_plot(plotgroup,name,strength,color,confidence);
01780 
01781   CMD_ARG_ASSERT_EMPTY;
01782   return (status ? CMD_NO_ERROR : CMD_PARAMETER_ERROR);
01783 }
01784 
01785 
01786 
01788 cmdstat NeuralRegionMap::cmd_measure_stimulus_map( CMD_ARGS )
01789 {
01790   CMD_ARG_PARAMS(measure_stimulus_map);
01791   const bool status = measure_stimulus_map(arglist,argparams);
01792   CMD_ARG_ASSERT_EMPTY;
01793   return (status ? CMD_NO_ERROR : CMD_PARAMETER_ERROR);  
01794 }
01795 
01796 
01797 
01800 template<class LoopContainer, class UpdatableObjectContainer>
01801 class NeuralRegionMap::measure_stimulus_map_iteration {
01802 public:
01803 
01810   measure_stimulus_map_iteration(const string& input_command_,
01811                                  const LoopContainer& loops_,
01812                                  const UpdatableObjectContainer& spmrs_)
01813     : input_command(input_command_), loops(loops_), spmrs(spmrs_)  {  };
01814   
01816   void operator() () {
01817     /* Make variable values public.  Uses the global parameter map. */
01818     string variables;
01819     for (typename LoopContainer::const_iterator i=loops.begin(); i!=loops.end(); i++) {
01820       variables += " " + String::stringrep(**i);
01821       blackboard.lookup((*i)->name()).datavalue().set(Polymorph<double>((*i)->value()));
01822     }
01823     message(Msg::Notify, "Setting variables:" + variables);
01824 
01825     /* Present input */
01826     cmddefs_exec_str(input_command.c_str());
01827     
01828     /* Tell each of the SPMRs to update to the current activation levels */
01829     for (typename UpdatableObjectContainer::const_iterator si=spmrs.begin(); si!=spmrs.end(); si++)
01830       (*si)->update();
01831   }
01832   
01833 private:
01834   const string& input_command;
01835   const LoopContainer& loops;
01836   const UpdatableObjectContainer& spmrs;
01837 };
01838 
01839 
01842 template<class T1, class T2>
01843 T1 accum_num_calls(const T1& accum, const T2* p)
01844 {  return accum*p->num();  }
01845 
01846 
01847 
01848 
01850 const bool NeuralRegionMap::measure_stimulus_map(StringArgs& arglist, ParameterMap<>& argparams)
01851 {
01852   typedef double                        VType;
01853   typedef ValueGenerator<VType>         VGenerator;
01854   typedef LoopSpec<VType>               Loop;
01855   typedef std::vector<Loop*>            Loops;
01856   typedef StimulusParameterMapsForRegion<const NeuralRegion::ActivityMatrix, NeuralRegion::MapBaseType, Loop>   SPMR;  
01857   typedef std::vector<SPMR*>            SPMRs;
01858   typedef SPMR::ScaleType               Scale;
01859   
01860   const string  input_command  = arglist.next(string(""));
01861   RegionManagerList regions    = retrieve_matching_regions(argparams);  
01862   
01863   SPMRs spmrs;
01864 
01866   for (RegionManagerList::iterator r=regions.begin(); r!=regions.end(); r++)
01867     spmrs.push_back(new SPMR(*r));
01868   
01869 
01871   Loops loops;
01872   DistributedValueGeneratorFactory<VType> vgf;
01873   while (!arglist.empty()) {
01874     StringArgs dimensionargs=arglist.recursiveparser();
01875 
01876     /* Set named parameters */
01877     ParameterMap<> subargparams(&argparams);
01878     cmdparams_set(subargparams,dimensionargs,true,false,false);
01879 
01880     /* Get parameter values */
01881     const string name                 = dimensionargs.next(subargparams.get_with_default("name",string("")));
01882     const int    divisions            = dimensionargs.next(subargparams.get_with_default("divisions",1));
01883     
01884     const bool   registermap          = subargparams.get_with_default("register",False);
01885     const bool   weighted_average     = subargparams.get_with_default("weighted_average",False);
01886     const bool   measure_distribution = subargparams.get_with_default("measure_distribution",True);
01887     const int    specified_num_bins   = subargparams.get_with_default("num_bins",-1);
01888     const Scale  selectivity_scale    = Scale(subargparams.get_with_default("selectivity_scale",1.0));
01889     const bool   cyclic               = subargparams.get_with_default("cyclic",True);
01890     const bool   discrete_inputs      = subargparams.get_with_default("discrete_inputs",True);
01891     const int    num_bins             = (specified_num_bins>0? specified_num_bins :
01892                                          (cyclic? divisions : divisions+1));
01893     const int    discrete_levels      = (discrete_inputs? divisions : -1 );
01894     const string varname              = subargparams.get_with_default("varname",string(""));
01895     const string loopspecname         = (varname!=""? varname : name);
01896     const string valuegenspec         = subargparams.get_with_default("valuegenerator",string(""));
01897     StringArgs   valuegenargs         = dimensionargs.recursiveparser(valuegenspec);
01898     VGenerator*  valuegen             = (valuegenargs.empty()? 0 : vgf.create(valuegenargs));
01899 
01900     Loop* lp                          = new Loop(loopspecname,divisions,cyclic,valuegen,discrete_levels);
01901     loops.push_back(lp);
01902     
01903     /* Add new SPM to each region for this dimension */    
01904     if (registermap) {
01905       if (num_bins>0)
01906         for (SPMRs::iterator s=spmrs.begin(); s!=spmrs.end(); s++)
01907           (*s)->create_spm(name,*lp,num_bins,measure_distribution,weighted_average,cyclic,selectivity_scale);
01908       else
01909         message(Msg::Warning, "Can't register a map for " + name +
01910                 " because it has no valid values (num_bins==" + String::stringrep(num_bins) +")");
01911     }
01912   }
01913   
01914   /* Give the user an idea how long this will take */
01915   const int num_loop_iterations =  std::accumulate(ISEQ(loops),1,&accum_num_calls<int,Loop>);
01916   message(Msg::Notify, "Presenting " + String::stringrep(num_loop_iterations) + " inputs");
01917   
01918   /* Execute the specified nested loops of dimensions to gather the raw data */
01919   measure_stimulus_map_iteration<Loops,SPMRs> iteration(input_command,loops,spmrs);
01920   LoopSpecs_ExecuteNested(loops, loops.begin(), iteration);
01921 
01922   /* Register a map plot for each dimension measured. */
01923   for (SPMRs::iterator s=spmrs.begin(); s!=spmrs.end(); s++) {
01924     const string warning = (*s)->register_maps();
01925     if (warning!="") message(Msg::Warning, warning);
01926   }
01927   
01928   Generic::delete_contents(loops);
01929   Generic::delete_contents(spmrs);
01930   
01931   return true;
01932 }
01933 
01934 
01938 cmdstat NeuralRegionMap::cmd_save_snapshot( CMD_ARGS )
01939 {  
01940   CMD_ARG_PARAMS(save_snapshot);
01941   const string plotgroup        = "SavedState"; /* Hard-coded */
01942   const string filename_format  = arglist.next(argparams.get_with_default("filename",string()));
01943   RegionManagerList regions     = retrieve_matching_regions(argparams);
01944   const bool   verbose          = argparams.get_with_default("verbose",True);
01945 
01946   for (RegionManagerList::iterator r=regions.begin(); r!=regions.end(); r++) {
01947     message((verbose? Msg::Notify : Msg::Verbose), "Saving state of " + (*r)->region()->name());
01948     define_globals(*r,Uninitialized,Uninitialized,plotgroup);
01949     (*r)->region()->save_state(filenamebase(plotgroup,filename_format));
01950     define_globals();
01951   }
01952   
01953   CMD_ARG_ASSERT_EMPTY;
01954   return CMD_NO_ERROR;
01955 }
01956 
01957 
01958 
01959 
01960 
01967 bool NeuralRegionMap::restore_state(const ParamMap& argparams,
01968                                     const int iteration, const string& filename)
01969 {
01970   RegionManagerList regions     = retrieve_matching_regions(argparams);
01971   const string plotgroup        = "SavedState"; /* Hard-coded */
01972   const bool   verbose          = argparams.get_with_default("verbose",True);
01973   bool status=false;
01974 
01975   for (RegionManagerList::iterator r=regions.begin(); r!=regions.end(); r++) {
01976     message((verbose? Msg::Notify : Msg::Verbose), "Restoring state of " + (*r)->region()->name());
01977     define_globals(*r,Uninitialized,Uninitialized,plotgroup);
01978     const bool newstatus = (*r)->region()->
01979       restore_state(iteration,filenamebase(plotgroup,filename));
01980     if (newstatus) status=true;
01981     define_globals();
01982   }
01983   
01984   return status;
01985 }
01986 
01987 
01988 
01989 cmdstat NeuralRegionMap::cmd_kill_connections( CMD_ARGS )
01990 {
01991   CMD_ARG_PARAMS(kill_connections);
01992   RegionManagerList regions     = retrieve_matching_regions(argparams);
01993   const bool   verbose          = argparams.get_with_default("verbose",True);
01994 
01995   for (RegionManagerList::iterator r=regions.begin(); r!=regions.end(); r++) {
01996     message((verbose? Msg::Notify : Msg::Verbose), "Killing connections in " + (*r)->region()->name());
01997     (*r)->region()->prune();
01998   }
01999   
02000   CMD_ARG_ASSERT_EMPTY;
02001   return CMD_NO_ERROR;
02002 }
02003 
02004 
02005 cmdstat NeuralRegionMap::cmd_map_statistics( CMD_ARGS )
02006 {
02007   CMD_ARG_PARAMS(map_statistics);
02008 
02009   const string mapname          = arglist.next(argparams.get_with_default("name",string("")));
02010 
02011   /* Currently the num_bins aren't useful to change, but if this command
02012      is extended they would be needed.. */
02013   //const int  divisions        = argparams.get_with_default("divisions",1);
02014   const int    divisions        = 1;
02015   const int    spec_num_bins    = argparams.get_with_default("num_bins",1);
02016   const bool   cyclic           = argparams.get_with_default("cyclic",True);
02017   const int    num_bins         = (spec_num_bins>0? spec_num_bins :
02018                                    (cyclic? divisions : divisions+1));
02019   const bool   verbose          = argparams.get_with_default("verbose",True);
02020   const bool   reset            = argparams.get_with_default("reset",False);
02021   const bool   cumulative       = argparams.get_with_default("cumulative",False);
02022   const bool   horizontal       = argparams.get_with_default("horizontal",True);
02023   const string label            = argparams.get_with_default("label",string());
02024   const bool   kurtosis         = argparams.get_with_default("kurtosis",False); /* yschoe */
02025   const bool   min_max          = argparams.get_with_default("min_max",False); /* yschoe */
02026   const string lineend          = label+"\n";
02027 
02028   RegionManagerList regions     = retrieve_matching_regions(argparams);
02029   
02030   static double cumulative_sum  = 0;
02031   static int    cumulative_count= 0;
02032 
02033   if (reset) {
02034     cumulative_sum=0;
02035     cumulative_count=0;
02036     return CMD_NO_ERROR;
02037   }
02038 
02039   /* String formatting */
02040   typedef String::StreamFormat SF;
02041   SF magsf (13,' ', 2,true ); /* Formatting for magnitudes */
02042   SF headsf(13,'_',-1,false); /* Formatting for headings   */
02043   SF strsf (14,' ',-1,false); /* Formatting for strings    */
02044   const string header = String::stringrep("",headsf);
02045 
02046   
02047   /* Print column headers, if needed */ 
02048   if (cumulative_count==0 || verbose) {
02049     for (RegionManagerList::iterator r=regions.begin(); r!=regions.end(); r++) {
02050       message(Msg::Requested,
02051               String::stringrep("Region",           strsf) +
02052               String::stringrep("Map",              strsf) +
02053               String::stringrep("Sum",              strsf) +
02054               (cumulative?
02055                String::stringrep("CumulativeAvg",   strsf) : "") +
02056               (min_max? /* yschoe */
02057                String::stringrep("Min",             strsf) +
02058                String::stringrep("Max",             strsf) : "") +
02059               (kurtosis? /* yschoe */
02060                String::stringrep("Kurtosis",        strsf) : "") +
02061               "  ",false);
02062       if (!horizontal) break;
02063     }
02064     message(Msg::Requested,"\n",false);
02065     
02066     for (RegionManagerList::iterator r=regions.begin(); r!=regions.end(); r++) {
02067       message(Msg::Requested,
02068               String::stringrep(header.c_str(),     strsf) +
02069               String::stringrep(header.c_str(),     strsf) +
02070               String::stringrep(header.c_str(),     strsf) +
02071               (cumulative?
02072                String::stringrep(header.c_str(),    strsf) : "") +
02073               (min_max? /* yschoe */
02074                String::stringrep(header.c_str(),    strsf) +
02075                String::stringrep(header.c_str(),    strsf) : "") +
02076               (kurtosis? /* yschoe */
02077                String::stringrep(header.c_str(),    strsf) : "") + 
02078               "  ",false);
02079       if (!horizontal) break;
02080     }
02081     message(Msg::Requested,"\n",false);
02082   }
02083 
02084   
02085   /* Measure and print statistics for each region */
02086   for (RegionManagerList::iterator r=regions.begin(); r!=regions.end(); r++) {
02087     const NeuralRegionManager* rm = *r;
02088     const NeuralRegion::MapBaseType* map = rm->region()->table().getptr(mapname);
02089     if (!map) continue;
02090   
02091     typedef Histo::OneDBinList<> Histogram;
02092     Histogram histo(num_bins);
02093     double tmp_kurt = 0.0; /* yschoe : store kurtosis value */
02094     double tmp_sum  = 0.0; /* yschoe : store sum value */
02095     double tmp_std  = 0.0; /* yschoe : store std value */
02096     double tmp_var  = 0.0; /* yschoe : store var value */
02097     double tmp_mean = 0.0; /* yschoe : store mean value */
02098     double min      = 1e20; /* yschoe */
02099     double max      = -1e20; /* yschoe */
02100 
02101     for   (int r=0; r<map->nrows(); r++)
02102       for (int c=0; c<map->ncols(); c++) {
02103         NeuralRegion::Magnitude val     = mat::elem(*map,r,c);
02104         NeuralRegion::Magnitude bin_mag = val; // Could accept any map here
02105         Histogram::size_type bin = (cyclic ?
02106                                     histo.bin_number(bin_mag) :
02107                                     histo.bin_number_inclusive(bin_mag));
02108         histo.add(bin,val);
02109         if (kurtosis) { /* yschoe */
02110           tmp_sum += val;       
02111         }
02112 
02113         if (min_max) {
02114           min = MIN(min,val);
02115           max = MAX(max,val);
02116         }
02117       }
02118 
02119     /* std(x)      = sqrt(sum((x-mean(x))^2)/(size(x)-1)); */
02120     /* kurtosis(x) = sum((x-mean(x))^4)/(size(x)*std(x)^4)-3; */
02121     if (kurtosis) { /* yschoe */
02122         tmp_mean = tmp_sum / (map->nrows()*map->ncols());       
02123 
02124         for   (int r=0; r<map->nrows(); r++)
02125           for (int c=0; c<map->ncols(); c++) {
02126             NeuralRegion::Magnitude val     = mat::elem(*map,r,c);
02127             NeuralRegion::Magnitude diff_val = val - tmp_mean;
02128             tmp_var += diff_val * diff_val;
02129             tmp_kurt += diff_val * diff_val * diff_val * diff_val;
02130           }
02131 
02132         if (tmp_var == 0 || (map->nrows()*map->ncols()<=1) ) {
02133           message(Msg::Error,"Division by zero; kurtosis undefined");
02134           tmp_kurt = 0.0;
02135         } else {
02136           tmp_var = tmp_var/(map->nrows()*map->ncols()-1);
02137           tmp_kurt = tmp_kurt / (map->nrows()*map->ncols()*tmp_var*tmp_var) - 3.0;
02138           tmp_std  = sqrt(tmp_var);
02139         }
02140     } 
02141 
02142     const double sum      = histo.sum_value();
02143     const string sumstr   = String::stringrep(sum,magsf);
02144     const double kurt     = tmp_kurt; /* yschoe */
02145     cumulative_sum += sum;
02146     cumulative_count++;
02147     message(  Msg::Requested,
02148               String::stringrep(rm->region()->name().c_str(), strsf) +
02149               String::stringrep(mapname.c_str(),    strsf) +
02150               String::stringrep(sum,                magsf) + " " +
02151               (cumulative? String::stringrep(cumulative_sum/cumulative_count, magsf) + " " : "") +
02152               (min_max? String::stringrep(min,magsf) + " " +
02153                         String::stringrep(max,magsf) + " " : "") + /* yschoe */
02154               (kurtosis? String::stringrep(kurt,magsf) + " " : "") + /* yschoe */
02155               (horizontal? "  " : lineend),false);
02156     
02157     /* Other quantities that would be useful to show:
02158     
02159        Min  histo.min_value()
02160        Avg  histo.average_value()
02161        Max  histo.max_value()
02162        Wsel (cyclic ? histo.vector_selectivity() : histo.relative_selectivity(),magsf)
02163        Wavg (cyclic ? histo.vector_direction()   : histo.weighted_average(),magsf)
02164   
02165      However, most of these operate on the values in a bin instead of
02166      all values encountered, which would be confusing.  Could extend
02167      Histogram to store the actual min, max, etc. values; presumably the
02168      above member function names would need to change to e.g.
02169      max_bin_value() for clarity.
02170     */
02171     
02172     //Could plot histogram as well 
02173 
02174   }
02175   if (horizontal) message(Msg::Requested,lineend,false);
02176     
02177   CMD_ARG_ASSERT_EMPTY;
02178   return CMD_NO_ERROR;
02179 }
02180 
02181 
02182 
02183 
02185 cmdstat NeuralRegionMap::cmd_backproject( CMD_ARGS )
02186 {  
02187   CMD_ARG_PARAMS(backproject);
02188 
02189   RegionManagerList regions     = retrieve_matching_regions(argparams);
02190   const bool   verbose          = argparams.get_with_default("verbose",True);
02191   bool  status  = True;
02192 
02193   // we need to backproject from the highest region, i.e. in reverse order
02194   for (RegionManagerList::reverse_iterator r=regions.rbegin(); r!=regions.rend(); r++) {
02195     if ((*r)->region()->is_internal()) {
02196         message((verbose? Msg::Notify : Msg::Verbose), "Backprojecting from " + (*r)->region()->name());
02197         InternalNeuralRegion* ir = dynamic_cast<InternalNeuralRegion*>((*r)->region());
02198         if (ir) {
02199                 ir->backproject();
02200         } else {
02201                 status = False;
02202         }
02203     }
02204   }
02205   
02206   CMD_ARG_ASSERT_EMPTY;
02207   return (status ? CMD_NO_ERROR : CMD_PARAMETER_ERROR);
02208 }
02209 
02210 #ifdef OBJ_LISSOM
02211 
02212 cmdstat NeuralRegionMap::cmd_resp_to_residual( CMD_ARGS )
02213 {  
02214   CMD_ARG_PARAMS(resp_to_residual);
02215 
02216   RegionManagerList regions     = retrieve_matching_regions(argparams);
02217   const bool   verbose          = argparams.get_with_default("verbose",True);
02218   bool  status  = True;
02219 
02220   // Propagate the residuals forward into the output of the target map.
02221   // Also add in lateral response here.
02222   for (RegionManagerList::iterator i=regions.begin(); i!=regions.end(); i++) {
02223 
02224         message((verbose? Msg::Notify : Msg::Verbose), "Calculating response to residual in " + (*i)->region()->name());
02225         InternalNeuralRegion* ir = dynamic_cast<InternalNeuralRegion*>((*i)->region());
02226         if (ir) {
02227                 ir->resp_to_residual();
02228         } else {
02229                 status = False;
02230         }
02231   }
02232   
02233   CMD_ARG_ASSERT_EMPTY;
02234   return (status ? CMD_NO_ERROR : CMD_PARAMETER_ERROR);
02235 }
02236 
02239 cmdstat NeuralRegionMap::cmd_train_obj_weights( CMD_ARGS )
02240 {  
02241   CMD_ARG_PARAMS(train_obj_weights);
02242 
02243   RegionManagerList regions     = retrieve_matching_regions(argparams);
02244   const bool   verbose          = argparams.get_with_default("verbose",True);
02245   bool  status  = True;
02246 
02247   for (RegionManagerList::iterator i=regions.begin(); i!=regions.end(); i++) {
02248 
02249         message((verbose? Msg::Notify : Msg::Verbose), "Training obj_weights in " + (*i)->region()->name());
02250         InternalNeuralRegion* ir = dynamic_cast<InternalNeuralRegion*>((*i)->region());
02251         if (ir) {
02252                 // update weights and normalize
02253                 ir->train_obj_weights();
02254         } else {
02255                 status = False;
02256         }
02257   }
02258   
02259   CMD_ARG_ASSERT_EMPTY;
02260   return (status ? CMD_NO_ERROR : CMD_PARAMETER_ERROR);
02261 }
02262 
02264 cmdstat NeuralRegionMap::cmd_randomize_lat_wts( CMD_ARGS )
02265 {  
02266   CMD_ARG_PARAMS(randomize_lat_wts);
02267 
02268   RegionManagerList regions     = retrieve_matching_regions(argparams);
02269   const bool   verbose          = argparams.get_with_default("verbose",True);
02270   bool  status  = True;
02271 
02272   for (RegionManagerList::iterator i=regions.begin(); i!=regions.end(); i++) {
02273 
02274         message((verbose? Msg::Notify : Msg::Verbose), "Randomizing lat wts in " + (*i)->region()->name());
02275         InternalNeuralRegion* ir = dynamic_cast<InternalNeuralRegion*>((*i)->region());
02276         if (ir) {
02277                 // update weights and noramlize
02278                 ir->randomize_lat_wts();
02279         } else {
02280                 status = False;
02281         }
02282   }
02283   
02284   CMD_ARG_ASSERT_EMPTY;
02285   return (status ? CMD_NO_ERROR : CMD_PARAMETER_ERROR);
02286 }
02287 #endif /* OBJ_LISSOM */
02288 

Generated on Mon Jan 20 02:35:45 2003 for RF-LISSOM by doxygen1.3-rc2