001        package com.croftsoft.apps.neuro;
002        
003        import java.util.*;
004    
005        import com.croftsoft.core.ai.neuro.Channel;
006        import com.croftsoft.core.ai.neuro.ChannelMut;
007        import com.croftsoft.core.ai.neuro.HhNeuron;
008        import com.croftsoft.core.ai.neuro.imp.ChannelMutImp;
009        import com.croftsoft.core.ai.neuro.imp.HhNeuronImp;
010        import com.croftsoft.core.lang.*;
011        import com.croftsoft.core.lang.lifecycle.Startable;
012        import com.croftsoft.core.lang.lifecycle.Updatable;
013        import com.croftsoft.core.math.MathConstants;
014        import com.croftsoft.core.sim.DeltaClock;
015        import com.croftsoft.core.sim.DeltaClockImp;
016        import com.croftsoft.core.sim.SimLib;
017        import com.croftsoft.core.util.mail.Mail;
018        import com.croftsoft.core.util.seq.ListSeq;
019        import com.croftsoft.core.util.seq.Seq;
020    
021        /***********************************************************************
022        * Model.
023        * 
024        * Maintains program state.
025        * 
026        * @version
027        *   $Id: NeuroModelImp.java,v 1.18 2008/08/30 01:37:30 croft Exp $
028        * @since
029        *   2008-08-17
030        * @author
031        *   <a href="https://www.croftsoft.com/">David Wallace Croft</a>
032        ***********************************************************************/
033    
034        public final class  NeuroModelImp
035          implements NeuroModel, Startable, Updatable
036        ////////////////////////////////////////////////////////////////////////
037        ////////////////////////////////////////////////////////////////////////
038        {
039          
040        private static final long
041          TIME_INTERVAL_NANOS = 100 * MathConstants.NANOSECONDS_PER_MICROSECOND,
042          UPDATES_PER_UPDATE  = 10,
043          DELTA_TIME_NANOS    = TIME_INTERVAL_NANOS / UPDATES_PER_UPDATE;
044           
045        private static final double
046          DELTA_TIME
047            = MathConstants.SECONDS_PER_NANOSECOND * DELTA_TIME_NANOS,
048          TIME_INTERVAL
049            = MathConstants.SECONDS_PER_NANOSECOND * TIME_INTERVAL_NANOS;
050        
051        private static final double
052          CHANNEL_CONDUCTANCE = 2.11e-10;
053        
054        // private final instance variables
055          
056        private final Mail<NeuroMessage>  mail;
057        
058        private final ChannelMut          channelMut;
059        
060        private final DeltaClock          deltaClock;
061           
062        private final HhNeuronImp         hhNeuronImp;
063         
064        // model state instance variables
065         
066        private double [ ]  membraneVoltageTimeSeries;
067         
068        private double  timeMin;
069        
070        private int
071          membraneVoltageLength,
072          offset;
073        
074        private long  timeStep;
075         
076        private boolean  simulationRunning = true;
077        
078        /** Number of spikes since the previous update. */
079        private int  spikeCount;
080        
081        ////////////////////////////////////////////////////////////////////////
082        ////////////////////////////////////////////////////////////////////////
083         
084        public  NeuroModelImp (
085          final NeuroConfig         neuroConfig,
086          final Mail<NeuroMessage>  mail )
087        ////////////////////////////////////////////////////////////////////////
088        {
089          NullArgumentException.checkArgs (
090            neuroConfig,
091            this.mail = mail );
092          
093          final List<Channel>  channelList = new ArrayList<Channel> ( );
094          
095          channelMut = new ChannelMutImp (
096            CHANNEL_CONDUCTANCE, HhNeuronImp.SODIUM_REVERSAL_POTENTIAL, false );
097          
098          channelList.add ( channelMut );
099          
100          final Seq<Channel>  channelSeq = new ListSeq<Channel> ( channelList );
101          
102          System.out.println ( "DELTA_TIME = " + DELTA_TIME );      
103          
104          System.out.println ( "TIME_INTERVAL = " + TIME_INTERVAL );
105          
106          deltaClock = new DeltaClockImp ( DELTA_TIME );
107          
108          hhNeuronImp = new HhNeuronImp ( channelSeq, deltaClock );
109          
110          membraneVoltageLength = 1000;
111          
112          membraneVoltageTimeSeries = new double [ membraneVoltageLength ];
113          
114          final double  membraneVoltage = hhNeuronImp.getMembraneVoltage ( );
115          
116          for ( int  i = 0; i < membraneVoltageLength; i++ )
117          {
118            membraneVoltageTimeSeries [ i ] = membraneVoltage;  
119          }
120        }
121         
122        ////////////////////////////////////////////////////////////////////////
123        // interface Accessor methods
124        ////////////////////////////////////////////////////////////////////////
125        
126        public HhNeuron  getHhNeuron ( )
127        ////////////////////////////////////////////////////////////////////////
128        {
129          return hhNeuronImp;
130        }
131         
132        public double  getMembraneVoltage ( final int  index )
133        ////////////////////////////////////////////////////////////////////////
134        {
135          return membraneVoltageTimeSeries [
136            ( offset + index ) % membraneVoltageLength ];
137        }
138         
139        public int  getMembraneVoltageLength ( )
140        ////////////////////////////////////////////////////////////////////////
141        {
142          return membraneVoltageLength;
143        }
144        
145        public double  getMembraneVoltageMax ( )
146        ////////////////////////////////////////////////////////////////////////
147        {
148          return 0.100;
149        }
150        
151        public int  getSpikeCount ( )
152        ////////////////////////////////////////////////////////////////////////
153        {
154          return spikeCount;
155        }
156        
157        public double  getTimeInterval ( )
158        ////////////////////////////////////////////////////////////////////////
159        {
160          return TIME_INTERVAL;
161        }
162        
163        public double  getTimeMin ( ) { return timeMin; }
164        
165        ////////////////////////////////////////////////////////////////////////
166        // lifecycle methods
167        ////////////////////////////////////////////////////////////////////////
168         
169        public void  start ( )
170        ////////////////////////////////////////////////////////////////////////
171        {
172          // empty
173        }
174         
175        public void  update ( )
176        ////////////////////////////////////////////////////////////////////////
177        {
178          final int  size = mail.size ( );
179          
180          for ( int  i = 0; i < size; i++ )
181          {      
182            final NeuroMessage  neuroMessage = mail.get ( i );
183           
184            final NeuroMessage.Type  type = neuroMessage.getType ( );
185             
186            switch ( type )
187            {
188              case TOGGLE_CHANNEL_REQUEST:
189                
190                channelMut.setOpen ( !channelMut.isOpen ( ) );
191                
192                break;
193                
194              case TOGGLE_PAUSE_REQUEST:
195                
196                simulationRunning = !simulationRunning;
197                
198                break;
199                
200              default:
201                
202                // ignore
203            }
204          }
205          
206          if ( simulationRunning )
207          {
208            spikeCount = 0;
209    
210            for ( int  i = 0; i < UPDATES_PER_UPDATE; i++ )
211            {      
212              SimLib.update ( hhNeuronImp );
213    
214              if ( hhNeuronImp.isSpiking ( ) )
215              {
216                spikeCount++;
217              }
218            }
219           
220            final double  membraneVoltage = hhNeuronImp.getMembraneVoltage ( );
221            
222            membraneVoltageTimeSeries [ offset ] = membraneVoltage;
223            
224            offset = ( offset + 1 ) % membraneVoltageLength;
225            
226            timeStep++;
227            
228            timeMin = ( timeStep - membraneVoltageLength ) * TIME_INTERVAL;
229          }
230        }
231         
232        ////////////////////////////////////////////////////////////////////////
233        ////////////////////////////////////////////////////////////////////////
234        }