summaryrefslogtreecommitdiff
path: root/axon_direction_model.hh
blob: fe4e0797f48698cb21582d714354f0bb4646a24f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
/*
  © Copyright 2008 Randal A. Koene <randalk@netmorph.org>
  
  With design assistance from J. van Pelt & A. van Ooyen, and support
  from the Netherlands Organization for Scientific Research (NWO)
  Program Computational Life Sciences grant CLS2003 (635.100.005) and
  from the EC Marie Curie Research and Training Network (RTN)
  NEURoVERS-it 019247.

  This file is part of NETMORPH.

  NETMORPH is free software: you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation, either version 3 of the License, or
  (at your option) any later version.

  NETMORPH is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with NETMORPH.  If not, see <http://www.gnu.org/licenses/>.
*/
// axon_direction_model.hh
// Randal A. Koene, 20051021

/* Documentation:
   This implements base and derived classes for models of axon direction during
   network development that are based on curvature statistics (rather than
   causal hypotheses about environmental interactions).
   The base model provides a reference to the history of an axon's growth.

   An obvious place in which to link to an axon direction model is in the
   terminal segment objects of axons.
 */

#ifndef __AXON_DIRECTION_MODEL_HH
#define __AXON_DIRECTION_MODEL_HH

#include "templates.hh"
//#include "fibre_structure.hh"
#include "spatial.hh"
#include "Command_Line_Parameters.hh"
#include "global.hh"

#ifndef __FIBRE_STRUCTURE_HH
class fibre_segment;
class terminal_segment;
#endif
#ifndef __NEURON_HH
class neuron;
#endif
class direction_history_selection;

// When speed is prioretized over space then histories contain actual
// data with which a direction can be calculated. Otherwise, histories
// are largely restricted to pointers to the fibre segment directly
// after the last branch and the number of segments to skip (i.e. not
// to include during calculations), with which the necessary data can
// be computed.
// [***NOTE] This is now defined in the Makefile.
//#define ADM_PRIORITIZE_SPEED_OVER_SPACE

enum direction_history_selection_type { no_dhs, random_truncation_dhs };

class general_direction_model_parameters_interface: public CLP_Modifiable {
  // This is used to set and provide general (default) parameter settings
  // used in functions of direction models and related models such as
  // direction history selection models.
public:
  general_direction_model_parameters_interface(): direction_history_selection_model(no_dhs), random_truncation_dh_probability(0.1), random_truncation_dh_minfraction(0.5), random_truncation_dh_maxfraction(1.0) {}
  virtual ~general_direction_model_parameters_interface() {}
  virtual void parse_CLP(Command_Line_Parameters & clp);
  virtual String report_parameters();
  direction_history_selection_type direction_history_selection_model;
  double random_truncation_dh_probability;
  double random_truncation_dh_minfraction;
  double random_truncation_dh_maxfraction;
};

extern general_direction_model_parameters_interface general_direction_model_parameters;

class axon_direction_history {
  friend class random_truncation_dh_selection;
  // This is a utility class that can autonomously handle data in a preferred
  // manner. Derivatives may make use of arrays, linked lists, or may even
  // calculate required data on-demand.
  // The history tracks those parts of a fibre that may affect the direction
  // of growth (in the statistical/phenomenological model). The intention is
  // that elements dropped from the history are not recovered. The actual
  // elements that are taken into account and their weighting depends on the
  // model used to compute the effect of the history on direction of growth,
  // which may involve the entire history, a certain number of turns, a
  // certain distance from the growth cone, etc.
  // Whether random or non-random events cause elements to be dropped from
  // the history, or whether they only affect the portion or weighting of
  // elements taken into account determines if a shortening of the history
  // that affects the direction of growth can be reversed by subsequent
  // events.
  // The history does not contain information about the fibre segment
  // associated with the terminal segment object, since the history is
  // only needed when the direction must be determined for a new
  // terminal segment, so that the associated fibre segment data can not
  // provide contributing information.
  // The update_effective_history() function provides an opportunity to
  // update the selection of a portion of the segment history that is
  // considered effective, if a direction history selection model has been
  // specified in dhs.
protected:
  direction_history_selection * dhs; // an optional model of history modification
  double effective_length; // in terms of fibre length
public:
  axon_direction_history();
  virtual ~axon_direction_history() {}
  virtual void add(fibre_segment * fs, double len) = 0;
  virtual void remove_tail() = 0;
  virtual void clear() { effective_length = 0.0; }
  virtual void restart_at_nearest() = 0;
  virtual void next_further() = 0;
  virtual double segment_length() = 0;
  virtual double segment_radius_squared() = 0;
  virtual spatial & segment_unit_direction() = 0;
  virtual void update_effective_history() = 0;
};

