package cnslab.cnsnetwork;
import java.io.*;
import java.util.*;
import cnslab.image.imageIO;
import cnslab.image.Convolution;
import cnslab.cnsmath.*;
import edu.jhu.mb.ernst.model.ModelFactory;
import edu.jhu.mb.ernst.model.Synapse;
/***********************************************************************
* Stimulus class contains all types of stimulus.
*
* The injected spikes are assumed to be inhomogeneous Poisson spikes,
* similar to BKPoissonNeuron.
*
* @version
* $Date: 2012-08-04 20:43:22 +0200 (Sat, 04 Aug 2012) $
* $Rev: 104 $
* $Author: croft $
* @author
* Yi Dong
* @author
* David Wallace Croft, M.Sc.
* @author
* Jeremy Cohen
***********************************************************************/
public final class Stimulus
implements Serializable, Transmissible
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
{
private static final long
serialVersionUID = 0L;
// public variables
public Seed seed;
public SimulatorParser simulatorParser;
// private variables
private final ModelFactory modelFactory;
private final double
strength,
onTime,
offTime,
freq,
decay; // the decay of the frequency
/** array of neuron gets input. */
private final List<Integer>
neuronIndexList;
private final List<Double>
relativeStrengthList;
// private ArrayList<Double> relativeStrH;
// private ArrayList<Double> relativeStrV;
private final int
type,
channel;
////////////////////////////////////////////////////////////////////////
// constructor methods
////////////////////////////////////////////////////////////////////////
public Stimulus (
final ModelFactory modelFactory,
final SimulatorParser simulatorParser,
final double strength,
final int type,
final double onTime,
final double offTime,
final double freq,
final double decay,
final Seed seed,
final int channel )
////////////////////////////////////////////////////////////////////////
{
this.modelFactory = modelFactory;
this.strength = strength;
this.type = type;
this.simulatorParser = simulatorParser;
this.onTime = onTime;
this.offTime = offTime;
this.freq = freq;
this.decay = decay;
this.seed = seed;
this.channel = channel;
neuronIndexList = new ArrayList<Integer> ( );
relativeStrengthList = new ArrayList<Double> ( );
// relativeStrH= new ArrayList<Double>();
// relativeStrV= new ArrayList<Double>();
}
////////////////////////////////////////////////////////////////////////
// accessor methods
////////////////////////////////////////////////////////////////////////
public int getChannel ( ) { return channel; }
public double getDecay ( ) { return decay; }
public double getFreq ( ) { return freq; }
public double getOffTime ( ) { return offTime; }
public double getOnTime ( ) { return onTime; }
public double getStrength ( ) { return strength; }
public int getType ( ) { return type; }
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
public ArrayList<PInputEvent> init ( final int sourceID )
////////////////////////////////////////////////////////////////////////
{
final ArrayList<PInputEvent> out = new ArrayList<PInputEvent> ( );
final int neuronIndexListSize = neuronIndexList.size ( );
for ( int i = 0; i < neuronIndexListSize; i++ )
{
final int toNeuronIndex = neuronIndexList.get ( i ).intValue ( );
final double
relativeStrength = relativeStrengthList.get ( i ).doubleValue ( );
final double
synapseStrength = relativeStrength * strength;
final Synapse synapse = modelFactory.createSynapse (
toNeuronIndex,
( byte ) type,
( float ) synapseStrength );
final double time = getNextTime ( onTime );
if ( time >= 0 )
{
out.add ( new PInputEvent ( time, synapse, sourceID ) );
}
}
return out;
}
/*
public ArrayList<PInputEvent> initH(int sourceID)
////////////////////////////////////////////////////////////////////////
{
ArrayList<PInputEvent> out = new ArrayList<PInputEvent>();
Synapse syn;
for(int i = 0 ; i < neuIndex.size();i++)
{
syn = new Synapse(neuIndex.get(i),relativeStrH.get(i)*strength,type);
double time = getNextTime(onTime);
if(time>=0)
{
out.add(new PInputEvent(time,syn,sourceID));
}
}
return out;
}
public ArrayList<PInputEvent> initV(int sourceID)
////////////////////////////////////////////////////////////////////////
{
ArrayList<PInputEvent> out = new ArrayList<PInputEvent>();
Synapse syn;
for(int i = 0 ; i < neuIndex.size();i++)
{
syn = new Synapse(neuIndex.get(i),relativeStrV.get(i)*strength,type);
double time = getNextTime(onTime);
if(time>=0)
{
out.add(new PInputEvent(time,syn,sourceID));
}
}
return out;
}
*/
/***********************************************************************
* Get the next time given current time.
*
* Inhomogeneous Poisson process.
***********************************************************************/
public double getNextTime ( final double currTime )
////////////////////////////////////////////////////////////////////////
{
double time = currTime;
time += ( -Math.log ( Cnsran.ran2 ( seed ) ) / freq );
while ( Cnsran.ran2 ( seed )
> Math.exp ( -decay * ( time - onTime ) ) )
{
time += ( -Math.log ( Cnsran.ran2 ( seed ) ) / freq );
if ( time > offTime )
{
return -1.0;
}
}
if ( time > offTime )
{
return -1.0;
}
return time;
}
/***********************************************************************
* Stimulate a square of neurons.
*
* @param x1
* @param y1
* @param x2
* @param y2
* @param pre
* @param suf
* @param hostId
***********************************************************************/
public void plotSquare (
final int x1,
final int y1,
final int x2,
final int y2,
final String pre,
final String suf,
final int hostId )
////////////////////////////////////////////////////////////////////////
{
int xTotal=0;
int yTotal=0;
int xstep=0;
int ystep=0;
int xMul=simulatorParser.layerStructure.getXmultiplier(pre,suf);
int yMul=simulatorParser.layerStructure.getYmultiplier(pre,suf);
if(xMul < 0 )
{
xTotal=simulatorParser.xEdgeLength;
xstep=-xMul;
}
else
{
xTotal=simulatorParser.xEdgeLength*xMul;
xstep=1;
}
if(yMul < 0 )
{
yTotal=simulatorParser.yEdgeLength;
ystep=-yMul;
}
else
{
yTotal=simulatorParser.yEdgeLength*yMul;
ystep=1;
}
if ( x1> xTotal || x2 > xTotal || y1> yTotal || y2> yTotal )
{
throw new RuntimeException("out of range error");
}
// Draw four non-overlapping lines
final int xShift = x1 > x2 ? xstep : -xstep;
final int yShift = y1 > y2 ? ystep : -ystep;
plotLine( x1 , y1 , x1 , y2 + yShift, pre , suf , hostId );
plotLine( x1 , y2 , x2 + xShift, y2 , pre , suf , hostId );
plotLine( x2 , y2 , x2 , y1 - yShift, pre , suf , hostId );
plotLine( x2 , y1 , x1 - xShift, y1 , pre , suf , hostId );
}
/***********************************************************************
* Stimulate a filled square of neurons
***********************************************************************/
public void plotFilledSquare (
final int x1,
final int y1,
final int x2,
final int y2,
final String pre,
final String suf,
final int hostId )
////////////////////////////////////////////////////////////////////////
{
int xTotal=0;
int yTotal=0;
int xstep=0;
int ystep=0;
int xMul=simulatorParser.layerStructure.getXmultiplier(pre,suf);
int yMul=simulatorParser.layerStructure.getYmultiplier(pre,suf);
if(xMul < 0 )
{
xTotal=simulatorParser.xEdgeLength;
xstep=-xMul;
}
else
{
xTotal=simulatorParser.xEdgeLength*xMul;
xstep=1;
}
if(yMul < 0 )
{
yTotal=simulatorParser.yEdgeLength;
ystep=-yMul;
}
else
{
yTotal=simulatorParser.yEdgeLength*yMul;
ystep=1;
}
if ( x1> xTotal || x2 > xTotal || y1> yTotal || y2> yTotal )
{
throw new RuntimeException("out of range error");
}
for (int x = Math.min( x1 , x2 ); x <= Math.max( x1 , x2 ); x+= xstep)
{
plotLine( x , y1 , x, y2 , pre , suf , hostId );
}
}
/***********************************************************************
* Stimulate a line of neurons
***********************************************************************/
public void plotLine (
final int x1,
final int y1,
final int x2,
final int y2,
final String pre,
final String suf,
final int hostId )
////////////////////////////////////////////////////////////////////////
{
double length = Math.sqrt(
(double)(x2-x1)*(double)(x2-x1) +
(double)(y2-y1)*(double)(y2-y1));
if(length < 1e-5) // point stimulus
{
int id;
if ( ( id = simulatorParser.layerStructure.cellmap_slow (
pre, suf, x1, y1 ) ) != -1 )
{
if(FunUtil.hostId(
simulatorParser.layerStructure.nodeEndIndices, id) == hostId)
{
relativeStrengthList.add(1.0);
neuronIndexList.add(id);
}
}
else
{
throw new RuntimeException("point is not in grid");
}
return;
}
int xTotal=0;
int yTotal=0;
int xstep=0;
int ystep=0;
int xMul=simulatorParser.layerStructure.getXmultiplier(pre,suf);
int yMul=simulatorParser.layerStructure.getYmultiplier(pre,suf);
if(xMul < 0 )
{
xTotal=simulatorParser.xEdgeLength;
xstep=-xMul;
}
else
{
xTotal=simulatorParser.xEdgeLength*xMul;
xstep=1;
}
if(yMul < 0 )
{
yTotal=simulatorParser.yEdgeLength;
ystep=-yMul;
}
else
{
yTotal=simulatorParser.yEdgeLength*yMul;
ystep=1;
}
if ( x1> xTotal || x2 > xTotal || y1> yTotal || y2> yTotal )
{
throw new RuntimeException("out of range error");
}
// Here we determine the neurons that are "hit" by the line.
// See the Wikipedia page on Bresenham's line algorithm.
// If steep, swap x's and y's.
boolean steep = Math.abs(y2 - y1) > Math.abs(x2 - x1);
int _xBegin, _xEnd, _yBegin, _yEnd;
if (!steep)
{
_xBegin = x1;
_xEnd = x2;
_yBegin = y1;
_yEnd = y2;
}
else
{
_xBegin = y1;
_xEnd = y2;
_yBegin = x1;
_yEnd = x2;
}
// If flipped, swap begins and ends.
boolean flipped = _xBegin > _xEnd;
int xBegin, xEnd, yBegin, yEnd;
if (!flipped)
{
xBegin = _xBegin;
xEnd = _xEnd;
yBegin = _yBegin;
yEnd = _yEnd;
}
else
{
xBegin = _xEnd;
xEnd = _xBegin;
yBegin = _yEnd;
yEnd = _yBegin;
}
if(xBegin % xstep !=0) xBegin+= xstep - xBegin % xstep ;
if(yBegin % ystep !=0) yBegin+= ystep - yBegin % ystep ;
double slope = (double) (yEnd - yBegin) / (double) (xEnd - xBegin);
for (int x = xBegin; x <= xEnd; x += xstep)
{
int y = (int) Math.round(yBegin + slope * (x - xBegin));
y = y - (y % ystep);
// If steep, swap x's and y's
int xNeuron = steep ? y : x;
int yNeuron = steep ? x : y;
int id = simulatorParser.layerStructure.cellmap_slow(
pre,suf,xNeuron, yNeuron);
if(id != -1)
{
if(FunUtil.hostId(
simulatorParser.layerStructure.nodeEndIndices, id) == hostId)
{
// Calculate the shortest distance from the point
// (xNeuron, yNeuron) to the line between (x1, y1) and (x2, y2)
double distance = Math.abs((x2 - x1) * (y1 - yNeuron)
- (x1 - xNeuron) * (y2 - y1)) / length;
if(channel<0) // If there is no specified channel
{
// The relative strength of the synapse between this stimulus
// and a neuron is a function [ distanceTune() ]
// of the distance between the neuron and the line.
relativeStrengthList.add( distanceTune ( distance ) );
}
else if(channel >=0 && channel <= 180)
{
double lineAngle = Math.acos((double)(x2-x1)/length);
double channelAngle
= (double) channel * (Math.PI / (double) 180.0);
relativeStrengthList.add (
distanceTune (
distance * Math.cos(lineAngle - channelAngle) ) );
}
else
{
throw new RuntimeException (
"channel range error (0-180 or <0)" );
}
neuronIndexList.add(id);
}
}
}
}
/***********************************************************************
* Given image file, stimulate the layer of neurons accourding to image
* intensity
***********************************************************************/
public void plotImg (
final String pre,
final String suf,
final String filename,
final double [ ] [ ] filter )
////////////////////////////////////////////////////////////////////////
{
int [][] out;
imageIO imgIO = new imageIO();
out = imgIO.loadBWImage("imagelib/"+filename);
int [][] pic = Convolution.convolve_safe(out,filter);
int height = pic.length;
int width = pic[0].length;
int xstep,ystep;
int xmulti,ymulti;
xmulti = simulatorParser.layerStructure.getXmultiplier(pre,suf);
ymulti = simulatorParser.layerStructure.getYmultiplier(pre,suf);
int xreso,yreso;
if(xmulti>0)
{
xstep=1;
xreso=xmulti*simulatorParser.xEdgeLength;
}
else
{
xstep=-xmulti;
xreso=simulatorParser.xEdgeLength;
}
if(ymulti>0)
{
ystep=1;
yreso=ymulti*simulatorParser.yEdgeLength;
}
else
{
ystep=-ymulti;
yreso=simulatorParser.yEdgeLength;
}
double heightRatio;
double widthRatio;
try {
heightRatio = (double)height/(double)(yreso/ystep);
widthRatio = (double)width/(double)(xreso/xstep);
}
catch(Exception ex) {
throw new RuntimeException("Pre:"+pre+" Suf:"+suf);
}
for( int x = 0 ; x < xreso/xstep; x++)
{
for( int y = 0 ; y < yreso/ystep; y++)
{
// String neu = pre+","+x*xstep+","+ (yreso-y*ystep-1)+","+suf;
if ( pic [ ( int ) ( y * heightRatio ) + ystep - 1 ]
[ ( int ) ( x * widthRatio ) ] < 0 )
{
pic[(int)(y*heightRatio)+ystep-1][(int)(x*widthRatio)]=0;
}
if ( pic [ ( int ) ( y * heightRatio ) + ystep - 1 ]
[ ( int ) ( x * widthRatio ) ] > 255 )
{
pic[(int)(y*heightRatio)+ystep-1][(int)(x*widthRatio)]=255;
}
// double pixel = (double)(pic[(int)((y)*heightRatio
// +(int)(heightRatio/2.0))][(int)((x)*widthRatio
// +(int)(widthRatio/2.0))])/(double)256;
final double
pixel = ( double ) (
pic [ ( int ) ( y * heightRatio ) + ystep - 1 ]
[ ( int ) ( x * widthRatio ) ] ) / ( double ) 256;
if ( pixel > 0.01 )
{
relativeStrengthList.add(pixel);
neuronIndexList.add (
simulatorParser.layerStructure.cellmap_slow (
pre,
suf,
x * xstep,
( yreso - y * ystep - ystep ) ) );
}
}
}
}
/***********************************************************************
* Given image file, stimulate the layer of neurons accourding to reverse
* of image intensity.
***********************************************************************/
public void plotRImg (
final String pre,
final String suf,
final String filename,
final double [ ] [ ] filter ) //plot reverse img
////////////////////////////////////////////////////////////////////////
{
//pas.xEdgeLength;
//pas.yEdgeLength;
int [][] out;
imageIO imgIO = new imageIO();
out = imgIO.loadBWImage("imagelib/"+filename);
for(int i=0;i<out.length;i++)
{
for(int j=0;j<out[0].length;j++)
{
out[i][j]=255-out[i][j];
}
}
int [][] pic = Convolution.convolve_safe(out,filter);
int height = pic.length;
int width = pic[0].length;
int xstep,ystep;
int xmulti,ymulti;
xmulti = simulatorParser.layerStructure.getXmultiplier(pre,suf);
ymulti = simulatorParser.layerStructure.getYmultiplier(pre,suf);
int xreso,yreso;
if(xmulti>0)
{
xstep=1;
xreso=xmulti*simulatorParser.xEdgeLength;
}
else
{
xstep=-xmulti;
xreso=simulatorParser.xEdgeLength;
}
if(ymulti>0)
{
ystep=1;
yreso=ymulti*simulatorParser.yEdgeLength;
}
else
{
ystep=-ymulti;
yreso=simulatorParser.yEdgeLength;
}
double heightRatio = (double)height/(double)(yreso/ystep);
double widthRatio = (double)width/(double)(xreso/xstep);
for( int x = 0 ; x < xreso/xstep; x++)
{
for( int y = 0 ; y < yreso/ystep; y++)
{
// String neu = pre+","+x+","+ (pas.yEdgeLength-y-1)+","+suf;
if ( pic [ ( int ) ( y * heightRatio ) + ystep - 1 ]
[ ( int ) ( x * widthRatio ) ] < 0 )
{
pic[(int)(y*heightRatio)+ystep-1][(int)(x*widthRatio)]=0;
}
if ( pic [ ( int ) ( y * heightRatio ) + ystep - 1 ]
[ ( int ) ( x * widthRatio ) ] > 255 )
{
pic[(int)(y*heightRatio)+ystep-1][(int)(x*widthRatio)]=255;
}
final double pixel = ( double ) (
pic [ ( int ) ( y * heightRatio ) + ystep - 1 ]
[ ( int ) ( x * widthRatio ) ] ) / ( double ) 256;
//System.out.println("Layer pre:"+pre+" suf:"+suf+" heightRaito"
// +heightRatio+"X:"+(int)(y*heightRatio+ystep-1)+"_"+(x*xstep)
// +"Y:"+(int)(x*widthRatio)+"_"+(yreso-y*ystep-ystep)+" rate:"
// +(double)(pic[(int)(y*heightRatio)+ystep-1]
// [(int)(x*widthRatio)])/(double)256+" fin X:"+x+" Y:"+y);
if ( pixel > 0.01 )
{
relativeStrengthList.add ( pixel );
neuronIndexList.add (
simulatorParser.layerStructure.cellmap_slow (
pre,
suf,
x*xstep,
( yreso-y*ystep-ystep ) ) );
}
}
}
}
/***********************************************************************
* Stimulate the layer of neurons with a given matrix.
*
* cenX, cenY defines the center position of the matrix in the layer
***********************************************************************/
public void plotMatrix (
final String pre,
final String suf,
final int cenX,
final int cenY,
final double [ ] [ ] matrix,
final int hostId )
////////////////////////////////////////////////////////////////////////
{
final int [ ] center = simulatorParser.layerStructure.closePoint (
cenX,
cenY,
pre,
suf );
int halfMaX = matrix.length/2;
int halfMaY = matrix[0].length/2;
int xstep,ystep;
int xmulti,ymulti;
xmulti = simulatorParser.layerStructure.getXmultiplier(pre,suf);
ymulti = simulatorParser.layerStructure.getYmultiplier(pre,suf);
int xreso,yreso;
if(xmulti>0)
{
xstep=1;
xreso=xmulti*simulatorParser.xEdgeLength;
}
else
{
xstep=-xmulti;
xreso=simulatorParser.xEdgeLength;
}
if(ymulti>0)
{
ystep=1;
yreso=ymulti*simulatorParser.yEdgeLength;
}
else
{
ystep=-ymulti;
yreso=simulatorParser.yEdgeLength;
}
for (
int x = center [ 0 ] - halfMaX;
x < center [ 0 ]
+ ( matrix.length % 2 == 0 ? halfMaX : halfMaX + 1 );
x++ )
{
for (
int y = center [ 1 ] - halfMaY;
y < center [ 1 ]
+ ( matrix [ 0 ].length % 2 == 0 ? halfMaY : halfMaY + 1 );
y++ )
{
int MaX=x-center[0]+halfMaX;
int MaY=y-center[1]+halfMaY;
int xx,yy;
xx=x%xreso;
yy=y%yreso;
if(xx<0)xx=xx+xreso;
if(yy<0)yy=yy+yreso;
final int id = simulatorParser.layerStructure.cellmap_slow (
pre,
suf,
xx,
yy );
if(id != -1)
{
if ( FunUtil.hostId (
simulatorParser.layerStructure.nodeEndIndices,
id ) == hostId )
{
double pixel = matrix[MaX][MaY];
if(pixel!=0.0)
{
relativeStrengthList.add(pixel);
neuronIndexList.add(id);
}
}
}
}
}
}
public void plotMatrix (
final String pre,
final String suf,
final int cenX,
final int cenY,
final double [ ] [ ] matrix )
////////////////////////////////////////////////////////////////////////
{
final int [ ] center = simulatorParser.layerStructure.closePoint (
cenX,
cenY,
pre,
suf );
int halfMaX = matrix.length/2;
int halfMaY = matrix[0].length/2;
int xstep,ystep;
int xmulti,ymulti;
xmulti = simulatorParser.layerStructure.getXmultiplier(pre,suf);
ymulti = simulatorParser.layerStructure.getYmultiplier(pre,suf);
int xreso,yreso;
if(xmulti>0)
{
xstep=1;
xreso=xmulti*simulatorParser.xEdgeLength;
}
else
{
xstep=-xmulti;
xreso=simulatorParser.xEdgeLength;
}
if(ymulti>0)
{
ystep=1;
yreso=ymulti*simulatorParser.yEdgeLength;
}
else
{
ystep=-ymulti;
yreso=simulatorParser.yEdgeLength;
}
for (
int x = center [ 0 ] - halfMaX;
x < center [ 0 ]
+ ( matrix.length % 2 == 0 ? halfMaX : halfMaX + 1 );
x++ )
{
for (
int y = center [ 1 ] - halfMaY;
y < center [ 1 ]
+ ( matrix [ 0 ].length % 2 == 0 ? halfMaY : halfMaY + 1 );
y++ )
{
int MaX=x-center[0]+halfMaX;
int MaY=y-center[1]+halfMaY;
int xx,yy;
xx=x%xreso;
yy=y%yreso;
if(xx<0)xx=xx+xreso;
if(yy<0)yy=yy+yreso;
final int id = simulatorParser.layerStructure.cellmap_slow (
pre,
suf,
xx,
yy );
if(id != -1)
{
double pixel = matrix[MaX][MaY];
if(pixel!=0.0)
{
relativeStrengthList.add(pixel);
neuronIndexList.add(id);
}
}
}
}
}
/***********************************************************************
* Stimulate the whole layer of neurons.
*
* Injecting noise to the whole layer.
***********************************************************************/
public void background (
final String pre,
final String suf )
////////////////////////////////////////////////////////////////////////
{
int
xTotal = 0,
yTotal = 0,
xstep = 0,
ystep = 0,
xMul = simulatorParser.layerStructure.getXmultiplier ( pre, suf ),
yMul = simulatorParser.layerStructure.getYmultiplier ( pre, suf );
if ( xMul < 0 )
{
xTotal = simulatorParser.xEdgeLength;
xstep = -xMul;
}
else
{
xTotal = simulatorParser.xEdgeLength * xMul;
xstep = 1;
}
if ( yMul < 0 )
{
yTotal = simulatorParser.yEdgeLength;
ystep = -yMul;
}
else
{
yTotal = simulatorParser.yEdgeLength * yMul;
ystep = 1;
}
for ( int x = 0; x < xTotal; x = x + xstep )
{
for ( int y = 0; y < yTotal; y = y + ystep )
{
relativeStrengthList.add ( Double.valueOf ( 1.0 ) );
neuronIndexList.add (
simulatorParser.layerStructure.cellmap_slow (
pre,
suf,
x,
y ) );
}
}
}
/***********************************************************************
* Injecting noise to the whole layer.
***********************************************************************/
public void background (
final String pre,
final String suf,
final int hostId )
////////////////////////////////////////////////////////////////////////
{
int xTotal=0;
int yTotal=0;
int xstep=0;
int ystep=0;
int xMul=simulatorParser.layerStructure.getXmultiplier(pre,suf);
int yMul=simulatorParser.layerStructure.getYmultiplier(pre,suf);
if(xMul < 0 )
{
xTotal=simulatorParser.xEdgeLength;
xstep=-xMul;
}
else
{
xTotal=simulatorParser.xEdgeLength*xMul;
xstep=1;
}
if(yMul < 0 )
{
yTotal=simulatorParser.yEdgeLength;
ystep=-yMul;
}
else
{
yTotal=simulatorParser.yEdgeLength*yMul;
ystep=1;
}
for( int x = 0 ; x < xTotal; x=x+xstep)
{
for( int y = 0 ; y < yTotal ; y=y+ystep)
{
// String neu = pre+","+x+","+ y+","+suf;
int id = simulatorParser.layerStructure.cellmap_slow(pre,suf,x,y);
if ( FunUtil.hostId (
simulatorParser.layerStructure.nodeEndIndices,
id ) == hostId )
{
relativeStrengthList.add(1.0);
neuronIndexList.add (
simulatorParser.layerStructure.cellmap_slow (
pre,
suf,
x,
y ) );
}
}
}
}
/***********************************************************************
* Plot reverse image.
***********************************************************************/
public void plotRImg (
final String pre,
final String suf,
final String filename,
final double [ ] [ ] filter,
final double gamma,
final double k,
final int hostId )
////////////////////////////////////////////////////////////////////////
{
//pas.xEdgeLength;
//pas.yEdgeLength;
int [][] out;
imageIO imgIO = new imageIO();
out = imgIO.loadBWImage("imagelib/"+filename);
for(int i=0;i<out.length;i++)
{
for(int j=0;j<out[0].length;j++)
{
out[i][j]=255-out[i][j];
}
}
int [][] pic = Convolution.convolve_safe(out,filter);
int height = pic.length;
int width = pic[0].length;
int xstep,ystep;
int xmulti,ymulti;
xmulti = simulatorParser.layerStructure.getXmultiplier(pre,suf);
ymulti = simulatorParser.layerStructure.getYmultiplier(pre,suf);
int xreso,yreso;
if(xmulti>0)
{
xstep=1;
xreso=xmulti*simulatorParser.xEdgeLength;
}
else
{
xstep=-xmulti;
xreso=simulatorParser.xEdgeLength;
}
if(ymulti>0)
{
ystep=1;
yreso=ymulti*simulatorParser.yEdgeLength;
}
else
{
ystep=-ymulti;
yreso=simulatorParser.yEdgeLength;
}
double heightRatio = (double)height/(double)(yreso/ystep);
double widthRatio = (double)width/(double)(xreso/xstep);
for( int x = 0 ; x < xreso/xstep; x++)
{
for( int y = 0 ; y < yreso/ystep; y++)
{
// String neu = pre+","+x+","+ (pas.yEdgeLength-y-1)+","+suf;
int id = simulatorParser.layerStructure.cellmap_slow (
pre,
suf,
x*xstep,
(yreso-y*ystep-ystep));
if ( FunUtil.hostId (
simulatorParser.layerStructure.nodeEndIndices,
id ) == hostId )
// if(pas.ls.cellmap.containsKey(neu))
{
// if(pic[(int)(y*heightRatio+ystep-1)]
// [(int)(x*widthRatio)]<0)
// pic[(int)(y*heightRatio+ystep-1)][(int)(x*widthRatio)]=0;
// if(pic[(int)(y*heightRatio+ystep-1)]
// [(int)(x*widthRatio)]>255)
// pic[(int)(y*heightRatio+ystep-1)][(int)(x*widthRatio)]=255;
// double pixel = (double)(
// 255-pic[(int)(y*heightRatio)]
// [(int)(x*widthRatio)])/(double)256;
double pixel = 0.0;
int ii,jj;
for(ii=0;ii<ystep;ii++)
{
for(jj=0;jj<xstep;jj++)
{
if ( pic [ ( int ) ( y * heightRatio ) + ystep - 1 - ii ]
[ ( int ) ( x * widthRatio ) + jj ] < 0 )
{
pic [ ( int ) ( y * heightRatio ) + ystep - 1 - ii ]
[ ( int ) ( x * widthRatio ) + jj ] = 0;
}
if ( pic [ ( int ) ( y * heightRatio ) + ystep - 1 - ii ]
[ ( int ) ( x * widthRatio ) + jj ] > 255 )
{
pic [ ( int ) ( y * heightRatio ) + ystep - 1 - ii ]
[ ( int ) ( x * widthRatio ) + jj ] = 255;
}
pixel += nonlinearFilter (
( double ) ( pic
[ ( int ) ( y * heightRatio ) + ystep - 1 - ii ]
[ ( int ) ( x * widthRatio ) + jj ] )
/ ( double ) 256,
gamma,
k );
}
}
pixel = pixel /(double)(ystep*xstep);
// double pixel = (double)(pic[(int)(y*heightRatio)]
// [(int)(x*widthRatio)])/(double)256;
if(pixel>0.01)
{
relativeStrengthList.add(pixel);
neuronIndexList.add(id);
}
}
}
}
}
/***********************************************************************
* Non linear filter to simualte Retina
*
* @param x
* @param gamma
* @param k
* @return
***********************************************************************/
public double nonlinearFilter(double x, double gamma, double k)
////////////////////////////////////////////////////////////////////////
{
// double gamma = 1.0;
// double k=0.02;
if(gamma>0)
{
double var = Math.pow((x/k),gamma);
return var/(1+var);
}
return x;
}
public void plotImg (
final String pre,
final String suf,
final String filename,
final double [ ] [ ] filter,
final double gamma,
final double k,
final int hostId )
////////////////////////////////////////////////////////////////////////
{
//pas.xEdgeLength;
//pas.yEdgeLength;
int [][] out;
imageIO imgIO = new imageIO();
out = imgIO.loadBWImage("imagelib/"+filename);
int [][] pic = Convolution.convolve_safe(out,filter);
int height = pic.length;
int width = pic[0].length;
int xstep,ystep;
int xmulti,ymulti;
xmulti = simulatorParser.layerStructure.getXmultiplier(pre,suf);
ymulti = simulatorParser.layerStructure.getYmultiplier(pre,suf);
int xreso,yreso;
if(xmulti>0)
{
xstep=1;
xreso=xmulti*simulatorParser.xEdgeLength;
}
else
{
xstep=-xmulti;
xreso=simulatorParser.xEdgeLength;
}
if(ymulti>0)
{
ystep=1;
yreso=ymulti*simulatorParser.yEdgeLength;
}
else
{
ystep=-ymulti;
yreso=simulatorParser.yEdgeLength;
}
double heightRatio = (double)height/(double)(yreso/ystep);
double widthRatio = (double)width /(double)(xreso/xstep);
for( int x = 0 ; x < xreso/xstep; x++)
{
for( int y = 0 ; y < yreso/ystep; y++)
{
// String neu = pre+","+x+","+ (pas.yEdgeLength-y-1)+","+suf;
int id = simulatorParser.layerStructure.cellmap_slow(
pre,
suf,
x*xstep,
(yreso-y*ystep-ystep));
if ( FunUtil.hostId (
simulatorParser.layerStructure.nodeEndIndices,
id ) == hostId )
// if(pas.ls.cellmap.containsKey(neu))
{
// double pixel = (double)(255-pic[(int)(y*heightRatio)]
// [(int)(x*widthRatio)])/(double)256;
// double pixel = nonlinearFilter((double)(
// pic[(int)(y*heightRatio)+ystep-1]
// [(int)(x*widthRatio)])/(double)256,gamma,k);
double pixel = 0.0;
int ii,jj;
for(ii=0;ii<ystep;ii++)
{
for(jj=0;jj<xstep;jj++)
{
if ( pic [ ( int ) ( y * heightRatio ) + ystep - 1 - ii ]
[ ( int ) ( x * widthRatio ) + jj ] < 0 )
{
pic [ ( int ) ( y * heightRatio ) + ystep - 1 - ii ]
[ ( int ) ( x * widthRatio ) + jj ] = 0;
}
if ( pic [ ( int ) ( y * heightRatio ) + ystep - 1 - ii ]
[ ( int ) ( x * widthRatio ) + jj ] > 255 )
{
pic [ ( int ) ( y * heightRatio ) + ystep - 1 - ii ]
[ ( int ) ( x * widthRatio ) + jj ] = 255;
}
pixel += nonlinearFilter (
( double ) ( pic
[ ( int ) ( y * heightRatio ) + ystep - 1 - ii ]
[ ( int ) ( x * widthRatio ) +jj ] )
/ ( double ) 256,
gamma,
k );
}
}
pixel = pixel / ( double ) ( ystep * xstep );
if ( pixel > 0.01 )
{
relativeStrengthList.add ( pixel );
neuronIndexList.add ( id );
}
}
}
}
}
public void plotSquare (
final int x1,
final int y1,
final int x2,
final int y2,
final String pre,
final String suf )
////////////////////////////////////////////////////////////////////////
{
int xTotal=0;
int yTotal=0;
int xstep=0;
int ystep=0;
int xMul=simulatorParser.layerStructure.getXmultiplier(pre,suf);
int yMul=simulatorParser.layerStructure.getYmultiplier(pre,suf);
if(xMul < 0 )
{
xTotal=simulatorParser.xEdgeLength;
xstep=-xMul;
}
else
{
xTotal=simulatorParser.xEdgeLength*xMul;
xstep=1;
}
if(yMul < 0 )
{
yTotal=simulatorParser.yEdgeLength;
ystep=-yMul;
}
else
{
yTotal=simulatorParser.yEdgeLength*yMul;
ystep=1;
}
if ( x1> xTotal || x2 > xTotal || y1> yTotal || y2> yTotal )
{
throw new RuntimeException("out of range error");
}
// Draw four non-overlapping lines
final int xShift = x1 > x2 ? xstep : -xstep;
final int yShift = y1 > y2 ? ystep : -ystep;
plotLine( x1 , y1 , x1 , y2 + yShift, pre , suf );
plotLine( x1 , y2 , x2 + xShift, y2 , pre , suf );
plotLine( x2 , y2 , x2 , y1 - yShift, pre , suf );
plotLine( x2 , y1 , x1 - xShift, y1 , pre , suf );
}
public void plotFilledSquare (
final int x1,
final int y1,
final int x2,
final int y2,
final String pre,
final String suf )
////////////////////////////////////////////////////////////////////////
{
int xTotal=0;
int yTotal=0;
int xstep=0;
int ystep=0;
int xMul=simulatorParser.layerStructure.getXmultiplier(pre,suf);
int yMul=simulatorParser.layerStructure.getYmultiplier(pre,suf);
if(xMul < 0 )
{
xTotal=simulatorParser.xEdgeLength;
xstep=-xMul;
}
else
{
xTotal=simulatorParser.xEdgeLength*xMul;
xstep=1;
}
if(yMul < 0 )
{
yTotal=simulatorParser.yEdgeLength;
ystep=-yMul;
}
else
{
yTotal=simulatorParser.yEdgeLength*yMul;
ystep=1;
}
if ( x1> xTotal || x2 > xTotal || y1> yTotal || y2> yTotal )
{
throw new RuntimeException("out of range error");
}
for (int x = Math.min( x1 , x2 ); x <= Math.max( x1 , x2 ); x+= xstep)
{
plotLine( x , y1 , x, y2 , pre , suf );
}
}
public void plotLine (
final int x1,
final int y1,
final int x2,
final int y2,
final String pre,
final String suf )
////////////////////////////////////////////////////////////////////////
{
double length = Math.sqrt(
(double)(x2-x1)*(double)(x2-x1)+
(double)(y2-y1)*(double)(y2-y1));
if(length < 1e-5) // point stimulus
{
int id;
if ( ( id = simulatorParser.layerStructure.cellmap_slow (
pre, suf, x1, y1 ) ) != -1 )
{
relativeStrengthList.add(1.0);
neuronIndexList.add(id);
}
else
{
throw new RuntimeException("point is not in grid");
}
return;
}
int xTotal=0;
int yTotal=0;
int xstep=0;
int ystep=0;
int xMul=simulatorParser.layerStructure.getXmultiplier(pre,suf);
int yMul=simulatorParser.layerStructure.getYmultiplier(pre,suf);
if(xMul < 0 )
{
xTotal=simulatorParser.xEdgeLength;
xstep=-xMul;
}
else
{
xTotal=simulatorParser.xEdgeLength*xMul;
xstep=1;
}
if(yMul < 0 )
{
yTotal=simulatorParser.yEdgeLength;
ystep=-yMul;
}
else
{
yTotal=simulatorParser.yEdgeLength*yMul;
ystep=1;
}
if ( x1> xTotal || x2 > xTotal || y1> yTotal || y2> yTotal )
{
throw new RuntimeException("out of range error");
}
// Here we determine the neurons that are "hit" by the line.
// See the Wikipedia page on Bresenham's line algorithm.
// If steep, swap x's and y's.
boolean steep = Math.abs(y2 - y1) > Math.abs(x2 - x1);
int _xBegin, _xEnd, _yBegin, _yEnd;
if (!steep)
{
_xBegin = x1;
_xEnd = x2;
_yBegin = y1;
_yEnd = y2;
}
else
{
_xBegin = y1;
_xEnd = y2;
_yBegin = x1;
_yEnd = x2;
}
// If flipped, swap begins and ends.
boolean flipped = _xBegin > _xEnd;
int xBegin, xEnd, yBegin, yEnd;
if (!flipped)
{
xBegin = _xBegin;
xEnd = _xEnd;
yBegin = _yBegin;
yEnd = _yEnd;
}
else
{
xBegin = _xEnd;
xEnd = _xBegin;
yBegin = _yEnd;
yEnd = _yBegin;
}
if(xBegin % xstep !=0) xBegin+= xstep - xBegin % xstep ;
if(yBegin % ystep !=0) yBegin+= ystep - yBegin % ystep ;
double slope = (double) (yEnd - yBegin) / (double) (xEnd - xBegin);
for (int x = xBegin; x <= xEnd; x += xstep)
{
int y = (int) Math.round(yBegin + slope * (x - xBegin));
y = y - (y % ystep);
// If steep, swap x's and y's
int xNeuron = steep ? y : x;
int yNeuron = steep ? x : y;
int id = simulatorParser.layerStructure.cellmap_slow(
pre,suf,xNeuron, yNeuron);
if(id != -1)
{
// Calculate the shortest distance from the
// point (xNeuron, yNeuron) to the
// line between (x1, y1) and (x2, y2)
double distance = Math.abs(
(x2 - x1) * (y1 - yNeuron) -
(x1 - xNeuron) * (y2 - y1)) / length;
if(channel<0) // If there is no specified channel
{
// The relative strength of the synapse between this stimulus
// and a neuron is a function [ distanceTune() ]
// of the distance between the neuron and the line.
relativeStrengthList.add( distanceTune ( distance ) );
}
else if(channel >=0 && channel <= 180)
{
double lineAngle = Math.acos((double)(x2-x1)/length);
double
channelAngle = (double) channel * (Math.PI / (double) 180.0);
relativeStrengthList.add (
distanceTune (
distance * Math.cos(lineAngle - channelAngle) ) );
}
else
{
throw new RuntimeException (
"channel range error (0-180 or <0)" );
}
neuronIndexList.add(id);
}
}
}
private double distanceTune (double d)
////////////////////////////////////////////////////////////////////////
{
return 1 - Math.sqrt(2) * d;
}
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
}