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