class axon_direction_element: public PLLHandle<axon_direction_element> {
public:
  axon_direction_element(double _l): l(_l) {}
  axon_direction_element(fibre_segment * _fs);
  spatial u;
  double l;
  //double r; // This needs updating each time another element is added.
};

class pll_axon_direction_history: public axon_direction_history {
protected:
  PLLRoot<axon_direction_element> adr;
  axon_direction_element * segidx;
  axon_direction_element nullelement;
  double remaining;
public:
  pll_axon_direction_history(): segidx(&nullelement), nullelement(-1.0) {}
  virtual ~pll_axon_direction_history() {}
  virtual void add(fibre_segment * fs, double len) {
    adr.link_before(new axon_direction_element(fs));
    effective_length += len;
  }
  virtual void remove_tail() { if (adr.tail()) adr.tail()->remove(); }
  virtual void clear();
  virtual void restart_at_nearest() {
    segidx = adr.tail();
    if (!segidx) segidx = &nullelement;
    remaining = effective_length;
  }
  virtual void next_further() {
    remaining -= segidx->l;
    if (remaining<=0.0) segidx = &nullelement;
    else {
      segidx = segidx->Prev();
      if (!segidx) segidx = &nullelement;
    }
  }
  virtual double segment_length() {
    if (segidx->l < remaining) return segidx->l;
    else return remaining;
  }
  // [***INCOMPLETE] Segment radius is temporarily a fixed value.
  virtual double segment_radius_squared() { return 1.0; }
  virtual spatial & segment_unit_direction() { return segidx->u; }
  virtual void update_effective_history();
};

class parse_axon_direction_history: public axon_direction_history {
protected:
  fibre_segment * firstafterbranch;
  int skipafterbranch;
  int segmentsafterbranch;
  int segidx;
  fibre_segment * segidxfs;
  spatial u;
  fibre_segment * seek(int idx);
  double remaining;
public:
  parse_axon_direction_history(fibre_segment & fab): firstafterbranch(&fab), skipafterbranch(0), segmentsafterbranch(0), segidx(-1), segidxfs(NULL) {}
  ~parse_axon_direction_history() {}
  virtual void add(fibre_segment * fs, double len) { segmentsafterbranch++; effective_length += len; }
  virtual void remove_tail() { if (segmentsafterbranch>skipafterbranch) skipafterbranch++; }
  virtual void clear(fibre_segment & fab);
  virtual void restart_at_nearest() {
    if (segmentsafterbranch>skipafterbranch) {
      segidx = segmentsafterbranch-1;
      segidxfs = seek(segidx);
    } else segidx = -1;
    remaining = effective_length; 
  }
  virtual void next_further();
  virtual double segment_length();
  // [***INCOMPLETE] Segment radius is temporarily a fixed value.
  virtual double segment_radius_squared() { return 1.0; }
  virtual spatial & segment_unit_direction();
  virtual void update_effective_history();
};

class direction_history_selection {
  // This is the general class of models that vary the effective segment
  // history used to determine the predicted direction.
public:
  direction_history_selection() {}
  virtual ~direction_history_selection() {}
  virtual void history_reset() = 0;
  virtual void effective_history(axon_direction_history * adh) = 0;
};

class random_truncation_dh_selection: public direction_history_selection {
  // This simple segment history selection model uses only a uniform random
  // function to decide that the segment history should be truncated and
  // another random value to determine at which fibre length the segment
  // history should be truncated.
public:
  random_truncation_dh_selection() {}
  virtual void history_reset() {}
  virtual void effective_history(axon_direction_history * adh);
};

