Skip to content

Commit

Permalink
[publish] #217: HHN corrections, examples, tests, documentation.
Browse files Browse the repository at this point in the history
  • Loading branch information
annoviko committed Jan 13, 2018
1 parent 92619e1 commit 3e2d3be
Show file tree
Hide file tree
Showing 13 changed files with 464 additions and 82 deletions.
8 changes: 4 additions & 4 deletions ccore/src/nnet/dynamic_analyser.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,9 @@ class spike {
using ptr = std::shared_ptr<spike>;

private:
std::size_t m_begin;
std::size_t m_duration;
std::size_t m_end;
std::size_t m_begin = 0;
std::size_t m_duration = 0;
std::size_t m_end = 0;

public:
spike(void) = default;
Expand Down Expand Up @@ -208,4 +208,4 @@ void dynamic_analyser::extract_ensembles(const std::vector<spike_collection> & p

}

}
}
1 change: 1 addition & 0 deletions ccore/tst/utest-hhn.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -222,3 +222,4 @@ TEST(utest_hhn, two_sync_ensembles_02) {

template_ensemble_generation(6, 800, 200, 0.1, { 20, 20, 20, 50, 50, 50 }, expected_ensembles, dead_neurons);
}

1 change: 1 addition & 0 deletions docs/doxygen_conf_pyclustering
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ INPUT = pyclustering/__init__.py \
pyclustering/gcolor/sync.py \
pyclustering/nnet/__init__.py \
pyclustering/nnet/cnn.py \
pyclustering/nnet/dynamic_visualizer.py \
pyclustering/nnet/fsync.py \
pyclustering/nnet/hhn.py \
pyclustering/nnet/hysteresis.py \
Expand Down
Binary file added docs/img/hhn_three_ensembles.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
157 changes: 149 additions & 8 deletions pyclustering/nnet/dynamic_visualizer.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,32 +30,109 @@


class canvas_descr:
"""!
@brief Describes plot where dynamic is displayed.
@details Used by 'dynamic_visualizer' class.
"""

def __init__(self, x_title=None, y_title=None, x_lim=None, y_lim=None, x_labels=True, y_labels=True):
"""!
@brief Constructor of canvas.
@param[in] x_title (string): Title for X axis, if 'None', then nothing is displayed.
@param[in] y_title (string): Title for Y axis, if 'None', then nothing is displayed.
@param[in] x_lim (list): Defines borders of X axis like [from, to], for example [0, 3.14], if 'None' then
borders are calculated automatically.
@param[in] y_lim (list): Defines borders of Y axis like [from, to], if 'None' then borders are calculated
automatically.
@param[in] x_labels (bool): If True then labels of X axis are displayed.
@param[in] y_labels (bool): If True then labels of Y axis are displayed.
"""

## Title for X axis.
self.x_title = x_title;

## Title for Y axis.
self.y_title = y_title;

## Borders of X axis.
self.x_lim = x_lim;

## Borders of Y axis.
self.y_lim = y_lim;

## Defines whether X label should be displayed.
self.x_labels = x_labels;

## Defines whether Y label should be displayed.
self.y_labels = y_labels;


class dynamic_descr:
"""!
@brief Output dynamic description that used to display.
@details Used by 'dynamic_visualizer' class.
"""

def __init__(self, canvas, time, dynamics, separate, color):
"""!
@brief Constructor of output dynamic descriptor.
@param[in] canvas (uint): Index of canvas where dynamic should be displayed, in case of 'separate'
representation this argument is considered as a first canvas from that displaying should be done.
@param[in] time (list): Time points that are considered as a X axis.
@param[in] dynamics (list): Dynamic or dynamics that should be displayed.
@param[in] separate (bool|list): If 'True' then each dynamic is displayed on separate canvas, if it is defined
by list, for example, [ [1, 2], [3, 4] ], then the first and the second dynamics are displayed on
the canvas with index 'canvas' and the third and forth are displayed on the next 'canvas + 1'
canvas.
@param[in] color (string): Color that is used to display output dynamic(s).
"""

## Index of canvas where (or from which) dynamic should be displayed.
self.canvas = canvas;

## Time points.
self.time = time;

## Dynamic or dynamics.
self.dynamics = dynamics;
self.separate = separate;

## Defines how dynamic(s) should be displayed.
self.separate = self.__get_canonical_separate(separate);

## Color of dynamic.
self.color = color;

