001 package cnslab.cnsnetwork; 002 003 import java.io.*; 004 import java.util.*; 005 006 import cnslab.image.imageIO; 007 import cnslab.image.Convolution; 008 import cnslab.cnsmath.*; 009 import edu.jhu.mb.ernst.model.ModelFactory; 010 import edu.jhu.mb.ernst.model.Synapse; 011 012 /*********************************************************************** 013 * Stimulus class contains all types of stimulus. 014 * 015 * The injected spikes are assumed to be inhomogeneous Poisson spikes, 016 * similar to BKPoissonNeuron. 017 * 018 * @version 019 * $Date: 2012-08-04 13:43:22 -0500 (Sat, 04 Aug 2012) $ 020 * $Rev: 104 $ 021 * $Author: croft $ 022 * @author 023 * Yi Dong 024 * @author 025 * David Wallace Croft, M.Sc. 026 * @author 027 * Jeremy Cohen 028 ***********************************************************************/ 029 public final class Stimulus 030 implements Serializable, Transmissible 031 //////////////////////////////////////////////////////////////////////// 032 //////////////////////////////////////////////////////////////////////// 033 { 034 035 private static final long 036 serialVersionUID = 0L; 037 038 // public variables 039 040 public Seed seed; 041 042 public SimulatorParser simulatorParser; 043 044 // private variables 045 046 private final ModelFactory modelFactory; 047 048 private final double 049 strength, 050 onTime, 051 offTime, 052 freq, 053 decay; // the decay of the frequency 054 055 /** array of neuron gets input. */ 056 private final List<Integer> 057 neuronIndexList; 058 059 private final List<Double> 060 relativeStrengthList; 061 062 // private ArrayList<Double> relativeStrH; 063 064 // private ArrayList<Double> relativeStrV; 065 066 private final int 067 type, 068 channel; 069 070 //////////////////////////////////////////////////////////////////////// 071 // constructor methods 072 //////////////////////////////////////////////////////////////////////// 073 074 public Stimulus ( 075 final ModelFactory modelFactory, 076 final SimulatorParser simulatorParser, 077 final double strength, 078 final int type, 079 final double onTime, 080 final double offTime, 081 final double freq, 082 final double decay, 083 final Seed seed, 084 final int channel ) 085 //////////////////////////////////////////////////////////////////////// 086 { 087 this.modelFactory = modelFactory; 088 089 this.strength = strength; 090 091 this.type = type; 092 093 this.simulatorParser = simulatorParser; 094 095 this.onTime = onTime; 096 097 this.offTime = offTime; 098 099 this.freq = freq; 100 101 this.decay = decay; 102 103 this.seed = seed; 104 105 this.channel = channel; 106 107 neuronIndexList = new ArrayList<Integer> ( ); 108 109 relativeStrengthList = new ArrayList<Double> ( ); 110 111 // relativeStrH= new ArrayList<Double>(); 112 // relativeStrV= new ArrayList<Double>(); 113 } 114 115 //////////////////////////////////////////////////////////////////////// 116 // accessor methods 117 //////////////////////////////////////////////////////////////////////// 118 119 public int getChannel ( ) { return channel; } 120 121 public double getDecay ( ) { return decay; } 122 123 public double getFreq ( ) { return freq; } 124 125 public double getOffTime ( ) { return offTime; } 126 127 public double getOnTime ( ) { return onTime; } 128 129 public double getStrength ( ) { return strength; } 130 131 public int getType ( ) { return type; } 132 133 //////////////////////////////////////////////////////////////////////// 134 //////////////////////////////////////////////////////////////////////// 135 136 public ArrayList<PInputEvent> init ( final int sourceID ) 137 //////////////////////////////////////////////////////////////////////// 138 { 139 final ArrayList<PInputEvent> out = new ArrayList<PInputEvent> ( ); 140 141 final int neuronIndexListSize = neuronIndexList.size ( ); 142 143 for ( int i = 0; i < neuronIndexListSize; i++ ) 144 { 145 final int toNeuronIndex = neuronIndexList.get ( i ).intValue ( ); 146 147 final double 148 relativeStrength = relativeStrengthList.get ( i ).doubleValue ( ); 149 150 final double 151 synapseStrength = relativeStrength * strength; 152 153 final Synapse synapse = modelFactory.createSynapse ( 154 toNeuronIndex, 155 ( byte ) type, 156 ( float ) synapseStrength ); 157 158 final double time = getNextTime ( onTime ); 159 160 if ( time >= 0 ) 161 { 162 out.add ( new PInputEvent ( time, synapse, sourceID ) ); 163 } 164 } 165 166 return out; 167 } 168 169/* 170 public ArrayList<PInputEvent> initH(int sourceID) 171 //////////////////////////////////////////////////////////////////////// 172 { 173 ArrayList<PInputEvent> out = new ArrayList<PInputEvent>(); 174 Synapse syn; 175 for(int i = 0 ; i < neuIndex.size();i++) 176 { 177 syn = new Synapse(neuIndex.get(i),relativeStrH.get(i)*strength,type); 178 double time = getNextTime(onTime); 179 if(time>=0) 180 { 181 out.add(new PInputEvent(time,syn,sourceID)); 182 } 183 } 184 return out; 185 } 186 187 public ArrayList<PInputEvent> initV(int sourceID) 188 //////////////////////////////////////////////////////////////////////// 189 { 190 ArrayList<PInputEvent> out = new ArrayList<PInputEvent>(); 191 Synapse syn; 192 for(int i = 0 ; i < neuIndex.size();i++) 193 { 194 syn = new Synapse(neuIndex.get(i),relativeStrV.get(i)*strength,type); 195 double time = getNextTime(onTime); 196 if(time>=0) 197 { 198 out.add(new PInputEvent(time,syn,sourceID)); 199 } 200 } 201 return out; 202 } 203*/ 204 205 /*********************************************************************** 206 * Get the next time given current time. 207 * 208 * Inhomogeneous Poisson process. 209 ***********************************************************************/ 210 public double getNextTime ( final double currTime ) 211 //////////////////////////////////////////////////////////////////////// 212 { 213 double time = currTime; 214 215 time += ( -Math.log ( Cnsran.ran2 ( seed ) ) / freq ); 216 217 while ( Cnsran.ran2 ( seed ) 218 > Math.exp ( -decay * ( time - onTime ) ) ) 219 { 220 time += ( -Math.log ( Cnsran.ran2 ( seed ) ) / freq ); 221 222 if ( time > offTime ) 223 { 224 return -1.0; 225 } 226 } 227 228 if ( time > offTime ) 229 { 230 return -1.0; 231 } 232 233 return time; 234 } 235 236 /*********************************************************************** 237 * Stimulate a square of neurons. 238 * 239 * @param x1 240 * @param y1 241 * @param x2 242 * @param y2 243 * @param pre 244 * @param suf 245 * @param hostId 246 ***********************************************************************/ 247 public void plotSquare ( 248 final int x1, 249 final int y1, 250 final int x2, 251 final int y2, 252 final String pre, 253 final String suf, 254 final int hostId ) 255 //////////////////////////////////////////////////////////////////////// 256 { 257 int xTotal=0; 258 259 int yTotal=0; 260 261 int xstep=0; 262 263 int ystep=0; 264 265 int xMul=simulatorParser.layerStructure.getXmultiplier(pre,suf); 266 267 int yMul=simulatorParser.layerStructure.getYmultiplier(pre,suf); 268 269 if(xMul < 0 ) 270 { 271 xTotal=simulatorParser.xEdgeLength; 272 273 xstep=-xMul; 274 } 275 else 276 { 277 xTotal=simulatorParser.xEdgeLength*xMul; 278 279 xstep=1; 280 } 281 282 if(yMul < 0 ) 283 { 284 yTotal=simulatorParser.yEdgeLength; 285 286 ystep=-yMul; 287 } 288 else 289 { 290 yTotal=simulatorParser.yEdgeLength*yMul; 291 292 ystep=1; 293 } 294 295 if ( x1> xTotal || x2 > xTotal || y1> yTotal || y2> yTotal ) 296 { 297 throw new RuntimeException("out of range error"); 298 } 299 300 // Draw four non-overlapping lines 301 302 final int xShift = x1 > x2 ? xstep : -xstep; 303 304 final int yShift = y1 > y2 ? ystep : -ystep; 305 306 plotLine( x1 , y1 , x1 , y2 + yShift, pre , suf , hostId ); 307 308 plotLine( x1 , y2 , x2 + xShift, y2 , pre , suf , hostId ); 309 310 plotLine( x2 , y2 , x2 , y1 - yShift, pre , suf , hostId ); 311 312 plotLine( x2 , y1 , x1 - xShift, y1 , pre , suf , hostId ); 313 } 314 315 /*********************************************************************** 316 * Stimulate a filled square of neurons 317 ***********************************************************************/ 318 public void plotFilledSquare ( 319 final int x1, 320 final int y1, 321 final int x2, 322 final int y2, 323 final String pre, 324 final String suf, 325 final int hostId ) 326 //////////////////////////////////////////////////////////////////////// 327 { 328 int xTotal=0; 329 330 int yTotal=0; 331 332 int xstep=0; 333 334 int ystep=0; 335 336 int xMul=simulatorParser.layerStructure.getXmultiplier(pre,suf); 337 338 int yMul=simulatorParser.layerStructure.getYmultiplier(pre,suf); 339 340 if(xMul < 0 ) 341 { 342 xTotal=simulatorParser.xEdgeLength; 343 xstep=-xMul; 344 } 345 else 346 { 347 xTotal=simulatorParser.xEdgeLength*xMul; 348 xstep=1; 349 } 350 if(yMul < 0 ) 351 { 352 yTotal=simulatorParser.yEdgeLength; 353 ystep=-yMul; 354 } 355 else 356 { 357 yTotal=simulatorParser.yEdgeLength*yMul; 358 ystep=1; 359 } 360 361 if ( x1> xTotal || x2 > xTotal || y1> yTotal || y2> yTotal ) 362 { 363 throw new RuntimeException("out of range error"); 364 } 365 366 367 for (int x = Math.min( x1 , x2 ); x <= Math.max( x1 , x2 ); x+= xstep) 368 { 369 plotLine( x , y1 , x, y2 , pre , suf , hostId ); 370 } 371 } 372 373 /*********************************************************************** 374 * Stimulate a line of neurons 375 ***********************************************************************/ 376 public void plotLine ( 377 final int x1, 378 final int y1, 379 final int x2, 380 final int y2, 381 final String pre, 382 final String suf, 383 final int hostId ) 384 //////////////////////////////////////////////////////////////////////// 385 { 386 double length = Math.sqrt( 387 (double)(x2-x1)*(double)(x2-x1) + 388 (double)(y2-y1)*(double)(y2-y1)); 389 390 if(length < 1e-5) // point stimulus 391 { 392 int id; 393 394 if ( ( id = simulatorParser.layerStructure.cellmap_slow ( 395 pre, suf, x1, y1 ) ) != -1 ) 396 { 397 if(FunUtil.hostId( 398 simulatorParser.layerStructure.nodeEndIndices, id) == hostId) 399 { 400 relativeStrengthList.add(1.0); 401 neuronIndexList.add(id); 402 } 403 } 404 else 405 { 406 throw new RuntimeException("point is not in grid"); 407 } 408 return; 409 } 410 411 int xTotal=0; 412 413 int yTotal=0; 414 415 int xstep=0; 416 417 int ystep=0; 418 419 int xMul=simulatorParser.layerStructure.getXmultiplier(pre,suf); 420 421 int yMul=simulatorParser.layerStructure.getYmultiplier(pre,suf); 422 423 if(xMul < 0 ) 424 { 425 xTotal=simulatorParser.xEdgeLength; 426 xstep=-xMul; 427 } 428 else 429 { 430 xTotal=simulatorParser.xEdgeLength*xMul; 431 xstep=1; 432 } 433 if(yMul < 0 ) 434 { 435 yTotal=simulatorParser.yEdgeLength; 436 ystep=-yMul; 437 } 438 else 439 { 440 yTotal=simulatorParser.yEdgeLength*yMul; 441 ystep=1; 442 } 443 444 if ( x1> xTotal || x2 > xTotal || y1> yTotal || y2> yTotal ) 445 { 446 throw new RuntimeException("out of range error"); 447 } 448 449 // Here we determine the neurons that are "hit" by the line. 450 // See the Wikipedia page on Bresenham's line algorithm. 451 452 // If steep, swap x's and y's. 453 boolean steep = Math.abs(y2 - y1) > Math.abs(x2 - x1); 454 int _xBegin, _xEnd, _yBegin, _yEnd; 455 if (!steep) 456 { 457 _xBegin = x1; 458 _xEnd = x2; 459 _yBegin = y1; 460 _yEnd = y2; 461 } 462 else 463 { 464 _xBegin = y1; 465 _xEnd = y2; 466 _yBegin = x1; 467 _yEnd = x2; 468 } 469 470 // If flipped, swap begins and ends. 471 boolean flipped = _xBegin > _xEnd; 472 int xBegin, xEnd, yBegin, yEnd; 473 if (!flipped) 474 { 475 xBegin = _xBegin; 476 xEnd = _xEnd; 477 yBegin = _yBegin; 478 yEnd = _yEnd; 479 } 480 else 481 { 482 xBegin = _xEnd; 483 xEnd = _xBegin; 484 yBegin = _yEnd; 485 yEnd = _yBegin; 486 } 487 488 if(xBegin % xstep !=0) xBegin+= xstep - xBegin % xstep ; 489 if(yBegin % ystep !=0) yBegin+= ystep - yBegin % ystep ; 490 491 double slope = (double) (yEnd - yBegin) / (double) (xEnd - xBegin); 492 493 for (int x = xBegin; x <= xEnd; x += xstep) 494 { 495 int y = (int) Math.round(yBegin + slope * (x - xBegin)); 496 y = y - (y % ystep); 497 498 // If steep, swap x's and y's 499 int xNeuron = steep ? y : x; 500 int yNeuron = steep ? x : y; 501 502 int id = simulatorParser.layerStructure.cellmap_slow( 503 pre,suf,xNeuron, yNeuron); 504 505 if(id != -1) 506 { 507 if(FunUtil.hostId( 508 simulatorParser.layerStructure.nodeEndIndices, id) == hostId) 509 { 510 // Calculate the shortest distance from the point 511 // (xNeuron, yNeuron) to the line between (x1, y1) and (x2, y2) 512 513 double distance = Math.abs((x2 - x1) * (y1 - yNeuron) 514 - (x1 - xNeuron) * (y2 - y1)) / length; 515 516 if(channel<0) // If there is no specified channel 517 { 518 // The relative strength of the synapse between this stimulus 519 // and a neuron is a function [ distanceTune() ] 520 // of the distance between the neuron and the line. 521 522 relativeStrengthList.add( distanceTune ( distance ) ); 523 } 524 else if(channel >=0 && channel <= 180) 525 { 526 double lineAngle = Math.acos((double)(x2-x1)/length); 527 528 double channelAngle 529 = (double) channel * (Math.PI / (double) 180.0); 530 531 relativeStrengthList.add ( 532 distanceTune ( 533 distance * Math.cos(lineAngle - channelAngle) ) ); 534 } 535 else 536 { 537 throw new RuntimeException ( 538 "channel range error (0-180 or <0)" ); 539 } 540 541 neuronIndexList.add(id); 542 } 543 } 544 } 545 } 546 547 /*********************************************************************** 548 * Given image file, stimulate the layer of neurons accourding to image 549 * intensity 550 ***********************************************************************/ 551 public void plotImg ( 552 final String pre, 553 final String suf, 554 final String filename, 555 final double [ ] [ ] filter ) 556 //////////////////////////////////////////////////////////////////////// 557 { 558 int [][] out; 559 imageIO imgIO = new imageIO(); 560 out = imgIO.loadBWImage("imagelib/"+filename); 561 int [][] pic = Convolution.convolve_safe(out,filter); 562 563 int height = pic.length; 564 int width = pic[0].length; 565 566 int xstep,ystep; 567 int xmulti,ymulti; 568 xmulti = simulatorParser.layerStructure.getXmultiplier(pre,suf); 569 ymulti = simulatorParser.layerStructure.getYmultiplier(pre,suf); 570 571 int xreso,yreso; 572 573 if(xmulti>0) 574 { 575 xstep=1; 576 xreso=xmulti*simulatorParser.xEdgeLength; 577 } 578 else 579 { 580 xstep=-xmulti; 581 xreso=simulatorParser.xEdgeLength; 582 } 583 584 if(ymulti>0) 585 { 586 ystep=1; 587 yreso=ymulti*simulatorParser.yEdgeLength; 588 } 589 else 590 { 591 ystep=-ymulti; 592 yreso=simulatorParser.yEdgeLength; 593 } 594 595 double heightRatio; 596 double widthRatio; 597 598 try { 599 heightRatio = (double)height/(double)(yreso/ystep); 600 widthRatio = (double)width/(double)(xreso/xstep); 601 602 } 603 catch(Exception ex) { 604 throw new RuntimeException("Pre:"+pre+" Suf:"+suf); 605 } 606 607 608 for( int x = 0 ; x < xreso/xstep; x++) 609 { 610 for( int y = 0 ; y < yreso/ystep; y++) 611 { 612 // String neu = pre+","+x*xstep+","+ (yreso-y*ystep-1)+","+suf; 613 614 if ( pic [ ( int ) ( y * heightRatio ) + ystep - 1 ] 615 [ ( int ) ( x * widthRatio ) ] < 0 ) 616 { 617 pic[(int)(y*heightRatio)+ystep-1][(int)(x*widthRatio)]=0; 618 } 619 620 if ( pic [ ( int ) ( y * heightRatio ) + ystep - 1 ] 621 [ ( int ) ( x * widthRatio ) ] > 255 ) 622 { 623 pic[(int)(y*heightRatio)+ystep-1][(int)(x*widthRatio)]=255; 624 } 625 626 // double pixel = (double)(pic[(int)((y)*heightRatio 627 // +(int)(heightRatio/2.0))][(int)((x)*widthRatio 628 // +(int)(widthRatio/2.0))])/(double)256; 629 630 final double 631 pixel = ( double ) ( 632 pic [ ( int ) ( y * heightRatio ) + ystep - 1 ] 633 [ ( int ) ( x * widthRatio ) ] ) / ( double ) 256; 634 635 if ( pixel > 0.01 ) 636 { 637 relativeStrengthList.add(pixel); 638 639 neuronIndexList.add ( 640 simulatorParser.layerStructure.cellmap_slow ( 641 pre, 642 suf, 643 x * xstep, 644 ( yreso - y * ystep - ystep ) ) ); 645 } 646 } 647 } 648 } 649 650 /*********************************************************************** 651 * Given image file, stimulate the layer of neurons accourding to reverse 652 * of image intensity. 653 ***********************************************************************/ 654 public void plotRImg ( 655 final String pre, 656 final String suf, 657 final String filename, 658 final double [ ] [ ] filter ) //plot reverse img 659 //////////////////////////////////////////////////////////////////////// 660 { 661 //pas.xEdgeLength; 662 //pas.yEdgeLength; 663 int [][] out; 664 imageIO imgIO = new imageIO(); 665 out = imgIO.loadBWImage("imagelib/"+filename); 666 for(int i=0;i<out.length;i++) 667 { 668 for(int j=0;j<out[0].length;j++) 669 { 670 out[i][j]=255-out[i][j]; 671 } 672 } 673 int [][] pic = Convolution.convolve_safe(out,filter); 674 int height = pic.length; 675 int width = pic[0].length; 676 677 int xstep,ystep; 678 int xmulti,ymulti; 679 xmulti = simulatorParser.layerStructure.getXmultiplier(pre,suf); 680 ymulti = simulatorParser.layerStructure.getYmultiplier(pre,suf); 681 682 int xreso,yreso; 683 684 if(xmulti>0) 685 { 686 xstep=1; 687 xreso=xmulti*simulatorParser.xEdgeLength; 688 } 689 else 690 { 691 xstep=-xmulti; 692 xreso=simulatorParser.xEdgeLength; 693 } 694 695 if(ymulti>0) 696 { 697 ystep=1; 698 yreso=ymulti*simulatorParser.yEdgeLength; 699 } 700 else 701 { 702 ystep=-ymulti; 703 yreso=simulatorParser.yEdgeLength; 704 } 705 706 double heightRatio = (double)height/(double)(yreso/ystep); 707 double widthRatio = (double)width/(double)(xreso/xstep); 708 709 for( int x = 0 ; x < xreso/xstep; x++) 710 { 711 for( int y = 0 ; y < yreso/ystep; y++) 712 { 713 // String neu = pre+","+x+","+ (pas.yEdgeLength-y-1)+","+suf; 714 715 if ( pic [ ( int ) ( y * heightRatio ) + ystep - 1 ] 716 [ ( int ) ( x * widthRatio ) ] < 0 ) 717 { 718 pic[(int)(y*heightRatio)+ystep-1][(int)(x*widthRatio)]=0; 719 } 720 721 if ( pic [ ( int ) ( y * heightRatio ) + ystep - 1 ] 722 [ ( int ) ( x * widthRatio ) ] > 255 ) 723 { 724 pic[(int)(y*heightRatio)+ystep-1][(int)(x*widthRatio)]=255; 725 } 726 727 final double pixel = ( double ) ( 728 pic [ ( int ) ( y * heightRatio ) + ystep - 1 ] 729 [ ( int ) ( x * widthRatio ) ] ) / ( double ) 256; 730 731 //System.out.println("Layer pre:"+pre+" suf:"+suf+" heightRaito" 732 // +heightRatio+"X:"+(int)(y*heightRatio+ystep-1)+"_"+(x*xstep) 733 // +"Y:"+(int)(x*widthRatio)+"_"+(yreso-y*ystep-ystep)+" rate:" 734 // +(double)(pic[(int)(y*heightRatio)+ystep-1] 735 // [(int)(x*widthRatio)])/(double)256+" fin X:"+x+" Y:"+y); 736 737 if ( pixel > 0.01 ) 738 { 739 relativeStrengthList.add ( pixel ); 740 741 neuronIndexList.add ( 742 simulatorParser.layerStructure.cellmap_slow ( 743 pre, 744 suf, 745 x*xstep, 746 ( yreso-y*ystep-ystep ) ) ); 747 } 748 } 749 } 750 } 751 752 /*********************************************************************** 753 * Stimulate the layer of neurons with a given matrix. 754 * 755 * cenX, cenY defines the center position of the matrix in the layer 756 ***********************************************************************/ 757 public void plotMatrix ( 758 final String pre, 759 final String suf, 760 final int cenX, 761 final int cenY, 762 final double [ ] [ ] matrix, 763 final int hostId ) 764 //////////////////////////////////////////////////////////////////////// 765 { 766 final int [ ] center = simulatorParser.layerStructure.closePoint ( 767 cenX, 768 cenY, 769 pre, 770 suf ); 771 772 int halfMaX = matrix.length/2; 773 int halfMaY = matrix[0].length/2; 774 775 int xstep,ystep; 776 int xmulti,ymulti; 777 xmulti = simulatorParser.layerStructure.getXmultiplier(pre,suf); 778 ymulti = simulatorParser.layerStructure.getYmultiplier(pre,suf); 779 780 int xreso,yreso; 781 782 if(xmulti>0) 783 { 784 xstep=1; 785 xreso=xmulti*simulatorParser.xEdgeLength; 786 } 787 else 788 { 789 xstep=-xmulti; 790 xreso=simulatorParser.xEdgeLength; 791 } 792 793 if(ymulti>0) 794 { 795 ystep=1; 796 yreso=ymulti*simulatorParser.yEdgeLength; 797 } 798 else 799 { 800 ystep=-ymulti; 801 yreso=simulatorParser.yEdgeLength; 802 } 803 804 for ( 805 int x = center [ 0 ] - halfMaX; 806 x < center [ 0 ] 807 + ( matrix.length % 2 == 0 ? halfMaX : halfMaX + 1 ); 808 x++ ) 809 { 810 for ( 811 int y = center [ 1 ] - halfMaY; 812 y < center [ 1 ] 813 + ( matrix [ 0 ].length % 2 == 0 ? halfMaY : halfMaY + 1 ); 814 y++ ) 815 { 816 int MaX=x-center[0]+halfMaX; 817 int MaY=y-center[1]+halfMaY; 818 int xx,yy; 819 xx=x%xreso; 820 yy=y%yreso; 821 if(xx<0)xx=xx+xreso; 822 if(yy<0)yy=yy+yreso; 823 824 final int id = simulatorParser.layerStructure.cellmap_slow ( 825 pre, 826 suf, 827 xx, 828 yy ); 829 830 if(id != -1) 831 { 832 if ( FunUtil.hostId ( 833 simulatorParser.layerStructure.nodeEndIndices, 834 id ) == hostId ) 835 { 836 double pixel = matrix[MaX][MaY]; 837 838 if(pixel!=0.0) 839 { 840 relativeStrengthList.add(pixel); 841 neuronIndexList.add(id); 842 } 843 } 844 } 845 } 846 } 847 } 848 849 public void plotMatrix ( 850 final String pre, 851 final String suf, 852 final int cenX, 853 final int cenY, 854 final double [ ] [ ] matrix ) 855 //////////////////////////////////////////////////////////////////////// 856 { 857 final int [ ] center = simulatorParser.layerStructure.closePoint ( 858 cenX, 859 cenY, 860 pre, 861 suf ); 862 863 int halfMaX = matrix.length/2; 864 865 int halfMaY = matrix[0].length/2; 866 867 int xstep,ystep; 868 int xmulti,ymulti; 869 xmulti = simulatorParser.layerStructure.getXmultiplier(pre,suf); 870 ymulti = simulatorParser.layerStructure.getYmultiplier(pre,suf); 871 872 int xreso,yreso; 873 874 if(xmulti>0) 875 { 876 xstep=1; 877 xreso=xmulti*simulatorParser.xEdgeLength; 878 } 879 else 880 { 881 xstep=-xmulti; 882 xreso=simulatorParser.xEdgeLength; 883 } 884 885 if(ymulti>0) 886 { 887 ystep=1; 888 yreso=ymulti*simulatorParser.yEdgeLength; 889 } 890 else 891 { 892 ystep=-ymulti; 893 yreso=simulatorParser.yEdgeLength; 894 } 895 896 for ( 897 int x = center [ 0 ] - halfMaX; 898 x < center [ 0 ] 899 + ( matrix.length % 2 == 0 ? halfMaX : halfMaX + 1 ); 900 x++ ) 901 { 902 for ( 903 int y = center [ 1 ] - halfMaY; 904 y < center [ 1 ] 905 + ( matrix [ 0 ].length % 2 == 0 ? halfMaY : halfMaY + 1 ); 906 y++ ) 907 { 908 int MaX=x-center[0]+halfMaX; 909 int MaY=y-center[1]+halfMaY; 910 int xx,yy; 911 xx=x%xreso; 912 yy=y%yreso; 913 if(xx<0)xx=xx+xreso; 914 if(yy<0)yy=yy+yreso; 915 916 final int id = simulatorParser.layerStructure.cellmap_slow ( 917 pre, 918 suf, 919 xx, 920 yy ); 921 922 if(id != -1) 923 { 924 double pixel = matrix[MaX][MaY]; 925 if(pixel!=0.0) 926 { 927 relativeStrengthList.add(pixel); 928 neuronIndexList.add(id); 929 } 930 } 931 } 932 } 933 } 934 935 /*********************************************************************** 936 * Stimulate the whole layer of neurons. 937 * 938 * Injecting noise to the whole layer. 939 ***********************************************************************/ 940 public void background ( 941 final String pre, 942 final String suf ) 943 //////////////////////////////////////////////////////////////////////// 944 { 945 int 946 xTotal = 0, 947 yTotal = 0, 948 xstep = 0, 949 ystep = 0, 950 xMul = simulatorParser.layerStructure.getXmultiplier ( pre, suf ), 951 yMul = simulatorParser.layerStructure.getYmultiplier ( pre, suf ); 952 953 if ( xMul < 0 ) 954 { 955 xTotal = simulatorParser.xEdgeLength; 956 957 xstep = -xMul; 958 } 959 else 960 { 961 xTotal = simulatorParser.xEdgeLength * xMul; 962 963 xstep = 1; 964 } 965 966 if ( yMul < 0 ) 967 { 968 yTotal = simulatorParser.yEdgeLength; 969 970 ystep = -yMul; 971 } 972 else 973 { 974 yTotal = simulatorParser.yEdgeLength * yMul; 975 976 ystep = 1; 977 } 978 979 for ( int x = 0; x < xTotal; x = x + xstep ) 980 { 981 for ( int y = 0; y < yTotal; y = y + ystep ) 982 { 983 relativeStrengthList.add ( Double.valueOf ( 1.0 ) ); 984 985 neuronIndexList.add ( 986 simulatorParser.layerStructure.cellmap_slow ( 987 pre, 988 suf, 989 x, 990 y ) ); 991 } 992 } 993 } 994 995 /*********************************************************************** 996 * Injecting noise to the whole layer. 997 ***********************************************************************/ 998 public void background ( 999 final String pre, 1000 final String suf, 1001 final int hostId ) 1002 //////////////////////////////////////////////////////////////////////// 1003 { 1004 int xTotal=0; 1005 int yTotal=0; 1006 int xstep=0; 1007 int ystep=0; 1008 int xMul=simulatorParser.layerStructure.getXmultiplier(pre,suf); 1009 int yMul=simulatorParser.layerStructure.getYmultiplier(pre,suf); 1010 1011 1012 if(xMul < 0 ) 1013 { 1014 xTotal=simulatorParser.xEdgeLength; 1015 xstep=-xMul; 1016 } 1017 else 1018 { 1019 xTotal=simulatorParser.xEdgeLength*xMul; 1020 xstep=1; 1021 } 1022 if(yMul < 0 ) 1023 { 1024 yTotal=simulatorParser.yEdgeLength; 1025 ystep=-yMul; 1026 } 1027 else 1028 { 1029 yTotal=simulatorParser.yEdgeLength*yMul; 1030 ystep=1; 1031 } 1032 1033 1034 for( int x = 0 ; x < xTotal; x=x+xstep) 1035 { 1036 for( int y = 0 ; y < yTotal ; y=y+ystep) 1037 { 1038 // String neu = pre+","+x+","+ y+","+suf; 1039 int id = simulatorParser.layerStructure.cellmap_slow(pre,suf,x,y); 1040 1041 if ( FunUtil.hostId ( 1042 simulatorParser.layerStructure.nodeEndIndices, 1043 id ) == hostId ) 1044 { 1045 relativeStrengthList.add(1.0); 1046 1047 neuronIndexList.add ( 1048 simulatorParser.layerStructure.cellmap_slow ( 1049 pre, 1050 suf, 1051 x, 1052 y ) ); 1053 } 1054 } 1055 } 1056 } 1057 1058 /*********************************************************************** 1059 * Plot reverse image. 1060 ***********************************************************************/ 1061 public void plotRImg ( 1062 final String pre, 1063 final String suf, 1064 final String filename, 1065 final double [ ] [ ] filter, 1066 final double gamma, 1067 final double k, 1068 final int hostId ) 1069 //////////////////////////////////////////////////////////////////////// 1070 { 1071 //pas.xEdgeLength; 1072 //pas.yEdgeLength; 1073 int [][] out; 1074 imageIO imgIO = new imageIO(); 1075 1076 out = imgIO.loadBWImage("imagelib/"+filename); 1077 1078 for(int i=0;i<out.length;i++) 1079 { 1080 for(int j=0;j<out[0].length;j++) 1081 { 1082 out[i][j]=255-out[i][j]; 1083 } 1084 } 1085 int [][] pic = Convolution.convolve_safe(out,filter); 1086 int height = pic.length; 1087 int width = pic[0].length; 1088 1089 int xstep,ystep; 1090 int xmulti,ymulti; 1091 xmulti = simulatorParser.layerStructure.getXmultiplier(pre,suf); 1092 ymulti = simulatorParser.layerStructure.getYmultiplier(pre,suf); 1093 1094 int xreso,yreso; 1095 1096 if(xmulti>0) 1097 { 1098 xstep=1; 1099 xreso=xmulti*simulatorParser.xEdgeLength; 1100 } 1101 else 1102 { 1103 xstep=-xmulti; 1104 xreso=simulatorParser.xEdgeLength; 1105 } 1106 1107 if(ymulti>0) 1108 { 1109 ystep=1; 1110 yreso=ymulti*simulatorParser.yEdgeLength; 1111 } 1112 else 1113 { 1114 ystep=-ymulti; 1115 yreso=simulatorParser.yEdgeLength; 1116 } 1117 1118 double heightRatio = (double)height/(double)(yreso/ystep); 1119 double widthRatio = (double)width/(double)(xreso/xstep); 1120 1121 for( int x = 0 ; x < xreso/xstep; x++) 1122 { 1123 for( int y = 0 ; y < yreso/ystep; y++) 1124 { 1125 // String neu = pre+","+x+","+ (pas.yEdgeLength-y-1)+","+suf; 1126 1127 int id = simulatorParser.layerStructure.cellmap_slow ( 1128 pre, 1129 suf, 1130 x*xstep, 1131 (yreso-y*ystep-ystep)); 1132 1133 if ( FunUtil.hostId ( 1134 simulatorParser.layerStructure.nodeEndIndices, 1135 id ) == hostId ) 1136 // if(pas.ls.cellmap.containsKey(neu)) 1137 { 1138 // if(pic[(int)(y*heightRatio+ystep-1)] 1139 // [(int)(x*widthRatio)]<0) 1140 // pic[(int)(y*heightRatio+ystep-1)][(int)(x*widthRatio)]=0; 1141 1142 // if(pic[(int)(y*heightRatio+ystep-1)] 1143 // [(int)(x*widthRatio)]>255) 1144 // pic[(int)(y*heightRatio+ystep-1)][(int)(x*widthRatio)]=255; 1145 1146 // double pixel = (double)( 1147 // 255-pic[(int)(y*heightRatio)] 1148 // [(int)(x*widthRatio)])/(double)256; 1149 1150 double pixel = 0.0; 1151 1152 int ii,jj; 1153 1154 for(ii=0;ii<ystep;ii++) 1155 { 1156 for(jj=0;jj<xstep;jj++) 1157 { 1158 if ( pic [ ( int ) ( y * heightRatio ) + ystep - 1 - ii ] 1159 [ ( int ) ( x * widthRatio ) + jj ] < 0 ) 1160 { 1161 pic [ ( int ) ( y * heightRatio ) + ystep - 1 - ii ] 1162 [ ( int ) ( x * widthRatio ) + jj ] = 0; 1163 } 1164 1165 if ( pic [ ( int ) ( y * heightRatio ) + ystep - 1 - ii ] 1166 [ ( int ) ( x * widthRatio ) + jj ] > 255 ) 1167 { 1168 pic [ ( int ) ( y * heightRatio ) + ystep - 1 - ii ] 1169 [ ( int ) ( x * widthRatio ) + jj ] = 255; 1170 } 1171 1172 pixel += nonlinearFilter ( 1173 ( double ) ( pic 1174 [ ( int ) ( y * heightRatio ) + ystep - 1 - ii ] 1175 [ ( int ) ( x * widthRatio ) + jj ] ) 1176 / ( double ) 256, 1177 gamma, 1178 k ); 1179 } 1180 } 1181 1182 pixel = pixel /(double)(ystep*xstep); 1183 1184 // double pixel = (double)(pic[(int)(y*heightRatio)] 1185 // [(int)(x*widthRatio)])/(double)256; 1186 1187 if(pixel>0.01) 1188 { 1189 relativeStrengthList.add(pixel); 1190 neuronIndexList.add(id); 1191 } 1192 } 1193 } 1194 } 1195 } 1196 1197 /*********************************************************************** 1198 * Non linear filter to simualte Retina 1199 * 1200 * @param x 1201 * @param gamma 1202 * @param k 1203 * @return 1204 ***********************************************************************/ 1205 public double nonlinearFilter(double x, double gamma, double k) 1206 //////////////////////////////////////////////////////////////////////// 1207 { 1208 // double gamma = 1.0; 1209 // double k=0.02; 1210 if(gamma>0) 1211 { 1212 double var = Math.pow((x/k),gamma); 1213 1214 return var/(1+var); 1215 } 1216 1217 return x; 1218 } 1219 1220 public void plotImg ( 1221 final String pre, 1222 final String suf, 1223 final String filename, 1224 final double [ ] [ ] filter, 1225 final double gamma, 1226 final double k, 1227 final int hostId ) 1228 //////////////////////////////////////////////////////////////////////// 1229 { 1230 //pas.xEdgeLength; 1231 //pas.yEdgeLength; 1232 int [][] out; 1233 imageIO imgIO = new imageIO(); 1234 out = imgIO.loadBWImage("imagelib/"+filename); 1235 int [][] pic = Convolution.convolve_safe(out,filter); 1236 1237 int height = pic.length; 1238 int width = pic[0].length; 1239 1240 int xstep,ystep; 1241 int xmulti,ymulti; 1242 xmulti = simulatorParser.layerStructure.getXmultiplier(pre,suf); 1243 ymulti = simulatorParser.layerStructure.getYmultiplier(pre,suf); 1244 1245 int xreso,yreso; 1246 1247 if(xmulti>0) 1248 { 1249 xstep=1; 1250 xreso=xmulti*simulatorParser.xEdgeLength; 1251 } 1252 else 1253 { 1254 xstep=-xmulti; 1255 xreso=simulatorParser.xEdgeLength; 1256 } 1257 1258 if(ymulti>0) 1259 { 1260 ystep=1; 1261 yreso=ymulti*simulatorParser.yEdgeLength; 1262 } 1263 else 1264 { 1265 ystep=-ymulti; 1266 yreso=simulatorParser.yEdgeLength; 1267 } 1268 1269 double heightRatio = (double)height/(double)(yreso/ystep); 1270 1271 double widthRatio = (double)width /(double)(xreso/xstep); 1272 1273 for( int x = 0 ; x < xreso/xstep; x++) 1274 { 1275 for( int y = 0 ; y < yreso/ystep; y++) 1276 { 1277 // String neu = pre+","+x+","+ (pas.yEdgeLength-y-1)+","+suf; 1278 1279 int id = simulatorParser.layerStructure.cellmap_slow( 1280 pre, 1281 suf, 1282 x*xstep, 1283 (yreso-y*ystep-ystep)); 1284 1285 if ( FunUtil.hostId ( 1286 simulatorParser.layerStructure.nodeEndIndices, 1287 id ) == hostId ) 1288 // if(pas.ls.cellmap.containsKey(neu)) 1289 { 1290 // double pixel = (double)(255-pic[(int)(y*heightRatio)] 1291 // [(int)(x*widthRatio)])/(double)256; 1292 1293 // double pixel = nonlinearFilter((double)( 1294 // pic[(int)(y*heightRatio)+ystep-1] 1295 // [(int)(x*widthRatio)])/(double)256,gamma,k); 1296 1297 double pixel = 0.0; 1298 1299 int ii,jj; 1300 1301 for(ii=0;ii<ystep;ii++) 1302 { 1303 for(jj=0;jj<xstep;jj++) 1304 { 1305 if ( pic [ ( int ) ( y * heightRatio ) + ystep - 1 - ii ] 1306 [ ( int ) ( x * widthRatio ) + jj ] < 0 ) 1307 { 1308 pic [ ( int ) ( y * heightRatio ) + ystep - 1 - ii ] 1309 [ ( int ) ( x * widthRatio ) + jj ] = 0; 1310 } 1311 1312 if ( pic [ ( int ) ( y * heightRatio ) + ystep - 1 - ii ] 1313 [ ( int ) ( x * widthRatio ) + jj ] > 255 ) 1314 { 1315 pic [ ( int ) ( y * heightRatio ) + ystep - 1 - ii ] 1316 [ ( int ) ( x * widthRatio ) + jj ] = 255; 1317 } 1318 1319 pixel += nonlinearFilter ( 1320 ( double ) ( pic 1321 [ ( int ) ( y * heightRatio ) + ystep - 1 - ii ] 1322 [ ( int ) ( x * widthRatio ) +jj ] ) 1323 / ( double ) 256, 1324 gamma, 1325 k ); 1326 } 1327 } 1328 1329 pixel = pixel / ( double ) ( ystep * xstep ); 1330 1331 if ( pixel > 0.01 ) 1332 { 1333 relativeStrengthList.add ( pixel ); 1334 1335 neuronIndexList.add ( id ); 1336 } 1337 } 1338 } 1339 } 1340 } 1341 1342 public void plotSquare ( 1343 final int x1, 1344 final int y1, 1345 final int x2, 1346 final int y2, 1347 final String pre, 1348 final String suf ) 1349 //////////////////////////////////////////////////////////////////////// 1350 { 1351 int xTotal=0; 1352 1353 int yTotal=0; 1354 1355 int xstep=0; 1356 1357 int ystep=0; 1358 1359 int xMul=simulatorParser.layerStructure.getXmultiplier(pre,suf); 1360 1361 int yMul=simulatorParser.layerStructure.getYmultiplier(pre,suf); 1362 1363 if(xMul < 0 ) 1364 { 1365 xTotal=simulatorParser.xEdgeLength; 1366 xstep=-xMul; 1367 } 1368 else 1369 { 1370 xTotal=simulatorParser.xEdgeLength*xMul; 1371 xstep=1; 1372 } 1373 if(yMul < 0 ) 1374 { 1375 yTotal=simulatorParser.yEdgeLength; 1376 ystep=-yMul; 1377 } 1378 else 1379 { 1380 yTotal=simulatorParser.yEdgeLength*yMul; 1381 ystep=1; 1382 } 1383 1384 if ( x1> xTotal || x2 > xTotal || y1> yTotal || y2> yTotal ) 1385 { 1386 throw new RuntimeException("out of range error"); 1387 } 1388 1389 // Draw four non-overlapping lines 1390 1391 final int xShift = x1 > x2 ? xstep : -xstep; 1392 1393 final int yShift = y1 > y2 ? ystep : -ystep; 1394 1395 plotLine( x1 , y1 , x1 , y2 + yShift, pre , suf ); 1396 1397 plotLine( x1 , y2 , x2 + xShift, y2 , pre , suf ); 1398 1399 plotLine( x2 , y2 , x2 , y1 - yShift, pre , suf ); 1400 1401 plotLine( x2 , y1 , x1 - xShift, y1 , pre , suf ); 1402 } 1403 1404 public void plotFilledSquare ( 1405 final int x1, 1406 final int y1, 1407 final int x2, 1408 final int y2, 1409 final String pre, 1410 final String suf ) 1411 //////////////////////////////////////////////////////////////////////// 1412 { 1413 int xTotal=0; 1414 1415 int yTotal=0; 1416 1417 int xstep=0; 1418 1419 int ystep=0; 1420 1421 int xMul=simulatorParser.layerStructure.getXmultiplier(pre,suf); 1422 1423 int yMul=simulatorParser.layerStructure.getYmultiplier(pre,suf); 1424 1425 if(xMul < 0 ) 1426 { 1427 xTotal=simulatorParser.xEdgeLength; 1428 xstep=-xMul; 1429 } 1430 else 1431 { 1432 xTotal=simulatorParser.xEdgeLength*xMul; 1433 xstep=1; 1434 } 1435 if(yMul < 0 ) 1436 { 1437 yTotal=simulatorParser.yEdgeLength; 1438 ystep=-yMul; 1439 } 1440 else 1441 { 1442 yTotal=simulatorParser.yEdgeLength*yMul; 1443 ystep=1; 1444 } 1445 1446 if ( x1> xTotal || x2 > xTotal || y1> yTotal || y2> yTotal ) 1447 { 1448 throw new RuntimeException("out of range error"); 1449 } 1450 1451 1452 for (int x = Math.min( x1 , x2 ); x <= Math.max( x1 , x2 ); x+= xstep) 1453 { 1454 plotLine( x , y1 , x, y2 , pre , suf ); 1455 } 1456 } 1457 1458 public void plotLine ( 1459 final int x1, 1460 final int y1, 1461 final int x2, 1462 final int y2, 1463 final String pre, 1464 final String suf ) 1465 //////////////////////////////////////////////////////////////////////// 1466 { 1467 double length = Math.sqrt( 1468 (double)(x2-x1)*(double)(x2-x1)+ 1469 (double)(y2-y1)*(double)(y2-y1)); 1470 1471 if(length < 1e-5) // point stimulus 1472 { 1473 int id; 1474 if ( ( id = simulatorParser.layerStructure.cellmap_slow ( 1475 pre, suf, x1, y1 ) ) != -1 ) 1476 { 1477 relativeStrengthList.add(1.0); 1478 neuronIndexList.add(id); 1479 } 1480 else 1481 { 1482 throw new RuntimeException("point is not in grid"); 1483 } 1484 return; 1485 } 1486 1487 int xTotal=0; 1488 1489 int yTotal=0; 1490 1491 int xstep=0; 1492 1493 int ystep=0; 1494 1495 int xMul=simulatorParser.layerStructure.getXmultiplier(pre,suf); 1496 1497 int yMul=simulatorParser.layerStructure.getYmultiplier(pre,suf); 1498 1499 if(xMul < 0 ) 1500 { 1501 xTotal=simulatorParser.xEdgeLength; 1502 xstep=-xMul; 1503 } 1504 else 1505 { 1506 xTotal=simulatorParser.xEdgeLength*xMul; 1507 xstep=1; 1508 } 1509 if(yMul < 0 ) 1510 { 1511 yTotal=simulatorParser.yEdgeLength; 1512 ystep=-yMul; 1513 } 1514 else 1515 { 1516 yTotal=simulatorParser.yEdgeLength*yMul; 1517 ystep=1; 1518 } 1519 1520 if ( x1> xTotal || x2 > xTotal || y1> yTotal || y2> yTotal ) 1521 { 1522 throw new RuntimeException("out of range error"); 1523 } 1524 1525 // Here we determine the neurons that are "hit" by the line. 1526 // See the Wikipedia page on Bresenham's line algorithm. 1527 1528 // If steep, swap x's and y's. 1529 boolean steep = Math.abs(y2 - y1) > Math.abs(x2 - x1); 1530 int _xBegin, _xEnd, _yBegin, _yEnd; 1531 if (!steep) 1532 { 1533 _xBegin = x1; 1534 _xEnd = x2; 1535 _yBegin = y1; 1536 _yEnd = y2; 1537 } 1538 else 1539 { 1540 _xBegin = y1; 1541 _xEnd = y2; 1542 _yBegin = x1; 1543 _yEnd = x2; 1544 } 1545 1546 // If flipped, swap begins and ends. 1547 boolean flipped = _xBegin > _xEnd; 1548 int xBegin, xEnd, yBegin, yEnd; 1549 if (!flipped) 1550 { 1551 xBegin = _xBegin; 1552 xEnd = _xEnd; 1553 yBegin = _yBegin; 1554 yEnd = _yEnd; 1555 } 1556 else 1557 { 1558 xBegin = _xEnd; 1559 xEnd = _xBegin; 1560 yBegin = _yEnd; 1561 yEnd = _yBegin; 1562 } 1563 1564 if(xBegin % xstep !=0) xBegin+= xstep - xBegin % xstep ; 1565 if(yBegin % ystep !=0) yBegin+= ystep - yBegin % ystep ; 1566 1567 double slope = (double) (yEnd - yBegin) / (double) (xEnd - xBegin); 1568 1569 for (int x = xBegin; x <= xEnd; x += xstep) 1570 { 1571 int y = (int) Math.round(yBegin + slope * (x - xBegin)); 1572 y = y - (y % ystep); 1573 1574 // If steep, swap x's and y's 1575 int xNeuron = steep ? y : x; 1576 int yNeuron = steep ? x : y; 1577 1578 int id = simulatorParser.layerStructure.cellmap_slow( 1579 pre,suf,xNeuron, yNeuron); 1580 1581 if(id != -1) 1582 { 1583 // Calculate the shortest distance from the 1584 // point (xNeuron, yNeuron) to the 1585 // line between (x1, y1) and (x2, y2) 1586 1587 double distance = Math.abs( 1588 (x2 - x1) * (y1 - yNeuron) - 1589 (x1 - xNeuron) * (y2 - y1)) / length; 1590 1591 if(channel<0) // If there is no specified channel 1592 { 1593 // The relative strength of the synapse between this stimulus 1594 // and a neuron is a function [ distanceTune() ] 1595 // of the distance between the neuron and the line. 1596 relativeStrengthList.add( distanceTune ( distance ) ); 1597 } 1598 else if(channel >=0 && channel <= 180) 1599 { 1600 double lineAngle = Math.acos((double)(x2-x1)/length); 1601 1602 double 1603 channelAngle = (double) channel * (Math.PI / (double) 180.0); 1604 1605 relativeStrengthList.add ( 1606 distanceTune ( 1607 distance * Math.cos(lineAngle - channelAngle) ) ); 1608 } 1609 else 1610 { 1611 throw new RuntimeException ( 1612 "channel range error (0-180 or <0)" ); 1613 } 1614 1615 neuronIndexList.add(id); 1616 } 1617 } 1618 } 1619 1620 private double distanceTune (double d) 1621 //////////////////////////////////////////////////////////////////////// 1622 { 1623 return 1 - Math.sqrt(2) * d; 1624 } 1625 1626 //////////////////////////////////////////////////////////////////////// 1627 //////////////////////////////////////////////////////////////////////// 1628 }