class direction_model_base {
  // Unless the alternative (legacy) direction models are selected, in which
  // case a NULL pointer is assigned, each terminal_segment object is
  // designated an axon_direction_model object. That way, there is no need
  // to specify the specific history to use each time an event must be
  // handled.
  // The selection of the type of axon_direction_model to use (if any) can
  // be done at the level of all neurons (globally), per neuron or per
  // pre/postsynaptic structure.
  // [***INCOMPLETE] If I want to insure that all direction models define
  // the correct set of constructors and go about procedures correctly
  // then I should create a template for direction models that all inherit
  // this direction_model_base.
protected:
  // The following is shared among direction models in order to produce
  // random veering about a predicted direction. If there should also be
  // direction models with no such randomness then create a
  // direction_model_base_base without these elements.
#ifdef ADM_PRIORITIZE_SPEED_OVER_SPACE
  linear_pdf admpdf; // [***INCOMPLETE] The pdf is not yet an option.
#endif
  direction_model_base * contributing;
  double contributingweight;
  void turn(terminal_segment * ts, spatial & predicted, double initlen);
  struct direction_model_base_parameters {
    double veeranglemin, veeranglemax; // perturbed expected elongation
    direction_model_base_parameters(double _veeranglemin, double _veeranglemax): veeranglemin(_veeranglemin), veeranglemax(_veeranglemax) {}
  } base_parameters;
  virtual ~direction_model_base() { if (contributing) contributing->delete_shared(); }
public:
  direction_model_base(direction_model_base * dmcontrib, double & dmweight, direction_model_base & schema);
  direction_model_base(String & thislabel, String & label, Command_Line_Parameters & clp);
  virtual direction_model_base * clone() = 0;
  virtual void delete_shared() { delete this; }
  virtual void handle_branching(terminal_segment & ts1, terminal_segment & ts2) = 0;
  virtual void handle_turning(terminal_segment & ts) = 0;
  virtual spatial predict(double weight, terminal_segment * ts, neuron * e) = 0;
  virtual void direction(terminal_segment * ts, neuron * e, double initlen = 0.0) = 0;
  virtual String report_parameters_specific() = 0;
  String report_parameters();
};

typedef direction_model_base * direction_model_base_ptr;

class radial_direction_model: public direction_model_base {
  // This is the simplest model of growth cone direction, which
  // makes only the optional assumption (based on a hypothesis
  // by Samsonovich) that dendrite growth cones tend to return
  // to a growth direction that is radial to the soma.
protected:
  struct radial_dm_parameters {
    bool Samsonovich_hypothesis;
    radial_dm_parameters(bool samshyp): Samsonovich_hypothesis(samshyp) {}
  } radial_parameters;
  void predict_direction(spatial & predicted, neuron * n, terminal_segment * ts);
public:
  radial_direction_model(direction_model_base * dmbcontrib, double & dmbweight, radial_direction_model & schema);
  radial_direction_model(String & thislabel, String & label, Command_Line_Parameters & clp);
  ~radial_direction_model() {}
  virtual direction_model_base * clone();
  virtual void handle_branching(terminal_segment & ts1, terminal_segment & ts2);
  virtual void handle_turning(terminal_segment & ts);
  virtual spatial predict(double weight, terminal_segment * ts, neuron * e);
  virtual void direction(terminal_segment * ts, neuron * e, double initlen = 0.0);
  virtual String report_parameters_specific();
};