self.separate = self.__get_canonical_separate();


def get_axis_index(self, index_dynamic):
"""!
@brief Returns index of canvas where specified dynamic (by index 'index_dynamic') should be displayed.
@param[in] index_dynamic (uint): Index of dynamic that should be displayed.
@return (uint) Index of canvas.
"""
return self.separate[index_dynamic];


def __get_canonical_separate(self):
if (isinstance(self.separate, list)):
def __get_canonical_separate(self, separate):
"""!
@brief Return unified representation of separation value.
@details It represents list whose size is equal to amount of dynamics, where index of dynamic will show
where it should be displayed.
@param[in] separate (bool|list): Input separate representation that should transformed.
@return (list) Indexes where each dynamic should be displayed.
"""
if (isinstance(separate, list)):
separate = [0] * len(self.dynamics[0]);
for canvas_index in range(len(self.separate)):
dynamic_indexes = self.separate[canvas_index];
Expand All @@ -64,46 +141,110 @@ def __get_canonical_separate(self):

return separate;

elif (self.separate is False):
elif (separate is False):
if (isinstance(self.dynamics[0], list) is True):
return [ self.canvas ] * len(self.dynamics[0]);
else:
return [ self.canvas ];

elif (self.separate is True):
elif (separate is True):
if (isinstance(self.dynamics[0], list) is True):
return range(self.canvas, self.canvas + len(self.dynamics[0]));
else:
return [ self.canvas ];

else:
raise Exception("Incorrect type of argument 'separate' '%s'." % type(self.separate));
raise Exception("Incorrect type of argument 'separate' '%s'." % type(separate));


class dynamic_visualizer:
"""!
@brief Basic output dynamic visualizer.
@details The aim of the visualizer is to displayed output dynamic of any process, for example, output dynamic of
oscillatory network.
"""

def __init__(self, canvas, x_title=None, y_title=None, x_lim=None, y_lim=None, x_labels=True, y_labels=True):
"""!
@brief Construct dynamic visualizer.
@details Default properties that are generalized in the constructor, for example, X axis title, can be
changed by corresponding method: 'set_canvas_properties'.
@param[in] canvas (uint): Amount of canvases that is used for visualization.
@param[in] x_title (string): Title for X axis of canvases, if 'None', then nothing is displayed.
@param[in] y_title (string): Title for Y axis of canvases, if 'None', then nothing is displayed.
@param[in] x_lim (list): Defines borders of X axis like [from, to], for example [0, 3.14], if 'None' then
borders are calculated automatically.
@param[in] y_lim (list): Defines borders of Y axis like [from, to], if 'None' then borders are calculated
automatically.
@param[in] x_labels (bool): If True then labels of X axis are displayed.
@param[in] y_labels (bool): If True then labels of Y axis are displayed.
"""
self.__size = canvas;
self.__canvases = [ canvas_descr(x_title, y_title, x_lim, y_lim, x_labels, y_labels) for _ in range(canvas) ];
self.__dynamic_storage = [];


def set_canvas_properties(self, canvas, x_title=None, y_title=None, x_lim=None, y_lim=None, x_labels=True, y_labels=True):
"""!
@brief Set properties for specified canvas.
@param[in] canvas (uint): Index of canvas whose properties should changed.
@param[in] x_title (string): Title for X axis, if 'None', then nothing is displayed.
@param[in] y_title (string): Title for Y axis, if 'None', then nothing is displayed.
@param[in] x_lim (list): Defines borders of X axis like [from, to], for example [0, 3.14], if 'None' then
borders are calculated automatically.
@param[in] y_lim (list): Defines borders of Y axis like [from, to], if 'None' then borders are calculated
automatically.
@param[in] x_labels (bool): If True then labels of X axis are displayed.
@param[in] y_labels (bool): If True then labels of Y axis are displayed.
"""
self.__canvases[canvas] = canvas_descr(x_title, y_title, x_lim, y_lim, x_labels, y_labels);


def append_dynamic(self, t, dynamic, canvas=0, color='blue'):
"""!
@brief Append single dynamic to specified canvas (by default to the first with index '0').
@param[in] t (list): Time points that corresponds to dynamic values and considered on a X axis.
@param[in] dynamic (list): Value points of dynamic that are considered on an Y axis.
@param[in] canvas (uint): Canvas where dynamic should be displayed.
@param[in] color (string): Color that is used for drawing dynamic on the canvas.
"""
description = dynamic_descr(canvas, t, dynamic, False, color);
self.__dynamic_storage.append(description);
self.__update_canvas_xlim(description.time, description.separate);


