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 }