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

tilt.c

Go to the documentation of this file.
00001 
00045 #include <math.h>
00046 #include <string.h>
00047 #include <stdio.h>
00048 
00049 #include "ipc.h"
00050 #include "cmdparam.h"
00051 #include "inputs.h"
00052 #include "tilt.h"
00053 #include "ppm_draw.h"
00054 
00055 #include "analyze.h"
00056 #include "file_io.h"
00057 #include "globals.h"
00058 #include "kernel.h"
00059 #include "lissom.h"
00060 
00061 /* #define DEBUG */
00062 
00063 
00064 /******************************************************************************/
00065 /* Defines and typedefs                                                       */
00066 /******************************************************************************/
00067 
00068 #define NMAP_FEATURES 10
00069 
00070 #define MAX_NUMBER_OF_PRESENTATIONS 3
00071 
00072 #define MAX_NUM_PORTIONS 2
00073 
00075 #define MAX_ANGLE_STEPS 360
00076 
00077 
00079 #define MAX_NUMBER_OF_SPOTS 5
00080 
00081 
00082 /* enumerated type values */
00083 #define ALL_UNITS 0
00084 #define MAX_UNITS 1
00085 
00086 #define INIT 0
00087 #define SETL 1
00088 
00089 /* Same as Joseph's Map_Feature but with activity levels. */
00090 typedef struct                   
00091 {
00092   int i,j               ;        
00093   double or_selectivity ;        
00094   int or_preference     ;        
00095   int phase, freq       ;        
00096   double od             ;        
00097   double activity       ;        
00098 } Act_Feature           ;
00099 
00100 
00101 
00102 /******************************************************************************/
00103 /* Parameters                                                                 */
00104 /******************************************************************************/
00105  
00106 int    save_steps = 1;
00107 int    t_presentation=Uninitialized; 
00108 int    number_of_portions      = Uninitialized;
00109 int    cortex_portion_boundary = Uninitialized;
00110 int    save_angle_responses = False;
00111  
00113 int    retina_portion_boundary=Uninitialized;
00114 int    truncate_inputs_across_boundary = False;
00115 
00116  
00117 /******************************************************************************/
00118 /* Command prototypes                                                         */
00119 /******************************************************************************/
00120  
00121 CMD_DECLARE(analyze_activity);
00122 CMD_DECLARE(analyze_portions);
00123 CMD_DECLARE(divide_cortex);
00124 CMD_DECLARE(training_angle_distribution);
00125  
00126  
00127  
00128 /******************************************************************************/
00129 /* Prototypes for private functions                                           */
00130 /******************************************************************************/
00131  
00132 void   compute_activity_statistics(double activity[NMAX][NMAX], 
00133                                    double weighted_or_prefs[3][2][2], 
00134                                    double base_response[MAX_ANGLE_STEPS][MAX_NUMBER_OF_SPOTS][2],
00135                                    FILE *fp);
00136 void   find_activity_max(double activity[NMAX][NMAX],
00137                          int *nexamples, Act_Feature *examples, 
00138                          double weightedORpref[2],
00139                          int ilow, int ihigh, int jlow, int jhigh);
00140 void   print_summary_header(FILE *fp, int num_portions);
00141 
00142  
00143  
00144 /******************************************************************************/
00145 /* Global variables                                                           */
00146 /******************************************************************************/
00147  
00149 int current_angle_step=0;
00150  
00152 double average_or_prefs[2][3][MAX_NUM_PORTIONS][2]; 
00153  
00157 int append_summary = False;
00158  
00161 double ae_base_response[2][MAX_ANGLE_STEPS][MAX_NUMBER_OF_SPOTS][2];
00162  
00163 
00164 /* To store information about which angles have been used in training, 
00165    and with what frequency, for computing a histogram if desired
00166 */
00167 //int training_angle_total_count;
00168 //int training_angle_counts[MAX_NUM_ANGLES];
00169  
00170  
00171  
00172 /******************************************************************************/
00173 /* Initialization hook                                                        */
00174 /******************************************************************************/
00175  
00176 void  tilt_init_hook( void )
00177 {
00178   CMD_DOC(analyze_activity,NULL,2,"%s <start> <end>",
00179           "Sets the start and end iterations for analyze_portions measures");
00180   
00181   CMD_DOC(analyze_portions,"init_network",0,"%s",
00182           "Compute activity statistics for the initial and settled responses,\n"
00183           "saving pictures if needed.  The statistics are computed separately for\n"
00184           "each portion.");
00185   
00186   CMD_DOC(divide_cortex,"init_network",0,"%s",
00187           "Lesions receptive fields down the cortex_portion_boundary, typically the\n"
00188           "vertical midline. After this call, all weights on neurons on the left side\n"
00189           "of the cortex to receptors on the right side of the retina are zero, and\n"
00190           "vice-versa for the right side. The changes are permanent and irreversible;\n"
00191           "the old weight values are lost.\n\n"
00192           "Also, the input patterns used henceforth are truncated at the\n"
00193           "retina_portion_boundary to ensure that the patterns do not cross over into \n"
00194           "the receptive fields of the opposite side of the cortex (CURRENTLY UNIMPLEMENTED).\n\n"
00195           "This is used to distinguish lateral connection effects from receptive field\n"
00196           "effects, since after this call the only way for the left and right halves\n"
00197           "to interact is through the lateral connections.\n\n"
00198           "If there is some receptive field scatter enabled, the operation of\n"
00199           "this routine will need to be scrutinized very carefully to ensure\n"
00200           "that it is operating as intended.  Having neurons on one side of the\n"
00201           "cortex whose receptive fields are on the opposite side of the retina\n"
00202           "may make the results difficult to interpret.");
00203   
00204 //  CMD_DOC(training_angle_distribution,"init_network",0,"%s",
00205 //          "Determine the distribution of angles trained since last reset_presentation.\n\n"
00206 //          "Creates a file with a histogram of the percentage of each angle during\n"
00207 //          "training.  This gives a way to judge the (an)isotropicity of the distribution\n"
00208 //          "of training inputs.\n\n"
00209 //          "The file is suitable for plotting with xmgr (ACE/gr) or just about any other\n"
00210 //          "graphing program.");
00211   
00212   
00213   PARAM_I(PARAM_INT,   cortex_portion_boundary,0,NMAX,
00214           "Unit number specifying the boundary between right and left sides\n"
00215           "of the cortex,");
00216   params_define_default_expr("cortex_portion_boundary","N/inputs_pereye");
00217   
00218   PARAM_I(PARAM_INT,   number_of_portions,0,MAX_NUM_PORTIONS,
00219           "Number of portions in which the cortex shall be divided for testing purposes.");
00220   /* Default should be MIN(inputs_pereye,MAX_NUM_PORTIONS) but can't express that right now */
00221   params_define_default_expr("number_of_portions","1"); 
00222   
00223   PARAM_I(PARAM_BOOL,  save_angle_responses,False,True,
00224           "Whether to save a copy of the average orientation activated for each angle\n"
00225           "when analyze_portions executes.");
00226   
00227   PARAM_L(PARAM_INT,   save_steps,Uninitialized,
00228           "Save network activation, etc. every (save_steps)th time analyze_portions\n"
00229           "is called. E.g.\n"
00230           "save_steps =             1 : save every step\n"
00231           "save_steps =             3 : save every third step\n"
00232           "save_steps = Uninitialized : do not save images.");
00233 }
00234 
00235 
00236 
00237 /******************************************************************************/
00238 /* Commands                                                                   */
00239 /******************************************************************************/
00240 
00241 cmdstat cmd_analyze_portions( CMD_ARGS )
00242 {
00243   static FILE *init_summary;
00244   static FILE *setl_summary;
00245   static int has_been_called=False;
00246   
00247   (void)argc; /* ignored */
00248   (void)argv; /* ignored */
00249   
00250   if (or_dumped == Uninitialized) {
00251     if (!has_been_called)
00252       ipc_notify(IPC_ONE,IPC_WARNING,"analyze_portions results will be incomplete because measure_or_pref has not yet been called");
00253   }
00254   /* Conservative about warning, since it's not always an error (e.g. for TAE tests) */
00255   else if (learning && (iteration-or_dumped) > 180) { 
00256     ipc_notify(IPC_ONE,IPC_WARNING,
00257                "measure_or_pref was called %d iterations ago; analyze_activity data may be stale",
00258                iteration-or_dumped);
00259   }
00260  
00261   /* Open summary files and print header info, if needed */
00262   if ((AMPARENTPE) && ((init_summary == NULL) || (setl_summary == NULL)) ) {
00263         
00264     char append[2]    = "a";
00265     char overwrite[2] = "w";
00266     char *openflags;
00267     char filename[50];
00268         
00269     openflags = (append_summary ? append : overwrite);
00270     append_summary = True;      /* for all future calls */
00271         
00272     if (init_summary == NULL) {
00273       sprintf(filename,"%s.init.txt",filebase);
00274       if( (init_summary=fopen(filename,openflags))==NULL ) {
00275         ipc_notify(IPC_ALL,IPC_ERROR,"File %s not opened", filename );
00276         return CMD_FILE_ERROR;
00277       }
00278       print_summary_header(init_summary,number_of_portions);
00279     }
00280         
00281     if (setl_summary == NULL) {
00282       sprintf(filename,"%s.setl.txt",filebase);
00283       if( (setl_summary=fopen(filename,openflags))==NULL ) {
00284         ipc_notify(IPC_ALL,IPC_ERROR,"File %s not opened", filename );
00285         return CMD_FILE_ERROR;
00286       }
00287       print_summary_header(setl_summary,number_of_portions);
00288     }
00289         
00290   }
00291         
00292   /* Analyze initial response */
00293   compute_activity_statistics(init_activity,average_or_prefs[INIT],
00294                               ae_base_response[INIT], init_summary); 
00295   
00296   /* Analyze settled response */
00297   compute_activity_statistics(prev_map_activity,average_or_prefs[SETL], 
00298                               ae_base_response[SETL], setl_summary);  
00299   
00300   /* Close files if done with analysis */
00301   //if (iteration == activity_analysis_end) {
00302   //      fclose(init_summary); init_summary=NULL;
00303   //      fclose(setl_summary); setl_summary=NULL;
00304   //}
00305   
00306   /* Save network activation, etc. if requested */
00307   if (save_steps && (save_steps != Uninitialized) && (current_angle_step % save_steps == 0))
00308     cmd_plot_activity(0,NULL);
00309 
00310   has_been_called=True;
00311 
00312   return CMD_NO_ERROR;
00313 }
00314  
00315  
00316  
00319 cmdstat cmd_analyze_activity( CMD_ARGS )
00320 {
00321   /* fetch parameters */
00322   int activity_analysis_start = cmdi(argv[0]); 
00323   int activity_analysis_end   = cmdi(argv[1]);
00324  
00325   (void)argc; /* ignored */
00326  
00327   //define_portion_parameters();
00328  
00329   { /* Set up hook */
00330     char specifier[20];
00331     const char *args[]={"after_presentation",NULL,"analyze_portions"};
00332     snprintf(specifier,20,"%d-%d",activity_analysis_start,activity_analysis_end);
00333     args[1]=specifier;
00334     cmd_hook(3,args);
00335   }
00336   
00337   //ipc_notify(IPC_ONE,IPC_STD,"Analyzing portions from iterations %d to %d",
00338   //               activity_analysis_start,activity_analysis_end);
00339  
00340   return CMD_NO_ERROR;
00341 }
00342  
00343  
00344  
00345 cmdstat cmd_divide_cortex( CMD_ARGS )
00346 {
00347   int i,j,k,l,lowk,lowl,highk,highl,basek;
00348   (void)argv; /* ignored for now; could accept a boundary */
00349   (void)argc; /* ignored */
00350   
00351   //define_portion_parameters();
00352  
00353   /* Set flag to indicate that inputs should be drawn on one side only */
00354   truncate_inputs_across_boundary = True;
00355   
00356   for(i=0; i<nrows; i++){
00357     const int row = MAPROW(i);                              
00358     for(j=0; j<N; j++)                              
00359       { 
00360         /* If this neuron is on the left side of the cortex, mark connections 
00361            looking rightward past retina_portion_boundary to be killed */
00362         if (row < cortex_portion_boundary) {
00363           lowk = MAX(cortex_map[row][j].centerx-rf_radius,retina_portion_boundary);
00364           highk= MIN(cortex_map[row][j].centerx+rf_radius,RN-1);
00365         }
00366  
00367         /* If this neuron is on the right side of the cortex, mark connections 
00368            looking leftward past retina_portion_boundary to be killed */
00369         else {
00370           lowk = MAX(cortex_map[row][j].centerx-rf_radius,0);
00371           highk= MIN(cortex_map[row][j].centerx+rf_radius,retina_portion_boundary-1);
00372         }
00373  
00374         basek = MAX(cortex_map[row][j].centerx-rf_radius,0   );
00375         lowl  = MAX(cortex_map[row][j].centery-rf_radius,0   );
00376         highl = MIN(cortex_map[row][j].centery+rf_radius,RN-1);
00377             
00378  
00379         /* if ((highk >= lowk) && (highl >= lowl))
00380            ipc_notify(IPC_ALL,IPC_STD,"Killing weights to [%03d--%03d,%03d--%03d] of neuron [%03d,%03d]",
00381            lowk,highk,lowl,highl,i,j); */
00382  
00383         /* Kill the specified connections */
00384         for (k=lowk; k <=highk; k++)
00385           for (l=lowl; l<=highl; l++) {
00386             cortex_map[row][j].weights[0][k-basek][l-lowl] = 0.0;
00387             cortex_map[row][j].weights[1][k-basek][l-lowl] = 0.0;
00388           }
00389       }
00390   }
00391  
00392   ipc_notify(IPC_ONE,IPC_STD,"Cortex divided at vertical coordinate %d along retina vertical coordinate %d",
00393              cortex_portion_boundary,retina_portion_boundary);
00394  
00395   return CMD_NO_ERROR;
00396 }
00397 
00398 
00399 /* No longer implemented; should be moved to inputs.c */
00400 //cmdstat cmd_training_angle_distribution( CMD_ARGS )
00401 //{
00402 //  int angle;
00403 //  (void)argc; /* ignored */
00404 //  (void)argv; /* ignored */
00405 // 
00406 //  if (plot_pe == Uninitialized || MyPE == plot_pe) {
00407 // 
00408 //    /* Save data to a file for graphing */
00409 //    char filename[50];
00410 //    static FILE *training_angle_histo_file;    
00411 // 
00412 //    /* Open file */
00413 //    sprintf(filename,"%s.%d.train_histo",filebase,iteration);
00414 // 
00415 //    if (plot_pe == Uninitialized) /* Add PE tag to filename when each PE plots */
00416 //      sprintf(filename+(strlen(filename)-1),".pe%02d",MyPE);
00417 //        
00418 //    if( (training_angle_histo_file=fopen(filename,"w"))==NULL ) {
00419 //      ipc_notify(IPC_ALL,IPC_ERROR,"File %s not opened", filename );
00420 //      return -1;
00421 //    }
00422 // 
00423 //    /* Print header */
00424 //    fprintf(training_angle_histo_file,"# Training angle histogram at iteration %d.\n",iteration);
00425 //    fprintf(training_angle_histo_file,"# Angle Percentage   Count (out of %d total)\n",training_angle_total_count);
00426 // 
00427 //    /* Print count for each angle */
00428 //    for (angle=0; angle < or_num_angles; angle++) 
00429 //      fprintf(training_angle_histo_file,"  %5.1f      %5.1f   %5d \n",
00430 //              OR_PREF_TO_DEGREES(angle),
00431 //              (100.0*training_angle_counts[angle])/training_angle_total_count,
00432 //              training_angle_counts[angle]);
00433 // 
00434 //    fclose(training_angle_histo_file);
00435 // 
00436 //    ipc_notify(IPC_ONE,IPC_STD,"Created %s",filename);
00437 //  }
00438 // 
00439 //  return CMD_NO_ERROR;
00440 //}
00441 
00442 
00443 
00444 /******************************************************************************/
00445 /* Private routines                                                           */
00446 /******************************************************************************/
00447  
00449 void print_summary_header(FILE *fp, int num_portions)
00450 {
00451   int i;
00452 
00453   /* Typing savers */
00454 #define PLINE(start,repeat) fprintf(fp,start); for (i=0;i<num_portions; i++) fprintf(fp,repeat); fprintf(fp,"\n")
00455 #define PPORT(start,repeat) fprintf(fp,start); for (i=0;i<num_portions; i++) fprintf(fp,repeat,i); fprintf(fp,"\n")
00456 
00457   PPORT("       |","---------- Portion%2d ------------------------|");
00458   PLINE("       |","                                             |");
00459   PLINE("       |","t    |Orientation       |Maximum Activation  |");
00460   PLINE("       |","h    |Preference        |           P        |");
00461   PPORT("       |","e%2d  |                  |         O r        |");
00462   PLINE("       |","t    | all   max   all- |   Unit  R e activ  |");
00463   PLINE("     t |","a    |units units  base |(  i,  j)  f:ation  |");
00464   PLINE(" -------","----------------------------------------------");
00465 
00466 #undef PLINE
00467 #undef PPORT  
00468 }
00469  
00470  
00471 
00482 void compute_activity_statistics(double activity[NMAX][NMAX], 
00483                                  double weighted_or_prefs[3][2][2], 
00484                                  double base_response[MAX_ANGLE_STEPS][MAX_NUMBER_OF_SPOTS][2],
00485                                  FILE *fp)
00486 {
00487   int pres_index=0; /* local copy of t_presentation, if defined */
00488   int nexamples = 1;
00489  
00490   /* [portion_number][example_number] */
00491   Act_Feature examples[2][ NMAP_FEATURES];  /* To save MAX & MIN map features in each portion */
00492  
00493  
00494   /* update local copy as an array index if global version exists */
00495   if (t_presentation != Uninitialized) 
00496     pres_index = t_presentation;
00497   
00498   if (AMPARENTPE){  /* PE 0 determines nexamples maxima and minima values, 
00499                        and writes to files */
00500  
00501  
00502     /* Find maxima on left and right halves of the cortex */
00503     /* This could be put on two separate PEs if it is time-consuming */
00504     find_activity_max(activity,
00505                       &nexamples,&(examples[0][0]),  
00506                       weighted_or_prefs[pres_index][0],
00507                       0,  cortex_portion_boundary-1,  0, (N-1) );
00508  
00509     if (number_of_portions > 1)
00510       find_activity_max(activity,
00511                         &nexamples,&(examples[1][0]),
00512                         weighted_or_prefs[pres_index][1],
00513                         cortex_portion_boundary, (N-1), 0, (N-1) );
00514  
00515         
00516     /* print summary lines */
00517     {
00518       int portion_number, which_units, example_number;
00519  
00520       /* print iteration number */
00521       fprintf(fp,"%6d",iteration);  
00522  
00523       /* print data for each spot's portion of the retina */
00524       for (portion_number=0; portion_number < number_of_portions; portion_number++) {
00525         char   or_pref_string[8]      = "";     
00526  
00527         /* Save copy of average values if asked and available and not full */
00528         if (save_angle_responses && 
00529             (pres_index == 0) && 
00530             (current_angle_step < MAX_ANGLE_STEPS)) 
00531           for (which_units=ALL_UNITS; which_units<=MAX_UNITS; which_units++) {
00532             base_response[current_angle_step][portion_number][which_units] = 
00533               weighted_or_prefs[pres_index][portion_number][which_units];
00534             /*      printf("base_response[%d][%d][%d] = %g  ",
00535                     current_angle_step,portion_number,which_units,
00536                     (double)(RADIANS_TO_DEGREES(weighted_or_prefs[pres_index][portion_number][which_units]))); */
00537           }
00538  
00539         /* Print angle of spot in this portion if valid */
00540         if (inputs->is_active(portion_number,0)) {
00541           const double thetarad = inputs->angle_of_object(portion_number,0);
00542           const double theta = RADIANS_TO_DEGREES(thetarad);
00543           fprintf(fp," |%5.1f ",theta);
00544         }
00545         else
00546           fprintf(fp," |      ");
00547         
00548         /* Weighted averages of orientation preferences, if available */
00549         for (which_units=ALL_UNITS; which_units<=MAX_UNITS; which_units++) 
00550           if ( or_dumped == Uninitialized ||
00551                weighted_or_prefs[pres_index][portion_number][which_units] == Uninitialized)
00552             fprintf(fp,"      ");
00553           else fprintf(fp,"%5.1f ",
00554                        RADIANS_TO_DEGREES(weighted_or_prefs[pres_index]
00555                                           [portion_number][which_units]));
00556           
00557         /* Difference between observed angle (based on average of all units)
00558            and base angle */
00559         if (or_dumped == Uninitialized ||
00560             weighted_or_prefs[pres_index][portion_number][ALL_UNITS]     == Uninitialized || 
00561             base_response[current_angle_step][portion_number][ALL_UNITS] == Uninitialized || 
00562             (pres_index != 0))
00563           fprintf(fp,"       ");
00564         else 
00565           fprintf(fp,"%6.2f ",
00566                   RADIANS_TO_DEGREES(CONSTRAIN_SYMMETRIC(
00567                                                          weighted_or_prefs[pres_index]
00568                                                          [portion_number][ALL_UNITS] -
00569                                                          base_response[current_angle_step]
00570                                                          [portion_number][ALL_UNITS])));
00571  
00572         /* Maximum activity values */
00573         for (example_number=0; example_number < nexamples; example_number++) {
00574           if (or_dumped != Uninitialized) 
00575             sprintf(or_pref_string, "%03d",
00576                     (int)OR_PREF_TO_DEGREES(examples[portion_number]
00577                                             [example_number].or_preference));
00578           fprintf(fp,"(%3d,%3d)%3s:%5.3f ",
00579                   examples[portion_number][example_number].i, 
00580                   examples[portion_number][example_number].j,
00581                   or_pref_string,
00582                   examples[portion_number][example_number].activity);
00583         }
00584       }
00585       fprintf(fp,"\n");
00586  
00587       /* Compute illusion magnitude, if available yet */
00588       if (pres_index == 2) {
00589         fprintf(fp,"\n"); 
00590  
00591         for (which_units=ALL_UNITS; which_units<=MAX_UNITS; which_units++) {
00592           double perceived_angle_separate                = Uninitialized;
00593           char   perceived_angle_separate_string[8]      = "";
00594           double perceived_angle_simultaneous            = Uninitialized;
00595           char   perceived_angle_simultaneous_string[8]  = "";
00596           double difference                              = Uninitialized;
00597           char   difference_string[8]                    = "";
00598               
00599               
00600           if ( or_dumped != Uninitialized &&
00601                (weighted_or_prefs[0][0][which_units] != Uninitialized) &&
00602                (weighted_or_prefs[2][1][which_units] != Uninitialized)) {
00603             perceived_angle_separate =
00604               fabs(weighted_or_prefs[0][0][which_units] -
00605                    weighted_or_prefs[2][1][which_units]);
00606             sprintf(perceived_angle_separate_string, "%5.1f",
00607                     RADIANS_TO_DEGREES(perceived_angle_separate));
00608           }
00609                 
00610           /* difference of responses to each spot seen together */
00611           if (or_dumped != Uninitialized &&
00612               (weighted_or_prefs[0][0][which_units] != Uninitialized) &&
00613               (weighted_or_prefs[2][1][which_units] != Uninitialized)) {
00614             perceived_angle_simultaneous =
00615               fabs(weighted_or_prefs[1][0][which_units] -
00616                    weighted_or_prefs[1][1][which_units]);
00617             sprintf(perceived_angle_simultaneous_string, "%5.1f",
00618                     RADIANS_TO_DEGREES(perceived_angle_simultaneous));
00619           }
00620               
00621           if ((perceived_angle_simultaneous != Uninitialized) &&
00622               (perceived_angle_separate     != Uninitialized)) {
00623             difference = perceived_angle_simultaneous - perceived_angle_separate;
00624             sprintf(difference_string, "%6.2f",
00625                     RADIANS_TO_DEGREES(difference));
00626           }
00627               
00628           switch (which_units){
00629           case ALL_UNITS:  fprintf(fp,"AngleDiffs(allUnits) "); break;
00630           case MAX_UNITS:  fprintf(fp,"AngleDiffs(maxUnits) "); break;
00631           }
00632 
00633           if (inputs->is_active(1,0)) {
00634             const double thetadiff = fabs(inputs->angle_of_object(0,0)-inputs->angle_of_object(1,0));
00635             
00636             fprintf(fp,"retina:%5.1f  perceived,separate:%5s  p,both:%5s  illusory:%6s \n",
00637                     RADIANS_TO_DEGREES(thetadiff),
00638                     perceived_angle_separate_string,
00639                     perceived_angle_simultaneous_string,
00640                     difference_string);
00641           }
00642         }
00643             
00644         fprintf(fp,"\n\n"); 
00645       }
00646     }
00647   }
00648 }
00649 
00650 
00651 
00667 void find_activity_max(double activity[NMAX][NMAX],
00668                            int *nexamples, Act_Feature *examples, 
00669                            double weightedORpref[2],
00670                            int ilow, int ihigh, int jlow, int jhigh) 
00671 {
00672   int i,j,k,m,example_number;
00673   /* Coordinate sums of vector given by by orientation (theta) and activation (r) */
00674   double or_vector_sum_x[2] = {0,0}; /* ALL_UNITS or MAX_UNITS */
00675   double or_vector_sum_y[2] = {0,0};
00676  
00677   /* Check parameters */
00678   if (( (ihigh-ilow+1)*(jhigh-jlow+1) < *nexamples) || (*nexamples >= NMAP_FEATURES)){
00679     ipc_notify(IPC_ALL,IPC_WARNING,"Not enough data, or index overflow: ihigh-ilow+1 = %d, jhigh-jlow+1 = %d, nexamples=%d",
00680                ihigh-ilow+1, jhigh-jlow+1, *nexamples);
00681     *nexamples = 0;
00682     return;
00683   }
00684  
00685   /* Initialize array */
00686   for(i=0; i < *nexamples; i++)
00687     examples[i].activity = 0.0; /* Init to min possible value */
00688  
00689   /* Look at rectangular region of net under consideration */
00690   /* ipc_notify(IPC_ALL,IPC_STD,"Looking at (%d,%d) to (%d,%d)",ilow,jlow,ihigh,jhigh); */
00691   for(i=ilow; i<=ihigh; i++)
00692     for(j=jlow; j<=jhigh; j++){ 
00693  
00694       if ((or_dumped != Uninitialized) && (activity[i][j] > 0.0)) {
00695         /* Get angle in range [0,2pi] */
00696         const double angle = 2*DEGREES_TO_RADIANS(OR_PREF_TO_DEGREES(or_pref[combined_eyes][i][j]));
00697             
00698         /* Add this unit to running vector sums */
00699         or_vector_sum_x[ALL_UNITS] += activity[i][j] * cos(angle);
00700         or_vector_sum_y[ALL_UNITS] += activity[i][j] * sin(angle);
00701             
00702         /* If at maximum activation add this unit to running vector sums */
00703         if (activity[i][j] >= 1.0){
00704           or_vector_sum_x[MAX_UNITS] += activity[i][j] * cos(angle);
00705           or_vector_sum_y[MAX_UNITS] += activity[i][j] * sin(angle);
00706         }
00707       }
00708  
00709       /* Insert maximum values at highest indeces in the examples array */
00710       for(m=0; (m < *nexamples) &&        /* search for insert_position */
00711             (examples[m].activity > activity[i][j]); m++);
00712  
00713       for(k= (*nexamples); k >m; k--) /* Move things over upto m-th position */
00714         examples[k] = examples[k-1];
00715  
00716       examples[m].activity = activity[i][j]; /* Insert */
00717       examples[m].i = i;  examples[m].j = j;
00718  
00719       /* ipc_notify(IPC_ALL,IPC_VERBOSE,"t=%d activity: i=%d j=%d m=%d act=%g",t,i,j,m,(double)activity[i][j]); */
00720          
00721     }
00722  
00723   /* Fill in all the other fields to complete the records */
00724   for (example_number=0; example_number < *nexamples; example_number++) {
00725     i = examples[example_number].i; 
00726     j = examples[example_number].j;
00727     if (or_dumped != Uninitialized) {
00728       examples[example_number].or_preference = or_pref[ combined_eyes][i][j];
00729       examples[example_number].freq          = sp_freq[ combined_eyes][i][j];
00730       examples[example_number].phase         = sp_phase[combined_eyes][i][j];
00731     }
00732   }
00733  
00734   /* Compute average orientations from vector sum, if available */
00735   {
00736     double magnitude[2];
00737     double angle[2]; 
00738     double angle_around_origin;
00739     int which_units;
00740  
00741     for (which_units=ALL_UNITS; which_units<=MAX_UNITS; which_units++) {
00742  
00743       /*
00744         ipc_notify(IPC_ALL,IPC_VERBOSE,"\nsum_x[%d]:%g sum_y[%d]:%g", 
00745         which_units,
00746         (double)or_vector_sum_x[which_units],
00747         which_units,
00748         (double)or_vector_sum_y[which_units]
00749         );
00750       */
00751  
00752       magnitude[which_units] = 
00753         sqrt(or_vector_sum_x[which_units]*or_vector_sum_x[which_units] +
00754              or_vector_sum_y[which_units]*or_vector_sum_y[which_units]);
00755           
00756       if (magnitude[which_units] > 0) {
00757  
00758         /* Angle in range +/- pi out on a scale of 2pi */
00759         angle_around_origin = atan2(or_vector_sum_y[which_units],
00760                                     or_vector_sum_x[which_units]);
00761  
00762         /* Convert angle from 2pi scale to pi scale to account for symmetry,
00763            and normalize to 0..pi range */
00764         angle[which_units] = CONSTRAIN_ANGLE(angle_around_origin/2);
00765  
00766         /*
00767           ipc_notify(IPC_ALL,IPC_VERBOSE,"Mag:%g Angle:%g",
00768           (double)magnitude[which_units],
00769           (double)(RADIANS_TO_DEGREES(angle[which_units])));
00770         */
00771  
00772         weightedORpref[which_units] = angle[which_units];
00773       }
00774       else 
00775         weightedORpref[which_units] = Uninitialized;
00776  
00777     }
00778   }
00779  
00780   /* if no units are at 1.0, just take OR pref of top unit, if any */
00781   if ((weightedORpref[MAX_UNITS] == Uninitialized) &&
00782       (activity[examples[*nexamples-1].i][examples[*nexamples-1].j] > 0))
00783     weightedORpref[MAX_UNITS] = 
00784       DEGREES_TO_RADIANS(OR_PREF_TO_DEGREES(examples[*nexamples-1].or_preference));
00785 }
00786  
00787  
00788  

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