def append_dynamics(self, t, dynamics, canvas=0, separate=False, color='blue'):
"""!
@brief Append several dynamics to canvas or canvases (defined by 'canvas' and 'separate' arguments).
@param[in] t (list): Time points that corresponds to dynamic values and considered on a X axis.
@param[in] dynamics (list): Dynamics where each of them is considered on Y axis.
@param[in] canvas (uint): Index of canvas where dynamic should be displayed, in case of 'separate'
representation this argument is considered as a first canvas from that displaying should be done.
@param[in] separate (bool|list): If 'True' then each dynamic is displayed on separate canvas, if it is defined
by list, for example, [ [1, 2], [3, 4] ], then the first and the second dynamics are displayed on
the canvas with index 'canvas' and the third and forth are displayed on the next 'canvas + 1'
canvas.
@param[in] color (string): Color that is used to display output dynamic(s).
"""
description = dynamic_descr(canvas, t, dynamics, separate, color);
self.__dynamic_storage.append(description);
self.__update_canvas_xlim(description.time, description.separate);


def show(self):
"""!
@brief Draw and show output dynamics.
"""
(_, axis) = plt.subplots(self.__size, 1);

self.__format_canvases(axis);
Expand Down
71 changes: 44 additions & 27 deletions pyclustering/nnet/examples/hhn_examples.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,38 +30,42 @@
from pyclustering.nnet.hhn import hhn_network, hhn_parameters;


def template_dynamic_hhn(num_osc, steps, time, stimulus = None, params = None, separate_representation = False, ccore_flag = False):
def template_dynamic_hhn(num_osc, steps, time, stimulus = None, params = None, separate = False, ccore_flag = False):
net = hhn_network(num_osc, stimulus, params, ccore = ccore_flag);

(t, dyn_peripheral, dyn_central) = net.simulate(steps, time);

amount_canvases = 1;
if (isinstance(separate_representation, list)):
amount_canvases = len(separate_representation) + 2;
elif (separate_representation is True):
if (isinstance(separate, list)):
amount_canvases = len(separate) + 2;
elif (separate is True):
amount_canvases = len(dyn_peripheral[0]) + 2;

visualizer = dynamic_visualizer(amount_canvases, x_title = "Time", y_title = "V", y_labels = False);
visualizer.append_dynamics(t, dyn_peripheral, 0, separate_representation);
visualizer.append_dynamics(t, dyn_central, amount_canvases - 2, separate_representation);
visualizer.append_dynamics(t, dyn_peripheral, 0, separate);
visualizer.append_dynamics(t, dyn_central, amount_canvases - 2, True);
visualizer.show();


def one_oscillator_unstimulated():
template_dynamic_hhn(1, 750, 100, separate_representation = True, ccore_flag = False);
template_dynamic_hhn(1, 750, 100, separate_representation = True, ccore_flag = True);
template_dynamic_hhn(1, 750, 100, separate=True, ccore_flag=False);
template_dynamic_hhn(1, 750, 100, separate=True, ccore_flag=True);


def one_oscillator_stimulated():
template_dynamic_hhn(1, 750, 100, [25], separate_representation = True, ccore_flag = False);
template_dynamic_hhn(1, 750, 100, [25], separate_representation = True, ccore_flag = True);
template_dynamic_hhn(1, 750, 100, [25], separate=True, ccore_flag=False);
template_dynamic_hhn(1, 750, 100, [25], separate=True, ccore_flag=True);


def three_oscillators_stimulated():
template_dynamic_hhn(3, 750, 100, [25] * 3, separate_representation = True, ccore_flag = False);
template_dynamic_hhn(3, 750, 100, [25] * 3, separate_representation = True, ccore_flag = True);
template_dynamic_hhn(3, 750, 100, [25] * 3, separate=True, ccore_flag=False);
template_dynamic_hhn(3, 750, 100, [25] * 3, separate=True, ccore_flag=True);


def two_sync_ensembles():
template_dynamic_hhn(4, 400, 200, [25, 25, 50, 50], separate_representation = True, ccore_flag = False);
template_dynamic_hhn(4, 800, 200, [25, 25, 50, 50], separate_representation = True, ccore_flag = True);
template_dynamic_hhn(4, 400, 200, [25, 25, 50, 50], separate=True, ccore_flag=False);
template_dynamic_hhn(4, 800, 200, [25, 25, 50, 50], separate=True, ccore_flag=True);


