class_docstr: !
  @brief Common cluster visualizer for 1-, 2- and 3-dimensional data.
  @details `cluster_visualizer_multidim` visualizer can be used to display clusters in N-dimensional data.
  
  The general difference between `cluster_visualizer` and `cluster_visualizer_multidim` is a way of representation
  of 3-dimensional data. In case of `cluster_visualizer` 3-dimensional data is displayed in 3-dimensional plot with
  `x0`, `x1` and `x2` axis. In case of `cluster_visualizer_multidim` it displayed on three 2-dimensional plots:
  `(x0, x1)`, `(x0, x2)` and `(x1, x2)`.
  
  There is an example where sample `Atom` is used for clustering and displayed by `cluster_visualizer`:
  @code
      from pyclustering.utils import read_sample
      from pyclustering.samples.definitions import FCPS_SAMPLES
      from pyclustering.cluster import cluster_visualizer
      from pyclustering.cluster.dbscan import dbscan
  
      sample = read_sample(FCPS_SAMPLES.SAMPLE_ATOM)
      clusters = dbscan(sample, 15, 3).process().get_clusters()
  
      visualizer = cluster_visualizer()
      visualizer.append_clusters(clusters, sample)
      visualizer.show()
  @endcode
  
  Visualized clustering results of `Atom` data:
  @image html dbscan_atom_visualizer.png "Fig. 1. DBSCAN clustering results (3-dimensional data 'Atom')."
  
  @see cluster_visualizer_multidim
docstr: !
  @brief Constructor of cluster visualizer.
  
  @param[in] number_canvases (uint): Number of canvases that is used for visualization.
  @param[in] size_row (uint): Amount of canvases that can be placed in one row.
  @param[in] titles (list): List of canvas's titles.
  
  Example:
  @code
      # load 2D data sample
      sample_2d = read_sample(SIMPLE_SAMPLES.SAMPLE_SIMPLE1);
      
      # load 3D data sample
      sample_3d = read_sample(FCPS_SAMPLES.SAMPLE_HEPTA);
      
      # extract clusters from the first sample using DBSCAN algorithm
      dbscan_instance = dbscan(sample_2d, 0.4, 2, False);
      dbscan_instance.process();
      clusters_sample_2d = dbscan_instance.get_clusters();
  
      # extract clusters from the second sample using DBSCAN algorithm
      dbscan_instance = dbscan(sample_3d, 1, 3, True);
      dbscan_instance.process();
      clusters_sample_3d = dbscan_instance.get_clusters();
      
      # create plot with two canvases where each row contains 2 canvases.
      size = 2;
      row_size = 2;
      visualizer = cluster_visualizer(size, row_size);
      
      # place clustering result of sample_2d to the first canvas
      visualizer.append_clusters(clusters_sample_2d, sample_2d, 0, markersize = 5);
      
      # place clustering result of sample_3d to the second canvas
      visualizer.append_clusters(clusters_sample_3d, sample_3d, 1, markersize = 30);
      
      # show plot
      visualizer.show();
  @endcode
docstr_tok: ["!","@","brief","Constructor","of","cluster","visualizer",".","@","param","[","in","]","number_canvases","(","uint",")",":","Number","of","canvases","that","is","used","for","visualization",".","@","param","[","in","]","size_row","(","uint",")",":","Amount","of","canvases","that","can","be","placed","in","one","row",".","@","param","[","in","]","titles","(","list",")",":","List","of","canvas","'s","titles",".","Example",":","@","code","#","load","2D","data","sample","sample_2d","=","read_sample","(","SIMPLE_SAMPLES.SAMPLE_SIMPLE1",")",";","#","load","3D","data","sample","sample_3d","=","read_sample","(","FCPS_SAMPLES.SAMPLE_HEPTA",")",";","#","extract","clusters","from","the","first","sample","using","DBSCAN","algorithm","dbscan_instance","=","dbscan","(","sample_2d",",","0.4",",","2",",","False",")",";","dbscan_instance.process","(",")",";","clusters_sample_2d","=","dbscan_instance.get_clusters","(",")",";","#","extract","clusters","from","the","second","sample","using","DBSCAN","algorithm","dbscan_instance","=","dbscan","(","sample_3d",",","1",",","3",",","True",")",";","dbscan_instance.process","(",")",";","clusters_sample_3d","=","dbscan_instance.get_clusters","(",")",";","#","create","plot","with","two","canvases","where","each","row","contains","2","canvases",".","size","=","2",";","row_size","=","2",";","visualizer","=","cluster_visualizer","(","size",",","row_size",")",";","#","place","clustering","result","of","sample_2d","to","the","first","canvas","visualizer.append_clusters","(","clusters_sample_2d",",","sample_2d",",","0",",","markersize","=","5",")",";","#","place","clustering","result","of","sample_3d","to","the","second","canvas","visualizer.append_clusters","(","clusters_sample_3d",",","sample_3d",",","1",",","markersize","=","30",")",";","#","show","plot","visualizer.show","(",")",";","@","endcode"]
code: def __init__(self, number_canvases=1, size_row=1, titles=None):
      """!
      @brief Constructor of cluster visualizer.
  
      @param[in] number_canvases (uint): Number of canvases that is used for visualization.
      @param[in] size_row (uint): Amount of canvases that can be placed in one row.
      @param[in] titles (list): List of canvas's titles.
  
      Example:
      @code
          # load 2D data sample
          sample_2d = read_sample(SIMPLE_SAMPLES.SAMPLE_SIMPLE1);
  
          # load 3D data sample
          sample_3d = read_sample(FCPS_SAMPLES.SAMPLE_HEPTA);
  
          # extract clusters from the first sample using DBSCAN algorithm
          dbscan_instance = dbscan(sample_2d, 0.4, 2, False);
          dbscan_instance.process();
          clusters_sample_2d = dbscan_instance.get_clusters();
  
          # extract clusters from the second sample using DBSCAN algorithm
          dbscan_instance = dbscan(sample_3d, 1, 3, True);
          dbscan_instance.process();
          clusters_sample_3d = dbscan_instance.get_clusters();
  
          # create plot with two canvases where each row contains 2 canvases.
          size = 2;
          row_size = 2;
          visualizer = cluster_visualizer(size, row_size);
  
          # place clustering result of sample_2d to the first canvas
          visualizer.append_clusters(clusters_sample_2d, sample_2d, 0, markersize = 5);
  
          # place clustering result of sample_3d to the second canvas
          visualizer.append_clusters(clusters_sample_3d, sample_3d, 1, markersize = 30);
  
          # show plot
          visualizer.show();
      @endcode
  
      """
  
      self.__number_canvases = number_canvases
      self.__size_row = size_row
      self.__canvas_clusters = [[] for _ in range(number_canvases)]
      self.__canvas_dimensions = [None for _ in range(number_canvases)]
      self.__canvas_titles = [None for _ in range(number_canvases)]
  
      if titles is not None:
          self.__canvas_titles = titles
  
      self.__default_2d_marker_size = 5
      self.__default_3d_marker_size = 30
  
imports: import itertools
  import math
  import matplotlib.pyplot
  import matplotlib.gridspec
  from mpl_toolkits.mplot3d import Axes3D
  from pyclustering.utils.color import color
label_desc: Use image node_id 1 to create a new cluster_visualizer object  with example: obj = cluster_visualizer(number_canvases, size_row, titles)