001    package cnslab.cnsnetwork;
002    
003    import java.io.Serializable;
004    import java.util.ArrayList;
005
006    import org.slf4j.Logger;
007    import org.slf4j.LoggerFactory;
008
009    /***********************************************************************
010    * The class used to record neuron activities.
011    *
012    * @version
013    *   $Date: 2012-08-04 13:43:22 -0500 (Sat, 04 Aug 2012) $
014    *   $Rev: 104 $
015    *   $Author: croft $
016    * @author
017    *   Yi Dong
018    * @author
019    *   David Wallace Croft
020    ***********************************************************************/
021    public final class  Recorder
022      implements Serializable, Transmissible
023    ////////////////////////////////////////////////////////////////////////
024    ////////////////////////////////////////////////////////////////////////
025    {
026
027    private static final Class<Recorder>
028      CLASS = Recorder.class;
029
030    private static final Logger
031      LOGGER = LoggerFactory.getLogger ( CLASS );
032    
033    private static final long  serialVersionUID = 0L;
034    
035    //
036
037    public String outputFile;
038
039    public boolean plot;
040
041    public SimulatorParser simulatorParser;
042    
043    //type 1 single unit electrode.
044    /**
045     *  Single unit array, stored the array of recorded index of neurons
046     */
047    public ArrayList<Integer>  singleUnit;
048    
049    /**
050     *  Single unit name array
051     */
052    public ArrayList<String>  suNames;
053
054    //type 2 multiunit electrode.
055    /**
056     *  Multi unit array, stored the array of recorded index of neurons
057     */
058    public ArrayList<ArrayList<Integer>>  multiUnit;
059    
060    /**
061     *  Multi unit array, stored the array of recorded neuron names
062     */
063    public ArrayList<ArrayList<String>>  neuronNames;
064    
065    /**
066     *  Multi unit recorder names 
067     */
068    public ArrayList<String>  multiNames;
069    
070    /**
071     *  time resolution
072     */
073    public double timeBinSize; 
074
075    //type 3a field electrode. 
076    public ArrayList<Layer>  fieldEle;
077    
078    public ArrayList<String>  fieldNames;
079    
080    public double fieldTimeBinSize; 
081
082    //type 3b vector electrode.
083    public ArrayList<VComponents>  vectorUnit;
084    
085    public ArrayList<String>  vectorNames;
086    
087    public double vectorTimeBinSize;
088
089    //type 4 curr and memV intracellular electrode.
090    /**
091     * Intracelluar electrodes, pool the inner arraylist of neurons info
092     * together
093     */
094    public ArrayList<ArrayList<Integer>> intraEle;
095    
096    /**
097     * Intracelluar electrodes, the current channels that needs to be
098     * recorded.
099     */
100    public ArrayList<ArrayList<Integer>> currChannel;
101    
102    public ArrayList<String> intraNames;
103    
104    public double intraTimeBinSize;
105
106    ////////////////////////////////////////////////////////////////////////
107    // constructor methods
108    ////////////////////////////////////////////////////////////////////////
109    
110    public  Recorder (
111      final SimulatorParser  simulatorParser,
112      final boolean          plot )
113    ////////////////////////////////////////////////////////////////////////
114    {
115      this.simulatorParser = simulatorParser;
116      
117      this.plot = plot;
118      
119      singleUnit = new ArrayList<Integer> ( );
120      
121      suNames = new ArrayList<String> ( );
122
123      multiUnit = new ArrayList< ArrayList<Integer> >();
124      neuronNames = new ArrayList< ArrayList<String> >();
125      multiNames = new ArrayList< String >();
126
127      fieldEle = new ArrayList< Layer >();
128      fieldNames = new  ArrayList< String >();
129
130      vectorUnit = new ArrayList< VComponents >();
131      vectorNames = new ArrayList< String > ();
132
133      intraEle = new ArrayList< ArrayList<Integer> >();
134      currChannel = new ArrayList< ArrayList<Integer> >();
135      intraNames = new  ArrayList< String >();
136      outputFile="";
137    }
138
139    ////////////////////////////////////////////////////////////////////////
140    ////////////////////////////////////////////////////////////////////////
141    
142    public int  intraIndex ( final int  neuron )
143    ////////////////////////////////////////////////////////////////////////
144    {
145      for ( int  i = 0; i < intraEle.size ( ); i++ )
146      {
147        for ( int  j = 0; j < intraEle.get ( i ).size ( ); j++ )
148        {
149          if ( intraEle.get ( i ).get ( j ).intValue ( ) == neuron )
150          {
151            return i;
152          }
153        }
154      }
155      
156      throw new RuntimeException ( "recorded wrong cell" );
157    }
158
159    public int [ ]  intraNeurons ( )
160    ////////////////////////////////////////////////////////////////////////
161    {
162      ArrayList<Integer> allNeurons = new ArrayList<Integer>();
163      
164      for(int i =0 ; i< intraEle.size(); i++)
165      {
166        allNeurons.addAll(intraEle.get(i));
167      }
168      
169      int [] tmp = new int[allNeurons.size()];
170      
171      int i=0;
172      
173      for( int x : allNeurons)
174      {
175        tmp[i] = x;
176        
177        i++;
178      }
179      
180      return tmp;
181    }
182
183    public VComponents addComs()
184    ////////////////////////////////////////////////////////////////////////
185    {
186      VComponents vs;
187      vectorUnit.add(vs=new VComponents());
188      return vs;
189    }
190
191    /***********************************************************************
192    * Set the layer of neurons which needs to be recorded.
193    * 
194    * @param layer
195    ***********************************************************************/
196    public void setLayerNeurons(Layer layer, int hostId)
197    ////////////////////////////////////////////////////////////////////////
198    {
199      int xTotal=0;           
200      int yTotal=0;
201      int xstep=0;
202      int ystep=0;
203
204      int xMul = layer.getMultiplierX();
205      int yMul = layer.getMultiplierY();
206
207      if(xMul < 0 )
208      {           
209        xTotal=simulatorParser.xEdgeLength;
210        xstep=-xMul;
211      }
212      else
213      {       
214        xTotal=simulatorParser.xEdgeLength*xMul;
215        xstep=1;
216      } 
217      if(yMul < 0 )
218      {       
219        yTotal=simulatorParser.yEdgeLength;
220        ystep=-yMul;
221      }
222      else
223      {       
224        yTotal=simulatorParser.yEdgeLength*yMul;
225        ystep=1;
226      }
227
228      for( int x = 0; x< xTotal; x+=xstep)
229      {
230        for(int y = 0; y< yTotal; y+=ystep)
231        {
232          // String neu
233          //   = layer.getPrefix()+","+x+","+y+","+layer.getSuffix();
234
235          int  id = simulatorParser.layerStructure.cellmap_slow (
236            layer.getPrefix(),
237            layer.getSuffix(),x,
238            y);
239          
240          if(id!=-1)
241          {
242            if ( FunUtil.hostId (
243              simulatorParser.layerStructure.nodeEndIndices, id )
244              == hostId )
245            {
246              simulatorParser.layerStructure.neurons [
247                id - simulatorParser.layerStructure.base ]
248                  .setRecord ( true );
249            }
250          }
251          else
252          {
253            // throw new RuntimeException("not in the grid");
254          }
255        }
256      }
257    }
258
259    /***********************************************************************
260    * Set the layer of neurons which needs to be recorded.
261    ***********************************************************************/
262    public void  setLayerNeurons ( final Layer  layer )
263    ////////////////////////////////////////////////////////////////////////
264    {
265      int xTotal=0;           
266      int yTotal=0;
267      int xstep=0;
268      int ystep=0;
269
270      int xMul = layer.getMultiplierX();
271      int yMul = layer.getMultiplierY();
272
273      if(xMul < 0 )
274      {           
275        xTotal=simulatorParser.xEdgeLength;
276        xstep=-xMul;
277      }
278      else
279      {       
280        xTotal=simulatorParser.xEdgeLength*xMul;
281        xstep=1;
282      } 
283      if(yMul < 0 )
284      {       
285        yTotal=simulatorParser.yEdgeLength;
286        ystep=-yMul;
287      }
288      else
289      {       
290        yTotal=simulatorParser.yEdgeLength*yMul;
291        ystep=1;
292      }
293
294      for( int x = 0; x< xTotal; x+=xstep)
295      {
296        for(int y = 0; y< yTotal; y+=ystep)
297        {
298          // String neu
299          //   = layer.getPrefix()+","+x+","+y+","+layer.getSuffix();
300
301          //        if(pas.ls.cellmap.containsKey(neu))
302          //        {
303          
304          int id;
305          
306          id = simulatorParser.layerStructure.cellmap_slow (
307            layer.getPrefix(),layer.getSuffix(),x,y );
308          
309          if(simulatorParser.layerStructure.neurons != null)
310          {
311            simulatorParser.layerStructure.neurons[
312              id - simulatorParser.layerStructure.base].setRecord(true);
313          }
314          
315          //        }
316          //        else
317          //        {
318          //          throw new RuntimeException("not in the grid");
319          //        }
320
321        }
322      }
323    }
324
325    /***********************************************************************
326    * Add a line of neurons to be recorded
327    ***********************************************************************/
328    public  ArrayList<Integer>  addLine (
329      final int                x1,
330      final int                y1,
331      final int                x2,
332      final int                y2,
333      final String             pre,
334      final String             suf,
335      final ArrayList<String>  names )
336    ////////////////////////////////////////////////////////////////////////
337    {
338      final ArrayList<Integer>  out = new ArrayList<Integer> ( );
339      
340//    int xTotal=0;
341//      
342//    int yTotal=0;
343      
344      int
345        xstep = 0,
346        ystep = 0;
347      
348      final int
349        xMul = simulatorParser.layerStructure.getXmultiplier ( pre, suf ),
350        yMul = simulatorParser.layerStructure.getYmultiplier ( pre, suf );
351
352      if ( xMul < 0 )
353      {           
354//      xTotal=simulatorParser.xEdgeLength;
355        
356        xstep = -xMul;
357      }
358      else
359      {       
360//      xTotal=simulatorParser.xEdgeLength*xMul;
361        
362        xstep = 1;
363      } 
364      
365      if ( yMul < 0 )
366      {       
367//      yTotal=simulatorParser.yEdgeLength;
368        
369        ystep = -yMul;
370      }
371      else
372      {       
373//      yTotal=simulatorParser.yEdgeLength*yMul;
374        
375        ystep = 1;
376      }
377
378      if ( x1 == x2
379        && y1 == y2 ) 
380      {
381        final String  neu = pre + "," + x1 + "," + y1 + "," + suf;
382        
383        final int  id = simulatorParser.layerStructure.cellmap_slow (
384          pre,
385          suf,
386          x1,
387          y1 );
388        
389        if ( id != -1 )
390        {
391          out.add ( id );
392          
393          names.add ( neu );
394          
395          if ( simulatorParser.layerStructure.neurons != null )
396          {
397            simulatorParser.layerStructure.neurons [ id ].setRecord (
398              true );
399          }
400        }
401        
402        return out;
403      }
404
405      int  xBegin = x1 < x2 ? x1 : x2;
406      
407      if ( xBegin % xstep != 0 )
408      {
409        xBegin += xstep - xBegin % xstep;
410      }
411
412      int  yBegin = y1 < y2 ? y1 : y2;
413      
414      if ( yBegin % ystep != 0 )
415      {
416        yBegin += ystep - yBegin % ystep;
417      }
418
419      if ( Math.abs ( x1 - x2 ) < Math.abs ( y1 - y2 ) )
420      {
421        for ( int y = yBegin; y <= ( y1 > y2 ? y1 : y2 ); y += ystep )
422        {
423          final double  k = ( double ) ( x2 - x1 ) / ( double ) ( y2 - y1 );
424          
425          String neu = pre+","+ (int)(x1 + (double)(y-y1)*k)+","+y+","+suf;
426          
427          int id;
428          
429          if ( ( id = simulatorParser.layerStructure.cellmap_slow (
430            pre,
431            suf,
432            ( int ) ( x1 + ( double ) ( y - y1 ) *k ),
433            y ) ) != -1 )
434          {
435            out.add ( id );
436            
437            names.add ( neu );
438            
439            if ( simulatorParser.layerStructure.neurons != null )
440            {
441              simulatorParser.layerStructure.neurons [ id ].setRecord (
442                true );
443            }
444          }
445        }
446      }
447      else
448      {
449        for ( int  x = xBegin; x <= ( x1 > x2 ? x1 : x2 ); x += xstep )
450        {
451          final double  k = ( double ) ( y2 - y1 ) / ( double ) ( x2 - x1 );
452          
453          final String  neu
454            = pre
455            + ","
456            + x
457            + ","
458            + ( int ) ( y1 + ( double ) ( x - x1 ) * k )
459            + ","
460            + suf;
461          
462          int id;
463          
464          if ( ( id = simulatorParser.layerStructure.cellmap_slow (
465            pre,
466            suf,
467            x,
468            ( int ) ( y1 + ( double ) ( x - x1 ) * k ) ) ) !=-1 )
469          {
470            out.add ( id );
471            
472            names.add ( neu );
473            
474            if ( simulatorParser.layerStructure.neurons != null )
475            {
476              simulatorParser.layerStructure.neurons [ id ].setRecord (
477                true );
478            }
479          }
480        }
481      }
482      
483      return out;
484    }
485
486    /***********************************************************************
487    * Add a square of neurons to be recorded. 
488    * 
489    * @param x1
490    * @param y1
491    * @param x2
492    * @param y2
493    * @param pre
494    * @param suf
495    * @param names
496    ***********************************************************************/
497    public ArrayList<Integer>  addSquare (
498      final int                x1,
499      final int                y1,
500      final int                x2,
501      final int                y2,
502      final String             pre,
503      final String             suf,
504      final ArrayList<String>  names )
505    ////////////////////////////////////////////////////////////////////////
506    {
507      // LOGGER.trace ( "addSquare() entered" );
508      
509      final ArrayList<Integer>  out = new ArrayList<Integer> ( );
510      
511      int xTotal=0;
512      
513      int yTotal=0;
514      
515      int xstep=0;
516      
517      int ystep=0;
518      
519      int  xMul = simulatorParser.layerStructure.getXmultiplier(pre,suf);
520      
521      int  yMul = simulatorParser.layerStructure.getYmultiplier(pre,suf);
522
523      if(xMul < 0 )
524      {           
525        xTotal=simulatorParser.xEdgeLength;
526        
527        xstep=-xMul;
528      }
529      else
530      {       
531        xTotal=simulatorParser.xEdgeLength*xMul;
532        
533        xstep=1;
534      } 
535      
536      if(yMul < 0 )
537      {       
538        yTotal=simulatorParser.yEdgeLength;
539        
540        ystep=-yMul;
541      }
542      else
543      {       
544        yTotal=simulatorParser.yEdgeLength*yMul;
545        
546        ystep=1;
547      }
548
549      int xBegin =  (x1<x2 ? x1: x2);
550      
551      if(xBegin % xstep !=0) xBegin+= xstep - xBegin % xstep ;
552
553      int yBegin =  (y1<y2 ? y1: y2);
554      
555      if(yBegin % ystep !=0) yBegin+= ystep - yBegin % ystep ;
556
557      for( int x = xBegin  ; x <= (x1>x2?x1:x2); x+=xstep)
558      {
559        for( int y = yBegin  ; y <= (y1>y2?y1:y2); y+=ystep)
560        {
561          int id;
562          
563          if ( ( id = simulatorParser.layerStructure.cellmap_slow (
564            pre,
565            suf,
566            x,
567            y ) ) != -1 )
568          {
569            out.add(id);
570            
571            final String  neu = pre + "," + x + "," + y + "," + suf;
572
573            names.add ( neu );
574            
575            if ( simulatorParser.layerStructure.neurons != null )
576            {
577              simulatorParser.layerStructure.neurons [ id ].setRecord (
578                true );
579            }
580            
581            // LOGGER.trace ( "Recording neuron id {}", id );
582          }
583        }
584      }
585      
586      return out;
587    }
588
589    /***********************************************************************
590    * Add a line of neurons to be recorded 
591    * 
592    * @param x1
593    * @param y1
594    * @param x2
595    * @param y2
596    * @param pre
597    * @param suf
598    * @param hostId
599    * @param names
600    ***********************************************************************/
601    public ArrayList<Integer>  addLine (
602      final int                x1,
603      final int                y1,
604      final int                x2,
605      final int                y2,
606      final String             pre,
607      final String             suf,
608      final int                hostId,
609      final ArrayList<String>  names )
610    ////////////////////////////////////////////////////////////////////////
611    {
612      final ArrayList<Integer> out = new ArrayList<Integer>();
613      
614      int xTotal=0;
615      
616      int yTotal=0;
617      
618      int xstep=0;
619      
620      int ystep=0;
621      
622      int xMul=simulatorParser.layerStructure.getXmultiplier(pre,suf);
623      
624      int yMul=simulatorParser.layerStructure.getYmultiplier(pre,suf);
625
626      if(xMul < 0 )
627      {           
628        xTotal=simulatorParser.xEdgeLength;
629        
630        xstep=-xMul;
631      }
632      else
633      {       
634        xTotal=simulatorParser.xEdgeLength*xMul;
635        
636        xstep=1;
637      } 
638      
639      if(yMul < 0 )
640      {       
641        yTotal=simulatorParser.yEdgeLength;
642        
643        ystep=-yMul;
644      }
645      else
646      {       
647        yTotal=simulatorParser.yEdgeLength*yMul;
648        
649        ystep=1;
650      }
651
652      if(x1==x2 && y1==y2) 
653      {
654        String neu = pre+","+ x1+","+y1+","+suf;
655        
656        int id = simulatorParser.layerStructure.cellmap_slow(pre,suf,x1,y1);
657        
658        if(id!=-1)
659        {
660          if ( FunUtil.hostId (
661            simulatorParser.layerStructure.nodeEndIndices, id )
662            == hostId )
663          {
664            out.add(id);
665            
666            names.add(neu);
667            
668            simulatorParser.layerStructure.neurons [
669              id - simulatorParser.layerStructure.base].setRecord(true);
670          }
671        }
672        
673        return out;
674      }
675
676      int xBegin =  (x1<x2 ? x1: x2);
677      
678      if(xBegin % xstep !=0) xBegin+= xstep - xBegin % xstep ;
679
680      int yBegin =  (y1<y2 ? y1: y2);
681      
682      if(yBegin % ystep !=0) yBegin+= ystep - yBegin % ystep ;
683
684      if( Math.abs(x1-x2)<Math.abs(y1-y2))
685      {
686        for( int y = yBegin  ; y <= (y1>y2?y1:y2); y+=ystep)
687        {
688          double k=(double)(x2-x1)/(double)(y2-y1);
689          
690          String neu = pre+","+ (int)(x1 + (double)(y-y1)*k)+","+y+","+suf;
691          
692          int id;
693          
694          if ( ( id = simulatorParser.layerStructure.cellmap_slow (
695            pre,
696            suf,
697            ( int ) ( x1 + ( double ) ( y - y1 ) * k ),
698            y ) ) !=-1 )
699          {
700            if ( FunUtil.hostId (
701              simulatorParser.layerStructure.nodeEndIndices, id )
702              == hostId )
703            {
704              out.add(id);
705              
706              names.add(neu);
707              
708              simulatorParser.layerStructure.neurons[
709                id - simulatorParser.layerStructure.base].setRecord(true);
710            }
711          }
712        }
713      }
714      else
715      {
716        for( int x = xBegin  ; x <= (x1>x2?x1:x2); x+=xstep)
717        {
718          double k=(double)(y2-y1)/(double)(x2-x1);
719          
720          String neu = pre+","+ x+","+ (int)(y1 + (double)(x-x1)*k)+","+suf;
721          
722          int id;
723          
724          if ( ( id = simulatorParser.layerStructure.cellmap_slow (
725            pre,
726            suf,
727            x,
728            ( int ) ( y1 + ( double ) ( x - x1 ) * k ) ) ) !=-1 )
729          {
730            // id=pas.ls.cellmap.get(neu);
731            
732            if ( FunUtil.hostId (
733              simulatorParser.layerStructure.nodeEndIndices, id )
734              == hostId )
735            {
736              out.add(id);
737              
738              names.add(neu);
739              
740              simulatorParser.layerStructure.neurons [
741                id-simulatorParser.layerStructure.base ].setRecord ( true );
742            }
743          }
744        }
745      }
746      
747      return out;
748    }
749
750    /***********************************************************************
751    * Add a square of neurons to be recorded. 
752    * 
753    * @param x1
754    * @param y1
755    * @param x2
756    * @param y2
757    * @param pre
758    * @param suf
759    * @param hostId
760    * @param names
761    ***********************************************************************/
762    public ArrayList<Integer>  addSquare (
763      final int                x1,
764      final int                y1,
765      final int                x2,
766      final int                y2,
767      final String             pre,
768      final String             suf,
769      final int                hostId,
770      final ArrayList<String>  names )
771    ////////////////////////////////////////////////////////////////////////
772    {
773      // LOGGER.trace ( "addSquare(hostId) entered" );
774      
775      final ArrayList<Integer>  out = new ArrayList<Integer>();
776      
777      int xTotal=0;
778      
779      int yTotal=0;
780      
781      int xstep=0;
782      
783      int ystep=0;
784      
785      int xMul=simulatorParser.layerStructure.getXmultiplier(pre,suf);
786      
787      int yMul=simulatorParser.layerStructure.getYmultiplier(pre,suf);
788
789      if(xMul < 0 )
790      {           
791        xTotal=simulatorParser.xEdgeLength;
792        
793        xstep=-xMul;
794      }
795      else
796      {       
797        xTotal=simulatorParser.xEdgeLength*xMul;
798        
799        xstep=1;
800      } 
801      
802      if(yMul < 0 )
803      {       
804        yTotal=simulatorParser.yEdgeLength;
805        
806        ystep=-yMul;
807      }
808      else
809      {       
810        yTotal=simulatorParser.yEdgeLength*yMul;
811        
812        ystep=1;
813      }
814
815      int xBegin =  (x1<x2 ? x1: x2);
816      
817      if(xBegin % xstep !=0) xBegin+= xstep - xBegin % xstep ;
818
819      int yBegin =  (y1<y2 ? y1: y2);
820      
821      if(yBegin % ystep !=0) yBegin+= ystep - yBegin % ystep ;
822
823      for( int x = xBegin  ; x <= (x1>x2?x1:x2); x+=xstep)
824      {
825        for( int y = yBegin  ; y <= (y1>y2?y1:y2); y+=ystep)
826        {
827          String neu = pre+","+ x+","+y+","+suf;
828
829          int id = simulatorParser.layerStructure.cellmap_slow(pre,suf,x,y);
830          
831          if(id!=-1)
832          {
833            if ( FunUtil.hostId (
834              simulatorParser.layerStructure.nodeEndIndices, id )
835              == hostId )
836            {
837              out.add(id);
838              
839              names.add(neu);
840              
841              simulatorParser.layerStructure.neurons[
842                id-simulatorParser.layerStructure.base].setRecord(true);
843            }
844          }
845        }
846      }
847      
848      return out;
849    }
850
851    ////////////////////////////////////////////////////////////////////////
852    ////////////////////////////////////////////////////////////////////////
853    }