__init__.py
1 """!
2 
3 @brief Utils that are used by modules of pyclustering.
4 
5 @authors Andrei Novikov (pyclustering@yandex.ru)
6 @date 2014-2020
7 @copyright GNU Public License
8 
9 @cond GNU_PUBLIC_LICENSE
10  PyClustering is free software: you can redistribute it and/or modify
11  it under the terms of the GNU General Public License as published by
12  the Free Software Foundation, either version 3 of the License, or
13  (at your option) any later version.
14 
15  PyClustering is distributed in the hope that it will be useful,
16  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  GNU General Public License for more details.
19 
20  You should have received a copy of the GNU General Public License
21  along with this program. If not, see <http://www.gnu.org/licenses/>.
22 @endcond
23 
24 """
25 
26 import time
27 import numpy
28 import warnings
29 
30 from numpy import array
31 
32 try:
33  from PIL import Image
34 except Exception as error_instance:
35  warnings.warn("Impossible to import PIL (please, install 'PIL'), pyclustering's visualization "
36  "functionality is partially not available (details: '%s')." % str(error_instance))
37 
38 try:
39  import matplotlib.pyplot as plt
40  from mpl_toolkits.mplot3d import Axes3D
41 except Exception as error_instance:
42  warnings.warn("Impossible to import matplotlib (please, install 'matplotlib'), pyclustering's visualization "
43  "functionality is not available (details: '%s')." % str(error_instance))
44 
45 from sys import platform as _platform
46 
47 from pyclustering.utils.metric import distance_metric, type_metric
48 
49 
50 
51 pi = 3.1415926535
52 
53 
54 def read_sample(filename):
55  """!
56  @brief Returns data sample from simple text file.
57  @details This function should be used for text file with following format:
58  @code
59  point_1_coord_1 point_1_coord_2 ... point_1_coord_n
60  point_2_coord_1 point_2_coord_2 ... point_2_coord_n
61  ... ...
62  @endcode
63 
64  @param[in] filename (string): Path to file with data.
65 
66  @return (list) Points where each point represented by list of coordinates.
67 
68  """
69 
70  file = open(filename, 'r')
71 
72  sample = [[float(val) for val in line.split()] for line in file if len(line.strip()) > 0]
73 
74  file.close()
75  return sample
76 
77 
78 def calculate_distance_matrix(sample, metric=distance_metric(type_metric.EUCLIDEAN)):
79  """!
80  @brief Calculates distance matrix for data sample (sequence of points) using specified metric (by default Euclidean distance).
81 
82  @param[in] sample (array_like): Data points that are used for distance calculation.
83  @param[in] metric (distance_metric): Metric that is used for distance calculation between two points.
84 
85  @return (list) Matrix distance between data points.
86 
87  """
88 
89  amount_rows = len(sample)
90  return [[metric(sample[i], sample[j]) for j in range(amount_rows)] for i in range(amount_rows)]
91 
92 
93 def read_image(filename):
94  """!
95  @brief Returns image as N-dimension (depends on the input image) matrix, where one element of list describes pixel.
96 
97  @param[in] filename (string): Path to image.
98 
99  @return (list) Pixels where each pixel described by list of RGB-values.
100 
101  """
102 
103  with Image.open(filename) as image_source:
104  data = [list(pixel) for pixel in image_source.getdata()]
105  return data
106 
107 
108 def rgb2gray(image_rgb_array):
109  """!
110  @brief Returns image as 1-dimension (gray colored) matrix, where one element of list describes pixel.
111  @details Luma coding is used for transformation and that is calculated directly from gamma-compressed primary intensities as a weighted sum:
112 
113  \f[Y = 0.2989R + 0.587G + 0.114B\f]
114 
115  @param[in] image_rgb_array (list): Image represented by RGB list.
116 
117  @return (list) Image as gray colored matrix, where one element of list describes pixel.
118 
119  @code
120  colored_image = read_image(file_name);
121  gray_image = rgb2gray(colored_image);
122  @endcode
123 
124  @see read_image()
125 
126  """
127 
128  image_gray_array = [0.0] * len(image_rgb_array)
129  for index in range(0, len(image_rgb_array), 1):
130  image_gray_array[index] = float(image_rgb_array[index][0]) * 0.2989 \
131  + float(image_rgb_array[index][1]) * 0.5870 \
132  + float(image_rgb_array[index][2]) * 0.1140
133 
134  return image_gray_array
135 
136 
137 def stretch_pattern(image_source):
138  """!
139  @brief Returns stretched content as 1-dimension (gray colored) matrix with size of input image.
140 
141  @param[in] image_source (Image): PIL Image instance.
142 
143  @return (list, Image) Stretched image as gray colored matrix and source image.
144 
145  """
146  wsize, hsize = image_source.size
147 
148  # Crop digit exactly
149  (ws, hs, we, he) = gray_pattern_borders(image_source)
150  image_source = image_source.crop((ws, hs, we, he))
151 
152  # Stretch it to initial sizes
153  image_source = image_source.resize((wsize, hsize), Image.ANTIALIAS)
154 
155  # Transform image to simple array
156  data = [pixel for pixel in image_source.getdata()]
157  image_pattern = rgb2gray(data)
158 
159  return image_pattern, image_source
160 
161 
163  """!
164  @brief Returns coordinates of gray image content on the input image.
165 
166  @param[in] image (Image): PIL Image instance that is processed.
167 
168  @return (tuple) Returns coordinates of gray image content as (width_start, height_start, width_end, height_end).
169 
170  """
171 
172  width, height = image.size
173 
174  width_start = width
175  width_end = 0
176  height_start = height
177  height_end = 0
178 
179  row, col = 0, 0
180  for pixel in image.getdata():
181  value = float(pixel[0]) * 0.2989 + float(pixel[1]) * 0.5870 + float(pixel[2]) * 0.1140
182 
183  if value < 128:
184  if width_end < col:
185  width_end = col
186 
187  if height_end < row:
188  height_end = row
189 
190  if width_start > col:
191  width_start = col
192 
193  if height_start > row:
194  height_start = row
195 
196  col += 1
197  if col >= width:
198  col = 0
199  row += 1
200 
201  return width_start, height_start, width_end + 1, height_end + 1
202 
203 
204 def average_neighbor_distance(points, num_neigh):
205  """!
206  @brief Returns average distance for establish links between specified number of nearest neighbors.
207 
208  @param[in] points (list): Input data, list of points where each point represented by list.
209  @param[in] num_neigh (uint): Number of neighbors that should be used for distance calculation.
210 
211  @return (double) Average distance for establish links between 'num_neigh' in data set 'points'.
212 
213  """
214 
215  if num_neigh > len(points) - 1:
216  raise NameError('Impossible to calculate average distance to neighbors '
217  'when number of object is less than number of neighbors.')
218 
219  dist_matrix = [[0.0 for i in range(len(points))] for _ in range(len(points))]
220  for i in range(0, len(points), 1):
221  for j in range(i + 1, len(points), 1):
222  distance = euclidean_distance(points[i], points[j])
223  dist_matrix[i][j] = distance
224  dist_matrix[j][i] = distance
225 
226  dist_matrix[i] = sorted(dist_matrix[i])
227 
228  total_distance = 0
229  for i in range(0, len(points), 1):
230  # start from 0 - first element is distance to itself.
231  for j in range(0, num_neigh, 1):
232  total_distance += dist_matrix[i][j + 1]
233 
234  return total_distance / (num_neigh * len(points))
235 
236 
237 def medoid(data, indexes=None, **kwargs):
238  """!
239  @brief Calculate medoid for input points using Euclidean distance.
240 
241  @param[in] data (list): Set of points for that median should be calculated.
242  @param[in] indexes (list): Indexes of input set of points that will be taken into account during median calculation.
243  @param[in] **kwargs: Arbitrary keyword arguments (available arguments: 'metric', 'data_type').
244 
245  <b>Keyword Args:</b><br>
246  - metric (distance_metric): Metric that is used for distance calculation between two points.
247  - data_type (string): Data type of input sample 'data' (available values: 'points', 'distance_matrix').
248 
249  @return (uint) index of point in input set that corresponds to median.
250 
251  """
252 
253  index_median = None
254  distance = float('Inf')
255 
256  metric = kwargs.get('metric', type_metric.EUCLIDEAN_SQUARE)
257  data_type = kwargs.get('data_type', 'points')
258 
259  if data_type == 'points':
260  calculator = lambda index1, index2: metric(data[index1], data[index2])
261  elif data_type == 'distance_matrix':
262  if isinstance(data, numpy.matrix):
263  calculator = lambda index1, index2: data.item(index1, index2)
264 
265  else:
266  calculator = lambda index1, index2: data[index1][index2]
267  else:
268  raise TypeError("Unknown type of data is specified '%s'." % data_type)
269 
270  if indexes is None:
271  range_points = range(len(data))
272  else:
273  range_points = indexes
274 
275  for index_candidate in range_points:
276  distance_candidate = 0.0
277  for index in range_points:
278  distance_candidate += calculator(index_candidate, index)
279 
280  if distance_candidate < distance:
281  distance = distance_candidate
282  index_median = index_candidate
283 
284  return index_median
285 
286 
288  """!
289  @brief Calculate Euclidean distance between vector a and b.
290  @details The Euclidean between vectors (points) a and b is calculated by following formula:
291 
292  \f[
293  dist(a, b) = \sqrt{ \sum_{i=0}^{N}(b_{i} - a_{i})^{2}) };
294  \f]
295 
296  Where N is a length of each vector.
297 
298  @param[in] a (list): The first vector.
299  @param[in] b (list): The second vector.
300 
301  @return (double) Euclidian distance between two vectors.
302 
303  @note This function for calculation is faster then standard function in ~100 times!
304 
305  """
306 
307  distance = euclidean_distance_square(a, b);
308  return distance**(0.5);
309 
310 
312  """!
313  @brief Calculate square Euclidian distance between vector a and b.
314 
315  @param[in] a (list): The first vector.
316  @param[in] b (list): The second vector.
317 
318  @return (double) Square Euclidian distance between two vectors.
319 
320  """
321 
322  if ( ((type(a) == float) and (type(b) == float)) or ((type(a) == int) and (type(b) == int)) ):
323  return (a - b)**2.0;
324 
325  distance = 0.0;
326  for i in range(0, len(a)):
327  distance += (a[i] - b[i])**2.0;
328 
329  return distance;
330 
331 
333  """!
334  @brief Calculate Manhattan distance between vector a and b.
335 
336  @param[in] a (list): The first cluster.
337  @param[in] b (list): The second cluster.
338 
339  @return (double) Manhattan distance between two vectors.
340 
341  """
342 
343  if ( ((type(a) == float) and (type(b) == float)) or ((type(a) == int) and (type(b) == int)) ):
344  return abs(a - b);
345 
346  distance = 0.0;
347  dimension = len(a);
348 
349  for i in range(0, dimension):
350  distance += abs(a[i] - b[i]);
351 
352  return distance;
353 
354 
355 def average_inter_cluster_distance(cluster1, cluster2, data = None):
356  """!
357  @brief Calculates average inter-cluster distance between two clusters.
358  @details Clusters can be represented by list of coordinates (in this case data shouldn't be specified),
359  or by list of indexes of points from the data (represented by list of points), in this case
360  data should be specified.
361 
362  @param[in] cluster1 (list): The first cluster where each element can represent index from the data or object itself.
363  @param[in] cluster2 (list): The second cluster where each element can represent index from the data or object itself.
364  @param[in] data (list): If specified than elements of clusters will be used as indexes,
365  otherwise elements of cluster will be considered as points.
366 
367  @return (double) Average inter-cluster distance between two clusters.
368 
369  """
370 
371  distance = 0.0;
372 
373  if (data is None):
374  for i in range(len(cluster1)):
375  for j in range(len(cluster2)):
376  distance += euclidean_distance_square(cluster1[i], cluster2[j]);
377  else:
378  for i in range(len(cluster1)):
379  for j in range(len(cluster2)):
380  distance += euclidean_distance_square(data[ cluster1[i]], data[ cluster2[j]]);
381 
382  distance /= float(len(cluster1) * len(cluster2));
383  return distance ** 0.5;
384 
385 
386 def average_intra_cluster_distance(cluster1, cluster2, data=None):
387  """!
388  @brief Calculates average intra-cluster distance between two clusters.
389  @details Clusters can be represented by list of coordinates (in this case data shouldn't be specified),
390  or by list of indexes of points from the data (represented by list of points), in this case
391  data should be specified.
392 
393  @param[in] cluster1 (list): The first cluster.
394  @param[in] cluster2 (list): The second cluster.
395  @param[in] data (list): If specified than elements of clusters will be used as indexes,
396  otherwise elements of cluster will be considered as points.
397 
398  @return (double) Average intra-cluster distance between two clusters.
399 
400  """
401 
402  distance = 0.0
403 
404  for i in range(len(cluster1) + len(cluster2)):
405  for j in range(len(cluster1) + len(cluster2)):
406  if data is None:
407  # the first point
408  if i < len(cluster1):
409  first_point = cluster1[i]
410  else:
411  first_point = cluster2[i - len(cluster1)]
412 
413  # the second point
414  if j < len(cluster1):
415  second_point = cluster1[j]
416  else:
417  second_point = cluster2[j - len(cluster1)]
418 
419  else:
420  # the first point
421  if i < len(cluster1):
422  first_point = data[cluster1[i]]
423  else:
424  first_point = data[cluster2[i - len(cluster1)]]
425 
426  if j < len(cluster1):
427  second_point = data[cluster1[j]]
428  else:
429  second_point = data[cluster2[j - len(cluster1)]]
430 
431  distance += euclidean_distance_square(first_point, second_point)
432 
433  distance /= float((len(cluster1) + len(cluster2)) * (len(cluster1) + len(cluster2) - 1.0))
434  return distance ** 0.5
435 
436 
437 def variance_increase_distance(cluster1, cluster2, data = None):
438  """!
439  @brief Calculates variance increase distance between two clusters.
440  @details Clusters can be represented by list of coordinates (in this case data shouldn't be specified),
441  or by list of indexes of points from the data (represented by list of points), in this case
442  data should be specified.
443 
444  @param[in] cluster1 (list): The first cluster.
445  @param[in] cluster2 (list): The second cluster.
446  @param[in] data (list): If specified than elements of clusters will be used as indexes,
447  otherwise elements of cluster will be considered as points.
448 
449  @return (double) Average variance increase distance between two clusters.
450 
451  """
452 
453  # calculate local sum
454  if data is None:
455  member_cluster1 = [0.0] * len(cluster1[0])
456  member_cluster2 = [0.0] * len(cluster2[0])
457 
458  else:
459  member_cluster1 = [0.0] * len(data[0])
460  member_cluster2 = [0.0] * len(data[0])
461 
462  for i in range(len(cluster1)):
463  if data is None:
464  member_cluster1 = list_math_addition(member_cluster1, cluster1[i])
465  else:
466  member_cluster1 = list_math_addition(member_cluster1, data[ cluster1[i] ])
467 
468  for j in range(len(cluster2)):
469  if data is None:
470  member_cluster2 = list_math_addition(member_cluster2, cluster2[j])
471  else:
472  member_cluster2 = list_math_addition(member_cluster2, data[ cluster2[j] ])
473 
474  member_cluster_general = list_math_addition(member_cluster1, member_cluster2)
475  member_cluster_general = list_math_division_number(member_cluster_general, len(cluster1) + len(cluster2))
476 
477  member_cluster1 = list_math_division_number(member_cluster1, len(cluster1))
478  member_cluster2 = list_math_division_number(member_cluster2, len(cluster2))
479 
480  # calculate global sum
481  distance_general = 0.0
482  distance_cluster1 = 0.0
483  distance_cluster2 = 0.0
484 
485  for i in range(len(cluster1)):
486  if data is None:
487  distance_cluster1 += euclidean_distance_square(cluster1[i], member_cluster1)
488  distance_general += euclidean_distance_square(cluster1[i], member_cluster_general)
489 
490  else:
491  distance_cluster1 += euclidean_distance_square(data[ cluster1[i]], member_cluster1)
492  distance_general += euclidean_distance_square(data[ cluster1[i]], member_cluster_general)
493 
494  for j in range(len(cluster2)):
495  if data is None:
496  distance_cluster2 += euclidean_distance_square(cluster2[j], member_cluster2)
497  distance_general += euclidean_distance_square(cluster2[j], member_cluster_general)
498 
499  else:
500  distance_cluster2 += euclidean_distance_square(data[ cluster2[j]], member_cluster2)
501  distance_general += euclidean_distance_square(data[ cluster2[j]], member_cluster_general)
502 
503  return distance_general - distance_cluster1 - distance_cluster2
504 
505 
506 def calculate_ellipse_description(covariance, scale = 2.0):
507  """!
508  @brief Calculates description of ellipse using covariance matrix.
509 
510  @param[in] covariance (numpy.array): Covariance matrix for which ellipse area should be calculated.
511  @param[in] scale (float): Scale of the ellipse.
512 
513  @return (float, float, float) Return ellipse description: angle, width, height.
514 
515  """
516 
517  eigh_values, eigh_vectors = numpy.linalg.eigh(covariance)
518  order = eigh_values.argsort()[::-1]
519 
520  values, vectors = eigh_values[order], eigh_vectors[order]
521  angle = numpy.degrees(numpy.arctan2(*vectors[:,0][::-1]))
522 
523  if 0.0 in values:
524  return 0, 0, 0
525 
526  width, height = 2.0 * scale * numpy.sqrt(values)
527  return angle, width, height
528 
529 
530 def data_corners(data, data_filter = None):
531  """!
532  @brief Finds maximum and minimum corner in each dimension of the specified data.
533 
534  @param[in] data (list): List of points that should be analysed.
535  @param[in] data_filter (list): List of indexes of the data that should be analysed,
536  if it is 'None' then whole 'data' is analysed to obtain corners.
537 
538  @return (list) Tuple of two points that corresponds to minimum and maximum corner (min_corner, max_corner).
539 
540  """
541 
542  dimensions = len(data[0])
543 
544  bypass = data_filter
545  if bypass is None:
546  bypass = range(len(data))
547 
548  maximum_corner = list(data[bypass[0]][:])
549  minimum_corner = list(data[bypass[0]][:])
550 
551  for index_point in bypass:
552  for index_dimension in range(dimensions):
553  if data[index_point][index_dimension] > maximum_corner[index_dimension]:
554  maximum_corner[index_dimension] = data[index_point][index_dimension]
555 
556  if data[index_point][index_dimension] < minimum_corner[index_dimension]:
557  minimum_corner[index_dimension] = data[index_point][index_dimension]
558 
559  return minimum_corner, maximum_corner
560 
561 
562 def norm_vector(vector):
563  """!
564  @brief Calculates norm of an input vector that is known as a vector length.
565 
566  @param[in] vector (list): The input vector whose length is calculated.
567 
568  @return (double) vector norm known as vector length.
569 
570  """
571 
572  length = 0.0
573  for component in vector:
574  length += component * component
575 
576  length = length ** 0.5
577 
578  return length
579 
580 
581 def heaviside(value):
582  """!
583  @brief Calculates Heaviside function that represents step function.
584  @details If input value is greater than 0 then returns 1, otherwise returns 0.
585 
586  @param[in] value (double): Argument of Heaviside function.
587 
588  @return (double) Value of Heaviside function.
589 
590  """
591  if (value > 0.0):
592  return 1.0;
593 
594  return 0.0;
595 
596 
597 def timedcall(executable_function, *args, **kwargs):
598  """!
599  @brief Executes specified method or function with measuring of execution time.
600 
601  @param[in] executable_function (pointer): Pointer to a function or method that should be called.
602  @param[in] *args: Arguments of the called function or method.
603  @param[in] **kwargs: Arbitrary keyword arguments of the called function or method.
604 
605  @return (tuple) Execution time and result of execution of function or method (execution_time, result_execution).
606 
607  """
608 
609  time_start = time.perf_counter()
610  result = executable_function(*args, **kwargs)
611  time_end = time.perf_counter()
612 
613  return time_end - time_start, result
614 
615 
616 def extract_number_oscillations(osc_dyn, index = 0, amplitude_threshold = 1.0):
617  """!
618  @brief Extracts number of oscillations of specified oscillator.
619 
620  @param[in] osc_dyn (list): Dynamic of oscillators.
621  @param[in] index (uint): Index of oscillator in dynamic.
622  @param[in] amplitude_threshold (double): Amplitude threshold when oscillation is taken into account, for example,
623  when oscillator amplitude is greater than threshold then oscillation is incremented.
624 
625  @return (uint) Number of oscillations of specified oscillator.
626 
627  """
628 
629  number_oscillations = 0;
630  waiting_differential = False;
631  threshold_passed = False;
632  high_level_trigger = True if (osc_dyn[0][index] > amplitude_threshold) else False;
633 
634  for values in osc_dyn:
635  if ( (values[index] >= amplitude_threshold) and (high_level_trigger is False) ):
636  high_level_trigger = True;
637  threshold_passed = True;
638 
639  elif ( (values[index] < amplitude_threshold) and (high_level_trigger is True) ):
640  high_level_trigger = False;
641  threshold_passed = True;
642 
643  if (threshold_passed is True):
644  threshold_passed = False;
645  if (waiting_differential is True and high_level_trigger is False):
646  number_oscillations += 1;
647  waiting_differential = False;
648 
649  else:
650  waiting_differential = True;
651 
652  return number_oscillations;
653 
654 
655 def allocate_sync_ensembles(dynamic, tolerance = 0.1, threshold = 1.0, ignore = None):
656  """!
657  @brief Allocate clusters in line with ensembles of synchronous oscillators where each
658  synchronous ensemble corresponds to only one cluster.
659 
660  @param[in] dynamic (dynamic): Dynamic of each oscillator.
661  @param[in] tolerance (double): Maximum error for allocation of synchronous ensemble oscillators.
662  @param[in] threshold (double): Amlitude trigger when spike is taken into account.
663  @param[in] ignore (bool): Set of indexes that shouldn't be taken into account.
664 
665  @return (list) Grours (lists) of indexes of synchronous oscillators, for example,
666  [ [index_osc1, index_osc3], [index_osc2], [index_osc4, index_osc5] ].
667 
668  """
669 
670  descriptors = [ [] for _ in range(len(dynamic[0])) ];
671 
672  # Check from the end for obtaining result
673  for index_dyn in range(0, len(dynamic[0]), 1):
674  if ((ignore is not None) and (index_dyn in ignore)):
675  continue;
676 
677  time_stop_simulation = len(dynamic) - 1;
678  active_state = False;
679 
680  if (dynamic[time_stop_simulation][index_dyn] > threshold):
681  active_state = True;
682 
683  # if active state is detected, it means we don't have whole oscillatory period for the considered oscillator, should be skipped.
684  if (active_state is True):
685  while ( (dynamic[time_stop_simulation][index_dyn] > threshold) and (time_stop_simulation > 0) ):
686  time_stop_simulation -= 1;
687 
688  # if there are no any oscillation than let's consider it like noise
689  if (time_stop_simulation == 0):
690  continue;
691 
692  # reset
693  active_state = False;
694 
695  desc = [0, 0, 0]; # end, start, average time of oscillation
696  for t in range(time_stop_simulation, 0, -1):
697  if ( (dynamic[t][index_dyn] > threshold) and (active_state is False) ):
698  desc[0] = t;
699  active_state = True;
700  elif ( (dynamic[t][index_dyn] < threshold) and (active_state is True) ):
701  desc[1] = t;
702  active_state = False;
703 
704  break;
705 
706  if (desc == [0, 0, 0]):
707  continue;
708 
709  desc[2] = desc[1] + (desc[0] - desc[1]) / 2.0;
710  descriptors[index_dyn] = desc;
711 
712 
713  # Cluster allocation
714  sync_ensembles = [];
715  desc_sync_ensembles = [];
716 
717  for index_desc in range(0, len(descriptors), 1):
718  if (descriptors[index_desc] == []):
719  continue;
720 
721  if (len(sync_ensembles) == 0):
722  desc_ensemble = descriptors[index_desc];
723  reducer = (desc_ensemble[0] - desc_ensemble[1]) * tolerance;
724 
725  desc_ensemble[0] = desc_ensemble[2] + reducer;
726  desc_ensemble[1] = desc_ensemble[2] - reducer;
727 
728  desc_sync_ensembles.append(desc_ensemble);
729  sync_ensembles.append([ index_desc ]);
730  else:
731  oscillator_captured = False;
732  for index_ensemble in range(0, len(sync_ensembles), 1):
733  if ( (desc_sync_ensembles[index_ensemble][0] > descriptors[index_desc][2]) and (desc_sync_ensembles[index_ensemble][1] < descriptors[index_desc][2])):
734  sync_ensembles[index_ensemble].append(index_desc);
735  oscillator_captured = True;
736  break;
737 
738  if (oscillator_captured is False):
739  desc_ensemble = descriptors[index_desc];
740  reducer = (desc_ensemble[0] - desc_ensemble[1]) * tolerance;
741 
742  desc_ensemble[0] = desc_ensemble[2] + reducer;
743  desc_ensemble[1] = desc_ensemble[2] - reducer;
744 
745  desc_sync_ensembles.append(desc_ensemble);
746  sync_ensembles.append([ index_desc ]);
747 
748  return sync_ensembles;
749 
750 
751 def draw_clusters(data, clusters, noise = [], marker_descr = '.', hide_axes = False, axes = None, display_result = True):
752  """!
753  @brief Displays clusters for data in 2D or 3D.
754 
755  @param[in] data (list): Points that are described by coordinates represented.
756  @param[in] clusters (list): Clusters that are represented by lists of indexes where each index corresponds to point in data.
757  @param[in] noise (list): Points that are regarded to noise.
758  @param[in] marker_descr (string): Marker for displaying points.
759  @param[in] hide_axes (bool): If True - axes is not displayed.
760  @param[in] axes (ax) Matplotlib axes where clusters should be drawn, if it is not specified (None) then new plot will be created.
761  @param[in] display_result (bool): If specified then matplotlib axes will be used for drawing and plot will not be shown.
762 
763  @return (ax) Matplotlib axes where drawn clusters are presented.
764 
765  """
766  # Get dimension
767  dimension = 0;
768  if ( (data is not None) and (clusters is not None) ):
769  dimension = len(data[0]);
770  elif ( (data is None) and (clusters is not None) ):
771  dimension = len(clusters[0][0]);
772  else:
773  raise NameError('Data or clusters should be specified exactly.');
774 
775  "Draw clusters"
776  colors = [ 'red', 'blue', 'darkgreen', 'brown', 'violet',
777  'deepskyblue', 'darkgrey', 'lightsalmon', 'deeppink', 'yellow',
778  'black', 'mediumspringgreen', 'orange', 'darkviolet', 'darkblue',
779  'silver', 'lime', 'pink', 'gold', 'bisque' ];
780 
781  if (len(clusters) > len(colors)):
782  raise NameError('Impossible to represent clusters due to number of specified colors.');
783 
784  fig = plt.figure();
785 
786  if (axes is None):
787  # Check for dimensions
788  if ((dimension) == 1 or (dimension == 2)):
789  axes = fig.add_subplot(111);
790  elif (dimension == 3):
791  axes = fig.gca(projection='3d');
792  else:
793  raise NameError('Drawer supports only 2d and 3d data representation');
794 
795  color_index = 0;
796  for cluster in clusters:
797  color = colors[color_index];
798  for item in cluster:
799  if (dimension == 1):
800  if (data is None):
801  axes.plot(item[0], 0.0, color = color, marker = marker_descr);
802  else:
803  axes.plot(data[item][0], 0.0, color = color, marker = marker_descr);
804 
805  if (dimension == 2):
806  if (data is None):
807  axes.plot(item[0], item[1], color = color, marker = marker_descr);
808  else:
809  axes.plot(data[item][0], data[item][1], color = color, marker = marker_descr);
810 
811  elif (dimension == 3):
812  if (data is None):
813  axes.scatter(item[0], item[1], item[2], c = color, marker = marker_descr);
814  else:
815  axes.scatter(data[item][0], data[item][1], data[item][2], c = color, marker = marker_descr);
816 
817  color_index += 1;
818 
819  for item in noise:
820  if (dimension == 1):
821  if (data is None):
822  axes.plot(item[0], 0.0, 'w' + marker_descr);
823  else:
824  axes.plot(data[item][0], 0.0, 'w' + marker_descr);
825 
826  if (dimension == 2):
827  if (data is None):
828  axes.plot(item[0], item[1], 'w' + marker_descr);
829  else:
830  axes.plot(data[item][0], data[item][1], 'w' + marker_descr);
831 
832  elif (dimension == 3):
833  if (data is None):
834  axes.scatter(item[0], item[1], item[2], c = 'w', marker = marker_descr);
835  else:
836  axes.scatter(data[item][0], data[item][1], data[item][2], c = 'w', marker = marker_descr);
837 
838  axes.grid(True);
839 
840  if (hide_axes is True):
841  axes.xaxis.set_ticklabels([]);
842  axes.yaxis.set_ticklabels([]);
843 
844  if (dimension == 3):
845  axes.zaxis.set_ticklabels([]);
846 
847  if (display_result is True):
848  plt.show();
849 
850  return axes;
851 
852 
853 def draw_dynamics(t, dyn, x_title = None, y_title = None, x_lim = None, y_lim = None, x_labels = True, y_labels = True, separate = False, axes = None):
854  """!
855  @brief Draw dynamics of neurons (oscillators) in the network.
856  @details It draws if matplotlib is not specified (None), othewise it should be performed manually.
857 
858  @param[in] t (list): Values of time (used by x axis).
859  @param[in] dyn (list): Values of output of oscillators (used by y axis).
860  @param[in] x_title (string): Title for Y.
861  @param[in] y_title (string): Title for X.
862  @param[in] x_lim (double): X limit.
863  @param[in] y_lim (double): Y limit.
864  @param[in] x_labels (bool): If True - shows X labels.
865  @param[in] y_labels (bool): If True - shows Y labels.
866  @param[in] separate (list): Consists of lists of oscillators where each such list consists of oscillator indexes that will be shown on separated stage.
867  @param[in] axes (ax): If specified then matplotlib axes will be used for drawing and plot will not be shown.
868 
869  @return (ax) Axes of matplotlib.
870 
871  """
872 
873  number_lines = 0;
874 
875  stage_xlim = None;
876  if (x_lim is not None):
877  stage_xlim = x_lim;
878  elif (len(t) > 0):
879  stage_xlim = [0, t[len(t) - 1]];
880 
881  if ( (isinstance(separate, bool) is True) and (separate is True) ):
882  if (isinstance(dyn[0], list) is True):
883  number_lines = len(dyn[0]);
884  else:
885  number_lines = 1;
886 
887  elif (isinstance(separate, list) is True):
888  number_lines = len(separate);
889 
890  else:
891  number_lines = 1;
892 
893  dysplay_result = False;
894  if (axes is None):
895  dysplay_result = True;
896  (fig, axes) = plt.subplots(number_lines, 1);
897 
898  # Check if we have more than one dynamic
899  if (isinstance(dyn[0], list) is True):
900  num_items = len(dyn[0]);
901  for index in range(0, num_items, 1):
902  y = [item[index] for item in dyn];
903 
904  if (number_lines > 1):
905  index_stage = -1;
906 
907  # Find required axes for the y
908  if (isinstance(separate, bool) is True):
909  index_stage = index;
910 
911  elif (isinstance(separate, list) is True):
912  for index_group in range(0, len(separate), 1):
913  if (index in separate[index_group]):
914  index_stage = index_group;
915  break;
916 
917  if (index_stage != -1):
918  if (index_stage != number_lines - 1):
919  axes[index_stage].get_xaxis().set_visible(False);
920 
921  axes[index_stage].plot(t, y, 'b-', linewidth = 0.5);
922  set_ax_param(axes[index_stage], x_title, y_title, stage_xlim, y_lim, x_labels, y_labels, True);
923 
924  else:
925  axes.plot(t, y, 'b-', linewidth = 0.5);
926  set_ax_param(axes, x_title, y_title, stage_xlim, y_lim, x_labels, y_labels, True);
927  else:
928  axes.plot(t, dyn, 'b-', linewidth = 0.5);
929  set_ax_param(axes, x_title, y_title, stage_xlim, y_lim, x_labels, y_labels, True);
930 
931  if (dysplay_result is True):
932  plt.show();
933 
934  return axes;
935 
936 
937 def set_ax_param(ax, x_title = None, y_title = None, x_lim = None, y_lim = None, x_labels = True, y_labels = True, grid = True):
938  """!
939  @brief Sets parameters for matplotlib ax.
940 
941  @param[in] ax (Axes): Axes for which parameters should applied.
942  @param[in] x_title (string): Title for Y.
943  @param[in] y_title (string): Title for X.
944  @param[in] x_lim (double): X limit.
945  @param[in] y_lim (double): Y limit.
946  @param[in] x_labels (bool): If True - shows X labels.
947  @param[in] y_labels (bool): If True - shows Y labels.
948  @param[in] grid (bool): If True - shows grid.
949 
950  """
951  from matplotlib.font_manager import FontProperties;
952  from matplotlib import rcParams;
953 
954  if (_platform == "linux") or (_platform == "linux2"):
955  rcParams['font.sans-serif'] = ['Liberation Serif'];
956  else:
957  rcParams['font.sans-serif'] = ['Arial'];
958 
959  rcParams['font.size'] = 12;
960 
961  surface_font = FontProperties();
962  if (_platform == "linux") or (_platform == "linux2"):
963  surface_font.set_name('Liberation Serif');
964  else:
965  surface_font.set_name('Arial');
966 
967  surface_font.set_size('12');
968 
969  if (y_title is not None): ax.set_ylabel(y_title, fontproperties = surface_font);
970  if (x_title is not None): ax.set_xlabel(x_title, fontproperties = surface_font);
971 
972  if (x_lim is not None): ax.set_xlim(x_lim[0], x_lim[1]);
973  if (y_lim is not None): ax.set_ylim(y_lim[0], y_lim[1]);
974 
975  if (x_labels is False): ax.xaxis.set_ticklabels([]);
976  if (y_labels is False): ax.yaxis.set_ticklabels([]);
977 
978  ax.grid(grid);
979 
980 
981 def draw_dynamics_set(dynamics, xtitle = None, ytitle = None, xlim = None, ylim = None, xlabels = False, ylabels = False):
982  """!
983  @brief Draw lists of dynamics of neurons (oscillators) in the network.
984 
985  @param[in] dynamics (list): List of network outputs that are represented by values of output of oscillators (used by y axis).
986  @param[in] xtitle (string): Title for Y.
987  @param[in] ytitle (string): Title for X.
988  @param[in] xlim (double): X limit.
989  @param[in] ylim (double): Y limit.
990  @param[in] xlabels (bool): If True - shows X labels.
991  @param[in] ylabels (bool): If True - shows Y labels.
992 
993  """
994  # Calculate edge for confortable representation.
995  number_dynamics = len(dynamics);
996  if (number_dynamics == 1):
997  draw_dynamics(dynamics[0][0], dynamics[0][1], xtitle, ytitle, xlim, ylim, xlabels, ylabels);
998  return;
999 
1000  number_cols = int(numpy.ceil(number_dynamics ** 0.5));
1001  number_rows = int(numpy.ceil(number_dynamics / number_cols));
1002 
1003  real_index = 0, 0;
1004  double_indexer = True;
1005  if ( (number_cols == 1) or (number_rows == 1) ):
1006  real_index = 0;
1007  double_indexer = False;
1008 
1009  (_, axarr) = plt.subplots(number_rows, number_cols);
1010  #plt.setp([ax for ax in axarr], visible = False);
1011 
1012  for dynamic in dynamics:
1013  axarr[real_index] = draw_dynamics(dynamic[0], dynamic[1], xtitle, ytitle, xlim, ylim, xlabels, ylabels, axes = axarr[real_index]);
1014  #plt.setp(axarr[real_index], visible = True);
1015 
1016  if (double_indexer is True):
1017  real_index = real_index[0], real_index[1] + 1;
1018  if (real_index[1] >= number_cols):
1019  real_index = real_index[0] + 1, 0;
1020  else:
1021  real_index += 1;
1022 
1023  plt.show();
1024 
1025 
1026 def draw_image_color_segments(source, clusters, hide_axes = True):
1027  """!
1028  @brief Shows image segments using colored image.
1029  @details Each color on result image represents allocated segment. The first image is initial and other is result of segmentation.
1030 
1031  @param[in] source (string): Path to image.
1032  @param[in] clusters (list): List of clusters (allocated segments of image) where each cluster
1033  consists of indexes of pixel from source image.
1034  @param[in] hide_axes (bool): If True then axes will not be displayed.
1035 
1036  """
1037 
1038  image_source = Image.open(source);
1039  image_size = image_source.size;
1040 
1041  (fig, axarr) = plt.subplots(1, 2);
1042 
1043  plt.setp([ax for ax in axarr], visible = False);
1044 
1045  available_colors = [ (0, 162, 232), (34, 177, 76), (237, 28, 36),
1046  (255, 242, 0), (0, 0, 0), (237, 28, 36),
1047  (255, 174, 201), (127, 127, 127), (185, 122, 87),
1048  (200, 191, 231), (136, 0, 21), (255, 127, 39),
1049  (63, 72, 204), (195, 195, 195), (255, 201, 14),
1050  (239, 228, 176), (181, 230, 29), (153, 217, 234),
1051  (112, 146, 180) ];
1052 
1053  image_color_segments = [(255, 255, 255)] * (image_size[0] * image_size[1]);
1054 
1055  for index_segment in range(len(clusters)):
1056  for index_pixel in clusters[index_segment]:
1057  image_color_segments[index_pixel] = available_colors[index_segment];
1058 
1059  stage = array(image_color_segments, numpy.uint8);
1060  stage = numpy.reshape(stage, (image_size[1], image_size[0]) + ((3),)); # ((3),) it's size of RGB - third dimension.
1061  image_cluster = Image.fromarray(stage, 'RGB');
1062 
1063  axarr[0].imshow(image_source, interpolation = 'none');
1064  axarr[1].imshow(image_cluster, interpolation = 'none');
1065 
1066  for i in range(2):
1067  plt.setp(axarr[i], visible = True);
1068 
1069  if (hide_axes is True):
1070  axarr[i].xaxis.set_ticklabels([]);
1071  axarr[i].yaxis.set_ticklabels([]);
1072  axarr[i].xaxis.set_ticks_position('none');
1073  axarr[i].yaxis.set_ticks_position('none');
1074 
1075  plt.show();
1076 
1077 
1078 def draw_image_mask_segments(source, clusters, hide_axes = True):
1079  """!
1080  @brief Shows image segments using black masks.
1081  @details Each black mask of allocated segment is presented on separate plot.
1082  The first image is initial and others are black masks of segments.
1083 
1084  @param[in] source (string): Path to image.
1085  @param[in] clusters (list): List of clusters (allocated segments of image) where each cluster
1086  consists of indexes of pixel from source image.
1087  @param[in] hide_axes (bool): If True then axes will not be displayed.
1088 
1089  """
1090  if len(clusters) == 0:
1091  print("Warning: Nothing to draw - list of clusters is empty.")
1092  return
1093 
1094  image_source = Image.open(source)
1095  image_size = image_source.size
1096 
1097  # Calculate edge for confortable representation.
1098  number_clusters = len(clusters) + 1 # show with the source image
1099 
1100  number_cols = int(numpy.ceil(number_clusters ** 0.5))
1101  number_rows = int(numpy.ceil(number_clusters / number_cols))
1102 
1103  real_index = 0, 0
1104  double_indexer = True
1105  if (number_cols == 1) or (number_rows == 1):
1106  real_index = 0
1107  double_indexer = False
1108 
1109  (fig, axarr) = plt.subplots(number_rows, number_cols)
1110  plt.setp([ax for ax in axarr], visible=False)
1111 
1112  axarr[real_index].imshow(image_source, interpolation='none')
1113  plt.setp(axarr[real_index], visible=True)
1114 
1115  if hide_axes is True:
1116  axarr[real_index].xaxis.set_ticklabels([])
1117  axarr[real_index].yaxis.set_ticklabels([])
1118  axarr[real_index].xaxis.set_ticks_position('none')
1119  axarr[real_index].yaxis.set_ticks_position('none')
1120 
1121  if double_indexer is True:
1122  real_index = 0, 1
1123  else:
1124  real_index += 1
1125 
1126  for cluster in clusters:
1127  stage_cluster = [(255, 255, 255)] * (image_size[0] * image_size[1])
1128  for index in cluster:
1129  stage_cluster[index] = (0, 0, 0)
1130 
1131  stage = array(stage_cluster, numpy.uint8)
1132  stage = numpy.reshape(stage, (image_size[1], image_size[0]) + ((3),)) # ((3),) it's size of RGB - 3rd dimension.
1133 
1134  image_cluster = Image.fromarray(stage, 'RGB')
1135 
1136  axarr[real_index].imshow(image_cluster, interpolation = 'none')
1137  plt.setp(axarr[real_index], visible = True)
1138 
1139  if hide_axes is True:
1140  axarr[real_index].xaxis.set_ticklabels([])
1141  axarr[real_index].yaxis.set_ticklabels([])
1142 
1143  axarr[real_index].xaxis.set_ticks_position('none')
1144  axarr[real_index].yaxis.set_ticks_position('none')
1145 
1146  if double_indexer is True:
1147  real_index = real_index[0], real_index[1] + 1
1148  if real_index[1] >= number_cols:
1149  real_index = real_index[0] + 1, 0
1150  else:
1151  real_index += 1
1152 
1153  plt.show()
1154 
1155 
1156 def find_left_element(sorted_data, right, comparator):
1157  """!
1158  @brief Returns the element's index at the left side from the right border with the same value as the
1159  last element in the range `sorted_data`.
1160 
1161  @details The element at the right is considered as target to search. `sorted_data` must
1162  be sorted collection. The complexity of the algorithm is `O(log(n))`. The
1163  algorithm is based on the binary search algorithm.
1164 
1165  @param[in] sorted_data: input data to find the element.
1166  @param[in] right: the index of the right element from that search is started.
1167  @param[in] comparator: comparison function object which returns `True` if the first argument
1168  is less than the second.
1169 
1170  @return The element's index at the left side from the right border with the same value as the
1171  last element in the range `sorted_data`.
1172 
1173  """
1174  if len(sorted_data) == 0:
1175  raise ValueError("Input data is empty.")
1176 
1177  left = 0
1178  middle = (right - left) // 2
1179  target = sorted_data[right]
1180 
1181  while left < right:
1182  if comparator(sorted_data[middle], target):
1183  left = middle + 1
1184  else:
1185  right = middle
1186 
1187  offset = (right - left) // 2
1188  middle = left + offset
1189 
1190  return left
1191 
1192 
1193 def linear_sum(list_vector):
1194  """!
1195  @brief Calculates linear sum of vector that is represented by list, each element can be represented by list - multidimensional elements.
1196 
1197  @param[in] list_vector (list): Input vector.
1198 
1199  @return (list|double) Linear sum of vector that can be represented by list in case of multidimensional elements.
1200 
1201  """
1202  dimension = 1
1203  linear_sum = 0.0
1204  list_representation = (type(list_vector[0]) == list)
1205 
1206  if list_representation is True:
1207  dimension = len(list_vector[0])
1208  linear_sum = [0] * dimension
1209 
1210  for index_element in range(0, len(list_vector)):
1211  if list_representation is True:
1212  for index_dimension in range(0, dimension):
1213  linear_sum[index_dimension] += list_vector[index_element][index_dimension]
1214  else:
1215  linear_sum += list_vector[index_element]
1216 
1217  return linear_sum
1218 
1219 
1220 def square_sum(list_vector):
1221  """!
1222  @brief Calculates square sum of vector that is represented by list, each element can be represented by list - multidimensional elements.
1223 
1224  @param[in] list_vector (list): Input vector.
1225 
1226  @return (double) Square sum of vector.
1227 
1228  """
1229 
1230  square_sum = 0.0
1231  list_representation = (type(list_vector[0]) == list)
1232 
1233  for index_element in range(0, len(list_vector)):
1234  if list_representation is True:
1235  square_sum += sum(list_math_multiplication(list_vector[index_element], list_vector[index_element]))
1236  else:
1237  square_sum += list_vector[index_element] * list_vector[index_element]
1238 
1239  return square_sum
1240 
1241 
1243  """!
1244  @brief Calculates subtraction of two lists.
1245  @details Each element from list 'a' is subtracted by element from list 'b' accordingly.
1246 
1247  @param[in] a (list): List of elements that supports mathematical subtraction.
1248  @param[in] b (list): List of elements that supports mathematical subtraction.
1249 
1250  @return (list) Results of subtraction of two lists.
1251 
1252  """
1253  return [a[i] - b[i] for i in range(len(a))]
1254 
1255 
1257  """!
1258  @brief Calculates subtraction between list and number.
1259  @details Each element from list 'a' is subtracted by number 'b'.
1260 
1261  @param[in] a (list): List of elements that supports mathematical subtraction.
1262  @param[in] b (list): Value that supports mathematical subtraction.
1263 
1264  @return (list) Results of subtraction between list and number.
1265 
1266  """
1267  return [a[i] - b for i in range(len(a))]
1268 
1269 
1271  """!
1272  @brief Addition of two lists.
1273  @details Each element from list 'a' is added to element from list 'b' accordingly.
1274 
1275  @param[in] a (list): List of elements that supports mathematic addition..
1276  @param[in] b (list): List of elements that supports mathematic addition..
1277 
1278  @return (list) Results of addtion of two lists.
1279 
1280  """
1281  return [a[i] + b[i] for i in range(len(a))]
1282 
1283 
1285  """!
1286  @brief Addition between list and number.
1287  @details Each element from list 'a' is added to number 'b'.
1288 
1289  @param[in] a (list): List of elements that supports mathematic addition.
1290  @param[in] b (double): Value that supports mathematic addition.
1291 
1292  @return (list) Result of addtion of two lists.
1293 
1294  """
1295  return [a[i] + b for i in range(len(a))]
1296 
1297 
1299  """!
1300  @brief Division between list and number.
1301  @details Each element from list 'a' is divided by number 'b'.
1302 
1303  @param[in] a (list): List of elements that supports mathematic division.
1304  @param[in] b (double): Value that supports mathematic division.
1305 
1306  @return (list) Result of division between list and number.
1307 
1308  """
1309  return [a[i] / b for i in range(len(a))]
1310 
1311 
1313  """!
1314  @brief Division of two lists.
1315  @details Each element from list 'a' is divided by element from list 'b' accordingly.
1316 
1317  @param[in] a (list): List of elements that supports mathematic division.
1318  @param[in] b (list): List of elements that supports mathematic division.
1319 
1320  @return (list) Result of division of two lists.
1321 
1322  """
1323  return [a[i] / b[i] for i in range(len(a))]
1324 
1325 
1327  """!
1328  @brief Multiplication between list and number.
1329  @details Each element from list 'a' is multiplied by number 'b'.
1330 
1331  @param[in] a (list): List of elements that supports mathematic division.
1332  @param[in] b (double): Number that supports mathematic division.
1333 
1334  @return (list) Result of division between list and number.
1335 
1336  """
1337  return [a[i] * b for i in range(len(a))]
1338 
1339 
1341  """!
1342  @brief Multiplication of two lists.
1343  @details Each element from list 'a' is multiplied by element from list 'b' accordingly.
1344 
1345  @param[in] a (list): List of elements that supports mathematic multiplication.
1346  @param[in] b (list): List of elements that supports mathematic multiplication.
1347 
1348  @return (list) Result of multiplication of elements in two lists.
1349 
1350  """
1351  return [a[i] * b[i] for i in range(len(a))]
def find_left_element(sorted_data, right, comparator)
Returns the element&#39;s index at the left side from the right border with the same value as the last el...
Definition: __init__.py:1156
def euclidean_distance(a, b)
Calculate Euclidean distance between vector a and b.
Definition: __init__.py:287
def square_sum(list_vector)
Calculates square sum of vector that is represented by list, each element can be represented by list ...
Definition: __init__.py:1220
def draw_clusters(data, clusters, noise=[], marker_descr='.', hide_axes=False, axes=None, display_result=True)
Displays clusters for data in 2D or 3D.
Definition: __init__.py:751
def heaviside(value)
Calculates Heaviside function that represents step function.
Definition: __init__.py:581
def manhattan_distance(a, b)
Calculate Manhattan distance between vector a and b.
Definition: __init__.py:332
def read_image(filename)
Returns image as N-dimension (depends on the input image) matrix, where one element of list describes...
Definition: __init__.py:93
Module provides various distance metrics - abstraction of the notion of distance in a metric space...
Definition: metric.py:1
def timedcall(executable_function, args, kwargs)
Executes specified method or function with measuring of execution time.
Definition: __init__.py:597
def average_intra_cluster_distance(cluster1, cluster2, data=None)
Calculates average intra-cluster distance between two clusters.
Definition: __init__.py:386
def list_math_multiplication_number(a, b)
Multiplication between list and number.
Definition: __init__.py:1326
def extract_number_oscillations(osc_dyn, index=0, amplitude_threshold=1.0)
Extracts number of oscillations of specified oscillator.
Definition: __init__.py:616
def list_math_division(a, b)
Division of two lists.
Definition: __init__.py:1312
def list_math_multiplication(a, b)
Multiplication of two lists.
Definition: __init__.py:1340
def allocate_sync_ensembles(dynamic, tolerance=0.1, threshold=1.0, ignore=None)
Allocate clusters in line with ensembles of synchronous oscillators where each synchronous ensemble c...
Definition: __init__.py:655
def average_neighbor_distance(points, num_neigh)
Returns average distance for establish links between specified number of nearest neighbors.
Definition: __init__.py:204
def average_inter_cluster_distance(cluster1, cluster2, data=None)
Calculates average inter-cluster distance between two clusters.
Definition: __init__.py:355
def read_sample(filename)
Returns data sample from simple text file.
Definition: __init__.py:54
def draw_image_color_segments(source, clusters, hide_axes=True)
Shows image segments using colored image.
Definition: __init__.py:1026
def norm_vector(vector)
Calculates norm of an input vector that is known as a vector length.
Definition: __init__.py:562
def list_math_substraction_number(a, b)
Calculates subtraction between list and number.
Definition: __init__.py:1256
def stretch_pattern(image_source)
Returns stretched content as 1-dimension (gray colored) matrix with size of input image...
Definition: __init__.py:137
def draw_dynamics_set(dynamics, xtitle=None, ytitle=None, xlim=None, ylim=None, xlabels=False, ylabels=False)
Draw lists of dynamics of neurons (oscillators) in the network.
Definition: __init__.py:981
def draw_dynamics(t, dyn, x_title=None, y_title=None, x_lim=None, y_lim=None, x_labels=True, y_labels=True, separate=False, axes=None)
Draw dynamics of neurons (oscillators) in the network.
Definition: __init__.py:853
def data_corners(data, data_filter=None)
Finds maximum and minimum corner in each dimension of the specified data.
Definition: __init__.py:530
def list_math_addition(a, b)
Addition of two lists.
Definition: __init__.py:1270
def calculate_ellipse_description(covariance, scale=2.0)
Calculates description of ellipse using covariance matrix.
Definition: __init__.py:506
def euclidean_distance_square(a, b)
Calculate square Euclidian distance between vector a and b.
Definition: __init__.py:311
def gray_pattern_borders(image)
Returns coordinates of gray image content on the input image.
Definition: __init__.py:162
def list_math_division_number(a, b)
Division between list and number.
Definition: __init__.py:1298
def linear_sum(list_vector)
Calculates linear sum of vector that is represented by list, each element can be represented by list ...
Definition: __init__.py:1193
def medoid(data, indexes=None, kwargs)
Calculate medoid for input points using Euclidean distance.
Definition: __init__.py:237
def calculate_distance_matrix(sample, metric=distance_metric(type_metric.EUCLIDEAN))
Calculates distance matrix for data sample (sequence of points) using specified metric (by default Eu...
Definition: __init__.py:78
def set_ax_param(ax, x_title=None, y_title=None, x_lim=None, y_lim=None, x_labels=True, y_labels=True, grid=True)
Sets parameters for matplotlib ax.
Definition: __init__.py:937
def draw_image_mask_segments(source, clusters, hide_axes=True)
Shows image segments using black masks.
Definition: __init__.py:1078
def list_math_subtraction(a, b)
Calculates subtraction of two lists.
Definition: __init__.py:1242
def list_math_addition_number(a, b)
Addition between list and number.
Definition: __init__.py:1284
def variance_increase_distance(cluster1, cluster2, data=None)
Calculates variance increase distance between two clusters.
Definition: __init__.py:437
def rgb2gray(image_rgb_array)
Returns image as 1-dimension (gray colored) matrix, where one element of list describes pixel...
Definition: __init__.py:108