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