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

analyze.c

Go to the documentation of this file.
00001 
00007 #include <math.h>
00008 #include <string.h>
00009 #include <time.h>
00010 #include <ctype.h>
00011 
00012 #include "ipc.h"
00013 #include "cmdparam.h"
00014 #include "lissom.h"
00015 #include "kernel.h"
00016 #include "globals.h"
00017 #include "vgen.h"
00018 #include "tilt.h"
00019 #include "ppm_draw.h"
00020 #include "fit_gauss.h"
00021 #include "file_io.h"
00022 #include "analyze.h"
00023 
00024 
00025 
00026 /******************************************************************************/
00027 /* Defines and typedefs                                                       */
00028 /******************************************************************************/
00029 
00031 #define SAVE_OR_PPM_ONLY
00032 
00034 #define SAVE_WTS_PPM_ONLY
00035 
00036 #define MAPLE   1
00037 #define MATH    2
00038 
00039 #define OR_INPUT_RESPONSE 0
00040 #define OR_GAUSSFIT       1
00041 #define OR_MAX_METHOD     1
00042 
00043                               
00044 
00045 #define NMAP_FEATURES   50
00046 #define NSELECTIVITIES  10
00047 
00049 #define NUM_BUBBLE_AREAS 2
00050 
00051 /* Measure two types of OR features, max and min */
00052 #define ORF_MIN 0
00053 #define ORF_MAX 1
00054 #define NUM_OR_FEATURE_TYPES 2
00055 
00056 #define GAUSSIAN_LEN    7.0      
00057 #define GAUSSIAN_WIDTH  1.5      
00060 /* The record type for OR map features */
00061 typedef struct                   
00062 {
00063   int i,j;                       
00064   double or_selectivity ;        
00065   int or_preference;             
00066   int phase, freq;               
00067   double od;                     
00068 } Map_Feature;
00069 
00070 /* Histogram structure */
00071 typedef struct                   
00072 {
00073   double value;
00074   int count;
00075 }Histo;
00076 
00077 
00092 #define ACTIVE_RN (RN-2*retina_edge_buffer)
00093 
00094 #define NUMBER_TO_FREQ(freqnumber)   ((double)(2*rf_radius+1)/(double)ACTIVE_RN * sp_min_frequency * M_PI/(double)ACTIVE_RN * (double)(sp_num_frequencies/(double)(freqnumber)))
00095 
00096 #define NUMBER_TO_PHASE(phasenumber) ((((double)(phasenumber))/sp_num_phases ) * 2.0 * M_PI)
00097 #define PHASE_TO_NUMBER(phase)       ((int)((phase)*sp_num_phases/(2.0*M_PI)))
00098 
00099 
00100 
00101 /******************************************************************************/
00102 /* Global parameters                                                          */
00103 /******************************************************************************/
00104 
00105 int    save_images_from_measure_or_pref=0;
00106 
00107 int    or_pref_method=Uninitialized;
00108 double sp_min_frequency=10;
00109 int    sp_num_frequencies=Uninitialized;
00110 int    sp_num_phases=Uninitialized;
00111 int    sp_random_phases=False;
00112 
00113 /******************************************************************************/
00114 /* Global variables                                                           */
00115 /******************************************************************************/
00116 
00117 int    end_dynamic=MAXITERATION;            
00118 double final_bubblewidth = 0.0;             
00119 double gaussfit_array[RNMAX][RNMAX];        
00120 double gaussian[RNMAX][RNMAX];              
00121 double init_bubblewidth  = 0.0;             
00122 int    lesion_radius;                       
00123 double max_resp[EYE_ARRAY_SIZE][NROWS][NMAX];
00124 double max_resp_angle[EYE_ARRAY_SIZE][NROWS][NMAX][MAX_NUM_ANGLES];
00125 double od_pref[NMAX][NMAX];                 
00126 int    od_dumped = Uninitialized;           
00127 int    or_dumped = Uninitialized;           
00128 Map_Feature or_features[NUM_OR_FEATURE_TYPES][NMAP_FEATURES];  /* MAX & MIN map features*/
00129 double or_select[EYE_ARRAY_SIZE][NMAX][NMAX];
00130 int    or_pref[EYE_ARRAY_SIZE][NMAX][NMAX]; 
00131 Histo  OR_histo[NSELECTIVITIES][NUM_BUBBLE_AREAS][MAX_NUM_ANGLES][MAX_NUM_ANGLES]; 
00132 FILE*  peakfile;
00133 double peak_aff_wt[MAX_NUM_EYES][NROWS][NMAX]; 
00134 double rf_threshold=0.0;                    
00135 int    rf_i=0, rf_j=0;                      
00136 int    sp_freq[EYE_ARRAY_SIZE][NMAX][NMAX]; 
00137 int    sp_phase[EYE_ARRAY_SIZE][NMAX][NMAX];
00138 int    start_dynamic=MAXITERATION;          
00139 Wts    temp_wts;
00140 int    ui_dynamic;                          
00141 int    uj_dynamic; 
00142 int    width_analysis_end  =MAXITERATION;   
00143 int    width_analysis_start=MAXITERATION;   
00147 #ifdef ALLOW_COPY_AND_RESTORE
00148 #include <string.h>
00149 Wts    backup_wts[NROWS][NMAX];
00150 Neuron backup_map[NMAX][NMAX];
00151 double backup_or_select[EYE_ARRAY_SIZE][NMAX][NMAX];
00152 int    backup_or_pref[EYE_ARRAY_SIZE][NMAX][NMAX];
00153 int    backup_sp_freq[EYE_ARRAY_SIZE][NMAX][NMAX];
00154 int    backup_sp_phase[EYE_ARRAY_SIZE][NMAX][NMAX];
00155 #endif
00156     
00157 
00158 
00159 /******************************************************************************/
00160 /* Command prototypes                                                         */
00161 /******************************************************************************/
00162 
00163 CMD_DECLARE(analyze_bubblewidth);
00164 CMD_DECLARE(connection_statistics);
00165 CMD_DECLARE(copy_network);
00166 CMD_DECLARE(find_bubblewidth);
00167 CMD_DECLARE(kurtosis_contrast);
00168 CMD_DECLARE(measure_od_pref);
00169 CMD_DECLARE(measure_or_pref);
00170 CMD_DECLARE(OD_features);
00171 CMD_DECLARE(OR_features);
00172 CMD_DECLARE(orientation_contrast);
00173 CMD_DECLARE(plot_od_pref);
00174 CMD_DECLARE(plot_or_pref);
00175 CMD_DECLARE(restore_network);
00176 CMD_DECLARE(SP_features);
00177 CMD_DECLARE(spatial_contrast);
00178 CMD_DECLARE(visualize);
00179 
00180 
00181 
00182 /******************************************************************************/
00183 /* Prototypes for private functions                                           */
00184 /******************************************************************************/
00185 
00186 void   compute_mexhat(int i, int j);
00187 void   find_max(double *max_or_select, double *max_od, int low_index, int high_index);
00188 int    find_OD_maxmin(int *nexamples, int low, int high);
00189 int    find_OR_maxmin(int *nexamples, int low, int high);
00190 void   find_peak_aff_wts(int low,int high);
00191 int    find_sp_maxmin(int *nexamples, int low, int high);
00192 double gauss_2d(double x, double y, double r, double theta, double cx, double cy, double sigmax, double sigmay);
00193 void   gaussfit_preferences(Neuron nmap[NMAX][NMAX], int low, int high);
00194 void   graph_histo(int sel, double or_division);
00195 void   graph_od(int ui, int uj, int output_routine);
00196 void   graph_wts(int ui, int uj, int output_routine);
00197 void   input_response(Neuron nmap[NMAX][NMAX], double response[MAX_NUM_EYES][NROWS][NMAX], int eye, int input_eye, int low, int high, double peak_scale);
00198 void   input_response_ij(Neuron nmap[NMAX][NMAX], double response[MAX_NUM_EYES][NMAX][NMAX], int eye, int ui, int uj);
00199 void   kurtosis(double map_act[NMAX][NMAX], double *input_v, int lowk, int lowl, int highk, int highl, double *kurt_act, double *kurt_inp);
00200 void   maple(FILE *fp, l_weight *weights, int radius, int ui, int uj, const char *title, const char *zaxis);
00201 void   mathematica(FILE *fp, l_weight *weights, int radius, int ui, int uj);
00202 void   measure_rf(int ui, int uj);
00203 void   moment(double *data, int n, double sum, double *ave, double *adev, double *sdev, double *svar, double *curt);
00204 void   or_preferences(Neuron nmap[NMAX][NMAX], int low, int high);
00205 void   or_selectivity(int low, int high);
00206 void   oriented_rfinput(double angle, double sigmax, double sigmay, int c_1, int c_2, double scale);
00207 void   plot_afferent_wts(int output_routine, FILE *fp, int ui, int uj, char *title, const char *zaxis);
00208 void   save_ascii_or_pref_file(void);
00209 void   sine_grating_input(int eye, double freq, double phase, double angle);
00210 
00211 
00212 
00213 /******************************************************************************/
00214 /* Initialization hook                                                        */
00215 /******************************************************************************/
00216 
00217 void  analyze_init_hook( void )
00218 {
00219   /* CMD_DEFINE(0,analyze_bubblewidth); Not completed */
00220 
00221   CMD_DOC(connection_statistics,"init_network",0,
00222           "%s [<num_selectivities> [<num_OD_values> [<low> [<high>]]]]",
00223           "Derives lateral connection statistics, by first estimating average bubble\n"
00224           "width.  Then calculates OR and OD preferences and selectivity.  Then\n"
00225           "calls for statistics, specifying how many histogram points are required,\n"
00226           "and which central region of the network should be used for statistics.\n"
00227           "This routine can be called only after measure_or_pref has been called.\n"
00228           "The first two parameters are the number of histogram divisions.  The\n"
00229           "last two arguments specify the part of the net to focus on -- collects\n"
00230           "statistics in the square region (<low>,<low>) to (<high>,<high>).\n\n"
00231           
00232           "Not fully implemented or debugged.");
00233 
00234 #ifdef ALLOW_COPY_AND_RESTORE
00235   CMD_DOC(copy_network,"init_network",0,"%s",
00236           "Copy network to scratch area for later recovery.");
00237 #endif
00238   
00239   /* CMD_DOC(find_bubblewidth,"init_network",2,"find_bubblewidth <start> <end>",
00240       "Sets the iterations between which to find widths.");  Not completed */
00241   
00242   CMD_DOC(kurtosis_contrast,"init_network",5,
00243           "%s <x> <y> <num_contrasts> <max_contrast> <preset_wts>",
00244 
00245           "Measure the change for unit (x,y) in kurtosis with contrast for input\n"
00246           "activity and settled activity.  The result should indicate how\n"
00247           "selectivity is maintained in spite of contrast.  Kurtosis is measured\n"
00248           "with the wts of the given neuron as input, but multiplied by different\n"         
00249           "scale factors.  <preset_wts> lets you initialize the lateral weights\n"
00250           "before measuring contrast: value of 1 = random wts, 2 = gaussian\n"
00251           "weights (in which case preset_sigma_exc and preset_sigma_inh must\n"
00252           "be set explicitly).");
00253   
00254   CMD_DOC(measure_od_pref,"init_network",0, "%s [<low> [<high>]]",
00255           "Computes current ocular dominance preferences based on the afferent weights,\n"
00256           "then calls plot_od_pref.");
00257   
00258   CMD_DOC(measure_or_pref,"init_network",0, "%s [<low> [<high> [<plot_filename>]]]",
00259           "Computes and saves current orientation (and related) preferences.  The\n"
00260           "information computed is saved in memory, and is used by many other analysis\n"
00261           "and graphing routines, so it is important to make sure that this command\n"
00262           "has been called recently before using such routines.  Depending upon parameter\n"
00263           "settings, this command can take several minutes to complete.\n\n"
00264 
00265           "When measurement is complete, the command plot_or_pref is called automatically.\n"
00266           "The data can also be saved as an ASCII file, if desired.  In this case each\n"
00267           "text file contains data for all eyes; the or_file contains (or_pref,or_select)\n"
00268           "pairs for each neuron, and the sp_file contains (freq,phase) pairs.\n\n"
00269           
00270           "The <low> and <high> arguments specify the part of the net to focus on --\n"
00271           "it processes data in the square region (<low>,<low>) to (<high>,<high>).\n"
00272           "When specifying a cortical region that is less then the full cortex, make\n"
00273           "sure that the data outside the region will never be used.  OR pref data is\n"
00274           "used by many other routines, and if some uncomputed data becomes part of\n"
00275           "an orientation average, for instance, results will be incorrect without\n"
00276           "any warning.  So it's generally safest to compute data for the entire\n"
00277           "cortex (except for debugging runs) even though that can be very slow.\n\n"
00278           
00279           "See the help for parameter or_pref_method for information about options.\n"
00280           "Be careful to check for the artifacts present with the method chosen;\n"
00281           "no such method is perfect, since orientation preference is not a well-\n"
00282           "defined mathematical concept, just a handy abstraction.");
00283 
00284   CMD_DOC(OD_features,"init_network",0,"%s [<low> [<high> [<nexamples>]]]",
00285           "This command dumps the weights of the significant features in the\n"
00286           "ocular dominance map, such as regions of lowest and highest OD values.\n"
00287           "Arguments specify the part of the net to focus on -- looks for\n"
00288           "<nexamples> in the square region (<low>,<low>) to (<high>,<high>).");
00289   
00290   CMD_DOC(OR_features,"init_network",0,"%s [<low> [<high> [<nexamples> [<calc_select>]]]]",
00291           "Dumps the weights of the significant features in the orientation map,\n"
00292           "such as regions of lowest and highest OR selectivity, pinwheel centers,\n"
00293           "saddle points etc.  Must be called only after measure_or_pref has been\n"
00294           "called, to ensure that orientation selectivities have been already \n"
00295           "calculated.  Also measures the selectivity for the most tuned neuron.\n"
00296           "Arguments specify the part of the net to focus on -- looks for nexamples\n"
00297           "in the square region (<low>,<low>) to (<high>,<high>).  The last argument\n"
00298           "specifies whether to measure the selectivity with contrast for the max\n"
00299           "and min neurons.");
00300   
00301   CMD_DOC(orientation_contrast,"init_network",4,"%s <i> <j> <ncontrasts> <max_contrast>",
00302           "Measures the change with contrast in neural response for unit (i,j) for\n"
00303           "input activity and settled activity.  Uses gaussians of various widths.\n"
00304           "Subtracts gaussians from mean.  Multiplies receptive field with half the\n"
00305           "peak wt subtracted with the gaussian to get the input response.\n"
00306           "Multiplies the input response with various values and gets the map\n"
00307           "response after lateral interaction.  Stores the response of this neuron\n"
00308           "for all these values of contrast.");
00309   
00310   CMD_DOC(plot_od_pref,"init_network",0, "%s [<low> [<high> [<filename>]]]",
00311           "Plots ocular dominance preferences last computed by measure_od_pref.  This is\n"
00312           "automatically called by measure_od_pref, but it can be called explicitly\n"
00313           "to create another plot, e.g. for a subregion or with different PPM parameters,\n"
00314           "without having to recompute the ocular dominance data.\n\n"
00315           
00316           "If the filename is omitted, one is constructed using a standard format.\n"
00317           "If one is given but starts with a period (e.g. \".ocular.ppm\"), a complete\n"
00318           "filename is constructed by appending the given suffix to the current value\n"
00319           "of the filebase parameter.");
00320 
00321   CMD_DOC(plot_or_pref,"init_network",0, "%s [<low> [<high> [<filename>] [<selectivity_only]]]",
00322           "Plots orientation preferences last computed by measure_or_pref.  This is\n"
00323           "automatically called by measure_or_pref, but it can be called explicitly to\n"
00324           "create another plot, e.g. for a subregion, to get only the selectivity data\n"
00325           "or with different PPM parameters, without having to recompute the orientation\n"
00326           "data.\n\n"
00327 
00328           "Orientation plots are shown for each eye from left to right, plus a combined\n"
00329           "(a.k.a. binocular) plot at the end, if num_eyes>1. After each plot is a\n"
00330           "histogram of the orientation distribution in the map, if ppm_histograms is\n"
00331           "true.  Other PPM parameters such as ppm_orientation_subplot and (if \n"
00332           "ppm_line_plots) ppm_line_orientation_subplot also apply.\n\n"
00333 
00334           "If the filename is omitted, one is constructed using a standard format.\n"
00335           "If one is given but starts with a period (e.g. \".orient.ppm\"), a complete\n"
00336           "filename is constructed by appending the given suffix to the current value\n"
00337           "of the filebase parameter.");
00338   
00339 #ifdef ALLOW_COPY_AND_RESTORE
00340   CMD_DOC(restore_network,"init_network",0,"%s",
00341           "Restore network from scratch area.");
00342 #endif
00343   
00344   CMD_DOC(SP_features,"init_network",0,"%s [<low> [<high> [<nexamples> [<calc_select>]]]]",
00345           "Dump the weights of the significant features in the spatial frequency\n"
00346           "map, such as regions of lowest and highest sp selectivity.  Must\n"
00347           "be called only after measure_or_pref has been called, to ensure that\n"
00348           "spatial frequency values have been already calculated.  Arguments\n"
00349           "specify the part of the net to focus on -- looks for nexamples in the\n"
00350           "square region (<low>,<low>) to (<high>,<high>).  The last argument\n"
00351           "specifies whether to measure the selectivity with contrast for the max\n"
00352           "and min neurons.");
00353   
00354   CMD_DOC(spatial_contrast,"init_network",6,
00355           "spatial_contrast <x> <y> <ncontrasts> <nfrequencies> <max_contrast> <max_sp_freq>",
00356           "Measure the change with contrast in neural response for unit (x,y) for\n"
00357           "input activity and settled activity.\n\n"
00358           
00359           "Not fully implemented or debugged.");
00360   
00361   CMD_DOC(visualize,"init_network",2,"%s <i> <j> [<output_routine>]",
00362           "Dumps weights for neuron (i,j) at the current iteration in a format\n"
00363           "suitable for external graphing programs.  By default, the format is\n"
00364           "suitable for MAPLE (value 1), but a 2 may be passed to get Mathematica\n"
00365           "format.");
00366   
00367 
00368   
00369   CONST_I(OR_Gaussfit,OR_GAUSSFIT,False,
00370           "Orientation preference computation method which uses NPSOL to fit\n"
00371           "Gaussians to the afferent weights.  NPSOL fitting is very accurate and\n"
00372           "often faster than getting comparable quality without it, and most importantly\n"
00373           "does not require any parameters to be tweaked to get good results.  However,\n"
00374           "NPSOL is a separate commercial package, and can't be distributed with LISSOM.\n\n"
00375           
00376           "Caveats: (1) spatial frequency and phase information has not been verified,\n"
00377           "so only try to use orientation and orientation selectivity information.  \n"
00378           "(2) The combined (binocular) preference is computed as a vector sum of the\n"
00379           "monocular preferences, which may not correspond to any single orientation\n"
00380           "that could be presented to both eyes simultaneously to get a maximal response\n"
00381           "(particularly if the preferences for each eye differ substantially.)\n\n"
00382           
00383           "Note that Gaussian-fitting works one neuron at a time, so any artifacts\n"
00384           "from a failure in the fitting algorithm are likely to appear as single\n"
00385           "speckles that differ from their neighbors.");
00386           
00387   CONST_I(OR_InputResponse,OR_INPUT_RESPONSE,False,
00388           "Orientation preference computation method which presents sine gratings\n"
00389           "of each angle, frequency, and phase, making a note of which one gave\n"
00390           "the maximum response (without lateral interactions) for each neuron.\n"
00391           "The number of test patterns used depends upon the parameters or_num_angles,\n"
00392           "sp_num_frequencies, and sp_num_phases.  The particular patterns chosen depend\n"
00393           "upon the parameters sp_min_frequency and sp_random_phases; these values may\n"
00394           "need to be tweaked for different network architectures.  Assuming\n"
00395           "appropriate patterns are chosen, the map is more accurate when more patterns\n"
00396           "are used, but it takes longer to compute.  The default values usually\n"
00397           "achieve reasonable accuracy in a reasonable time, but you may want to tune\n"
00398           "tune them for better accuracy or less time as desired.  See the parameter\n"
00399           "save_images_from_measure_or_pref when debugging such issues.\n\n"
00400 
00401           "This method computes data for the entire cortex at once by presenting a\n"
00402           "finite number of patterns on the retina, so artifacts usually show up as\n"
00403           "square outlines the scaled size of a single retinal pixel. Such artifacts\n"
00404           "are particularly obvious near the borders and when there is no receptive\n"
00405           "field scatter.  Also note that when too few patterns are presented, the map\n"
00406           "will be patchy even if orientation preference really changes smoothly.\n"
00407           "If measuring an untrained network with random afferent weights, the value\n"
00408           "computed is usually not particularly meaningful, since it is determined more\n"
00409           "by the coarse pixel outline of the receptive field than by weight values.\n\n"
00410           
00411           "Note that this method overwrites the input vectors and/or the current\n"
00412           "network activities, so it should be called only at the very beginning\n"
00413           "or end of a training iteration.");
00414 
00415   PARAM_L(PARAM_INT,   or_dumped,Uninitialized,
00416           "Use for debugging only -- setting this to an iteration makes the program\n"
00417           "believe that measure_or_pref has been called, even though (e.g. for multiple\n"
00418           "debugging runs) you don't want to spend the time actually doing it.");
00419   
00420   PARAM_I(PARAM_INT,   save_images_from_measure_or_pref,0,MAX_NUM_ANGLES,
00421           "Use nonzero values for debugging only -- if nonzero, saves some or all of\n"
00422           "the images used when calculating orientation preferences, overwriting the\n"
00423           "current network activity in the process.  If set to 1, every such image\n"
00424           "will be saved, which for typical settings of or_num_angles,\n"
00425           "sp_num_frequencies, and sp_num_phases will generate a huge number of images\n"
00426           "(possibly in the thousands!).  More often you will want to set this parameter\n"
00427           "to some higher value, e.g. 10, so that only images from every 10th angle (for\n"
00428           "example) will be saved.  Since these images would normally be used to make\n"
00429           "sure that the spatial frequencies are reasonable (since angles and phases are\n"
00430           "straightforward), you may want (also or instead) to reduce or_num_angles and\n"
00431           "sp_num_phases to correspondingly reduce the number of images generated.\n\n"
00432           
00433           "The image format is similar to that of plot_activity, and is controlled by the\n"
00434           "same parameters.  On the left is the retinal image presented in this iteration\n"
00435           "(only one eye's retina is used for drawing).  The next panel shows the\n"
00436           "response of the left eye's weights to the input before it is passed through\n"
00437           "the activation function, which is just a simple multiplication of the weights\n"
00438           "with the input image.  (This value is what is used to determine orientation\n"
00439           "preference for OR_InputResponse, without influences from the sigmoid function\n"
00440           "or settling due to the lateral interactions.)  The next panel shows the\n"
00441           "combined response of all eyes.  Panels for the remaining retinae follow, but\n"
00442           "are currently unused.");
00443 
00444   PARAM_L(PARAM_DOUBLE,sp_min_frequency,0,
00445           "The minimum spatial frequency to use during testing of the response of the\n"
00446           "network to various gratings, e.g. for measure_or_pref.  The scale is relative\n"
00447           "to the anatomical RF width (2*rf_radius+1) and (inversely) to the area of the\n"
00448           "retina, so it's simplest to consider it an arbitrary relative scale for a\n"
00449           "given network.  The default is suitable when sp_num_frequencies is 1, but when\n"
00450           "more frequencies are used you may wish to start with a lower value to cover a\n"
00451           "wider range, instead of having only medium and high frequencies.");
00452 
00453   PARAM_L(PARAM_INT,   sp_num_frequencies,0,
00454           "The number of spatial frequencies to use during testing of the response of the\n"
00455           "network to various patterns, e.g. for measure_or_pref.  The frequencies range\n"
00456           "from sp_min_frequency to sp_num_frequencies*sp_min_frequency.  The\n"
00457           "intermediate frequencies are chosen using the formula sp_min_frequency * \n"
00458           "sp_num_frequencies/n, where n is an integer from 1 to sp_num_frequencies,\n"
00459           "and thus the spacing is nonlinear.");
00460   /* Defaults to not varying spatial frequency */
00461   params_define_default_expr("sp_num_frequencies","1");
00462 
00463   PARAM_L(PARAM_INT,   sp_num_phases,0,
00464           "The number of different spatial phases (i.e. positions) to use during testing\n"
00465           "the response of the network to various patterns, e.g. for measure_or_pref.  If\n"
00466           "sp_random_phases is False, the retina is divided evenly by this number, and\n"
00467           "each of the resulting positions is used; otherwise sp_num_phases are chosen at\n"
00468           "random from across the retina.  The Nyquist minimum to avoid aliasing is RN*2,\n"
00469           "but often lower values suffice; RN/2 usually shows artifacts but is still\n"
00470           "usable.");
00471   /* Well under the sampling theorem limit of 2*RN, for speed: */
00472   params_define_default_expr("sp_num_phases","RN"); 
00473 
00474   PARAM_I(PARAM_BOOL,  sp_random_phases,False,True,
00475           "If True, random phase values are chosen when testing the response of the\n"
00476           "network to various patterns, e.g. for measure_or_pref.  Otherwise regularly\n"
00477           "spaced positions are used.");
00478 
00479   PARAM_I(PARAM_INT,   or_pref_method,0,OR_MAX_METHOD,
00480           "Method to use for computing the orientation map, OR_InputResponse by default.\n"
00481           "See the help for the currently-supported methods for more details:\n"
00482           "  OR_InputResponse,OR_Gaussfit");
00483   params_define_default_expr("or_pref_method","OR_InputResponse");
00484 }
00485 
00486 
00487 
00488 /******************************************************************************/
00489 /* Commands                                                                   */
00490 /******************************************************************************/
00491 
00492 
00493 cmdstat cmd_copy_network( CMD_ARGS )
00494 {
00495   (void)argc; /* ignored */
00496   (void)argv; /* ignored */
00497 
00498 #ifdef ALLOW_COPY_AND_RESTORE
00499   memmove(backup_wts,        wts,        sizeof(wts));
00500   memmove(backup_map,        map,        sizeof(map));
00501   memmove(backup_or_select,  or_select,  sizeof(or_select));
00502   memmove(backup_or_pref,    or_pref,    sizeof(or_pref));
00503   memmove(backup_sp_freq,    sp_freq,    sizeof(sp_freq));
00504   memmove(backup_sp_phase,   sp_phase,   sizeof(sp_phase));
00505   
00506   ipc_notify(IPC_ONE,IPC_STD,"Copied network to scratch area");
00507 #else
00508   ipc_notify(IPC_ONE,IPC_ERROR,"Can't copy network, since not compiled with scratch area support");
00509 #endif
00510   
00511   return CMD_NO_ERROR;
00512 }
00513 
00514 
00515 
00516 cmdstat cmd_restore_network( CMD_ARGS )
00517 {
00518   (void)argc; /* ignored */
00519   (void)argv; /* ignored */
00520 
00521 #ifdef ALLOW_COPY_AND_RESTORE
00522   memmove(wts,        backup_wts,        sizeof(wts));
00523   memmove(map,        backup_map,        sizeof(map));
00524   memmove(or_select,  backup_or_select,  sizeof(or_select));
00525   memmove(or_pref,    backup_or_pref,    sizeof(or_pref));
00526   memmove(sp_freq,    backup_sp_freq,    sizeof(sp_freq));
00527   memmove(sp_phase,   backup_sp_phase,   sizeof(sp_phase));
00528   
00529   ipc_notify(IPC_ONE,IPC_STD,"Restored network from scratch area");
00530 #else
00531   ipc_notify(IPC_ONE,IPC_ERROR,"Can't restore network, since not compiled with scratch area support");
00532 #endif
00533   
00534   return CMD_NO_ERROR;
00535 }
00536 
00537 
00538 
00546 cmdstat cmd_orientation_contrast( CMD_ARGS )
00547 {
00548   int an, c, i, j, eye, p;
00549   double angle, contrast,prev_contrast;
00550   static int centerx, centery;
00551   
00552   const int    ui            = cmdi(argv[0]); /* Neuron's contrast response */
00553   const int    uj            = cmdi(argv[1]); /*   to be calculated.        */
00554   const int    ncontrasts    = cmdi(argv[2]); /* Number of contrasts to try */
00555   const double max_contrast  = cmdf(argv[3]); /* Maximum contrast to be tested for */
00556   const int    pe            = PEFORROW(ui);
00557 
00558   (void)argc; /* ignored */
00559 
00560   ABORT_IF_NEURON_OUTSIDE_CORTEX(ui,uj);
00561   
00562   ipc_log(IPC_ONE,"Orientation selectivity information for neuron (%d,%d) at iteration %d:",
00563           ui,uj,iteration);
00564   
00565   for (an=1; an <= or_num_angles; an++){
00566     ipc_log(IPC_ONE,"\nangle=%d\n",an);
00567     
00568     if (PEISME(pe)) {
00569       centerx = cortex_map[ui][uj].centerx;
00570       centery = cortex_map[ui][uj].centery;
00571     }
00572     
00573     ipc_barrier();  
00574     ipc_get(&centerx, IPC_INT, 1, pe);
00575     ipc_get(&centery, IPC_INT, 1, pe);
00576     angle = M_PI * an/(double)or_num_angles; 
00577     oriented_rfinput(angle,GAUSSIAN_LEN,GAUSSIAN_WIDTH,centerx,centery,1.0); 
00578     if (PEISME(pe))
00579       ipc_log(IPC_ALL,"Or_preference = %f\n",
00580               (double)(angle/M_PI*or_num_angles));
00581     
00582     prev_contrast = 1.0;
00583     for (c=1; c<=ncontrasts; c++){
00584       contrast = (double)c/(double)ncontrasts * max_contrast;
00585       for (i=0; i<RN; i++)
00586         for (j=0; j<RN; j++)
00587           for (eye=0; eye<num_eyes; eye++)
00588             input_vectors[INP_INDEX(eye,i,j)] *= (contrast/prev_contrast);
00589       
00590       prev_contrast = contrast; /* Update prev_contrast */
00591       ipc_barrier();
00592       settle_responses(False);
00593       
00594       if (PEISME(pe))
00595         ipc_log(IPC_ALL,"Contrast=%f,angle=%d,response=%f\n",
00596                 (double)contrast,an,(double)map_activity[ui][uj]);
00597       
00598       ipc_barrier();
00599       
00600       for(p=0; p< NPEs; p++)    /* Get map_activity from each processor */
00601         for(i=0; i<nrows; i++)  /* 10 Apr 96 J.A.B. -- I wonder why this uses prev_map_activity? */
00602           ipc_get_to(prev_map_activity[ARBITRARY_MAPROW(i,p)],map_activity[ARBITRARY_MAPROW(i,p)],IPC_DOUBLE,N,p);
00603       
00604       ipc_log(IPC_ONE,"[%f,%f],",(double)contrast,(double)prev_map_activity[ui][uj]);
00605 
00606       /* if (c == ncontrasts) save_image_data(); */
00607       ipc_barrier();
00608     }
00609   } 
00610   ipc_log(IPC_ONE,"\n\n");
00611   ipc_notify(IPC_ONE,IPC_STD,"Orientation contrast information written to log file");
00612                
00613   return CMD_NO_ERROR;
00614 }
00615 
00616 
00617 
00618 cmdstat cmd_spatial_contrast( CMD_ARGS )
00619 {
00620   double inp_resp[EYE_ARRAY_SIZE][NROWS][NMAX];              /* To calculate inp_resp */
00621   int x, y, c, sp, i, j, k, l, eye, row;
00622   double xsq, ysq, sigmax, contrast;
00623   int ts, lowk, lowl, highk, highl;
00624 
00625   const int    ui            = cmdi(argv[0]); /* Neuron's contrast response to be calculated */
00626   const int    uj            = cmdi(argv[1]); 
00627   const int    ncontrasts    = cmdi(argv[2]); /* Number of contrasts & spatial freq to try */
00628   const int    nfrequencies  = cmdi(argv[3]);
00629   const double max_contrast  = cmdf(argv[4]); /* Maximum contrast to be tested for */
00630   const double max_spfreq    = cmdf(argv[5]); /* Maximum width of sigma to be tested */
00631   const int    pe            = PEFORROW(ui);
00632   const int    therow        = LOCALROW(ui); 
00633 
00634   int peak_k = 0;
00635   int peak_l = 0;
00636 
00637   (void)argc; /* ignored */
00638   
00639   ABORT_IF_NEURON_OUTSIDE_CORTEX(ui,uj);
00640   
00641   ipc_log(IPC_ONE,"Spatial contrast information for neuron (%d,%d) at iteration %d:\n",
00642           ui,uj,iteration);
00643                
00644   sigmax = (double)rf_radius;
00645   find_peak_aff_wts(0,N-1); /* Find the peak wts for each neuron */
00646 
00647   for (sp=1; sp <= nfrequencies; sp++){
00648     sigmax = (double)sp/(double)nfrequencies * max_spfreq;
00649     if (PEISME(pe)){  /* The PE of the neuron */
00650     
00651       lowk = cortex_map[ui][uj].centerx-rf_radius; if (lowk < 0   ) lowk = 0;
00652       highk= cortex_map[ui][uj].centerx+rf_radius; if (highk >= RN) highk= RN-1;
00653       lowl = cortex_map[ui][uj].centery-rf_radius; if (lowl < 0   ) lowl = 0;
00654       highl= cortex_map[ui][uj].centery+rf_radius; if (highl >= RN) highl= RN-1;
00655         
00656       for (k=lowk; k <=highk; k++) /* Search to find location of peak in first eye */
00657         for (l=lowl; l<=highl; l++)
00658           if (cortex_map[ui][uj].weights[0][k-lowk][l-lowl] == peak_aff_wt[0][therow][uj]){
00659             peak_k = k; peak_l = l;
00660           }
00661       /* Now, generate gaussian input centered on this peak. Subtract 0.5 */
00662       for (x=0; x<RN; x++)
00663         for (y=0; y<RN; y++){
00664           double value;
00665           xsq = (double)(x-peak_k); xsq *= xsq;
00666           ysq = (double)(y-peak_l); xsq *= xsq;
00667           value = exp( -((xsq+ysq)/(sigmax*sigmax))) - 0.5;
00668           for (eye=0; eye<num_eyes; eye++)
00669             input_vectors[INP_INDEX(eye,x,y)] = value;
00670         }
00671     }
00672     ipc_barrier();  /* Sync and get the new inputs to all processors */
00673     ipc_get(input_vectors, IPC_DOUBLE, RNMAX*RNMAX*num_eyes, pe);
00674     input_response(cortex_map,inp_resp,combined_eyes,0,0,N-1,0.5); /* The combined response from all eyes */
00675   
00676     for (c=1; c<=ncontrasts; c++){
00677       contrast = (double)c/(double)ncontrasts * max_contrast;
00678       for(i=0; i<nrows; i++){  /* Add up input and lateral activations. */
00679         row = MAPROW(i);
00680         for(j=0; j<N; j++)
00681           resp_to_inp[row][j] = contrast * inp_resp[combined_eyes][i][j];
00682       }
00683       /* Repeat the code in settle_responses here to calculate response */
00684       initialize_markers();
00685       initialize_actlists();
00686       for (ts=1; ts<=tsettle; ts++){ /* Let network settle */
00687         compute_responses(ts);
00688         ipc_barrier();
00689       }
00690       if (PEISME(pe)) /* Print the data to the log file */
00691         ipc_log(IPC_ALL,"Contrast=%f,sp_freq=%f,response=%f\n",
00692                 (double)contrast,(double)sigmax,(double)map_activity[ui][uj]);
00693     }
00694   }
00695 
00696   ipc_notify(IPC_ONE,IPC_STD,"Spatial contrast information written to log file");
00697                
00698   return CMD_NO_ERROR;
00699 }
00700 
00701 
00702 
00703 cmdstat cmd_kurtosis_contrast( CMD_ARGS )
00704 {
00705   int i,k,l,eye,ts,c,p;
00706   double contrast, kurt_act, kurt_inp;
00707 
00708   const int    ui            = cmdi(argv[0]);
00709   const int    uj            = cmdi(argv[1]);
00710   const int    ncontrasts    = cmdi(argv[2]); 
00711   const double max_contrast  = cmdf(argv[3]);
00712   const int    preset_wts    = cmdi(argv[4]);
00713 
00714   const int radius = (rf_radius+1)*N/RN; /* rf_radius mapped to the network */
00715   const int rlowk  = MAX(ui-radius,0  );
00716   const int rhighk = MIN(ui+radius,N-1);
00717   const int rlowl  = MAX(uj-radius,0  );
00718   const int rhighl = MIN(uj+radius,N-1);
00719   const int pe     = PEFORROW(ui);
00720     
00721   (void)argc; /* ignored */
00722   
00723   ABORT_IF_NEURON_OUTSIDE_CORTEX(ui,uj);
00724 
00725   ipc_log(IPC_ONE,"Kurtosis contrast information for neuron (%d,%d) at iteration %d:\n",
00726           ui,uj,iteration);
00727                
00728   ipc_log(IPC_ONE,"[");
00729 
00730   /* Presetting the lateral weights overwrites the previous wts */
00731   if (preset_wts > 0) {
00732     preset_lat_wts = preset_wts-1;
00733     setup_latw();
00734   }
00735 
00736   for (c=1; c<=ncontrasts; c++){
00737     contrast = (double)c/(double)ncontrasts * max_contrast;
00738 
00739     /* Present the afferent wts of the given neuron as input */
00740     if (PEISME(pe)){                 /* The PE of the neuron */   
00741       const int lowk  = MAX(cortex_map[ui][uj].centerx-rf_radius,0   );
00742       const int highk = MIN(cortex_map[ui][uj].centerx+rf_radius,RN-1);
00743       const int lowl  = MAX(cortex_map[ui][uj].centery-rf_radius,0   );
00744       const int highl = MIN(cortex_map[ui][uj].centery+rf_radius,RN-1);
00745       
00746       for (k=0; k<RN; k++)
00747         for (l=0; l<RN; l++)
00748           for (eye=0; eye<num_eyes; eye++)
00749             input_vectors[INP_INDEX(eye,k,l)] = 0.0;
00750       
00751       for (k=lowk; k <=highk; k++)
00752         for (l=lowl; l<=highl; l++)
00753           for (eye=0; eye<num_eyes; eye++){
00754             assert (INP_INDEX(eye,k,l) >= INP_INDEX(eye,  0,0));
00755             assert (INP_INDEX(eye,k,l) <  INP_INDEX(eye+1,0,0));
00756         
00757             input_vectors[INP_INDEX(eye,k,l)] = contrast*cortex_map[ui][uj].weights[eye][k-lowk][l-lowl];
00758           }
00759     }
00760 
00761     ipc_barrier();           /* Sync and get the new inputs to all processors */
00762 
00763     if (!PEISME(pe)) ipc_get(input_vectors, IPC_DOUBLE, RNMAX*RNMAX*num_eyes, pe);
00764 
00765     /* Repeat the code in settle_responses here to calculate response */
00766     response_to_input();
00767     initialize_markers();
00768     initialize_actlists();
00769     
00770     ipc_log(IPC_ONE,"******* contrast=%f *********\n",contrast);
00771     ipc_barrier();
00772     for (ts=1; ts<=tsettle; ts++){      /* Let network settle */
00773       compute_responses(ts);
00774       if ((AMPARENTPE) && (ts==2)){
00775         ipc_log(IPC_ALL,"Initial:\n");
00776         kurtosis(prev_map_activity,input_vectors,rlowk,rlowl,rhighk,rhighl,&kurt_act,&kurt_inp);      
00777         ipc_log(IPC_ALL,"[%f,%f],",(double)contrast,(double)kurt_act);
00778       }
00779       ipc_barrier();
00780     }
00781     if (AMPARENTPE){
00782       for(p=0; p< NPEs; p++)    /* Get map_activity from each processor */
00783         for(i=0; i<nrows; i++)
00784           ipc_get_to(prev_map_activity[ARBITRARY_MAPROW(i,p)],map_activity[ARBITRARY_MAPROW(i,p)],IPC_DOUBLE,N,p);
00785       ipc_log(IPC_ALL,"Final:\n");
00786       kurtosis(prev_map_activity,input_vectors,rlowk,rlowl,rhighk,rhighl,&kurt_act,&kurt_inp);
00787       ipc_log(IPC_ALL,"[%f,%f],",(double)contrast,(double)kurt_act);
00788     }
00789     ipc_barrier();
00790 /*    if (c%5==1) save_image_data(); */
00791   }
00792 
00793   ipc_log(IPC_ONE,"]\n\n");
00794   ipc_notify(IPC_ONE,IPC_STD,"Kurtosis contrast information written to log file");
00795   
00796   return CMD_NO_ERROR;
00797 }
00798 
00799 
00801 cmdstat cmd_find_bubblewidth( CMD_ARGS ) 
00802 {
00803   width_analysis_start = cmdi(argv[0]);
00804   width_analysis_end   = cmdi(argv[1]);
00805 
00806   (void)argc; /* ignored */
00807     
00808   init_bubblewidth  = 0.0;
00809   final_bubblewidth = 0.0;
00810   
00811   { /* Set up hook */
00812     char specifier[20];
00813     const char *args[]={"after_learning",NULL,"analyze_bubblewidth"};
00814     snprintf(specifier,20,"%d-%d",width_analysis_start,width_analysis_end);
00815     args[1]=specifier;
00816     cmd_hook(3,args);
00817   }    
00818 
00819   ipc_notify(IPC_ONE,IPC_STD,"Finding bubblewidth: start=%d, end=%d",
00820              (int)width_analysis_start, (int)width_analysis_end );
00821 
00822   return CMD_NO_ERROR;
00823 } 
00824 
00825 
00826 
00827 cmdstat cmd_analyze_bubblewidth( CMD_ARGS )
00828 {
00829   double  average_init, average_final;
00830   static double  overall_average_init, overall_average_final;
00831   int i,j;
00832   int start[2], end[2];        /* To track start and end of bubble */
00833   int count[2];                /* Two activity-width counters      */
00834   double width[2][NROWS];  /* NROWS*2  width values            */
00835 
00836   (void)argc; /* ignored */
00837   (void)argv; /* ignored */
00838   
00839   if (iteration < width_analysis_end) 
00840     {
00841  
00842       for (i=0; i<nrows; i++){
00843         const int row = MAPROW(i);
00844 
00845         width[0][i] = width[1][i] = 0.0; 
00846         count[0] = count[1] = 0;
00847 /* --------------------------------------- To be debugged -------------------
00848         for(j=0; j<N;){
00849           for(; (resp_to_inp[row][j] <= delta_[current_phase]) && (j<N); j++);
00850           start[0] = j;
00851           for(; (resp_to_inp[row][j] > delta_[current_phase]) && (j<N); j++);
00852           end[0] = j;
00853           if (end[0] > start[0]){
00854             width[0][i] += (double)(end[0] - start[0]);
00855             count[0]++;
00856           }
00857         }       
00858 
00859         if (count[0] > 0)
00860           width[0][i] /= ((double)count[0]);
00861         else width[0][i] = 0.0;
00862 -------------------------------------------------------------------------   */
00863         for(j=0; j<N;){
00864           for(;(map_activity[row][j]<=0.0) && (j<N); j++);
00865           start[1] = j;
00866           for(;(map_activity[row][j] >0.0) && (j<N); j++);
00867           end[1] = j;
00868           if (end[1] > start[1]){
00869             width[1][i] += (double)(end[1] - start[1]);
00870             count[1]++;
00871           }
00872         }
00873 
00874         if (count[1] > 0)
00875           width[1][i] /= ((double)count[1]);
00876         else width[1][i] = 0.0;
00877 /*
00878         ipc_notify(IPC_ALL,IPC_VERBOSE,"ROW=%d: width0=%f,width1=%f: count[0]=%d,count[1]=%d: No problem till here",
00879         row,(double)width[0][i],(double)width[1][i],count[0],count[1]);
00880 */
00881       } /*
00882       ipc_notify(IPC_ALL,IPC_VERBOSE,"No problem till here"); */
00883       average_init = average_final = 0.0;
00884       count[0] = count[1] = 0;
00885       for (i=0; i<nrows; i++){       /* Calculate averages over all rows */
00886         if (width[0][i] > 0.0){
00887           average_init += width[0][i];
00888           count[0]++;
00889         }
00890         if (width[1][i] > 0.0){
00891           average_final += width[1][i];
00892           count[1]++;
00893         }
00894       }
00895       if (count[0] > 0)
00896         average_init /= (double)count[0]; 
00897       if (count[1] > 0)
00898         average_final /= (double)count[1];
00899 
00900       if (iteration==width_analysis_start)
00901         overall_average_init = overall_average_final=0.0;
00902       overall_average_init  += average_init;
00903       overall_average_final += average_final;
00904     }
00905   else if ((iteration == width_analysis_end) && (iteration > width_analysis_start)){
00906     int pe;
00907     
00908     overall_average_init /= (double)(width_analysis_end-width_analysis_start);
00909     overall_average_final/= (double)(width_analysis_end-width_analysis_start);
00910 
00911     ipc_barrier();
00912     count[0] = count[1] = 0;
00913     for (pe=0; pe<NPEs; pe++)
00914       if (!PEISME(pe)){
00915         ipc_get(&overall_average_init, IPC_DOUBLE, 1, pe);
00916         ipc_get(&overall_average_final, IPC_DOUBLE, 1, pe);
00917         if (overall_average_init > 0.0){
00918           init_bubblewidth  += overall_average_init;
00919           count[0]++;
00920         }
00921         if (overall_average_final > 0.0){
00922           final_bubblewidth += overall_average_final;
00923           count[1]++;
00924         }
00925       }
00926     if (count[0] > 0)
00927       init_bubblewidth  /= (double)count[0];
00928     if (count[1] > 0)
00929       final_bubblewidth /= (double)count[1];
00930     
00931     ipc_notify(IPC_ONE,IPC_STD,"init_bubblewidth=%f, final_bubblewidth=%f",
00932                (double)init_bubblewidth,(double)final_bubblewidth);
00933   }
00934 
00935   return CMD_NO_ERROR;
00936 }
00937 
00938 
00939 
00940 /******************************************************************************/
00941 /* Private functions                                                          */
00942 /******************************************************************************/
00943 
00951 void kurtosis(double map_act[NMAX][NMAX], double *input_v, int lowk,
00952               int lowl, int highk, int highl, double *kurt_act, double
00953               *kurt_inp)  
00954 {
00955   /* low* and high* are the upper and lower indices defining the region */
00956   
00957   int i,j,eye;
00958   int count=0;
00959   int active_neurons=0;
00960   double sum=0.0,value;
00961   double ave, adev, sdev, svar;
00962 #if (NMAX*NMAX >= RNMAX*RNMAX*num_eyes)  /* Max data size is MAX(sizeof(map),sizeof(input_vectors)) */
00963   double data[NMAX*NMAX];    
00964 #else
00965   double data[RNMAX*RNMAX*MAX_NUM_EYES];   
00966 #endif
00967   
00968   /* Calculate kurtosis for network */
00969   for (i=lowk; i<=highk; i++)                    /* calc histogram */
00970     for (j=lowl; j<=highl; j++){           
00971       sum += (value= data[count++] = map_act[i][j]);
00972       if (value > 0.0) active_neurons++;
00973     }
00974 
00975   moment(data,count,sum,&ave,&adev,&sdev,&svar,kurt_act);
00976   ipc_log(IPC_ALL,"active_neurons=%d, sum_act=%f, ave_act=%f, kurt_act=%f\n",
00977           active_neurons,sum,ave,(double)(*kurt_act));
00978 
00979   sum = 0.0;
00980   count=0;   
00981   for (i=0; i< RN; i++)
00982     for (j=0; j < RN; j++)
00983       for (eye=0; eye<num_eyes; eye++)
00984         sum += (data[count++] = input_v[INP_INDEX(eye,i,j)]);
00985 
00986   moment(data,count,sum,&ave,&adev,&sdev,&svar,kurt_inp);
00987   ipc_log(IPC_ALL,"sum_inp=%f, ave_inp=%f, kurt_inp=%f, kurt_ratio=%f\n",
00988              sum,ave,(double)(*kurt_inp),(double)((*kurt_act)/(*kurt_inp)));
00989 }
00990 
00992 void moment(double *data, int n, double sum, double *ave, double *adev, double *sdev, double *svar, double *curt)
00993 {
00994   int j;
00995   float s,p;
00996   
00997   if (n <= 1) {
00998     ipc_notify(IPC_ALL,IPC_ERROR,"moment: n (%d) must be at least 2",n);
00999     return;
01000   }
01001   
01002   s=sum;
01003   *ave=s/(double)n;
01004   *adev=(*svar)=(*curt)=0.0;
01005   
01006   for (j=0;j<n;j++) {
01007     *adev += fabs(s=data[j]-(*ave));
01008     *svar += (p=s*s);
01009     *curt += (p *= s*s);
01010   }
01011   
01012   *adev /= n;
01013   *svar /= (n-1);
01014   *sdev=sqrt(*svar);
01015   
01016   if (*svar) 
01017     *curt=(*curt)/(n*(*svar)*(*svar))-3.0;
01018   else
01019     ipc_log(IPC_ALL,"moment: No skew/kurtosis when variance == 0\n");
01020 }
01021 
01022 
01023 
01029 void sine_grating_input(int eye, double freq, double phase, double angle)
01030 {
01031   const double sint = sin(angle);
01032   const double cost = cos(angle);
01033 
01034   int x,y;
01035   for(x=0; x < RN; x++) {
01036     const   double cos_comp = x*sint;
01037     for(y=0; y < RN; y++) {
01038       const double sin_comp = y*cost;
01039       input_vectors[INP_INDEX(eye,x,RN-y-1)] = sin( freq*(cos_comp-sin_comp+1.0) + phase);
01040     }
01041   }
01042 }
01043 
01044 
01045 
01046 void oriented_rfinput(double angle, double sigmax, double sigmay, int cx, int cy, double scale)
01047 {
01048   int x,y,eye;
01049   double xsq, ysq, value;
01050   for (x=0; x<RN; x++)
01051     for (y=0; y<RN; y++){
01052       xsq  =  (double)(x-cx) * cos(angle) + (double)(y-cy) * sin(angle); 
01053       xsq *= xsq/(sigmax*sigmax);      
01054       ysq  = -(double)(x-cx) * sin(angle) + (double)(y-cy) * cos(angle); 
01055       ysq *= ysq/(sigmay*sigmay);
01056       value = scale*exp(-(xsq+ysq));
01057       for (eye=0; eye<num_eyes; eye++)
01058         input_vectors[INP_INDEX(eye,x,y)] = value;
01059     }
01060 }
01061 
01062 
01070 void measure_rf(int ui, int uj)
01071 {
01072 
01073   char buf[50];
01074   FILE *fp;
01075   double response[WTMAX][WTMAX]; /* Response at each location */
01076   int i,k,l,x,y,eye,cx,cy,idx; double max_angle;    
01077   double resp, maxresp; static double angle;
01078   static int lowk,lowl,highk,highl,centerx,centery; 
01079   
01080   const int pe = PEFORROW(ui); /* The processor for the given neuron */
01081   
01082   if (PEISME(pe)){ /* This processor generates the input */
01083     centerx = cortex_map[ui][uj].centerx;
01084     centery = cortex_map[ui][uj].centery;    
01085     lowk    = MAX(centerx-rf_radius,0   );
01086     highk   = MIN(centerx+rf_radius,RN-1);
01087     lowl    = MAX(centery-rf_radius,0   );
01088     highl   = MIN(centery+rf_radius,RN-1);    
01089 
01090     for (x=0; x<WTMAX; x++) for (y=0; y<WTMAX; y++) response[x][y] = 0.0;
01091 
01092     /* Search and find out the optimal orientation for the gaussian */ 
01093 
01094     for(i=0,max_angle=0.0,maxresp=0.0; i<or_num_angles; i++){
01095       angle = M_PI * i/(double)or_num_angles; 
01096       oriented_rfinput(angle,GAUSSIAN_LEN,GAUSSIAN_WIDTH,centerx,centery,1.3);
01097       
01098       resp=0.0;
01099       for (eye=0; eye<num_eyes; eye++)
01100         for (k=lowk; k <=highk; k++){
01101           idx = INP_INDEX(eye,k,lowl);
01102           assert (idx >= INP_INDEX(eye,0,0));
01103           assert (idx <  INP_INDEX(eye+1,0,0));
01104           
01105           for (l=lowl; l<=highl; l++,idx++)
01106             resp+= input_vectors[idx]*cortex_map[ui][uj].weights[eye][k-lowk][l-lowl];
01107         }
01108       if (resp > maxresp){maxresp=resp; max_angle = angle;}
01109     }
01110     angle = max_angle;
01111     ipc_notify(IPC_ALL,IPC_STD,"Or_preference = %f",(double)(angle/M_PI*(double)or_num_angles));
01112   }
01113   ipc_barrier();
01114   ipc_get(&lowk, IPC_INT, 1, pe)  ; ipc_get(&lowl, IPC_INT, 1, pe)  ;
01115   ipc_get(&highk, IPC_INT, 1, pe); ipc_get(&highl, IPC_INT, 1, pe);
01116   ipc_get(&angle, IPC_INT, 1, pe); ipc_get(&centerx, IPC_INT, 1, pe);
01117   ipc_get(&centery, IPC_INT, 1, pe);
01118 
01119   /* Move from left to right, erasing all activity closer to the center,
01120      and plot the response when activity is encountered. */
01121   
01122   for (cx=lowk; cx <= highk; cx++)
01123     for (cy = lowl; cy <=highl; cy++){ /* Generate inputs at these */
01124       oriented_rfinput(angle,GAUSSIAN_LEN,GAUSSIAN_WIDTH,cx,cy,1.0);
01125 
01126       if ((angle < M_PI_4) || (angle > (M_PI-M_PI_4))){ /* Vertical Input */
01127         if (cx < centerx)
01128           for (x=cx+1; x<RN; x++) /*Set all above current centerx to zero */
01129             for (y=0; y<RN; y++)
01130               for (eye=0; eye<num_eyes; eye++)
01131                 input_vectors[INP_INDEX(eye,x,y)] = 0.0;
01132         else
01133           for (x=0; x<cx; x++) /* Set all below current centerx to zero */
01134             for (y=0; y<RN; y++)
01135               for (eye=0; eye<num_eyes; eye++){
01136                 assert (INP_INDEX(eye,x,y) >= INP_INDEX(eye,  0,0));
01137                 assert (INP_INDEX(eye,x,y) <  INP_INDEX(eye+1,0,0));
01138                 
01139                 input_vectors[INP_INDEX(eye,x,y)] = 0.0;
01140               }
01141       }
01142       else{
01143         if (cy < centery)
01144           for (x=0; x<RN; x++) /*Set all above current centerx to zero */
01145             for (y=cy+1; y<RN; y++)
01146               for (eye=0; eye<num_eyes; eye++)
01147                 input_vectors[INP_INDEX(eye,x,y)] = 0.0;
01148         else
01149           for (x=0; x<RN; x++) /* Set all below current centerx to zero */
01150             for (y=0; y<cy; y++)
01151               for (eye=0; eye<num_eyes; eye++) {
01152                 assert (INP_INDEX(eye,x,y) >= INP_INDEX(eye,  0,0));
01153                 assert (INP_INDEX(eye,x,y) <  INP_INDEX(eye+1,0,0));
01154 
01155                 input_vectors[INP_INDEX(eye,x,y)] = 0.0;
01156               }
01157       }
01158       settle_responses(False);  /* Compute input resp, and settle */
01159       if (PEISME(pe))
01160         if (map_activity[ui][uj] > 0.0) 
01161           response[cx-lowk][cy-lowl] = map_activity[ui][uj];
01162       /*if ((cy == (highl+lowl)/2) && (cx == (highl+lowl)/2)) 
01163         save_image_data();  */
01164     }
01165 
01166   ipc_barrier();
01167   if (PEISME(pe)){
01168     sprintf(buf,"%s.%d_%d.drf",filebase,ui,uj);
01169     if ((fp=fopen(buf,"a"))==NULL)
01170       ipc_notify(IPC_ALL,IPC_ERROR,"Couldn't open DRF file: %s",buf);
01171 /*  ipc_notify(IPC_ALL,IPC_STD,"buf=%s",buf); */
01172     fprintf(fp,"%d %d %d %d\n",ui,uj,iteration,WTMAX);
01173     for(x=0; x<WTMAX; x++){
01174       for (y=0; y<WTMAX; y++)
01175         fprintf(fp,"%f ",(double)response[x][y]);
01176       fprintf(fp,"\n");
01177     }
01178     fclose(fp);
01179   }
01180   ipc_barrier();
01181 }
01182 
01183 
01184 
01185 void find_peak_aff_wts(int low, int high)
01186 {
01187   int i,j,k,l,eye;
01188   
01189   for(i=0; i<nrows; i++) {
01190     const int row = MAPROW(i);              /* calculate row index */
01191     if (row >= low && row <= high)
01192       for(j=low; j<=high; j++) { 
01193         const int lowk  = MAX(cortex_map[row][j].centerx-rf_radius,0   );
01194         const int highk = MIN(cortex_map[row][j].centerx+rf_radius,RN-1);
01195         const int lowl  = MAX(cortex_map[row][j].centery-rf_radius,0   );
01196         const int highl = MIN(cortex_map[row][j].centery+rf_radius,RN-1);
01197         
01198         for (eye=0; eye <num_eyes; eye++){
01199           double peak_wt = 0.0;
01200           
01201           for (k=lowk; k <=highk; k++) 
01202             for (l=lowl; l<=highl; l++)
01203               if (cortex_map[row][j].weights[eye][k-lowk][l-lowl] > peak_wt)
01204                 peak_wt = cortex_map[row][j].weights[eye][k-lowk][l-lowl];
01205           
01206           peak_aff_wt[eye][i][j] = peak_wt;
01207         }
01208       }
01209   }
01210 }
01211 
01212 
01213 
01215 void input_response(Neuron nmap[NMAX][NMAX], double response[MAX_NUM_EYES][NROWS][NMAX], int eye, int input_eye, int low, int high, double peak_scale)
01216 {
01217   int i,j,k,l;
01218   
01219 #ifdef CRAY
01220 #pragma _CRI cache_align j,k,l
01221 #endif
01222   
01223   for(i=0; i<nrows; i++){
01224     const int row = MAPROW(i);              /* calculate row index */
01225 #ifdef CRAY
01226 #pragma _CRI cache_align row
01227 #endif
01228     if (i>=low && i<=high)
01229       for(j=low; j<=high; j++) { 
01230         const int lowk   = MAX(nmap[row][j].centerx-rf_radius,0   );
01231         const int highk  = MIN(nmap[row][j].centerx+rf_radius,RN-1);
01232         const int lowl   = MAX(nmap[row][j].centery-rf_radius,0   );
01233         const int highl  = MIN(nmap[row][j].centery+rf_radius,RN-1);
01234         
01235         double resp = 0.0;
01236         response[eye][i][j]=0.0;
01237 #ifdef CRAY
01238 #pragma _CRI cache_align lowk,lowl,highk,highl
01239 #endif
01240         if ((eye != combined_eyes) || (combined_eyes == 0)){ /* Single eye response */
01241           const double peak_wt = peak_scale * peak_aff_wt[eye][i][j];
01242           for (k=lowk; k <=highk; k++)
01243             for (l=lowl; l<=highl; l++)
01244               resp += input_vectors[INP_INDEX(input_eye,k,l)] * 
01245                 (nmap[row][j].weights[eye][k-lowk][l-lowl] - peak_wt);
01246         }
01247         else { /* Combine responses from all eyes */
01248           double peak_wt[MAX_NUM_EYES];
01249           int e;
01250           
01251           for (e=0; e<num_eyes; e++)
01252             peak_wt[e] = peak_scale * peak_aff_wt[e][i][j];
01253           
01254           for (k=lowk; k <=highk; k++)
01255             for (l=lowl; l<=highl; l++){
01256               double value=0.0;
01257               for (e=0; e<num_eyes; e++){
01258                 value += nmap[row][j].weights[e][k-lowk][l-lowl] - peak_wt[e];
01259                 resp += input_vectors[INP_INDEX(input_eye,k,l)] * (value);
01260               }
01261             }
01262         }
01263         response[eye][i][j] = resp;
01264       }
01265   }
01266 }
01267 
01268 
01270 void input_response_ij(Neuron nmap[NMAX][NMAX], double response[MAX_NUM_EYES][NMAX][NMAX], int eye, int ui, int uj)
01271 {
01272   const int lowk  = MAX(nmap[ui][uj].centerx-rf_radius, 0   );
01273   const int highk = MIN(nmap[ui][uj].centerx+rf_radius, RN-1);
01274   const int lowl  = MAX(nmap[ui][uj].centery-rf_radius, 0   );
01275   const int highl = MIN(nmap[ui][uj].centery+rf_radius, RN-1);
01276 
01277   int k,l;
01278   
01279   response[eye][LOCALROW(ui)][uj] = 0.0;
01280   for (k=lowk; k <=highk; k++) 
01281     for (l=lowl; l<=highl; l++)
01282       response[eye][LOCALROW(ui)][uj] += input_vectors[INP_INDEX(0,k,l)] * 
01283         (nmap[ui][uj].weights[eye][k-lowk][l-lowl] -
01284                0.5 * peak_aff_wt[eye][ui][uj]);
01285 }
01286 
01287 
01288 
01306 void or_preferences(Neuron nmap[NMAX][NMAX], int low, int high)
01307 {
01308   int i,j,k,eye, freq, phase, angle;
01309   double inp_resp[EYE_ARRAY_SIZE][NROWS][NMAX];
01310   int num_gratings = or_num_angles*sp_num_frequencies*sp_num_phases;
01311   time_t last_msg_time = time(NULL);
01312 
01313   /* find_peak_aff_wts(low,high);*/ /* Determine peak aff wts to calculate inp resp */
01314 
01315   for (i=0; i<nrows; i++)
01316     for (j=0; j<N; j++){
01317       for (eye=0; eye<=combined_eyes; eye++) {
01318         max_resp[eye][i][j] = 0.0;
01319         for (k=0; k<or_num_angles; k++) 
01320           max_resp_angle[eye][i][j][k] = 0.0;
01321       }
01322     }
01323   
01324   ipc_notify(IPC_ONE,IPC_STD,"Calculating responses to %d sine gratings (%d angles, %d frequencies from %4.2f to %4.2f, and %d %sphases)",
01325              num_gratings,or_num_angles,sp_num_frequencies,
01326              (double)NUMBER_TO_FREQ(1),(double)NUMBER_TO_FREQ(sp_num_frequencies),
01327              sp_num_phases,(sp_random_phases ? "random " : ""));
01328   
01329   /* Clear init and settled responses for use in plotting (for debugging only!) */
01330   if (save_images_from_measure_or_pref && (low != 0 || high != N-1))
01331     for(i=0; i<N; i++)
01332       for(j=0; j<N; j++) 
01333         init_activity[i][j] = prev_map_activity[i][j] = 0;
01334   
01335   for(angle=0; angle < or_num_angles; angle++) {
01336     for(freq=sp_num_frequencies; freq >= 1; freq--) /* For the largest to smallest freq */
01337       for(phase=0; phase<sp_num_phases; phase++) {   /* For each spatial phase */
01338         
01339         const double actual_angle = DEGREES_TO_RADIANS(OR_PREF_TO_DEGREES(angle));
01340         const double actual_freq  = NUMBER_TO_FREQ(freq);
01341         const double actual_phase = (sp_random_phases ? shuffled_rand() : NUMBER_TO_PHASE(phase));
01342         const int    phase_number = PHASE_TO_NUMBER(actual_phase);
01343         
01344         /*
01345           Sets input vector for the first eye to sine grating; calculations
01346           must use only that eye's data.
01347         */
01348         sine_grating_input(0,actual_freq,actual_phase,actual_angle); 
01349         
01350         ipc_notify(IPC_ALL,IPC_OVERWHELM,
01351                    "Drawing %5.3f degree sine wave with freq=%5.4f and phase=%0.2f (%d,%d,%d)",
01352                    RADIANS_TO_DEGREES(actual_angle),actual_freq,actual_phase,freq,phase,angle);
01353         
01354         if (PROGRESS_REPORT_NEEDED(last_msg_time)) {
01355           last_msg_time = time(NULL);
01356           ipc_notify(IPC_ONE,IPC_STD,
01357                      "Sine-grating presentation %5.1f%% completed; showing angle %3d at %.24s",
01358                      100.0/num_gratings *
01359                      (angle*sp_num_frequencies*sp_num_phases +
01360                       (sp_num_frequencies-freq)*sp_num_phases +
01361                       phase),
01362                      (int)OR_PREF_TO_DEGREES(angle),ctime(&last_msg_time));
01363         }
01364 
01365         /* calculate resp for each eye to input in retina 0 */
01366         for (eye=0; eye<=combined_eyes; eye++) 
01367           input_response(nmap,inp_resp,eye,0,low,high,0.0);
01368 
01369         if (save_images_from_measure_or_pref && angle%save_images_from_measure_or_pref==0) {
01370           /*
01371             For debugging only; copy resp_to_input as if it were an init_activity
01372             so it can be plotted
01373           */
01374           for(i=0; i<nrows; i++){
01375             const int row = MAPROW(i);
01376             if (i>=low && i<=high)
01377               for(j=low; j<=high; j++) {
01378                 init_activity[row][j]     = inp_resp[0][i][j];
01379                 prev_map_activity[row][j] = inp_resp[combined_eyes][i][j];
01380               }
01381           }
01382           
01383           save_presentation_image(NULL,(double)DEGREES_TO_RADIANS(OR_PREF_TO_DEGREES(angle)),
01384                                   input_vectors, init_activity, prev_map_activity, 10*freq+phase);
01385         }
01386         
01387         for (i=0; i<nrows; i++){
01388           const int row = MAPROW(i);
01389           
01390           if (row >= low && row <= high)
01391             for (j=low; j<=high; j++){
01392               for (eye=0; eye<=combined_eyes; eye++) {        
01393                 if (inp_resp[eye][i][j] > max_resp[eye][i][j]){ /* Max overall */
01394                   max_resp[eye][i][j]   = inp_resp[eye][i][j];
01395                   or_pref[ eye][row][j] = angle;
01396                   sp_freq[ eye][row][j] = freq;
01397                   sp_phase[eye][row][j] = phase_number;
01398                 }
01399                 /* Set max responses for the particular angle */
01400                 if (inp_resp[eye][i][j] > max_resp_angle[eye][i][j][angle])
01401                   max_resp_angle[eye][i][j][angle] = inp_resp[eye][i][j]; 
01402               }
01403             }
01404         }
01405       }
01406   }
01407 }
01408 
01409 
01410 
01418 void or_selectivity(int low, int high)
01419 {
01420   int i,j,eye,angle;
01421   double mean_length[EYE_ARRAY_SIZE][NROWS][NMAX];   /* sum of squares of vector lengths */
01422   double v_sum[EYE_ARRAY_SIZE][NROWS][NMAX][2];      /* (x,y) components of the vectors  */
01423 
01424   for(i=0; i<nrows; i++)
01425     for (j=0; j<N; j++)
01426       for (eye=0; eye<=combined_eyes; eye++) {
01427         mean_length[eye][i][j] = 0.0;
01428         v_sum[eye][i][j][0]    = 0.0;
01429         v_sum[eye][i][j][1]    = 0.0; 
01430       }
01431 
01432   /* The v_sum part can be made faster by register load store type coding */
01433   for(i=0; i<nrows; i++)
01434     for (j=low; j<=high; j++) {             /* For each neuron */
01435       double vsx[EYE_ARRAY_SIZE];
01436       double vsy[EYE_ARRAY_SIZE];
01437       double mean[EYE_ARRAY_SIZE];
01438 
01439       for (eye=0; eye<=combined_eyes; eye++) {
01440         vsx[ eye] = 0;
01441         vsy[ eye] = 0;
01442         mean[eye] = 0;
01443       }
01444       
01445       for(angle=0; angle < or_num_angles; angle++) { /* For each angle  */
01446         const double actual_angle = 2.0*M_PI*angle/(double)or_num_angles;
01447         const double cos_angle = cos(actual_angle);
01448         const double sin_angle = sin(actual_angle);
01449         
01450         /* Add x and y components of the vector */
01451         for (eye=0; eye<=combined_eyes; eye++) {
01452           vsx[eye]  += max_resp_angle[eye][i][j][angle] * cos_angle;
01453           vsy[eye]  += max_resp_angle[eye][i][j][angle] * sin_angle;
01454           mean[eye] += max_resp_angle[eye][i][j][angle];
01455         }
01456       }
01457       for (eye=0; eye<=combined_eyes; eye++) {
01458         v_sum[eye][i][j][0] = vsx[eye];
01459         v_sum[eye][i][j][1] = vsy[eye]; 
01460         mean_length[eye][i][j] = mean[eye];
01461       }
01462     }
01463   
01464   ipc_barrier();
01465 
01466   for(i=0; i<nrows; i++){
01467     const int row = MAPROW(i);
01468 
01469     if (row >= low && row <= high)
01470       for (j=low; j<=high; j++)
01471         for (eye=0; eye<=combined_eyes; eye++) {
01472           const double reciprocal_mean = (mean_length[eye][i][j]== 0 ? 0 : 1.0/mean_length[eye][i][j]);
01473           const double vsq_0 = v_sum[eye][i][j][0] * v_sum[eye][i][j][0];
01474           const double vsq_1 = v_sum[eye][i][j][1] * v_sum[eye][i][j][1];
01475           or_select[eye][row][j]= sqrt((vsq_0+vsq_1)*reciprocal_mean);
01476         }
01477   }
01478 }
01479 
01480 
01481 
01483 cmdstat cmd_measure_od_pref( CMD_ARGS ) 
01484 {
01485   const int low           = (argc>0 ? cmdi(argv[0]) :                   0);
01486   const int high          = (argc>1 ? cmdi(argv[1]) :                 N-1);
01487 
01488   int i,status;
01489 
01490   ABORT_IF_RANGE_OUTSIDE_CORTEX(low,low,high,high);
01491   
01492   ipc_notify(IPC_ONE,IPC_STD,
01493              "Calculating ocular dominance preferences for map region (%d,%d) to (%d,%d)",
01494              low,low,high,high);
01495   
01496   /* Compute ocular dominance */
01497   od_preferences(od_pref,cortex_map);
01498   
01499   /* Send data to parent for saving the data in file    */
01500   if (!AMPARENTPE)
01501     for (i=0; i<nrows; i++)
01502       ipc_put( &(od_pref[MAPROW(i)][0]), IPC_DOUBLE, N, PARENTPE);
01503   
01504   ipc_barrier();          /* Ensure all data reaches parent PE */
01505 
01506   if (!AMPARENTPE)        /* Make sure every PE has the data for e.g. plotting */
01507     for (i=0; i<N; i++)
01508       ipc_get( &(od_pref[i][0]), IPC_DOUBLE, N, PARENTPE);
01509 
01510   od_dumped = (iteration==Uninitialized ? 1 : iteration); /* set to current iteration, if valid */
01511   
01512   status = cmd_plot_od_pref(MIN(argc,2),argv);
01513   
01514   return status;
01515 }
01516 
01517 
01518 
01527 void od_preferences(double pref[NMAX][NMAX], Neuron nmap[NMAX][NMAX])
01528 {
01529   int i,j,k,l,m,eye;
01530   
01531   for(i=0; i<nrows; i++){
01532     const int row = MAPROW(i);
01533 
01534     for (j=0; j<N; j++) {
01535       const int lowk  = MAX(nmap[row][j].centerx-rf_radius,0   );
01536       const int highk = MIN(nmap[row][j].centerx+rf_radius,RN-1);
01537       const int lowl  = MAX(nmap[row][j].centery-rf_radius,0   );
01538       const int highl = MIN(nmap[row][j].centery+rf_radius,RN-1);
01539       double total[MAX_NUM_EYES];
01540       double rtotal=0;
01541       
01542       /* Find the difference in total weights to each eye */
01543       for(m=0; m<num_eyes; m++){
01544         double tot = 0.0;
01545         for(k=lowk; k <= highk; k++)
01546           for(l=lowl; l <= highl; l++)
01547             tot += nmap[row][j].weights[m][k-lowk][l-lowl];
01548         total[m] = tot;
01549       }
01550       /*
01551         If num_eyes>2 then there should be a similar value
01552         calculated for each of the eyes relative to the others,
01553         not just the left one as is currently implemented.
01554       */
01555       for (eye=1; eye<num_eyes; eye++) 
01556         rtotal += total[eye];
01557       pref[row][j] = (total[0]-rtotal+1.0*(num_eyes-1))/(1.0*num_eyes);
01558     }
01559   }
01560 }
01561 
01562 
01563 
01564 cmdstat cmd_measure_or_pref( CMD_ARGS ) 
01565 {
01566   const int low           = (argc>0 ? cmdi(argv[0]) :                   0);
01567   const int high          = (argc>1 ? cmdi(argv[1]) :                 N-1);
01568 
01569   int i,eye,status;
01570   
01571   ABORT_IF_RANGE_OUTSIDE_CORTEX(low,low,high,high);
01572 
01573   ipc_notify(IPC_ONE,IPC_STD,"Calculating orientation preferences for map region (%d,%d) to (%d,%d)",
01574              low,low,high,high);
01575 
01576   /* Calculate orientation preference and send data to parent */
01577   switch (or_pref_method) {
01578   case OR_GAUSSFIT:       gaussfit_preferences(cortex_map,low,high); break;
01579   case OR_INPUT_RESPONSE: or_preferences(cortex_map,low,high);       break;
01580   default:
01581     ipc_notify(IPC_ONE,IPC_ERROR,"Unknown or_pref_method; assuming OR_InputResponse");
01582     or_preferences(cortex_map,low,high);
01583   }
01584 
01585   /* Send data to parent */  
01586   if (!AMPARENTPE){     
01587     for (i=0; i<nrows; i++){
01588       const int row = MAPROW(i);
01589       for (eye=0; eye<=combined_eyes; eye++) {
01590         ipc_put( &(or_pref[ eye][row][0]), IPC_INT, N, PARENTPE);
01591         ipc_put( &(sp_freq[ eye][row][0]), IPC_INT, N, PARENTPE);
01592         ipc_put( &(sp_phase[eye][row][0]), IPC_INT, N, PARENTPE);
01593       }
01594     }
01595   }
01596 
01597   /* Calculate selectivity and send data to parent */
01598   or_selectivity(low,high);
01599   if (!AMPARENTPE){                
01600     for (i=0; i<nrows; i++){
01601       const int row = MAPROW(i);
01602       for (eye=0; eye<=combined_eyes; eye++) 
01603         ipc_put( &(or_select[eye][row][0]), IPC_DOUBLE, N, PARENTPE);
01604     }
01605   }
01606 
01607   ipc_barrier();  /* Ensure all data reaches parent */
01608 
01609   if (!AMPARENTPE)
01610     for (i=0; i<N; i++)
01611       for (eye=0; eye<=combined_eyes; eye++) {
01612         ipc_get( &(or_pref[  eye][i][0]), IPC_INT,    N, PARENTPE);
01613         ipc_get( &(sp_freq[  eye][i][0]), IPC_INT,    N, PARENTPE);
01614         ipc_get( &(sp_phase[ eye][i][0]), IPC_INT,    N, PARENTPE);
01615         ipc_get( &(or_select[eye][i][0]), IPC_DOUBLE, N, PARENTPE);
01616       }
01617   
01618   or_dumped = (iteration==Uninitialized ? 1 : iteration); /* set to current iteration, if valid */
01619 
01620   /* Save to disk */
01621 #ifndef SAVE_OR_PPM_ONLY
01622   save_ascii_or_pref_file();
01623 #endif
01624 
01625   status = cmd_plot_or_pref(MIN(argc,3),argv);
01626   
01627   return status;
01628 }
01629 
01630 
01631 
01632 void save_ascii_or_pref_file(void)
01633 {
01634   char buf[50], out_buffer[NMAX*14*4], *ptr_tobuf;
01635   FILE *or_file, *sp_file;
01636   int i,j, eye;  
01637   
01638   if (AMPARENTPE){
01639     sprintf( buf,"%s.%d.or",filebase,iteration);
01640     if( (or_file=fopen(buf,"w"))==NULL )
01641       ipc_notify(IPC_ALL,IPC_ERROR,"File %s not opened", buf );
01642 
01643     sprintf( buf,"%s.%d.sp",filebase,iteration);
01644     if( (sp_file=fopen(buf,"w"))==NULL )
01645       ipc_notify(IPC_ALL,IPC_ERROR,"File %s not opened", buf );
01646 
01647     for (eye=0; eye<=combined_eyes; eye++)
01648       for (i=0; i<N; i++){            /* Save sp freq patterns     */
01649 
01650         for (ptr_tobuf=out_buffer,j=0; j<N; j++,ptr_tobuf += strlen(ptr_tobuf))
01651 #ifdef CRAY
01652 #pragma _CRI suppress (sp_freq, sp_phase) /* Force data load from memory   */
01653 #endif
01654           sprintf(ptr_tobuf,"%d %d ", sp_freq[eye][i][j], 
01655                   sp_phase[eye][i][j]) ;
01656 
01657         sprintf( ptr_tobuf,"\n" );
01658 
01659         if ((i==0) && (eye==0))
01660           fprintf(sp_file,"%d %d %d %d %d\n",iteration,N,sp_num_frequencies,sp_num_phases,
01661                   strlen(out_buffer));
01662         fprintf(sp_file,"%d ",strlen(out_buffer));
01663         fwrite(out_buffer,sizeof(char),strlen(out_buffer),sp_file);
01664       }
01665     
01666     for (eye=0; eye<=combined_eyes; eye++)
01667       for (i=0; i<N; i++){            /* Save or_pref patterns     */
01668 
01669         for (ptr_tobuf=out_buffer,j=0; j<N; j++,ptr_tobuf += strlen(ptr_tobuf))
01670 #ifdef CRAY
01671 #pragma _CRI suppress (or_pref, or_select) /* Force data load from memory   */
01672 #endif
01673           sprintf(ptr_tobuf,"%d %e ", or_pref[eye][i][j], 
01674                   or_select[eye][i][j]) ;
01675 
01676         sprintf( ptr_tobuf,"\n" );
01677 
01678         if ((i==0) && (eye==0))
01679           fprintf(or_file,"%d %d %d %d\n", iteration ,N, or_num_angles, strlen(out_buffer));
01680         fprintf(or_file,"%d ",strlen(out_buffer));
01681         fwrite(out_buffer,sizeof(char),strlen(out_buffer),or_file);
01682       }
01683     fclose(sp_file); fclose(or_file);
01684   }
01685 }
01686 
01687 
01688 
01689 cmdstat cmd_plot_or_pref( CMD_ARGS )
01690 {
01691   const int low           = (argc>0 ? cmdi(argv[0]) :                   0);
01692   const int high          = (argc>1 ? cmdi(argv[1]) :                 N-1);
01693   const char *filename    = (argc>2 ? cmds(argv[2]) :                NULL);
01694   const int select_only   = (argc>3 ? cmdi(argv[3]) :               false);
01695   
01696   double global_master_scale = ppm_master_scale;
01697   int    global_ppm_start_i  = ppm_start_i;
01698   int    global_ppm_end_i    = ppm_end_i;
01699   int    global_ppm_start_j  = ppm_start_j;
01700   int    global_ppm_end_j    = ppm_end_j;
01701   double global_cortex_scale = ppm_cortex_scale;
01702 
01703   /* Whether to plot sub region only */
01704   int auto_constrain     = argc > 0;
01705   
01706   ABORT_IF_RANGE_OUTSIDE_CORTEX(low,low,high,high);
01707   VERIFY_ORPREF_AVAILABLE(0,plot_or_pref);
01708 
01709   /* First PE computes and saves entire image as a ppm file; could be improved
01710      by making each PE responsible for part of the image or for an activity 
01711      or input panel, etc., but the speedup is probably minimal since I imagine
01712      the process is IO-bound.
01713   */
01714   if (AMPARENTPE) {
01715     char buf[MAXFILENAMELENGTH]; 
01716     int width,height;
01717 
01718     if (auto_constrain) {
01719       if (ppm_master_scale != Uninitialized)
01720         ppm_cortex_scale = ppm_master_scale;
01721       ppm_master_scale = Uninitialized;
01722       ppm_start_i = low;   ppm_end_i = high+1;
01723       ppm_start_j = low;   ppm_end_j = high+1;
01724     }
01725     
01726     ppm_bitmap_initialize();
01727 
01728     if (auto_constrain) {
01729       ppm_cortex_scale = global_cortex_scale;
01730       ppm_master_scale = global_master_scale;
01731     }
01732 
01733     /* Compute height and scaling factors */
01734     height = ppm_presentation_height();
01735     if (height < 0) return CMD_MISC_ERROR;
01736     
01737     /* Draw the pictures in memory */
01738     width = ppm_draw_orientations(or_pref, or_select, select_only);
01739 
01740     if (!filename) {
01741       sprintf(buf, "%s.%06d.or.ppm",filebase, iteration);       
01742       filename=buf;
01743     }
01744     else if (*filename=='.' && isalnum(*(filename+1))) {
01745       /* Treat as a suffix for filebase */
01746       sprintf(buf, "%s%s",filebase, filename);       
01747       filename=buf;
01748     }
01749 
01750     /* Write PPM output file */
01751     if (ppm_write_to_file( filename, filename, width, height, 255))
01752       return CMD_FILE_ERROR;
01753 
01754     if (auto_constrain) {
01755       ppm_start_i = global_ppm_start_i;   ppm_end_i = global_ppm_end_i;
01756       ppm_start_j = global_ppm_start_j;   ppm_end_j = global_ppm_end_j; 
01757     }
01758   }
01759 
01760   return CMD_NO_ERROR;
01761 }
01762 
01763 
01764 
01765 cmdstat cmd_plot_od_pref( CMD_ARGS )
01766 {
01767   
01768   const int low           = (argc>0 ? cmdi(argv[0]) :                   0);
01769   const int high          = (argc>1 ? cmdi(argv[1]) :                 N-1);
01770   const char *filename    = (argc>2 ? cmds(argv[2]) :                NULL);
01771   
01772   double global_master_scale = ppm_master_scale;
01773   int    global_ppm_start_i  = ppm_start_i;
01774   int    global_ppm_end_i    = ppm_end_i;
01775   int    global_ppm_start_j  = ppm_start_j;
01776   int    global_ppm_end_j    = ppm_end_j;
01777   double global_cortex_scale = ppm_cortex_scale;
01778     
01779   /* Whether to plot sub region only */
01780   int auto_constrain     = argc > 0;
01781   
01782   ABORT_IF_RANGE_OUTSIDE_CORTEX(low,low,high,high);
01783   VERIFY_ODPREF_AVAILABLE(0,plot_od_pref);
01784 
01785   /* First PE computes and saves entire image as a ppm file; could be improved
01786      by making each PE responsible for part of the image or for an activity 
01787      or input panel, etc., but the speedup is probably minimal since I imagine
01788      the process is IO-bound.
01789   */
01790   if (AMPARENTPE) {
01791     char buf[MAXFILENAMELENGTH]; 
01792     int width,height;
01793 
01794     if (auto_constrain) {
01795       if (ppm_master_scale != Uninitialized)
01796         ppm_cortex_scale = ppm_master_scale;
01797       ppm_master_scale = Uninitialized;
01798       ppm_start_i = low;   ppm_end_i = high+1;
01799       ppm_start_j = low;   ppm_end_j = high+1;
01800     }
01801     
01802     ppm_bitmap_initialize();
01803 
01804     if (auto_constrain) {
01805       ppm_cortex_scale = global_cortex_scale;
01806       ppm_master_scale = global_master_scale;
01807     }
01808     
01809     /* Compute height and scaling factors */
01810     height = ppm_presentation_height();
01811     if (height < 0) return CMD_MISC_ERROR;
01812     
01813     /* Draw the pictures in memory */
01814     width = ppm_draw_ocular_dominance(od_pref);
01815 
01816     if (!filename) {
01817       sprintf(buf, "%s.%06d.od.ppm",filebase, iteration);       
01818       filename=buf;
01819     }
01820     else if (*filename=='.' && isalnum(*(filename+1))) {
01821       /* Treat as a suffix for filebase */
01822       sprintf(buf, "%s%s",filebase, filename);       
01823       filename=buf;
01824     }
01825 
01826     /* Write PPM output file */
01827     if (ppm_write_to_file( filename, filename, width, height, 255))
01828       return CMD_FILE_ERROR;
01829 
01830     if (auto_constrain) {
01831       ppm_start_i = global_ppm_start_i;   ppm_end_i = global_ppm_end_i;
01832       ppm_start_j = global_ppm_start_j;   ppm_end_j = global_ppm_end_j; 
01833     }
01834   }
01835 
01836   return CMD_NO_ERROR;
01837 }
01838 
01839 
01840 
01841 cmdstat cmd_OR_features( CMD_ARGS ) 
01842 {
01843   /* Look at nexamples of each feature in low---high. */
01844   const int low         = (argc>0 ? cmdi(argv[0]) :   0);  
01845   const int high        = (argc>1 ? cmdi(argv[1]) : N-1);
01846   int       nexamples   = (argc>2 ? cmdi(argv[2]) :   5);  
01847   /* Whether or not to measure selectivity for the best tuned neuron */
01848   int       calc_select = (argc>3 ? cmdi(argv[3]) : False);    
01849 
01850   char buf[50];
01851   FILE *fp;
01852   int i, j;
01853   
01854   (void)argc; /* ignored */
01855   
01856   ABORT_IF_RANGE_OUTSIDE_CORTEX(low,low,high,high);
01857   VERIFY_ORPREF_AVAILABLE(0,OR_features);
01858 
01859   if (AMPARENTPE)  /* PE 0 determines nexamples maxima and minima values */
01860     find_OR_maxmin(&nexamples,low,high);/*Returns no of values in or_features*/
01861 
01862   ipc_barrier();                             /* Get values from parent  */
01863 
01864   for (i=0; i<NUM_OR_FEATURE_TYPES; i++)
01865     ipc_get((int *)or_features[i], IPC_INT, nexamples*sizeof(or_features[i])/sizeof(int), 0);
01866   
01867   if (AMPARENTPE){  /* Save the or_features data in a data file */
01868     sprintf(buf,"%s.%06d.features",filebase,iteration);
01869     if( (fp=fopen(buf,"a"))==NULL )
01870       ipc_notify(IPC_ALL,IPC_ERROR,"File %s not opened", buf);
01871 
01872     fprintf(fp,"%d %d %d\n\n",low,high,nexamples);
01873     for(i=0; i<NUM_OR_FEATURE_TYPES; i++)
01874       for(j=0; j <nexamples; j++){
01875         fprintf(fp,"%d %d\n",or_features[i][j].i, or_features[i][j].j);
01876         fprintf(fp,"%f %d\n",(double)or_features[i][j].or_selectivity,
01877                 or_features[i][j].or_preference);
01878         fprintf(fp,"%d %d\n\n",or_features[i][j].freq,
01879                 or_features[i][j].phase);
01880       }
01881     fclose(fp);
01882   }
01883   for (i=0; i< NUM_OR_FEATURE_TYPES; i++){
01884     for (j=0; j < nexamples; j++)
01885       if (ROWISLOCAL(or_features[i][j].i)){
01886         plot_weights_to_file(or_features[i][j].i, or_features[i][j].j, filebase, iteration);
01887 #ifndef SAVE_WTS_PPM_ONLY
01888         graph_wts(or_features[i][j].i, or_features[i][j].j, MAPLE);
01889 #endif  
01890       }
01891     
01892     ipc_barrier();
01893   }
01894 
01895   /* Measure orientation selectivity with contrast of best tuned neuron. */
01896   if (calc_select) { 
01897     char ui[20], uj[20];
01898     const char *args[]={NULL,NULL,"40","2.0"};
01899     snprintf(ui,20,"%d",or_features[ORF_MAX][0].i); args[0]=ui;
01900     snprintf(uj,20,"%d",or_features[ORF_MAX][0].j); args[1]=uj;
01901     cmd_orientation_contrast(4,args);
01902   }
01903   
01904   return CMD_NO_ERROR;
01905 }
01906 
01907 
01908 #define TRUNCATE_EXAMPLES_TO_SPACE_AVAIL(ui,uj,uk,ul,examples)        \
01909 {                                                                     \
01910   const int max_examples = MIN( (uk-ui+1)*(ul-uj+1), NMAP_FEATURES ); \
01911   if (examples > max_examples) {                                      \
01912     ipc_notify(IPC_ALL,IPC_CAUTION,"Not enough neurons in region (%d,%d) to (%d,%d) to find %d examples; will look for at most %d", ui,uj,uk,ul,*nexamples,max_examples); \
01913     examples = max_examples;                                          \
01914   }                                                                   \
01915 } 
01916 
01917 
01918 
01920 int find_OR_maxmin(int *nexamples, int low, int high) /* Called only by PE 0 */
01921 {
01922   int i,j,k,m;
01923 
01924   ABORT_IF_RANGE_OUTSIDE_CORTEX(low,low,high,high);
01925   TRUNCATE_EXAMPLES_TO_SPACE_AVAIL(low,low,high,high,*nexamples);
01926   
01927   for(i=0; i < *nexamples; i++){
01928     or_features[ORF_MIN][i].or_selectivity = 2.0; /* Init to max possible value */
01929     or_features[ORF_MAX][i].or_selectivity = 0.0; /* Init to min possible value */
01930   }
01931   for(i=low; i<=high; i++)
01932     for(j=low; j<=high; j++){ /* Square region of net under consideration */
01933       
01934       /* Insert minimum values */
01935       for(m=0; (m < *nexamples) &&         /* search for insert position */
01936           (or_features[ORF_MIN][m].or_selectivity < or_select[combined_eyes][i][j]); m++);
01937 
01938       for(k= (*nexamples); k >m; k--) /* Move things over upto m-th position */
01939         or_features[ORF_MIN][k] = or_features[ORF_MIN][k-1];
01940 
01941       or_features[ORF_MIN][m].or_selectivity = or_select[combined_eyes][i][j]; /* Insert */
01942       or_features[ORF_MIN][m].i = i;
01943       or_features[ORF_MIN][m].j = j;
01944 
01945       /* Insert maximum values */
01946       for(m=0; (m < *nexamples) &&        /* search for insert_position */
01947           (or_features[ORF_MAX][m].or_selectivity > or_select[combined_eyes][i][j]); m++);
01948 
01949       for(k= (*nexamples); k >m; k--) /* Move things over upto m-th position */
01950         or_features[ORF_MAX][k] = or_features[ORF_MAX][k-1];
01951 
01952       or_features[ORF_MAX][m].or_selectivity = or_select[combined_eyes][i][j]; /* Insert */
01953       or_features[ORF_MAX][m].i = i;
01954       or_features[ORF_MAX][m].j = j;
01955 
01956     }
01957   /* Finally, fill in all the other fields of the record */
01958   for (m=0; m< NUM_OR_FEATURE_TYPES; m++)
01959     for(k=0; k < *nexamples; k++){
01960       const int ui = or_features[m][k].i;
01961       const int uj = or_features[m][k].j;
01962       or_features[m][k].or_preference = or_pref[combined_eyes][ui][uj];
01963       or_features[m][k].freq = sp_freq[combined_eyes][ui][uj];
01964       or_features[m][k].phase = sp_phase[combined_eyes][ui][uj];
01965     }
01966 
01967   return CMD_NO_ERROR;
01968 }
01969 
01970 
01971 
01972 cmdstat cmd_SP_features( CMD_ARGS )
01973 {
01974   /* Look at nexamples of each feature in region low---high. */
01975   const int low         = (argc>0 ? cmdi(argv[0]) :   0);  
01976   const int high        = (argc>1 ? cmdi(argv[1]) : N-1);
01977   int       nexamples   = (argc>2 ? cmdi(argv[2]) :   5);  
01978   /* Whether or not to measure spatial contrast for the min and max examples */
01979   int       calc_select = (argc>3 ? cmdi(argv[3]) : False);    
01980 
01981   char buf[50];
01982   FILE *fp;
01983   int i,j;
01984 
01985   (void)argc; /* ignored */
01986   
01987   ABORT_IF_RANGE_OUTSIDE_CORTEX(low,low,high,high);
01988   VERIFY_ORPREF_AVAILABLE(0,SP_features);
01989 
01990   if (AMPARENTPE)  /* PE 0 determines nexamples maxima and minima values */
01991     find_sp_maxmin(&nexamples,low,high);/*Returns no of values in or_features*/
01992 
01993   ipc_barrier();                             /* Get values from parent  */
01994   ipc_get((int *)or_features[ORF_MIN], IPC_INT, nexamples*sizeof(or_features[ORF_MIN])/sizeof(int), 0);
01995   ipc_get((int *)or_features[ORF_MAX], IPC_INT, nexamples*sizeof(or_features[ORF_MAX])/sizeof(int), 0);
01996 
01997   if (AMPARENTPE){  /* Save the or_features data in a data file */
01998     sprintf(buf,"%s.%06d.spfeatures",filebase,iteration);
01999     if( (fp=fopen(buf,"a"))==NULL )
02000       ipc_notify(IPC_ALL,IPC_ERROR,"File %s not opened", buf );
02001 
02002     fprintf(fp,"%d %d %d\n\n",low,high,nexamples);
02003     for(i=0; i< NUM_OR_FEATURE_TYPES; i++)
02004       for(j=0; j <nexamples; j++){
02005         fprintf(fp,"%d %d\n",or_features[i][j].i, or_features[i][j].j);
02006         fprintf(fp,"%f %d\n",(double)or_features[i][j].or_selectivity,
02007                 or_features[i][j].or_preference);
02008         fprintf(fp,"%d %d\n\n",or_features[i][j].freq,
02009                 or_features[i][j].phase);
02010       }
02011     fclose(fp);
02012   }
02013   for (i=0; i<NUM_OR_FEATURE_TYPES; i++){
02014     for (j=0; j < nexamples; j++)
02015       if (ROWISLOCAL(or_features[i][j].i)) {
02016         plot_weights_to_file(or_features[i][j].i, or_features[i][j].j, filebase, iteration);
02017 #ifndef SAVE_WTS_PPM_ONLY
02018         graph_wts(or_features[i][j].i, or_features[i][j].j, MAPLE);
02019 #endif  
02020       }
02021     ipc_barrier();
02022   }
02023 
02024   /* Measure sp freq selectivity with contrast, of min and max neurons */
02025   if (calc_select) { 
02026     char ui[20], uj[20];
02027     const char *args[]={NULL,NULL,"30","30","3.0","15.0"};
02028     args[0]=ui;
02029     args[1]=uj;
02030     
02031     snprintf(ui,20,"%d",or_features[ORF_MIN][0].i); 
02032     snprintf(uj,20,"%d",or_features[ORF_MIN][0].j);
02033     cmd_spatial_contrast(6,args);
02034 
02035     snprintf(ui,20,"%d",or_features[ORF_MAX][0].i);
02036     snprintf(uj,20,"%d",or_features[ORF_MAX][0].j);
02037     cmd_spatial_contrast(6,args);
02038   }
02039 
02040   return CMD_NO_ERROR;
02041 }
02042 
02043 
02044 
02045 int find_sp_maxmin(int *nexamples, int low, int high) /* Called only by PE 0 */
02046 {
02047   int i,j,k,m;
02048   
02049   ABORT_IF_RANGE_OUTSIDE_CORTEX(low,low,high,high);
02050   TRUNCATE_EXAMPLES_TO_SPACE_AVAIL(low,low,high,high,*nexamples);
02051   
02052   for(i=0; i < *nexamples; i++){
02053     or_features[ORF_MIN][i].phase = INT_MAX; /* Init to max possible value */
02054     or_features[ORF_MAX][i].phase = 0; /* Init to min possible value */
02055   }
02056   for(i=low; i<=high; i++)
02057     for(j=low; j<=high; j++){ /* Square region of net under consideration */
02058       const int spatial_frequency = sp_freq[combined_eyes][i][j] + sp_phase[combined_eyes][i][j];
02059       /* Insert minimum values */
02060       for(m=0; (m < *nexamples) &&         /* search for insert position */
02061           (or_features[ORF_MIN][m].phase < spatial_frequency); m++);
02062 
02063       for(k= (*nexamples); k >m; k--) /* Move things over upto m-th position */
02064         or_features[ORF_MIN][k] = or_features[ORF_MIN][k-1];
02065 
02066       or_features[ORF_MIN][m].phase = spatial_frequency; /* Insert */
02067       or_features[ORF_MIN][m].i = i;  or_features[ORF_MIN][m].j = j;
02068 
02069       /* Insert maximum values */
02070       for(m=0; (m < *nexamples) &&        /* search for insert_position */
02071           (or_features[ORF_MAX][m].phase > spatial_frequency); m++);
02072 
02073       for(k= (*nexamples); k >m; k--) /* Move things over upto m-th position */
02074         or_features[ORF_MAX][k] = or_features[ORF_MAX][k-1];
02075 
02076       or_features[ORF_MAX][m].phase = spatial_frequency; /* Insert */
02077       or_features[ORF_MAX][m].i = i;  or_features[ORF_MAX][m].j = j;
02078 
02079     }
02080   /* Finally, fill in all the other fields of the record */
02081   for (m=0; m< NUM_OR_FEATURE_TYPES; m++)
02082     for(k=0; k < *nexamples; k++){
02083       i = or_features[m][k].i; j = or_features[m][k].j;
02084       or_features[m][k].or_preference = or_pref[combined_eyes][i][j];
02085       or_features[m][k].or_selectivity = or_select[combined_eyes][i][j];
02086       or_features[m][k].freq = sp_freq[combined_eyes][i][j];
02087     }
02088 
02089   return CMD_NO_ERROR;
02090 }
02091 
02092 
02093 
02098 cmdstat cmd_OD_features( CMD_ARGS ) /* Arguments specify the part of the net to focus on */
02099 {
02100   const int low         = (argc>0 ? cmdi(argv[0]) :   0);  
02101   const int high        = (argc>1 ? cmdi(argv[1]) : N-1);
02102   int       nexamples   = (argc>2 ? cmdi(argv[2]) :   5);  
02103   
02104   char buf[50]; FILE *fp;
02105   int i, j;
02106 
02107   (void)argc; /* ignored */
02108   
02109   ABORT_IF_RANGE_OUTSIDE_CORTEX(low,low,high,high);
02110   
02111   if (AMPARENTPE)  /* PE 0 determines nexamples maxima and minima values */
02112     find_OD_maxmin(&nexamples,low,high); /* Returns no. of values in or_features*/
02113 
02114   ipc_barrier();                             /* Get values from parent  */
02115   ipc_get((int *)or_features[ORF_MIN], IPC_INT, nexamples*sizeof(or_features[ORF_MIN])/sizeof(int), 0);
02116   ipc_get((int *)or_features[ORF_MAX], IPC_INT, nexamples*sizeof(or_features[ORF_MAX])/sizeof(int), 0);
02117 
02118   if (AMPARENTPE){  /* Save the od_features data in a data file */
02119     sprintf(buf,"%s.%06d.odfeatures",filebase,iteration);
02120     if( (fp=fopen(buf,"a"))==NULL )
02121       ipc_notify(IPC_ALL,IPC_ERROR,"File %s not opened", buf );
02122 
02123     fprintf(fp,"%d %d %d\n\n",low,high,nexamples);
02124     for(i=0; i< NUM_OR_FEATURE_TYPES; i++)
02125       for(j=0; j <nexamples; j++){
02126         fprintf(fp,"%d %d\n",or_features[i][j].i, or_features[i][j].j);
02127         fprintf(fp,"%f\n",(double)or_features[i][j].od);
02128       }
02129     fclose(fp);
02130   }
02131   for (i=0; i< NUM_OR_FEATURE_TYPES; i++){
02132     for (j=0; j < nexamples; j++)
02133       if (ROWISLOCAL(or_features[i][j].i)) {
02134         plot_weights_to_file(or_features[i][j].i, or_features[i][j].j, filebase, iteration);
02135 #ifndef SAVE_WTS_PPM_ONLY
02136         graph_wts(or_features[i][j].i, or_features[i][j].j, MAPLE);
02137 #endif  
02138       }
02139     ipc_barrier();
02140   }
02141   return CMD_NO_ERROR;
02142 }
02143 
02144 
02145 
02146 int find_OD_maxmin(int *nexamples, int low, int high) /* Called only by PE 0 */
02147 {
02148   /* This one should find the maximum binocular and monocular cells */
02149   int i,j,k,m,row;
02150 
02151   ABORT_IF_RANGE_OUTSIDE_CORTEX(low,low,high,high);
02152   TRUNCATE_EXAMPLES_TO_SPACE_AVAIL(low,low,high,high,*nexamples);
02153   
02154   for (row=0; row <nrows; row++)
02155     for (i=1; i < NPEs; i++)              /* Get the calculated od_prefs */
02156       ipc_get(&(od_pref[ARBITRARY_MAPROW(row,i)][0]), IPC_DOUBLE, N, i);
02157 
02158   for(i=0; i < *nexamples; i++){
02159     or_features[ORF_MIN][i].od = 2.0; /* Init to max possible value */
02160     or_features[ORF_MAX][i].od = 0.0; /* Init to min possible value */
02161   }
02162   for(i=low; i<=high; i++)
02163     for(j=low; j<=high; j++){ /* Square region of net under consideration */
02164       
02165       /* Insert minimum values */
02166       for(m=0; (m < *nexamples) &&         /* search for insert position */
02167           (fabs(or_features[ORF_MIN][m].od-0.5) < fabs(od_pref[i][j]-0.5)); m++);
02168 
02169       for(k= (*nexamples); k >m; k--) /* Move things over upto m-th position */
02170         or_features[ORF_MIN][k] = or_features[ORF_MIN][k-1];
02171 
02172       or_features[ORF_MIN][m].od = od_pref[i][j]; /* Insert */
02173       or_features[ORF_MIN][m].i = i;  or_features[ORF_MIN][m].j = j;
02174 
02175       /* Insert maximum values */
02176       for(m=0; (m < *nexamples) &&        /* search for insert_position */
02177           (fabs(or_features[ORF_MAX][m].od-0.5) > fabs(od_pref[i][j]-0.5)); m++);
02178 
02179       for(k= (*nexamples); k >m; k--) /* Move things over upto m-th position */
02180         or_features[ORF_MAX][k] = or_features[ORF_MAX][k-1];
02181 
02182       or_features[ORF_MAX][m].od = od_pref[i][j]; /* Insert */
02183       or_features[ORF_MAX][m].i = i;  or_features[ORF_MAX][m].j = j;
02184 
02185     }
02186 
02187   /* Finally, fill in all the other fields of the record */
02188   for (m=0; m < NUM_OR_FEATURE_TYPES; m++)
02189     for(k=0; k < *nexamples; k++){
02190       i = or_features[m][k].i; j = or_features[m][k].j;
02191       or_features[m][k].or_preference = 0;
02192       or_features[m][k].freq = 0;
02193       or_features[m][k].phase = 0;
02194     }
02195 
02196   return CMD_NO_ERROR;
02197 }
02198 
02199 
02200 
02201 cmdstat cmd_visualize( CMD_ARGS )                  /* Dumps graphs at current iteration   */
02202 {
02203   const int ui             = cmdi(argv[0]);
02204   const int uj             = cmdi(argv[1]);
02205   const int output_routine = (argc>2 ? cmdi(argv[2]) : MAPLE);
02206 
02207   ABORT_IF_NEURON_OUTSIDE_CORTEX(ui,uj);
02208   
02209   ipc_notify(IPC_ONE,IPC_STD,"Visualizing neuron (%d,%d). Routine %d",ui,uj,output_routine);
02210 
02211   if (ROWISLOCAL(ui)){             /* The wts are local to this processor */
02212     graph_wts(ui, uj, output_routine);
02213   }
02214 /*  dump_peaks(ui, uj, output_routine); */
02215 
02216   graph_od(ui, uj, output_routine); 
02217 
02218   return CMD_NO_ERROR;
02219 }
02220 
02221 
02222 
02223 void graph_wts(int ui, int uj, int output_routine)
02224 {
02225   int m; FILE *excfile, *inhfile, *mexfile, *aff_file;
02226   char title[100], zaxis[100], bufexc[100], bufinh[100], bufmex[100], bufz[100];
02227 
02228   switch(output_routine){             /* set up correct extensions */
02229 
02230   case MATH: /* mathematica */
02231     sprintf(bufexc,"%s.%d_%d.%d.ex.ma",filebase,ui,uj,iteration);
02232     sprintf(bufinh,"%s.%d_%d.%d.in.ma",filebase,ui,uj,iteration);
02233     sprintf(bufmex,"%s.%d_%d.%d.mx.ma",filebase,ui,uj,iteration);
02234     sprintf(bufz, "%s.%d_%d.%d.aff.ma",filebase,ui,uj,iteration);
02235     break;
02236 
02237   case MAPLE: /* maple */
02238     sprintf(bufexc,"%s.%d_%d.%d.ex.mp",filebase,ui,uj,iteration);
02239     sprintf(bufinh,"%s.%d_%d.%d.in.mp",filebase,ui,uj,iteration);
02240     sprintf(bufmex,"%s.%d_%d.%d.mx.mp",filebase,ui,uj,iteration);
02241     sprintf(bufz, "%s.%d_%d.%d.aff.mp",filebase,ui,uj,iteration);
02242     break;
02243   }
02244   if( (excfile=fopen(bufexc,"w"))==NULL ){
02245     ipc_notify(IPC_ALL,IPC_ERROR,"out file %s could not be opened",bufexc);
02246     return;
02247   }
02248   if( (inhfile=fopen(bufinh,"w"))==NULL ){
02249     ipc_notify(IPC_ALL,IPC_ERROR,"out file %s could not be opened",bufinh);
02250     return;
02251   }
02252   if( (mexfile=fopen(bufmex,"w"))==NULL ){
02253     ipc_notify(IPC_ALL,IPC_ERROR,"out file %s could not be opened",bufmex);
02254     return;
02255   }
02256   if( (aff_file=fopen(bufz,"w"))==NULL){
02257     ipc_notify(IPC_ALL,IPC_ERROR,"out file %s could not be opened",bufz);
02258     return;
02259   }
02260   /* ipc_notify(IPC_ALL,IPC_VERBOSE,"RN=%d,gammaexc: %.3f,gammainh: %.3f",RN,(double)gammaexc,(double)gammainh); */
02261 
02262   for(m=0; m<lat_exc_dimension; m++)   
02263     temp_wts.lat_exc_wts[m] = cortex_map[ui][uj].lat_exc_wts[m] *  gammaexc;
02264 
02265   for(m=0; m<lat_inh_dimension; m++)
02266     temp_wts.lat_inh_wts[m] = cortex_map[ui][uj].lat_inh_wts[m] * -gammainh;
02267 
02268   switch(output_routine){
02269 
02270   case MATH: 
02271     mathematica(excfile, temp_wts.lat_exc_wts,
02272                 (exc_array_width-1)/2, ui, uj); /* Use original exc_radius */
02273     mathematica(inhfile,temp_wts.lat_inh_wts,inh_rad,ui,uj);
02274     break;
02275     
02276   case MAPLE: 
02277     sprintf(zaxis,"Exc");
02278            
02279     sprintf(title,"EXCITATION WTS OF A NEURON AT (%d,%d) IN A %dx%d GRID",
02280             ui,uj,N,N);
02281     maple(excfile, temp_wts.lat_exc_wts, (exc_array_width-1)/2,
02282           ui,uj,title, zaxis ); /* Use original exc_radius */
02283     sprintf(title,"INHIBITION WTS OF A NEURON AT (%d,%d) IN A %dx%d GRID",
02284             ui,uj,N,N);
02285     sprintf(zaxis,"Inh");
02286     maple(inhfile,temp_wts.lat_inh_wts,inh_rad,ui,uj,title, zaxis) ;
02287     break;
02288   }
02289   compute_mexhat(ui,uj);  /* Calculate the mexican hat now.               */
02290 
02291   switch(output_routine){ /* Output the mexican hat stored in lat_inh_wts */
02292 
02293   case MATH: 
02294     mathematica(mexfile,temp_wts.lat_inh_wts,inh_rad,ui,uj);
02295     break;
02296   case MAPLE: 
02297     sprintf(title,"SUM OF LATERAL WTS OF A NEURON AT (%d,%d) IN A %dx%d GRID",
02298             ui,uj,N,N);
02299     sprintf(zaxis,"Exc+Inh");
02300 
02301     maple(mexfile,temp_wts.lat_inh_wts,inh_rad,ui,uj,title,zaxis)  ;
02302     break;
02303   }
02304   sprintf(title,"AFFERENT WTS OF A NEURON AT (%d,%d) IN A %dx%d GRID",
02305             ui,uj,N,N);
02306 
02307   plot_afferent_wts(output_routine, aff_file, ui,uj, title, "");
02308 
02309   fclose(excfile); fclose(inhfile); fclose(mexfile); fclose(aff_file);
02310 }
02311 
02312 
02313 
02314 void graph_od(int ui, int uj, int output_routine)
02315 {
02316   int i,j,row;
02317   FILE *odfile=NULL;
02318   char bufod[100];
02319 
02320   od_preferences(od_pref,cortex_map);
02321 
02322   if (AMPARENTPE){
02323     if (output_routine == MATH)
02324       sprintf   (bufod, "%s.%d_%d.%d.od.ma", filebase, ui, uj, iteration);
02325     else sprintf(bufod, "%s.%d_%d.%d.od.mp", filebase, ui, uj, iteration);
02326 
02327     if( (odfile=fopen(bufod,"w"))==NULL){
02328       ipc_notify(IPC_ALL,IPC_ERROR,"out file %s could not be opened", bufod);
02329       return;
02330     } 
02331   }
02332 
02333   ipc_barrier();
02334   
02335   if (AMPARENTPE){
02336     
02337     for (row=0; row <nrows; row++)
02338       for (i=1; i < NPEs; i++)              /* Get the calculated od_prefs */
02339         ipc_get(&(od_pref[ARBITRARY_MAPROW(row,i)][0]), IPC_DOUBLE, N, i);
02340 
02341     switch(output_routine){
02342     case MATH:
02343       for(i=0; i<N; i++) {
02344         for(j=0; j<N-1; j++)
02345           fprintf(odfile,"%e ", od_pref[i][j]  - 0.5);
02346         fprintf(odfile, "%e\n", od_pref[i][N-1]- 0.5);
02347       }
02348       break;
02349 
02350     case MAPLE:
02351       /* Print header for maple */
02352       fprintf(odfile,"with(linalg);\nwith(plots);\n");
02353       fprintf(odfile,"z := matrix( [ \n");
02354 
02355       for(i=0; i<N; i++){
02356         fprintf(odfile, "[");
02357 
02358         for(j=0; j<N-1; j++) 
02359             fprintf(odfile,"%e,", od_pref[i][j] - 0.5);
02360         
02361         fprintf(odfile,"%e]", od_pref[i][N-1] - 0.5);
02362          
02363         if (i==N-1) fprintf(odfile," ] );\n");
02364         else fprintf(odfile,",\n");
02365       }
02366       fprintf(odfile,"matrixplot(z,title=`OCULAR DOMINANCE OF EACH NEURON`,labels=[`x`,`y`,`Ocular Dominance`],axes=BOXED,style=PATCH,shading=Z);\n");
02367       break;
02368     }
02369     fclose(odfile);
02370   }
02371 }
02372 
02373 
02374 
02379 void compute_mexhat(int i, int j) 
02380 {
02381   const int exc_ar_width = exc_array_width;
02382   const int inh_ar_width = 2*inh_rad+1;
02383   /* const int exc_rad = (exc_array_width-1)/2; */
02384 
02385   const int elowk  = MAX(i-exc_rad,0  );
02386   const int ehighk = MIN(i+exc_rad,N-1);
02387   const int ilowk  = MAX(i-inh_rad,0  );
02388   const int ihighk = MIN(i+inh_rad,N-1);
02389   const int elowl  = MAX(j-exc_rad,0  );
02390   const int ehighl = MIN(j+exc_rad,N-1);
02391   const int ilowl  = MAX(j-inh_rad,0  );
02392   const int ihighl = MIN(j+inh_rad,N-1);
02393 
02394   int k, l;
02395 
02396   for(k=ilowk; k<=ihighk; k++)   /* Go through larger inhibitory surround */
02397     if ((k >=elowk) && (k <= ehighk)) /* For k values in excitatory range */
02398       for(l=ilowl; l<=ihighl; l++) 
02399         if ((l >= elowl) && (l <= ehighl))  /* For l values in exc range  */
02400 
02401           temp_wts.lat_inh_wts[LAT_INDEX(i,j,k,l,inh_rad,inh_ar_width)] +=
02402             temp_wts.lat_exc_wts[LAT_INDEX(i,j,k,l,exc_rad,exc_ar_width)] ;
02403           
02404 }
02405 
02406 
02407 
02408 void maple(FILE *fp, l_weight *weights, int radius, int ui, int uj, const char *title, const char *zaxis)
02409 {
02410   const int ar_width = 2*radius+1;
02411 
02412   const int lowk  = MAX(ui-radius,0  );
02413   const int highk = MIN(ui+radius,N-1);
02414   const int lowl  = MAX(uj-radius,0  );
02415   const int highl = MIN(uj+radius,N-1);
02416 
02417   int k, l;
02418 
02419   /* Print header for maple */
02420   fprintf(fp,"with(linalg);\nwith(plots);\n");
02421   fprintf(fp,"z := matrix( [ \n");
02422 
02423   for(k=lowk; k<=highk; k++){
02424     fprintf(fp, "[");
02425 
02426     for(l=lowl; l<highl; l++) 
02427       fprintf(fp,"%e,", weights[LAT_INDEX(ui,uj,k,l,radius,ar_width)]);
02428       
02429     fprintf(fp,"%e]",   weights[LAT_INDEX(ui,uj,k,highl,radius,ar_width)]);
02430  
02431     if ( (k < highk) ) fprintf(fp,",\n");
02432   }
02433 
02434   fprintf(fp," ] );\n");
02435   fprintf(fp,"matrixplot(z,title=`%s`,labels=[`x`,`y`,`%s`],axes=BOXED,style=PATCH,shading=Z);\n",
02436           title,zaxis);
02437 }
02438 
02439 
02440 
02441 void mathematica(FILE *fp, l_weight *weights, int radius, int ui, int uj)
02442 {
02443   const int ar_width = 2*radius+1;
02444 
02445   const int lowk  = MAX(ui-radius,0  );
02446   const int highk = MIN(ui+radius,N-1);
02447   const int lowl  = MAX(uj-radius,0  );
02448   const int highl = MIN(uj+radius,N-1);
02449 
02450   int i,j,k,l;
02451   
02452   /* Pad the weights with zeros to see them in network co-ordinates */
02453   for(i=0; i<lowk; i++){
02454     for(j=0; j<N-1;j++)
02455       fprintf(fp,"0.0 ");
02456     fprintf(fp,"0.0\n");
02457   }
02458   for(k=lowk; k<=highk; k++){
02459     
02460     for(i=0;i<lowl; i++) fprintf(fp,"0.0 ");
02461     for(l=lowl; l<highl; l++) 
02462       fprintf(fp,"%e ", weights[LAT_INDEX(ui,uj,k,l,radius,ar_width)]);
02463     
02464     if (highl==(N-1))
02465       fprintf(fp,"%e",  weights[LAT_INDEX(ui,uj,k,highl,radius,ar_width)]);
02466 
02467     else{
02468       for(i=highl; i<N-1; i++)
02469         fprintf(fp,"0.0 ");
02470       fprintf(fp,"0.0");
02471     }
02472 
02473     fprintf(fp,"\n");
02474   }
02475   for(i=highk+1; i<N; i++){
02476     for(j=0; j<N-1;j++)
02477       fprintf(fp,"0.0 ");
02478     fprintf(fp,"0.0\n");
02479   }
02480 
02481 }
02482 
02483 
02484 
02485 void plot_afferent_wts(int output_routine, FILE *fp, int ui, int uj, char *title, const char *zaxis)
02486 {
02487   const int lowk  = MAX(cortex_map[ui][uj].centerx - rf_radius,0   );
02488   const int highk = MIN(cortex_map[ui][uj].centerx + rf_radius,RN-1);
02489   const int lowl  = MAX(cortex_map[ui][uj].centery - rf_radius,0   );
02490   const int highl = MIN(cortex_map[ui][uj].centery + rf_radius,RN-1);
02491 
02492   int k,l;
02493   a_weight (*weights)[WTMAX][WTMAX];
02494 
02495   if (num_eyes !=2){
02496     ipc_notify(IPC_ONE,IPC_ERROR,"plot_afferent_wts only supports a two-eye configuration");
02497     return;   /* at the moment, anyway */
02498   }
02499   else {
02500     
02501     weights = cortex_map[ui][uj].weights;
02502     
02503     switch(output_routine){
02504     case MATH:
02505       
02506       for(k=0; k<lowk; k++){
02507         
02508         for(l=0; l< RN-1; l++)
02509           fprintf(fp,"%e ",0.0);
02510         fprintf(fp,"0.0\n");
02511       }
02512       
02513       for(k=lowk; k<=highk; k++){   /* Go through larger inhibitory surround */
02514         
02515         for(l=0; l<lowl; l++) 
02516           fprintf(fp,"%e ", 0.0);
02517         
02518         for(l=lowl; l<=highl; l++) 
02519           fprintf(fp,"%e ", weights[0][k-lowk][l-lowl]);
02520         
02521         for(l=lowl; l< highl; l++) 
02522           fprintf(fp,"%e ", weights[1][k-lowk][l-lowl]);
02523         
02524         if (highl== RN-1)
02525           fprintf(fp,"%e\n", weights[1][k-lowk][highl-lowl]);
02526         else{
02527           for(l=highl+1; l<RN-1; l++)
02528             fprintf(fp,"%e ",0.0);
02529           fprintf(fp,"0.0\n");
02530         }
02531         
02532       }
02533       for(k=highk+1; k<RN; k++){
02534         
02535         for(l=0; l< RN-1; l++)
02536           fprintf(fp,"%e ",0.0);
02537         fprintf(fp,"0.0\n");
02538       }
02539       break;
02540       
02541     case MAPLE:
02542       /* Print header for maple */
02543       fprintf(fp,"with(linalg);\nwith(plots);\n");
02544       
02545       fprintf(fp,"y := matrix( [ \n");
02546       
02547       for(k=0; k< lowk; k++){
02548         fprintf(fp, "[");
02549         
02550         for(l=0; l<(RN-1); l++) 
02551           fprintf(fp,"%e,", 0.0);
02552         
02553         fprintf(fp,"%e],\n", 0.0);
02554       }
02555       
02556       for(k=lowk; k<=highk; k++){
02557         fprintf(fp, "[");
02558         
02559         for(l=0; l<lowl; l++) 
02560           fprintf(fp,"%e,",0.0);
02561         
02562         for(l=lowl; l< highl; l++) 
02563           fprintf(fp,"%e,",weights[0][k-lowk][l-lowl]);
02564         
02565         if (highl==RN-1)
02566           fprintf(fp,"%e]", weights[0][k-lowk][highl-lowl]);
02567         else{
02568           fprintf(fp,"%e,",weights[0][k-lowk][highl-lowl]);
02569           for(l=highl+1; l<RN-1; l++)
02570             fprintf(fp,"%e,",0.0);
02571           fprintf(fp,"0.0]");
02572         }
02573         if ( (k < (RN-1)) ) fprintf(fp,",\n");
02574         else if (k == (RN-1)) fprintf(fp," ] );\n");
02575       }
02576       for(k=highk+1; k<RN; k++){
02577         fprintf(fp, "[");
02578         for(l=0; l< RN-1; l++)
02579           fprintf(fp,"%e,",0.0);
02580         fprintf(fp,"0.0]");
02581         if ( (k < (RN-1)) ) fprintf(fp,",\n");
02582         else if (k == (RN-1)) fprintf(fp," ] );\n");
02583       }
02584       
02585       fprintf(fp,"A := matrixplot(y,title=`%s`,labels=[`x`,`y`,`%s`],axes=BOXED,style=PATCH,shading=Z);\n",title,zaxis);
02586       
02587       fprintf(fp,"z := matrix( [ \n");
02588       
02589       for(k=0; k< lowk; k++){
02590         fprintf(fp, "[");
02591         
02592         for(l=0; l<(RN-1); l++) 
02593           fprintf(fp,"%e,", 0.0);
02594         
02595         fprintf(fp,"%e],", 0.0);
02596       }
02597       
02598       for(k=lowk; k<=highk; k++){
02599         fprintf(fp, "[");
02600         
02601         for(l=0; l<lowl; l++) 
02602           fprintf(fp,"%e,",0.0);
02603         
02604         for(l=lowl; l< highl; l++) 
02605           fprintf(fp,"%e,",weights[1][k-lowk][l-lowl]);
02606         
02607         if (highl==RN-1)
02608           fprintf(fp,"%e]", weights[1][k-lowk][highl-lowl]);
02609         else{
02610           fprintf(fp,"%e,",weights[1][k-lowk][highl-lowl]);
02611           for(l=highl+1; l<RN-1; l++)
02612             fprintf(fp,"%e,",0.0);
02613           fprintf(fp,"0.0]");
02614         }
02615         if ( (k < (RN-1)) ) fprintf(fp,",\n");
02616         else if (k == (RN-1)) fprintf(fp," ] );\n");
02617       }
02618       for(k=highk+1; k<RN; k++){
02619         fprintf(fp, "[");
02620         for(l=0; l< RN-1; l++)
02621           fprintf(fp,"%e,",0.0);
02622         fprintf(fp,"0.0]");
02623         if ( (k < (RN-1)) ) fprintf(fp,",\n");
02624         else if (k == (RN-1)) fprintf(fp," ] );\n");
02625       }
02626       
02627       fprintf(fp,"B := matrixplot(z,title=`%s`,labels=[`x`,`y`,`%s`],axes=BOXED,style=PATCH,shading=Z);\n",title,zaxis);
02628       
02629       fprintf(fp,"display3d([A,B],insequence=true);\n");
02630     }
02631   }
02632 }
02633 
02634 
02635 
02641 void find_max(double *max_or_select, double *max_od, int low_index, int high_index)
02642 {
02643   int i,j;
02644   
02645   *max_od = *max_or_select = 0.0;
02646 
02647   for(i=low_index; i<=high_index; i++)    
02648     for(j=low_index; j<=high_index; j++)
02649       if (*max_or_select < or_select[combined_eyes][i][j])
02650         *max_or_select = or_select[combined_eyes][i][j];
02651 }
02652 
02653 
02654 
02655 cmdstat cmd_connection_statistics( CMD_ARGS )
02656 {
02657   /* Part of the net to collect statistics from. 
02658    * Only corresponding PEs are used. */
02659   const int nSelectivities = (argc>0 ? cmdi(argv[0]) :  24); /* Number of histogram divisions */
02660   const int nODvalues      = (argc>1 ? cmdi(argv[1]) :  10); /* Currently unused */ 
02661   const int low_index      = (argc>2 ? cmdi(argv[2]) :   0);
02662   const int high_index     = (argc>3 ? cmdi(argv[3]) : N-1);
02663 
02664   static Histo  temp_histo[NUM_BUBBLE_AREAS][MAX_NUM_ANGLES][MAX_NUM_ANGLES]; /* Temporary storage for ipc copying */
02665 
02666   int i,j,pe,k,l,m,eye;
02667   int bubble_rad;
02668   double max_or_select, max_od, or_division;
02669   /* double od_division; */
02670 
02671   Histo add_histo[NSELECTIVITIES][NUM_BUBBLE_AREAS][MAX_NUM_ANGLES][MAX_NUM_ANGLES]; /* Minimize roundoff */
02672 
02673   (void)argc; /* ignored */
02674 
02675   ABORT_IF_RANGE_OUTSIDE_CORTEX(low_index,low_index,high_index,high_index);
02676   VERIFY_ORPREF_AVAILABLE(0,connection_statistics);
02677 
02678   if (nSelectivities > NSELECTIVITIES) {
02679     ipc_notify(IPC_ONE,IPC_ERROR,"Number of selectivities is too large (%d > %d)",
02680               nSelectivities,
02681               NSELECTIVITIES );
02682     return CMD_PARAMETER_ERROR;
02683   }
02684 
02685   ipc_notify(IPC_ONE,IPC_STD,"Connection statistics: (%d,%d):(%d,%d)",
02686              nSelectivities,nODvalues,low_index,high_index);
02687 
02688   for(pe=0; pe<NPEs; pe++) /* Get all OR preference values */
02689     if (!PEISME(pe))
02690       for(i=0; i<nrows; i++){
02691         const int row = ARBITRARY_MAPROW(i,pe);
02692         for (eye=0; eye<=combined_eyes; eye++) {
02693           ipc_get( &(or_pref[  eye][row][0]), IPC_INT, N, pe);
02694           ipc_get( &(or_select[eye][row][0]), IPC_DOUBLE, N, pe);
02695         }
02696       }
02697   find_max(&max_or_select, &max_od, low_index, high_index); /* Max values */
02698 
02699   or_division = max_or_select/(double)nSelectivities;
02700   /* od_division = max_od/(double)nODvalues; */
02701 
02702   bubble_rad = (int)floor(0.5*final_bubblewidth);
02703   
02704   ipc_notify(IPC_ONE,IPC_STD,"max_or_select=%lf,or_division=%lf,bubble_rad=%d",
02705              (double)max_or_select,(double)or_division,bubble_rad);
02706 
02707   for(i=0; i<nSelectivities; i++)         /* Initialize the array */
02708     for(j=0; j< NUM_BUBBLE_AREAS; j++)
02709       for(k=0; k< or_num_angles; k++)
02710         for(l=0; l< or_num_angles; l++){
02711           OR_histo[i][j][k][l].value = 0.0;
02712           OR_histo[i][j][k][l].count = 0;
02713         }
02714   for(i=0; i<nrows; i++){
02715     const int row = MAPROW(i);
02716     
02717     for(m=0; m<nSelectivities; m++)   /* Initialize the array for each row*/
02718       for(j=0; j< NUM_BUBBLE_AREAS; j++)
02719         for(k=0; k< or_num_angles; k++)
02720           for(l=0; l< or_num_angles; l++){
02721             add_histo[m][j][k][l].value = 0.0;
02722             add_histo[m][j][k][l].count = 0;
02723           }
02724     if ((row>=low_index) && (row<=high_index))
02725       for(j=low_index; j<=high_index; j++){
02726         const int lowk  = MAX(row-inh_rad,low_index );
02727         const int highk = MIN(row+inh_rad,high_index);
02728         const int lowl  = MAX(j-inh_rad,  low_index );
02729         const int highl = MIN(j+inh_rad,  high_index);
02730         const int select_index = (int)floor(or_select[combined_eyes][row][j]/or_division);
02731         const int angle_ij     = or_pref[combined_eyes][row][j];
02732 
02733         for(k=lowk; k<=highk; k++)
02734           for(l=lowl; l<=highl; l++){
02735             const int angle_kl = or_pref[combined_eyes][k][l];
02736             const int bubble_index = ( ((abs(k-row) <= bubble_rad) && (abs(l-j) <= bubble_rad)) ? 0 : 1);
02737               
02738             add_histo[select_index][bubble_index][angle_ij][angle_kl].value+=
02739               cortex_map[row][j].lat_inh_wts[LAT_INDEX(row,j,k,l,inh_rad,inh_array_width)];
02740             
02741             add_histo[select_index][bubble_index][angle_ij][angle_kl].count++;
02742           }
02743       }
02744     for(m=0; m<nSelectivities; m++) /* Add it to OR_histo.  */
02745       for(j=0; j< NUM_BUBBLE_AREAS; j++)
02746         for(k=0; k< or_num_angles; k++)
02747           for(l=0; l< or_num_angles; l++){
02748             OR_histo[m][j][k][l].value += add_histo[m][j][k][l].value;
02749             OR_histo[m][j][k][l].count += add_histo[m][j][k][l].count;
02750           }
02751   }
02752   ipc_barrier();      /* Sync and find the average across PEs */
02753   
02754   for(i=0; i<nSelectivities; i++){
02755     
02756     for (pe=0; pe <NPEs; pe++)
02757       if (!PEISME(pe)){
02758         for(j=0; j< NUM_BUBBLE_AREAS; j++)
02759           for(k=0; k< or_num_angles; k++)
02760             for(l=0; l< or_num_angles; l++){
02761               ipc_get_to(&(temp_histo[j][k][l].value),
02762                         &(OR_histo[i][j][k][l].value),IPC_DOUBLE,1, pe);
02763               ipc_get_to(&(temp_histo[j][k][l].count),
02764                         &(OR_histo[i][j][k][l].count),IPC_INT,1, pe);
02765               OR_histo[i][j][k][l].value += temp_histo[j][k][l].value;
02766               OR_histo[i][j][k][l].count += temp_histo[j][k][l].count;
02767             }
02768       }
02769     for(j=0; j< NUM_BUBBLE_AREAS; j++) /* Find the average */
02770       for(k=0; k< or_num_angles; k++)
02771         for(l=0; l< or_num_angles; l++){
02772           if (OR_histo[i][j][k][l].count > 0)
02773             OR_histo[i][j][k][l].value /= ((double)OR_histo[i][j][k][l].count);
02774           else
02775             OR_histo[i][j][k][l].value = 0.0;
02776         }
02777     
02778     if (PEISME(i))
02779       graph_histo(i,or_division);
02780   }
02781 
02782   return CMD_NO_ERROR;
02783 }
02784 
02785 
02786 
02787 void graph_histo(int sel, double or_division) /* Graph histogram for each selectivity */
02788 {
02789   int k,l,m;
02790   char buf[50], title[50], zaxis[50];
02791   FILE *fp[MAX_NUM_EYES], *countfile[MAX_NUM_EYES];
02792 
02793   for(m=0; m<NUM_BUBBLE_AREAS; m++){
02794     if (m==0) 
02795       sprintf(title,"Within Bubble. Selectivity Range: (%f,%f)",
02796               (double)sel*or_division, (double)(sel+1)*or_division);
02797     else
02798       sprintf(title,"Outside Bubble. Selectivity Range: (%f,%f)",
02799               (double)sel*or_division, (double)(sel+1)*or_division);
02800 
02801     sprintf(zaxis,"Strength");
02802 
02803     sprintf(buf,"%s.stat.%d.%d.mp",filebase,sel,m);
02804     if( (fp[m]=fopen(buf,"w"))==NULL){
02805       ipc_notify(IPC_ALL,IPC_ERROR,"out file %s could not be opened", buf);
02806       return;
02807     }
02808     sprintf(buf,"%s.stat.%d.%d.count",filebase,sel,m);
02809     if( (countfile[m]=fopen(buf,"w"))==NULL){
02810       ipc_notify(IPC_ALL,IPC_ERROR,"out file %s could not be opened", buf);
02811       return;
02812     }
02813 
02814     /* Print header for maple */
02815     fprintf(fp[m],"with(linalg);\nwith(plots);\n");
02816     fprintf(fp[m],"z := matrix( [ \n");
02817 
02818     for(k=0; k<or_num_angles; k++){
02819       fprintf(fp[m], "[");
02820 
02821       for(l=0; l<or_num_angles-1; l++){ 
02822         fprintf(fp[m],"%e,", OR_histo[sel][m][k][l].value);
02823         fprintf(countfile[m],"%d ", OR_histo[sel][m][k][l].count);
02824       }
02825       fprintf(fp[m],"%e", OR_histo[sel][m][k][l].value);
02826       fprintf(countfile[m],"%d \n", OR_histo[sel][m][k][l].count);
02827       
02828       fprintf(fp[m],"]");
02829       
02830       if ( (k < or_num_angles-1) ) fprintf(fp[m],",\n");
02831       else if (k == or_num_angles-1) fprintf(fp[m]," ] );\n");
02832     }
02833 
02834     fprintf(fp[m],"matrixplot(z,title=`%s`,labels=[`x`,`y`,`%s`],axes=BOXED,style=PATCH,shading=Z);\n",title,zaxis);
02835     fclose(fp[m]);
02836     fclose(countfile[m]);
02837   }
02838 }
02839 
02840 
02841 
02842 void gaussfit_preferences(Neuron nmap[NMAX][NMAX], int low, int high)
02843 {
02844   int i,j,k,l,m,n,eye,angle;
02845   double r, theta, cx, cy, sigmax, sigmay;
02846   double resp, actual_angle,x,y;
02847   double peak_wt, sum_wts;
02848   time_t last_msg_time = time(NULL);
02849   int    neuronsinrow = (1+high-low);
02850   int    numneurons   = (1+LOCALROW(high)-LOCALROW(low))*neuronsinrow;
02851                        
02852   setup_solver();
02853   
02854   for (i=0; i<nrows; i++){
02855     const int row = MAPROW(i);
02856 
02857     if (row >= low && row <= high){
02858       for (j=low; j<=high; j++) {
02859         const int lowk  = MAX(nmap[row][j].centerx-rf_radius,0   );
02860         const int highk = MIN(nmap[row][j].centerx+rf_radius,RN-1);
02861         const int lowl  = MAX(nmap[row][j].centery-rf_radius,0   );
02862         const int highl = MIN(nmap[row][j].centery+rf_radius,RN-1);
02863         double or_pref_rad=0;
02864         double comb_or_pref_x=0;
02865         double comb_or_pref_y=0;
02866         
02867         if (PROGRESS_REPORT_NEEDED(last_msg_time)) {
02868           last_msg_time = time(NULL);
02869           ipc_notify(IPC_ONE,IPC_STD,
02870                      "NPSOL-fitting %5.1f%% completed; fitting neuron (%3d,%3d) %.24s",
02871                      ((i-LOCALROW(low))*neuronsinrow + (j-low)) * 100.0/numneurons,
02872                      i,row,ctime(&last_msg_time));
02873         }
02874 
02875         for(eye=0; eye<num_eyes; eye++){
02876           for(k=0; k<RN; k++)
02877             for(l=0; l<RN; l++)
02878               gaussfit_array[k][l] = 0.0;
02879           
02880           /* Find peak for use as lower bound for fitting, and (cx,cy) as
02881            * initial estimates of the center of the gaussian. The wts are
02882            * copied to the center of the gaussfit_array.
02883            */
02884           peak_wt = 0.0;
02885           cx = 0.0;
02886           cy = 0.0;
02887           sum_wts = 0.0;  
02888           for (k=lowk,   m=RN/2-rf_radius;  k <=highk; k++, m++) 
02889             for (l=lowl, n=RN/2-rf_radius;  l <=highl; l++, n++){
02890               
02891               resp = nmap[row][j].weights[eye][k-lowk][l-lowl];
02892               if ( resp > peak_wt) peak_wt = resp;
02893               gaussfit_array[m][n] = resp;  /* Store data in standard array */
02894               cx += (double)m*resp; cy+=(double)n*resp;
02895               sum_wts += resp;
02896             }
02897           cx/= (sum_wts* (double)RN); cy/= (sum_wts* (double)RN);
02898           
02899           /* **** The variable bounds on cx and cy is 3*rf_radius/2.   ******
02900            ****** These distances specify the zero padded distances    ******
02901            ****** centered on the center of gravity of the weights.    ******
02902            ****** Padding of the weights gives good gaussian fits.     ******/
02903           setup_variable_bounds(0.5*peak_wt, 1.0,
02904                                 0.0000, 0.999999,  /* angle is scaled also */
02905                                 (cx - ((double)rf_radius+0.5)/(double)RN),
02906                                 (cx + ((double)rf_radius+0.5)/(double)RN),
02907                                 (cy - ((double)rf_radius+0.5)/(double)RN),
02908                                 (cy + ((double)rf_radius+0.5)/(double)RN),
02909                                 1.0e-6, 2.0,
02910                                 1.0e-6, 2.0);
02911           
02912           /* Now supply the initial estimates */
02913           sigmax = sigmay = (double)rf_radius/(double)RN;
02914           r = peak_wt; theta = 0.5; /* Along diagonal gives max init error? */
02915 
02916           /* Fit the parameters using NPSOL */
02917           fit_gauss(&r, &theta, &cx, &cy, &sigmax, &sigmay); 
02918 
02919           /* Compute orientation preference */
02920           if (sigmay > sigmax) theta += 1.0;
02921           or_pref_rad = theta*M_PI; /* Angle in range [0,2PI) */
02922           or_pref[eye][row][j] = RADIANS_TO_OR_PREF(or_pref_rad/2);
02923           
02924           /* Add this angle to running vector sum */
02925           comb_or_pref_x +=cos(or_pref_rad);
02926           comb_or_pref_y +=sin(or_pref_rad);
02927 
02928           
02929           /* Scale values back to normal */
02930           cx     *= (double)RN;
02931           cy     *= (double)RN;
02932           sigmax *= (double)RN;
02933           sigmay *= (double)RN; 
02934           
02935           /*
02936             These lines don't make any sense whatsoever to me...
02937             Shouldn't the freq be something like MIN(sigmax,sigmay)?
02938             Shouldn't the phase be something like x/cos(or_pref_radians)?
02939             
02940             J.A.B.
02941           */
02942           sp_freq[eye][row][j]       = (int)floor(cx*10000);
02943           sp_phase[eye][row][j]      = (int)floor(cy*10000);
02944           sp_freq[combined_eyes][row][j]  = (int)floor(sigmax*10000);
02945           sp_phase[combined_eyes][row][j] = (int)floor(sigmay*10000);
02946           
02947           /* gaussian[k][l] is a global array set in the objective function.
02948            * Contains the values of the fitted gaussian at each of the x,y pts.
02949            */
02950           resp = 0.0;             /* Input response for fitted gaussian*/
02951           for (k=RN/2-rf_radius; k <= RN/2+rf_radius; k++)  
02952             for (l=RN/2-rf_radius; l<= RN/2+rf_radius; l++)
02953               resp += gaussian[k][l]*gaussfit_array[k][l];
02954           
02955           max_resp[eye][i][j]             = resp;  
02956           max_resp[combined_eyes][i][j]  += resp;
02957           
02958           /* ipc_log(IPC_ONE,"max_resp[eye][%d][%d] = %f\n",row,j,(double)resp);*/
02959           
02960           /* Now, compute responses for each of the angles and find mean.
02961            * The returned center and variances are the same, and only the angle
02962            * is different.
02963            */
02964           for(angle=0; angle < or_num_angles; angle++){
02965             resp = 0.0;
02966             for (k=lowk, m=RN/2-rf_radius; k <=highk; k++,m++) 
02967               for (l=lowl, n=RN/2-rf_radius; l<=highl; l++, n++){
02968                 
02969                 actual_angle = M_PI * angle/(double)or_num_angles;
02970                 x = (double)m;
02971                 y = (double)n;
02972                 resp += gauss_2d(x, y, r, actual_angle, cx, cy, sigmax, sigmay) *
02973                   gaussfit_array[m][n];
02974               }
02975             max_resp_angle[eye][i][j][angle] = resp;
02976             max_resp_angle[combined_eyes][i][j][angle] += resp;
02977             /* ipc_log(IPC_ONE,"max_resp_angle[eye][%d][%d][%d] = %f]\n",
02978                row,j,angle,(double)resp); */
02979           }
02980         }
02981         
02982         if (combined_eyes != 0) {
02983           /* Determine average preferred orientation in the vector domain,
02984              then convert it to 0..pi range and from there to an or_pref */
02985           const double vector_direction = atan2(comb_or_pref_y, comb_or_pref_x);
02986           const double or_pref_radians = CONSTRAIN_ANGLE(vector_direction/2);
02987           or_pref[combined_eyes][row][j] = RADIANS_TO_OR_PREF(or_pref_radians);
02988         }
02989       }
02990     }
02991   }
02992 }
02993 
02994 
02995 
02996 double gauss_2d(double x, double y, double r, double theta, double cx, double cy, double sigmax, double sigmay)
02997 {
02998   const double sint        = sin(theta);
02999   const double cost        = cos(theta);
03000   const double first       = ( (x-cx)*cost+(y-cy)*sint)/sigmax;
03001   const double second      = (-(x-cx)*sint+(y-cy)*cost)/sigmay;
03002   const double first_comp  = first  * first;
03003   const double second_comp = second * second;
03004 
03005   return(r*exp( -first_comp -second_comp));
03006 }
03007 

Generated at Mon Aug 21 00:30:53 2000 for RF-LISSOM by doxygen1.2.1 written by Dimitri van Heesch, © 1997-2000