def ten_oscillators_stimulated_desync():
params = hhn_parameters();
Expand All @@ -71,9 +75,10 @@ def ten_oscillators_stimulated_desync():

stumulus = [25, 25, 25, 25, 25, 11, 11, 11, 11, 11];

template_dynamic_hhn(10, 750, 100, stumulus, params, separate_representation=True, ccore_flag=False);
template_dynamic_hhn(10, 750, 100, stumulus, params, separate_representation=True, ccore_flag=True);

template_dynamic_hhn(10, 750, 100, stumulus, params, separate=True, ccore_flag=False);
template_dynamic_hhn(10, 750, 100, stumulus, params, separate=True, ccore_flag=True);


def ten_oscillators_stimulated_sync():
params = hhn_parameters();
params.w1 = 0.1;
Expand All @@ -82,36 +87,47 @@ def ten_oscillators_stimulated_sync():

stumulus = [25, 25, 25, 25, 25, 27, 27, 27, 27, 27];

template_dynamic_hhn(10, 750, 100, stumulus, params, separate_representation = True, ccore_flag=False);
template_dynamic_hhn(10, 750, 100, stumulus, params, separate_representation=True, ccore_flag=True);

template_dynamic_hhn(10, 750, 100, stumulus, params, separate=True, ccore_flag=False);
template_dynamic_hhn(10, 750, 100, stumulus, params, separate=True, ccore_flag=True);


def ten_oscillators_stimulated_partial_sync():
params = hhn_parameters();
params.w1 = 0.1;
params.w2 = 5.0;
params.w3 = 0;

stimulus = [25, 25, 25, 25, 25, 11, 11, 11, 11, 11];
template_dynamic_hhn(10, 750, 200, stimulus, params, separate_representation=True, ccore_flag=False);
template_dynamic_hhn(10, 750, 200, stimulus, params, separate_representation=True, ccore_flag=True);
template_dynamic_hhn(10, 750, 200, stimulus, params, separate=True, ccore_flag=False);
template_dynamic_hhn(10, 750, 200, stimulus, params, separate=True, ccore_flag=True);


def six_oscillators_mix_2_stimulated():
params = hhn_parameters();
params.deltah = 400;

stimulus = [25, 25, 25, 47, 47, 47];
template_dynamic_hhn(6, 1200, 600, stimulus, params, separate_representation=True, ccore_flag=False);
template_dynamic_hhn(6, 2400, 600, stimulus, params, separate_representation=True, ccore_flag=True);
template_dynamic_hhn(6, 1200, 600, stimulus, params, separate=True, ccore_flag=False);
template_dynamic_hhn(6, 2400, 600, stimulus, params, separate=True, ccore_flag=True);


def six_oscillators_mix_3_stimulated():
params = hhn_parameters();
params.deltah = 400;

stimulus = [0, 0, 25, 25, 47, 47];
template_dynamic_hhn(6, 1200, 600, stimulus, params, separate_representation=True, ccore_flag=False);
template_dynamic_hhn(6, 2400, 600, stimulus, params, separate_representation=True, ccore_flag=True);
template_dynamic_hhn(6, 1200, 600, stimulus, params, separate=True, ccore_flag=False);
template_dynamic_hhn(6, 2400, 600, stimulus, params, separate=True, ccore_flag=True);


def three_sync_ensembles():
params = hhn_parameters();
params.deltah = 400;

stimulus = [25, 26, 25, 25, 26, 45, 46, 45, 44, 45, 65, 65, 65, 64, 66];
separate = [ [0, 1, 2, 3, 4], [5, 6, 7, 8, 9], [10, 11, 12, 13, 14] ];
num_osc = len(stimulus);
template_dynamic_hhn(num_osc, 2400, 600, stimulus, params, separate=separate, ccore_flag=True);


one_oscillator_unstimulated();
Expand All @@ -122,4 +138,5 @@ def six_oscillators_mix_3_stimulated():
ten_oscillators_stimulated_sync();
ten_oscillators_stimulated_partial_sync();
six_oscillators_mix_2_stimulated();
six_oscillators_mix_3_stimulated();
six_oscillators_mix_3_stimulated();
three_sync_ensembles();

0 comments on commit 3e2d3be

Please sign in to comment.