class tension_direction_model: public direction_model_base {
  // This default model is based on the following hypotheses:
  // 1. The effect that each segment in the segment history has on the
  //    predicted direction of growth can be summed through a vector summation
  //    in which individual components have an amplitude that is represented
  //    by the length of their vectors.
  // 2. The amplitude of a specific segment's effect on the predicted direction
  //    can be calculated by a model that is analogous to gravitation, where
  //    the distance is measured from the "center of mass" of a segment to the
  //    tip of the growth cone along the path of the intervening fibre
  //    segments.
  // 3. A separately chosen model updates the effective segment history and
  //    the optiona ability to retrieve truncated segments.
  // (See further comments in axon_direction_model::direction().)
protected:
  axon_direction_history * adh;
  struct tension_dm_parameters {
    double history_power;
    tension_dm_parameters(double hp): history_power(hp) {}
  } tension_parameters;
  void predict_direction(spatial & predicted);
public:
  //tension_direction_model(axon_direction_history & _adh): adh(&_adh) {}
  tension_direction_model(axon_direction_history & _adh, direction_model_base * dmbcontrib, double & dmbweight,  tension_direction_model & schema);
  tension_direction_model(axon_direction_history & _adh, String & thislabel, String & label, Command_Line_Parameters & clp);
  ~tension_direction_model() { delete adh; }
  virtual direction_model_base * clone();
  virtual void handle_branching(terminal_segment & ts1, terminal_segment & ts2);
  virtual void handle_turning(terminal_segment & ts);
  virtual spatial predict(double weight, terminal_segment * ts, neuron * e);
  virtual void direction(terminal_segment * ts, neuron * e, double initlen = 0.0);
  virtual String report_parameters_specific();
};

class cell_attraction_direction_model: public direction_model_base {
  // This is a very simple direction model that uses attraction associations
  // beteween specific cells to predict the direction of growth.
  // This model can be used in conjunction with the axon_direction_model.
protected:
  void predict_direction(spatial & predicted, neuron * n, spatial & growthcone);
public:
  //cell_attraction_direction_model() {}
  cell_attraction_direction_model(direction_model_base * dmbcontrib, double & dmbweight, cell_attraction_direction_model & schema);
  cell_attraction_direction_model(String & thislabel, String & label, Command_Line_Parameters & clp): direction_model_base(thislabel,label,clp) {}
  virtual direction_model_base * clone();
  virtual void handle_branching(terminal_segment & ts1, terminal_segment & ts2);
  virtual void handle_turning(terminal_segment & ts);
  virtual spatial predict(double weight, terminal_segment * ts, neuron * e);
  virtual void direction(terminal_segment * ts, neuron * e, double initlen = 0.0);
  virtual String report_parameters_specific();
};

class vector_direction_model: public direction_model_base {
  // This growth cone direction model expects the direction
  // of growth to be along a specified vector.
  // This model can be useful, for example in a chain of
  // direction models that guide apical dendrite trunk growth
  // for demonstration purposes.
protected:
  struct vector_dm_parameters {
    spatial direction;
    vector_dm_parameters() {}
    vector_dm_parameters(spatial d): direction(d) {}
  } vector_parameters;
  void predict_direction(spatial & predicted, neuron * n, terminal_segment * ts);
public:
  vector_direction_model(direction_model_base * dmbcontrib, double & dmbweight, vector_direction_model & schema);
  vector_direction_model(String & thislabel, String & label, Command_Line_Parameters & clp);
  ~vector_direction_model() {}
  virtual direction_model_base * clone();
  virtual void handle_branching(terminal_segment & ts1, terminal_segment & ts2);
  virtual void handle_turning(terminal_segment & ts);
  virtual spatial predict(double weight, terminal_segment * ts, neuron * e);
  virtual void direction(terminal_segment * ts, neuron * e, double initlen = 0.0);
  virtual String report_parameters_specific();
};

// global variables
// See http://rak.minduploading.org:8080/caspan/Members/randalk/model-specification-implementation/.
extern direction_model default_direction_model; // identifier, changed when a different universal model is set
extern String universal_direction_model_root; // Used only to report if chaining at the universal set level.

// Region and natural subset specific schemas (initialized in neuron.cc:general_neuron_parameters_interface::parse_CLP(Command_Line_Parameters & clp, network & net))
typedef direction_model_base_ptr * region_direction_model_base_ptr;
extern region_direction_model_base_ptr * direction_model_region_subset_schemas;

// functions
direction_model_base * direction_model_selection(String & label, Command_Line_Parameters & clp, direction_model_base * superior_set, direction_model_base_ptr & dmbptr);

#endif