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
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
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
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
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
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
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];
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
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
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
00215
00216
00217 void analyze_init_hook( void )
00218 {
00219
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 00240
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
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
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
00490
00491
00492
00493 cmdstat cmd_copy_network( CMD_ARGS )
00494 {
00495 (void)argc;
00496 (void)argv;
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;
00519 (void)argv;
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]);
00553 const int uj = cmdi(argv[1]);
00554 const int ncontrasts = cmdi(argv[2]);
00555 const double max_contrast = cmdf(argv[3]);
00556 const int pe = PEFORROW(ui);
00557
00558 (void)argc;
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(¢erx, IPC_INT, 1, pe);
00575 ipc_get(¢ery, 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;
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++)
00601 for(i=0; i<nrows; i++)
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
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];
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]);
00626 const int uj = cmdi(argv[1]);
00627 const int ncontrasts = cmdi(argv[2]);
00628 const int nfrequencies = cmdi(argv[3]);
00629 const double max_contrast = cmdf(argv[4]);
00630 const double max_spfreq = cmdf(argv[5]);
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;
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);
00646
00647 for (sp=1; sp <= nfrequencies; sp++){
00648 sigmax = (double)sp/(double)nfrequencies * max_spfreq;
00649 if (PEISME(pe)){
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++)
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
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();
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);
00675
00676 for (c=1; c<=ncontrasts; c++){
00677 contrast = (double)c/(double)ncontrasts * max_contrast;
00678 for(i=0; i<nrows; i++){
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
00684 initialize_markers();
00685 initialize_actlists();
00686 for (ts=1; ts<=tsettle; ts++){
00687 compute_responses(ts);
00688 ipc_barrier();
00689 }
00690 if (PEISME(pe))
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;
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;
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
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
00740 if (PEISME(pe)){
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();
00762
00763 if (!PEISME(pe)) ipc_get(input_vectors, IPC_DOUBLE, RNMAX*RNMAX*num_eyes, pe);
00764
00765
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++){
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++)
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
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;
00807
00808 init_bubblewidth = 0.0;
00809 final_bubblewidth = 0.0;
00810
00811 {
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];
00833 int count[2];
00834 double width[2][NROWS];
00835
00836 (void)argc;
00837 (void)argv;
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 00848 00849 00850 00851 00852 00853 00854 00855 00856 00857 00858 00859 00860 00861 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 00879 00880
00881 } 00882
00883 average_init = average_final = 0.0;
00884 count[0] = count[1] = 0;
00885 for (i=0; i<nrows; i++){
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
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
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)
00963 double data[NMAX*NMAX];
00964 #else
00965 double data[RNMAX*RNMAX*MAX_NUM_EYES];
00966 #endif
00967
00968
00969 for (i=lowk; i<=highk; i++)
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];
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);
01081
01082 if (PEISME(pe)){
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
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(¢erx, IPC_INT, 1, pe);
01117 ipc_get(¢ery, IPC_INT, 1, pe);
01118
01119 01120
01121
01122 for (cx=lowk; cx <= highk; cx++)
01123 for (cy = lowl; cy <=highl; cy++){
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))){
01127 if (cx < centerx)
01128 for (x=cx+1; x<RN; x++)
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++)
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++)
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++)
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);
01159 if (PEISME(pe))
01160 if (map_activity[ui][uj] > 0.0)
01161 response[cx-lowk][cy-lowl] = map_activity[ui][uj];
01162 01163
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
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);
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);
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)){
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 {
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
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
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--)
01337 for(phase=0; phase<sp_num_phases; 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 01346 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
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 01372 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]){
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
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];
01422 double v_sum[EYE_ARRAY_SIZE][NROWS][NMAX][2];
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
01433 for(i=0; i<nrows; i++)
01434 for (j=low; j<=high; j++) {
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++) {
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
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
01497 od_preferences(od_pref,cortex_map);
01498
01499
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();
01505
01506 if (!AMPARENTPE)
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);
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
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 01552 01553 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
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
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
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();
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);
01619
01620
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++){
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)
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++){
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)
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
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 01710 01711 01712 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
01734 height = ppm_presentation_height();
01735 if (height < 0) return CMD_MISC_ERROR;
01736
01737
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
01746 sprintf(buf, "%s%s",filebase, filename);
01747 filename=buf;
01748 }
01749
01750
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
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 01786 01787 01788 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
01810 height = ppm_presentation_height();
01811 if (height < 0) return CMD_MISC_ERROR;
01812
01813
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
01822 sprintf(buf, "%s%s",filebase, filename);
01823 filename=buf;
01824 }
01825
01826
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
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
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;
01855
01856 ABORT_IF_RANGE_OUTSIDE_CORTEX(low,low,high,high);
01857 VERIFY_ORPREF_AVAILABLE(0,OR_features);
01858
01859 if (AMPARENTPE)
01860 find_OR_maxmin(&nexamples,low,high);
01861
01862 ipc_barrier();
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){
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
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)
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;
01929 or_features[ORF_MAX][i].or_selectivity = 0.0;
01930 }
01931 for(i=low; i<=high; i++)
01932 for(j=low; j<=high; j++){
01933
01934
01935 for(m=0; (m < *nexamples) &&
01936 (or_features[ORF_MIN][m].or_selectivity < or_select[combined_eyes][i][j]); m++);
01937
01938 for(k= (*nexamples); k >m; k--)
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];
01942 or_features[ORF_MIN][m].i = i;
01943 or_features[ORF_MIN][m].j = j;
01944
01945
01946 for(m=0; (m < *nexamples) &&
01947 (or_features[ORF_MAX][m].or_selectivity > or_select[combined_eyes][i][j]); m++);
01948
01949 for(k= (*nexamples); k >m; k--)
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];
01953 or_features[ORF_MAX][m].i = i;
01954 or_features[ORF_MAX][m].j = j;
01955
01956 }
01957
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
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
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;
01986
01987 ABORT_IF_RANGE_OUTSIDE_CORTEX(low,low,high,high);
01988 VERIFY_ORPREF_AVAILABLE(0,SP_features);
01989
01990 if (AMPARENTPE)
01991 find_sp_maxmin(&nexamples,low,high);
01992
01993 ipc_barrier();
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){
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
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)
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;
02054 or_features[ORF_MAX][i].phase = 0;
02055 }
02056 for(i=low; i<=high; i++)
02057 for(j=low; j<=high; j++){
02058 const int spatial_frequency = sp_freq[combined_eyes][i][j] + sp_phase[combined_eyes][i][j];
02059
02060 for(m=0; (m < *nexamples) &&
02061 (or_features[ORF_MIN][m].phase < spatial_frequency); m++);
02062
02063 for(k= (*nexamples); k >m; k--)
02064 or_features[ORF_MIN][k] = or_features[ORF_MIN][k-1];
02065
02066 or_features[ORF_MIN][m].phase = spatial_frequency;
02067 or_features[ORF_MIN][m].i = i; or_features[ORF_MIN][m].j = j;
02068
02069
02070 for(m=0; (m < *nexamples) &&
02071 (or_features[ORF_MAX][m].phase > spatial_frequency); m++);
02072
02073 for(k= (*nexamples); k >m; k--)
02074 or_features[ORF_MAX][k] = or_features[ORF_MAX][k-1];
02075
02076 or_features[ORF_MAX][m].phase = spatial_frequency;
02077 or_features[ORF_MAX][m].i = i; or_features[ORF_MAX][m].j = j;
02078
02079 }
02080
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 )
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;
02108
02109 ABORT_IF_RANGE_OUTSIDE_CORTEX(low,low,high,high);
02110
02111 if (AMPARENTPE)
02112 find_OD_maxmin(&nexamples,low,high);
02113
02114 ipc_barrier();
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){
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)
02147 {
02148
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++)
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;
02160 or_features[ORF_MAX][i].od = 0.0;
02161 }
02162 for(i=low; i<=high; i++)
02163 for(j=low; j<=high; j++){
02164
02165
02166 for(m=0; (m < *nexamples) &&
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--)
02170 or_features[ORF_MIN][k] = or_features[ORF_MIN][k-1];
02171
02172 or_features[ORF_MIN][m].od = od_pref[i][j];
02173 or_features[ORF_MIN][m].i = i; or_features[ORF_MIN][m].j = j;
02174
02175
02176 for(m=0; (m < *nexamples) &&
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--)
02180 or_features[ORF_MAX][k] = or_features[ORF_MAX][k-1];
02181
02182 or_features[ORF_MAX][m].od = od_pref[i][j];
02183 or_features[ORF_MAX][m].i = i; or_features[ORF_MAX][m].j = j;
02184
02185 }
02186
02187
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 )
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)){
02212 graph_wts(ui, uj, output_routine);
02213 }
02214
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){
02229
02230 case MATH:
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:
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
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);
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 );
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);
02290
02291 switch(output_routine){
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++)
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
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
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++)
02397 if ((k >=elowk) && (k <= ehighk))
02398 for(l=ilowl; l<=ihighl; l++)
02399 if ((l >= elowl) && (l <= ehighl))
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
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
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;
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++){
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
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 02658
02659 const int nSelectivities = (argc>0 ? cmdi(argv[0]) : 24);
02660 const int nODvalues = (argc>1 ? cmdi(argv[1]) : 10);
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];
02665
02666 int i,j,pe,k,l,m,eye;
02667 int bubble_rad;
02668 double max_or_select, max_od, or_division;
02669
02670
02671 Histo add_histo[NSELECTIVITIES][NUM_BUBBLE_AREAS][MAX_NUM_ANGLES][MAX_NUM_ANGLES];
02672
02673 (void)argc;
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++)
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);
02698
02699 or_division = max_or_select/(double)nSelectivities;
02700
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++)
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++)
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++)
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();
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++)
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)
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
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 02881 02882 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;
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 02900 02901 02902
02903 setup_variable_bounds(0.5*peak_wt, 1.0,
02904 0.0000, 0.999999,
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
02913 sigmax = sigmay = (double)rf_radius/(double)RN;
02914 r = peak_wt; theta = 0.5;
02915
02916
02917 fit_gauss(&r, &theta, &cx, &cy, &sigmax, &sigmay);
02918
02919
02920 if (sigmay > sigmax) theta += 1.0;
02921 or_pref_rad = theta*M_PI;
02922 or_pref[eye][row][j] = RADIANS_TO_OR_PREF(or_pref_rad/2);
02923
02924
02925 comb_or_pref_x +=cos(or_pref_rad);
02926 comb_or_pref_y +=sin(or_pref_rad);
02927
02928
02929
02930 cx *= (double)RN;
02931 cy *= (double)RN;
02932 sigmax *= (double)RN;
02933 sigmay *= (double)RN;
02934
02935 02936 02937 02938 02939 02940 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 02948 02949
02950 resp = 0.0;
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
02959
02960 02961 02962 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 02978
02979 }
02980 }
02981
02982 if (combined_eyes != 0) {
02983 02984
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