MOOSE - Multiscale Object Oriented Simulation Environment
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
Spine.cpp
Go to the documentation of this file.
1 /**********************************************************************
2 ** This program is part of 'MOOSE', the
3 ** Messaging Object Oriented Simulation Environment.
4 ** Copyright (C) 2003-2015 Upinder S. Bhalla. and NCBS
5 ** It is made available under the terms of the
6 ** GNU Lesser General Public License version 2.1
7 ** See the file COPYING.LIB for the full notice.
8 **********************************************************************/
9 
10 #include "header.h"
11 #include "ElementValueFinfo.h"
12 #include "../utility/Vec.h"
13 #include "SwcSegment.h"
14 #include "Spine.h"
15 #include "Neuron.h"
16 
18 {
20  // Field Definitions
22  static ElementValueFinfo< Spine, double > shaftLength (
23  "shaftLength",
24  "Length of spine shaft.",
27  );
28  static ElementValueFinfo< Spine, double > shaftDiameter (
29  "shaftDiameter",
30  "Diameter of spine shaft.",
33  );
34  static ElementValueFinfo< Spine, double > headLength (
35  "headLength",
36  "Length of spine head.",
39  );
40  static ElementValueFinfo< Spine, double > headDiameter (
41  "headDiameter",
42  "Diameter of spine head, and also the diameter of the PSD. ",
45  );
46  static ElementValueFinfo< Spine, double > psdArea (
47  "psdArea",
48  "Area of the Post synaptic density, PSD. This is the same as "
49  "the cross-section area of spine head, perpendicular to shaft. "
50  "Assumes that the head is a cylinder and that its length "
51  "does not change. \n"
52  "This is useful to scale # of surface molecules on the PSD. ",
55  );
56  static ElementValueFinfo< Spine, double > headVolume (
57  "headVolume",
58  "Volume of spine head, treating it as a cylinder. When this is "
59  "scaled by the user, both the diameter and the length of the "
60  "spine head scale by the cube root of the ratio to the "
61  "previous volume. The diameter of the PSD is pegged to the "
62  "diameter of the spine head. \n"
63  "This is useful to scale total # of molecules in the head. ",
66  );
67  static ElementValueFinfo< Spine, double > totalLength (
68  "totalLength",
69  "Length of entire spine. Scales both the length of the shaft "
70  "and of the spine head, without changing any of the diameters.",
73  );
75  "angle",
76  "Angle of spine around shaft. Longitude. 0 is away from soma. "
77  "Not yet implemented. ",
80  );
81  static ElementValueFinfo< Spine, double > inclination (
82  "inclination",
83  "inclination of spine with ref to shaft. Normal is 0. "
84  "Not yet activated. ",
87  );
88  static ElementValueFinfo< Spine, double > minimumSize (
89  "minimumSize",
90  "Sanity check for the smallest permitted length or diameter. "
91  "Used to avoid unreasonable physiological values, which "
92  "are all too easily reached when simulations run unbounded. "
93  "Defaults to 20 nanometers, which is somewhat smaller than the "
94  "30 nm size estimated for synaptic vesicles. "
95  "Does *not* retroactively resize anything. ",
98  );
99  static ElementValueFinfo< Spine, double > maximumSize (
100  "maximumSize",
101  "Sanity check for the largest permitted length or diameter. "
102  "Used to avoid unreasonable physiological values, which "
103  "are all too easily reached when simulations run unbounded. "
104  "Defaults to 10 microns, which is a pretty monstrous spine. "
105  "Does *not* retroactively resize anything. ",
108  );
109 
111  // MsgDest Definitions
114  // Shared definitions
116 
118  // SrcFinfo Definitions
120 
121  static Finfo* spineFinfos[] = {
122  &shaftLength, // Value
123  &shaftDiameter, // Value
124  &headLength, // Value
125  &headDiameter, // Value
126  &psdArea, // Value
127  &headVolume, // Value
128  &totalLength, // Value
129  };
130 
131  static string doc[] =
132  {
133  "Name", "Spine",
134  "Author", "Upi Bhalla",
135  "Description", "Spine wrapper, used to change its morphology "
136  "typically by a message from an adaptor. The Spine class "
137  "takes care of a lot of resultant scaling to electrical, "
138  "chemical, and diffusion properties. "
139  };
140  static Dinfo< Spine > dinfo;
141  static Cinfo spineCinfo (
142  "Spine",
144  spineFinfos,
145  sizeof( spineFinfos ) / sizeof ( Finfo* ),
146  &dinfo,
147  doc,
148  sizeof(doc)/sizeof( string ),
149  true // This IS a FieldElement, not be be created directly.
150  );
151 
152  return &spineCinfo;
153 }
154 
156 // Class definitions
159 
161  : parent_( 0 ),
162  minimumSize_( 20.0e-9 ), // 20 nanometres
163  maximumSize_( 10.0e-6 ) // 10 microns
164 {;}
165 
166 Spine::Spine( const Neuron* parent )
167  : parent_( parent ),
168  minimumSize_( 20.0e-9 ), // 20 nanometres
169  maximumSize_( 10.0e-6 ) // 10 microns
170 {;}
171 
173 // Field Definitions
175 
176 double Spine::getShaftLength( const Eref& e ) const
177 {
178  const vector< Id >& sl = parent_->spineIds( e.fieldIndex() );
179  if ( sl.size() > 0 &&
180  sl[0].element()->cinfo()->isA( "CompartmentBase" ) )
181  return Field< double >::get( sl[0], "length" );
182  return 0.0;
183 }
184 
185 void Spine::setShaftLength( const Eref& e, double len )
186 {
187  if ( len < minimumSize_ )
188  len = minimumSize_;
189  else if ( len > maximumSize_ )
190  len = maximumSize_;
191  vector< Id > sl = parent_->spineIds( e.fieldIndex() );
192  if ( sl.size() > 1 &&
193  sl[0].element()->cinfo()->isA( "CompartmentBase" ) )
194  {
195  double origDia = Field< double >::get( sl[0], "diameter" );
196  double dx = Field< double >::get( sl[0], "x" );
197  double dy = Field< double >::get( sl[0], "y" );
198  double dz = Field< double >::get( sl[0], "z" );
200  sl[0], "setGeomAndElec", len, origDia );
201 
202  dx = Field< double >::get( sl[0], "x" ) - dx;
203  dy = Field< double >::get( sl[0], "y" ) - dy;
204  dz = Field< double >::get( sl[0], "z" ) - dz;
205 
206  SetGet3< double, double, double >::set( sl[1], "displace",
207  dx, dy, dz );
208  // Here we've set the electrical and geometrical stuff. Now to
209  // do the diffusion. Chem doesn't come into the picture for the
210  // spine shaft.
211  // Assume the scaleDiffusion function propagates changes into the
212  // VoxelJunctions used by the Dsolve.
213  parent_->scaleShaftDiffusion( e.fieldIndex(), len, origDia );
214  }
215 }
216 
217 double Spine::getShaftDiameter( const Eref& e ) const
218 {
219  vector< Id > sl = parent_->spineIds( e.fieldIndex() );
220  if ( sl.size() > 0 &&
221  sl[0].element()->cinfo()->isA( "CompartmentBase" ) )
222  return Field< double >::get( sl[0], "diameter" );
223  return 0.0;
224 }
225 
226 void Spine::setShaftDiameter( const Eref& e, double dia )
227 {
228  if ( dia < minimumSize_ )
229  dia = minimumSize_;
230  else if ( dia > maximumSize_ )
231  dia = maximumSize_;
232 
233  vector< Id > sl = parent_->spineIds( e.fieldIndex() );
234  if ( sl.size() > 1 &&
235  sl[0].element()->cinfo()->isA( "CompartmentBase") )
236  {
237  double origLen = Field< double >::get( sl[0], "length" );
239  sl[0], "setGeomAndElec", origLen, dia );
240  // Dia is changing, leave the coords alone.
241  parent_->scaleShaftDiffusion( e.fieldIndex(), origLen, dia );
242  }
243 }
244 
245 double Spine::getHeadLength( const Eref& e ) const
246 {
247  vector< Id > sl = parent_->spineIds( e.fieldIndex() );
248  if ( sl.size() > 1 &&
249  sl[1].element()->cinfo()->isA( "CompartmentBase" ) )
250  return Field< double >::get( sl[1], "length" );
251  return 0.0;
252 }
253 
254 void Spine::setHeadLength( const Eref& e, double len )
255 {
256  if ( len < minimumSize_ )
257  len = minimumSize_;
258  else if ( len > maximumSize_ )
259  len = maximumSize_;
260 
261  vector< Id > sl = parent_->spineIds( e.fieldIndex() );
262  if ( sl.size() > 1 &&
263  sl[1].element()->cinfo()->isA( "CompartmentBase") )
264  {
265  double origDia = Field< double >::get( sl[1], "diameter" );
266  double origLen = Field< double >::get( sl[1], "length" );
268  sl[1], "setGeomAndElec", len, origDia );
269  // Here we've set the electrical and geometrical stuff. Now to
270  // do the diffusion.
271  // Assume the scaleDiffusion function propagates changes into the
272  // VoxelJunctions used by the Dsolve.
273  parent_->scaleHeadDiffusion( e.fieldIndex(), len, origDia );
274  // Now scale the chem stuff. The PSD mesh is assumed to scale only
275  // with top surface area of head, so it is not affected here.
276  parent_->scaleBufAndRates( e.fieldIndex(), len/origLen, 1.0 );
277  }
278 }
279 
280 double Spine::getHeadDiameter( const Eref& e ) const
281 {
282  vector< Id > sl = parent_->spineIds( e.fieldIndex() );
283  if ( sl.size() > 1 &&
284  sl[1].element()->cinfo()->isA( "CompartmentBase" ) )
285  return Field< double >::get( sl[1], "diameter" );
286  return 0.0;
287 }
288 
289 void Spine::setHeadDiameter( const Eref& e, double dia )
290 {
291  if ( dia < minimumSize_ )
292  dia = minimumSize_;
293  else if ( dia > maximumSize_ )
294  dia = maximumSize_;
295  vector< Id > sl = parent_->spineIds( e.fieldIndex() );
296  if ( sl.size() > 1 &&
297  sl[0].element()->cinfo()->isA( "CompartmentBase") )
298  {
299  double origLen = Field< double >::get( sl[1], "length" );
300  double origDia = Field< double >::get( sl[1], "diameter" );
302  sl[1], "setGeomAndElec", origLen, dia );
303  parent_->scaleHeadDiffusion( e.fieldIndex(), origLen, dia );
305  1.0, dia/origDia );
306  }
307 }
308 
309 double Spine::getPsdArea( const Eref& e ) const
310 {
311  double ret = getHeadDiameter( e );
312  return ret * ret * PI / 4.0;
313 }
314 
315 void Spine::setPsdArea( const Eref& e, double area )
316 {
317  if ( area < 0 ) {
319  } else {
320  double dia = 2.0 * sqrt( area / PI );
321  setHeadDiameter( e, dia );
322  }
323 }
324 
325 double Spine::getHeadVolume( const Eref& e ) const
326 {
327  double dia = getHeadDiameter( e );
328  return getHeadLength( e ) * dia * dia * PI / 4.0;
329 }
330 
331 // Handle like a cylinder of equal length and dia. vol = PI*dia*dia*len/4
332 void Spine::setHeadVolume( const Eref& e, double volume )
333 {
334  if ( volume < 0 )
335  volume = 0.0;
336  double dia = pow( volume * 4.0 / PI, 1.0/3.0 );
337  if ( dia < minimumSize_ )
338  volume = pow( minimumSize_, 3.0 ) * PI / 4.0;
339  else if ( dia > maximumSize_ )
340  volume = pow( maximumSize_, 3.0 ) * PI / 4.0;
341 
342  vector< Id > sl = parent_->spineIds( e.fieldIndex() );
343  if ( sl.size() > 1 &&
344  sl[0].element()->cinfo()->isA( "CompartmentBase") )
345  {
346  double origLen = Field< double >::get( sl[1], "length" );
347  double origDia = Field< double >::get( sl[1], "diameter" );
348  double oldVolume = origLen * origDia * origDia * PI / 4.0;
349  double ratio = pow( volume / oldVolume, 1.0/3.0 );
350 
352  sl[1], "setGeomAndElec", origLen * ratio, origDia * ratio );
353  parent_->scaleHeadDiffusion( e.fieldIndex(), origLen * ratio, origDia * ratio );
354  parent_->scaleBufAndRates( e.fieldIndex(), ratio, ratio );
355  }
356 }
357 
358 double Spine::getTotalLength( const Eref& e ) const
359 {
360  return getHeadLength( e ) + getShaftLength( e );
361 }
362 
363 void Spine::setTotalLength( const Eref& e, double len )
364 {
365  double shaftLen = getShaftLength( e );
366  double headLen = getHeadLength( e );
367  double totLen = shaftLen + headLen;
368 
369  shaftLen *= len / totLen;
370  headLen *= len / totLen;
371 
373  if ( shaftLen < minimumSize_ || shaftLen > maximumSize_ ||
374  headLen < minimumSize_ || headLen > maximumSize_ )
375  return;
376 
377  setShaftLength( e, shaftLen );
378  setHeadLength( e, headLen );
379 }
380 
381 double Spine::getAngle( const Eref& e ) const
382 {
383  return 0;
384 }
385 
386 void Spine::setAngle( const Eref& e, double theta )
387 {
388  ;
389 }
390 
391 double Spine::getInclination( const Eref& e ) const
392 {
393  return 0;
394 }
395 
396 void Spine::setInclination( const Eref& e, double theta )
397 {
398  ;
399 }
400 
401 double Spine::getMinimumSize( const Eref& e ) const
402 {
403  return minimumSize_;
404 }
405 
406 void Spine::setMinimumSize( const Eref& e, double len )
407 {
408  minimumSize_ = len;
409 }
410 
411 double Spine::getMaximumSize( const Eref& e ) const
412 {
413  return maximumSize_;
414 }
415 
416 void Spine::setMaximumSize( const Eref& e, double len )
417 {
418  maximumSize_ = len;
419 }
static const Cinfo * spineCinfo
Definition: Spine.cpp:158
const Neuron * parent_
Definition: Spine.h:78
double getHeadDiameter(const Eref &e) const
Definition: Spine.cpp:280
Definition: Neuron.h:18
void setMaximumSize(const Eref &e, double len)
Definition: Spine.cpp:416
void scaleHeadDiffusion(unsigned int spineNum, double len, double dia) const
Scale the diffusion parameters due to a change in the head dimensions.
Definition: Neuron.cpp:2106
double getHeadVolume(const Eref &e) const
Definition: Spine.cpp:325
Definition: Dinfo.h:60
Definition: SetGet.h:236
double getInclination(const Eref &e) const
Definition: Spine.cpp:391
Spine()
Definition: Spine.cpp:160
double getMinimumSize(const Eref &e) const
Definition: Spine.cpp:401
double getShaftDiameter(const Eref &e) const
Definition: Spine.cpp:217
unsigned int fieldIndex() const
Definition: Eref.h:61
void setShaftLength(const Eref &e, double len)
Definition: Spine.cpp:185
void setMinimumSize(const Eref &e, double len)
Definition: Spine.cpp:406
const vector< Id > & spineIds(unsigned int index) const
Definition: Neuron.cpp:2047
void setAngle(const Eref &e, double theta)
Definition: Spine.cpp:386
void setInclination(const Eref &e, double phi)
Definition: Spine.cpp:396
static const Cinfo * initCinfo()
Definition: Spine.cpp:17
double maximumSize_
Definition: Spine.h:86
void setPsdArea(const Eref &e, double area)
Definition: Spine.cpp:315
void scaleShaftDiffusion(unsigned int spineNum, double len, double dia) const
Scale the diffusion parameters due to a change in the shaft dimensions.
Definition: Neuron.cpp:2094
void setShaftDiameter(const Eref &e, double dia)
Definition: Spine.cpp:226
Definition: Eref.h:26
double getAngle(const Eref &e) const
Definition: Spine.cpp:381
double getTotalLength(const Eref &e) const
Definition: Spine.cpp:358
void setHeadLength(const Eref &e, double len)
Definition: Spine.cpp:254
double getPsdArea(const Eref &e) const
Definition: Spine.cpp:309
double getMaximumSize(const Eref &e) const
Definition: Spine.cpp:411
static bool set(const ObjId &dest, const string &field, A1 arg1, A2 arg2, A3 arg3)
Definition: SetGet.h:626
const double PI
Definition: consts.cpp:12
double minimumSize_
Definition: Spine.h:85
static A get(const ObjId &dest, const string &field)
Definition: SetGet.h:284
static const Cinfo * initCinfo()
Definition: Neutral.cpp:16
void setHeadVolume(const Eref &e, double vol)
Definition: Spine.cpp:332
void setHeadDiameter(const Eref &e, double dia)
Definition: Spine.cpp:289
double getShaftLength(const Eref &e) const
Definition: Spine.cpp:176
void scaleBufAndRates(unsigned int spineNum, double lenScale, double diaScale) const
Definition: Neuron.cpp:2055
Definition: Cinfo.h:18
void setTotalLength(const Eref &e, double len)
Definition: Spine.cpp:363
double getHeadLength(const Eref &e) const
Definition: Spine.cpp:245
Definition: Finfo.h:12
static bool set(const ObjId &dest, const string &field, A1 arg1, A2 arg2)
Definition: SetGet.h:365