001    package cnslab.cnsnetwork;
002    
003    import java.io.*;
004    import java.util.*;
005
006    import org.slf4j.Logger;
007    import org.slf4j.LoggerFactory;
008
009    import jpvm.*;
010
011    import cnslab.cnsmath.*;
012    import edu.jhu.mb.ernst.model.Synapse;
013
014    /***********************************************************************
015    * Sync neuron (fake neuron, id is the last neuron index),
016    * used to synchronize between NetHosts, used to send half minimum
017    * synaptic delay time ticks, send buffered spikes
018    * 
019    * @version
020    *   $Date: 2012-08-04 13:43:22 -0500 (Sat, 04 Aug 2012) $
021    *   $Rev: 104 $
022    *   $Author: croft $
023    * @author
024    *   Yi Dong
025    * @author
026    *   David Wallace Croft
027    ***********************************************************************/
028    public final class  SYNNeuron
029      implements Neuron, Serializable
030    ////////////////////////////////////////////////////////////////////////
031    ////////////////////////////////////////////////////////////////////////
032    {
033    
034    private static final Class<SYNNeuron>
035      CLASS = SYNNeuron.class;
036
037    private static final Logger
038      LOGGER = LoggerFactory.getLogger ( CLASS );  
039    
040    private static final long  serialVersionUID = 0L;
041    
042    //
043    
044    /** background frequency */
045    private Network  network;
046
047    public double    tick;
048
049//  Axon axon;
050
051    ////////////////////////////////////////////////////////////////////////
052    ////////////////////////////////////////////////////////////////////////
053    
054    public  SYNNeuron ( final Network  network )
055    ////////////////////////////////////////////////////////////////////////
056    {
057      this.network = network;
058      
059      tick = network.minSynapticDelay / 2.0;
060    }
061
062    ////////////////////////////////////////////////////////////////////////
063    ////////////////////////////////////////////////////////////////////////
064    
065    @Override
066    public void  setTimeOfNextFire ( final double  nextFire )
067    ////////////////////////////////////////////////////////////////////////
068    {
069      if ( network.info.jpvm == null )
070      {
071        // TODO:  Hack for unit testing without distributed computing
072        // I am not sure if this is correct. -- Croft
073        
074        final double  currTime = nextFire - tick;
075        
076        if ( currTime >= network.endOfTrial )
077        {
078          int trial = network.trialId;
079          
080          int expid = network.subExpId;
081
082          processData ( expid, trial );
083          
084          network.p.println ( "trial done" );
085          
086          network.trialDone = true;
087
088          network.spikeState = true;
089          
090          for ( int  iter = 0; iter < network.info.numTasks; iter++ )
091          {       
092            network.received [ iter ] = 1;
093          }
094          
095          network.rootTime = 0.0;
096          
097          network.clearQueues ( );
098          
099          network.countTrial++;
100          
101          // double hack
102          
103          network.stop = true;
104        }
105        
106        return;
107      }
108      
109      // if synNeuron at currTime could be processed, it was guaranteed that
110      // the spikes sent by synNeuron at currTime-tick are received.
111      
112//    network.p.print("sync T"+":"+network.rootTime+" ");
113//    network.p.print("\n");
114      
115      try
116      {
117        // send current time to the root;
118        
119        final double  currTime = nextFire - tick;
120
121        jpvmBuffer buff = new jpvmBuffer ( );
122        
123        buff.pack ( currTime ); //pack the sysTime
124        
125        buff.pack ( network.info.idIndex ); //pack the hostId
126        
127        // tell the root the current time
128        
129        network.info.jpvm.pvm_send (
130          buff,
131          network.info.parentJpvmTaskId,
132          NetMessageTag.sendTick );
133
134        int  countN = 0;
135        
136        for ( int  k = 0;
137          k < network.experiment.recorder.intraEle.size ( ); k++ )
138        {
139          for ( int  m = 0;
140            m < network.experiment.recorder.intraEle.get ( k ).size ( ); m++ )
141          {
142            final Neuron  tmpN = network.neurons [
143              network.intraRecBuffers.neurons [ k ] - network.base ];
144            
145            final LinkedList<Double>  curr = new LinkedList<Double> ( );
146            
147            final double [ ]  allCurr = tmpN.getCurr ( currTime );
148            
149            for( int  j = 0;
150              j < network.experiment.recorder.currChannel.get ( k ).size ( );
151              j++ )
152            {
153              curr.add ( allCurr [
154                network.experiment.recorder.currChannel.get ( k ).get ( j ) ] );
155            }
156            
157            network.intraRecBuffers.buff.get ( countN ).add (
158              new IntraInfo ( tmpN.getMemV ( currTime ), curr ) );
159            
160            countN++;
161          }
162        }
163
164        // network.p.print(network.intraBuff);
165
166        if ( currTime + network.minSynapticDelay < network.endOfTrial )
167        {
168//        network.p.println("sent at "+currTime);
169          
170          for ( int  i = 0; i < network.info.numTasks; i++ )
171          {
172            if ( i != network.info.idIndex ) //not to him self
173            {
174              buff = new jpvmBuffer();
175              
176              buff.pack(network.info.idIndex); //source id;
177              
178              buff.pack(network.countTrial);// trial id info
179
180//            buff.pack(network.rootTime); // local root time;
181//            buff.pack(currTime); // local root time;
182              
183              buff.pack(network.spikeBuffers[i]); //pack the spike buffer
184              
185              // send the spikes to the target host
186              
187              network.info.jpvm.pvm_send (
188                buff,
189                network.info.tids [ i ],
190                NetMessageTag.sendSpike );
191              
192              // clear buffer
193              
194              network.spikeBuffers [ i ].buff.clear ( );
195            }
196          }
197        }
198        else
199        {
200          for ( int  iter = 0; iter < network.info.numTasks; iter++ )
201          {
202            if ( iter != network.info.idIndex )
203            {
204              ( network.received [ iter ] )++;
205            }
206          }
207          
208          network.spikeState = true;
209        }
210
211        if ( currTime >= network.endOfTrial )
212        {
213          // network.p.println("trial done ini"+minTime);
214          
215          jpvmBuffer buf = new jpvmBuffer();
216          
217          int trial = network.trialId;
218          
219          int expid = network.subExpId;
220
221//        network.p.print("E"+network.subExpId+" T"+trial);
222
223          buf.pack(trial); //trial id and subexp id
224          
225          buf.pack(expid);
226          
227          //buf.pack(network.info.idIndex);
228
229          // don't send it, process it first
230          //  buf.pack(network.recordBuff);
231          
232          processData ( expid, trial );
233          
234          // send the intracellular info back to root
235
236          buf.pack ( network.intraRecBuffers );
237          
238          //send root to say the trial is done
239          
240          // network.info.jpvm.pvm_send(
241          //   buf,network.info.parent,NetMessageTag.trialDone);
242          
243          network.p.println ( "trial done" );
244          
245          //break;
246          
247          network.trialDone = true;
248
249          //added;
250          
251          network.spikeState = true;
252          
253          for ( int  iter = 0; iter < network.info.numTasks; iter++ )
254          {       
255            /*
256            while(!network.received[iter].empty())
257            {
258              network.received[iter].pop();
259            }
260            */
261            
262            // leave mark here
263            
264            network.received [ iter ] = 1;
265          }
266          
267          //added over;
268
269          //initialization
270          
271          network.rootTime = 0.0;
272          
273          network.clearQueues ( );
274          
275          network.countTrial++;
276          
277          //network.init();
278          
279          network.info.jpvm.pvm_send (
280            buf,
281            network.info.tids [ network.info.idIndex ],
282            NetMessageTag.trialDone );
283          
284          buf = new jpvmBuffer ( );
285          
286          // network.p.println(
287          // "e:"+expid+"t:"+trial+" host:"+network.info.parent.getHost());
288          
289          network.info.jpvm.pvm_barrier (
290            network.info.parentJpvmTaskId.getHost ( ),
291            expid * network.experiment.subExp.length + trial,
292            network.info.numTasks );
293          
294          // network.p.println("ov_e:"+expid+"t:"+trial);
295          // network.p.flush();
296          
297          network.info.jpvm.pvm_send (
298            buf,
299            network.info.parentJpvmTaskId,
300            NetMessageTag.trialDone );
301        }
302      }
303      catch ( final jpvmException  ex )
304      {
305        ex.printStackTrace(network.p);
306        
307        network.p.println (
308          "Error - Sync failed to send message to the root "
309          +network.rootTime );
310        
311        network.p.println ( ex );
312      }
313      catch ( final Exception  e )
314      {
315        e.printStackTrace ( );
316      }
317    }
318
319    /**
320     * @see cnslab.cnsnetwork.Neuron#timeOfFire() timeOfFire
321     */
322// TODO:  Why does @Override not work here? Interface changed?    
323// @Override
324    public double timeOfFire(double curr)
325    ////////////////////////////////////////////////////////////////////////
326    {
327      return tick;
328    }
329    
330    /**
331     * @see cnslab.cnsnetwork.Neuron#updateFire() updateFire
332     */
333    @Override
334    public double updateFire()
335    ////////////////////////////////////////////////////////////////////////
336    {
337//    throw new RuntimeException("sensory neuron won't update fire");
338      return tick;
339//    return true;
340    }
341    
342    /**
343     * @see cnslab.cnsnetwork.Neuron#updateInput(
344     * cnslab.cnsnetwork.InputEvent) updateInput
345     */
346    @Override
347    public double updateInput(double time, Synapse input)
348    ////////////////////////////////////////////////////////////////////////
349    {
350      throw new RuntimeException("sensory neuron won't recieve inputs");
351    }
352    
353    /**
354     * @see cnslab.cnsnetwork.Neuron#getTimeOfNextFire() getTimeOfNextFire
355     */
356    @Override
357    public double getTimeOfNextFire()
358    ////////////////////////////////////////////////////////////////////////
359    {
360      return -1;
361    }
362    
363/*
364  public Axon getAxon()
365  {
366    return axon;
367  }
368 */
369
370    /**
371     * @see java.lang.Object#toString() toString
372     */
373    @Override
374    public String toString()
375    ////////////////////////////////////////////////////////////////////////
376    {
377      String tmp="Synchroizing clock neuron\n";
378      return tmp;
379    } // END: toString
380
381    /**
382     * @see cnslab.cnsnetwork.Neuron#isSensory() isSensory
383     */
384    @Override
385    public boolean isSensory()
386    ////////////////////////////////////////////////////////////////////////
387    {
388      return true;
389    }
390
391    /**
392     * {@inheritDoc}
393     * @see Neuron#init(int,int,Seed,Network,int)
394     */
395    @Override
396    public void init(int expid, int trialid, Seed idum, Network net, int id)
397    ////////////////////////////////////////////////////////////////////////
398    {
399      throw new RuntimeException("sensory neuron won't need init");
400    }
401
402    /** 
403     * record the neuron 
404     * @return  boolean whether it should be recorded
405     */
406    @Override
407    public boolean getRecord()
408    ////////////////////////////////////////////////////////////////////////
409    {
410      return false; //fake neuron can't be recorded
411    }
412
413    /** 
414     *set the neuron record or not.
415     */
416    @Override
417    public void setRecord(boolean record)
418    ////////////////////////////////////////////////////////////////////////
419    {
420      //nothing is done
421    }
422
423    /** 
424     * @return neuron's current memory voltage
425     */
426    @Override
427    public double getMemV(double currTime)
428    ////////////////////////////////////////////////////////////////////////
429    {
430      throw new RuntimeException("no memV for sensory neuron");
431    }
432
433    /** 
434     * 
435     * @return neuron's current currents of all the channels
436     */
437    @Override
438    public double [] getCurr(double currTime)
439    ////////////////////////////////////////////////////////////////////////
440    {
441      throw new RuntimeException("no curr for sensory neuron");
442    }
443
444    ////////////////////////////////////////////////////////////////////////
445    ////////////////////////////////////////////////////////////////////////
446    
447    private void  processData (
448      final int  expid,
449      final int  trial )
450    ////////////////////////////////////////////////////////////////////////
451    {
452      //RecordBuffer spikes = Network.recordBuff;
453      
454      final Iterator<NetRecordSpike>
455        iter_spike = network.recordBuff.buff.iterator();
456      
457      while(iter_spike.hasNext())
458      {
459        NetRecordSpike spike = iter_spike.next();
460        
461        //single unit processing
462        
463        //if neuron is in single unit recorder
464        
465        if(network.experiment.recorder.singleUnit.contains(spike.from))
466        {
467          LinkedList<Double>  tmp
468            = network.recorderData.receiver.get (
469              "E" + expid + "T" + trial + "N" + spike.from );
470
471          if ( tmp == null )
472          {
473            network.recorderData.receiver.put (
474              "E" + expid + "T" + trial + "N" + spike.from,
475              tmp = ( new LinkedList<Double> ( ) ) );
476          }
477          
478          //put received info into memory
479          // if ( spike.time !=0.0 ) tmp.add(spike.time);
480          
481          //put received info into memory
482          tmp.add ( spike.time );
483          
484          // System.out.println(
485          //   "fire: time:"+spike.time+ " index:"+spike.from);
486        }
487        
488        // multiple unit processing
489        
490        final int
491          multiUnitSize = network.experiment.recorder.multiUnit.size ( );
492        
493        for ( int  mID = 0; mID < multiUnitSize; mID++ )
494        {
495          final ArrayList<Integer>  neuronIndexList
496            = network.experiment.recorder.multiUnit.get ( mID );
497          
498          if ( neuronIndexList.contains ( spike.from ) )
499          {
500            // LOGGER.trace (
501            //  "Recording MultiUnit spike from {}",
502            //  spike.from );
503            
504            final int  binIndex = ( int )
505              ( spike.time / network.experiment.recorder.timeBinSize );
506            
507            // LOGGER.trace ( "binIndex {}", binIndex );
508            
509            final String  key = "E" + expid + "N" + mID + "B" + binIndex; 
510            
511            Integer  tmpInt = network.recorderData.multiCounter.get ( key );
512            
513            if ( tmpInt == null )
514            {
515              tmpInt = new Integer ( 0 );
516            }
517            
518            tmpInt = tmpInt + 1;
519            
520            network.recorderData.multiCounter.put (
521              key,
522              tmpInt );
523            
524            // LOGGER.trace ( "key {} tmpInt {}", key, tmpInt );
525            
526            final String  keyAll
527              = "E" + expid + "T" + trial + "N" + mID + "B" + binIndex; 
528            
529            Integer  tmpIntAll
530              = network.recorderData.multiCounterAll.get ( keyAll );
531            
532            if ( tmpIntAll == null )
533            {
534              tmpIntAll = new Integer ( 0 );
535            }
536            
537            tmpIntAll = tmpIntAll + 1;
538            
539            network.recorderData.multiCounterAll.put (
540              keyAll,
541              tmpIntAll );
542          }
543        }
544        
545        // field processing
546        for ( int  fID = 0;
547          fID < network.experiment.recorder.fieldEle.size ( ); fID++ )
548        {
549          if ( network.simulatorParser.layerStructure.celltype [
550            spike.from - network.base ].matches ( "^"
551            + network.experiment.recorder.fieldEle.get ( fID ).getPrefix ( )
552            + ",.*,"
553            + network.experiment.recorder.fieldEle.get ( fID ).getSuffix ( )
554            + "$" ) )
555          {
556//          int [] xy  = network.pas.ls.celllayer_cordinate(
557//            spike.from,network.exp.rec.fieldEle.get(fID).getPrefix(),
558//            network.exp.rec.fieldEle.get(fID).getSuffix());
559            
560            final int  binIndex = ( int )
561              ( spike.time / network.experiment.recorder.fieldTimeBinSize );
562            
563            Integer  tmpInt = network.recorderData.fieldCounter.get (
564              "E" + expid + ","
565              + network.simulatorParser.layerStructure.celltype [
566              spike.from - network.base ]
567              + "," + "B" + binIndex );
568            
569            if ( tmpInt == null )
570            {
571              network.recorderData.fieldCounter.put (
572                "E"+expid+","
573                  + network.simulatorParser.layerStructure.celltype [
574                  spike.from-network.base ]
575                  + "," + "B" + binIndex,
576                tmpInt = ( new Integer ( 0 ) ) );
577            }
578            
579            tmpInt = tmpInt + 1;
580            
581            network.recorderData.fieldCounter.put (
582              "E" + expid + ","
583                + network.simulatorParser.layerStructure.celltype [
584                spike.from-network.base ]
585                + "," + "B" + binIndex,
586              tmpInt);
587          }
588        }
589        
590        //vector processing
591        
592        for ( int  vID = 0;
593          vID < network.experiment.recorder.vectorUnit.size ( ); vID++ )
594        {
595          for ( int  cID = 0;
596            cID
597              < network.experiment.recorder.vectorUnit.get ( vID ).coms.size ( );
598            cID++)
599          {
600            if ( network.simulatorParser.layerStructure.celltype [
601              spike.from-network.base ].matches (
602                "^" + network.experiment.recorder.vectorUnit.get ( vID )
603                .coms.get ( cID ).layer.getPrefix ( )
604                + ",.*," + network.experiment.recorder.vectorUnit.get ( vID )
605                .coms.get ( cID ).layer.getSuffix ( ) + "$" ) )
606            {
607              // int [] xy  = network.pas.ls.celllayer_cordinate(
608              // spike.from,network.exp.rec.vectorUnit.get(vID)
609              // .coms.get(cID).layer.getPrefix(),
610              // network.exp.rec.vectorUnit.get(vID)
611              // .coms.get(cID).layer.getSuffix());
612              
613              int id_begin=0;
614              
615              int id_mid=0;
616              
617              int id_end=0;
618              
619              id_begin = network.simulatorParser.layerStructure.celltype[
620                spike.from-network.base].indexOf(',',0);
621              
622              id_mid = network.simulatorParser.layerStructure.celltype[
623                spike.from-network.base].indexOf(',',id_begin+1);
624              
625              id_end = network.simulatorParser.layerStructure.celltype[
626                spike.from-network.base].indexOf(',',id_mid+1);
627              
628              String xy_x = network.simulatorParser.layerStructure.celltype[
629                spike.from-network.base].substring(id_begin+1,id_mid);
630              
631              String xy_y = network.simulatorParser.layerStructure.celltype[
632                spike.from-network.base].substring(id_mid+1,id_end);
633
634              final int  binIndex = ( int )
635                ( spike.time / network.experiment.recorder.vectorTimeBinSize );
636              
637              Double  tmpDX = network.recorderData.vectorCounterX.get (
638                "E"+expid+"V"+vID+"B"+binIndex+"C"+xy_x+","+xy_y );
639              
640              Double tmpDY = network.recorderData.vectorCounterY.get (
641                "E"+expid+"V"+vID+"B"+binIndex+"C"+xy_x+","+xy_y );
642
643              if ( tmpDX == null )
644              {
645                network.recorderData.vectorCounterX.put (
646                  "E"+expid+"V"+vID+"B"+binIndex+"C"+xy_x+","+xy_y,
647                  tmpDX=(new Double(0.0)));
648                
649                network.recorderData.vectorCounterY.put (
650                  "E"+expid+"V"+vID+"B"+binIndex+"C"+xy_x+","+xy_y,
651                  tmpDY=(new Double(0.0)));
652              }
653
654              tmpDX = tmpDX + Math.cos ( Math.PI / 180.0
655                * ( double ) network.experiment.recorder.vectorUnit.get ( vID )
656                .coms.get ( cID ).orientation );
657              
658              tmpDY = tmpDY + Math.sin ( Math.PI / 180.0
659                * ( double ) network.experiment.recorder.vectorUnit.get ( vID )
660                .coms.get ( cID ).orientation );
661              
662              network.recorderData.vectorCounterX.put (
663                "E"+expid+"V"+vID+"B"+binIndex+"C"+xy_x+","+xy_y,
664                tmpDX );
665              
666              network.recorderData.vectorCounterY.put (
667                "E"+expid+"V"+vID+"B"+binIndex+"C"+xy_x+","+xy_y,
668                tmpDY );
669            }
670          }
671        }
672      }
673    }
674
675    /**
676     * {@inheritDoc}
677     * @see Neuron#getTHost()
678     */
679    @Override
680    public long getTHost()
681    ////////////////////////////////////////////////////////////////////////
682    {
683      return 0;
684    }
685
686    /** 
687     * set the target host id //0 means none , 1 means yes 
688     */
689    @Override
690    public void setTHost(long id)
691    ////////////////////////////////////////////////////////////////////////
692    {
693
694    }
695
696    /**
697     * {@inheritDoc}
698     * @see Neuron#realFire()
699     */
700    @Override
701    public boolean realFire()
702    ////////////////////////////////////////////////////////////////////////
703    {
704      return true;
705    }
706    
707    ////////////////////////////////////////////////////////////////////////
708    ////////////////////////////////////////////////////////////////////////
709    }