docs: def plot(*args, legend=None, title=None, x_axis_label="Time (s)", y_axis_label=None,
           grid_plot=False, grid_lines=None, grid_columns=None, hor_lines=None, hor_lines_leg=None,
           vert_lines=None, vert_lines_leg=None, apply_opensignals_style=True, show_plot=True,
           warn_print=False, get_fig_list=False, file_name=None, **kwargs):
      """
      -----
      Brief
      -----
      Plotting function intended for an easy representation of OpenSignals acquired data.
  
      -----------
      Description
      -----------
      This function allows to plot data acquired with resource to OpenSignals, available at
      https://bitalino.com/en/software, in an easy way using the Bokeh library (https://bokeh.pydata.org/en/latest/).
      The plot will automatically present the OpenSignals style if the corresponding parameter is set to True
      (apply_opensignals_style=True).
  
      This allows to easily use multiple plot elements without the need to know any visualization libraries.
  
      ----------
      Parameters
      ----------
      *args: list
          Variable number of arguments with the purpose of giving the user the possibility of
          defining as an input only the "data" axis or both "time" and "data" axes.
  
      legend : list
          Input where the legend of each plot is specified. Should have the same shape of time.
  
      title : list
          Input where the title of each figure is specified. Should have the same shape of time.
  
      x_axis_label : list
          Input where the x label of each figure is specified. All figures will have the same x label
          in the current implementation.
  
      y_axis_label : list
          Input where the y label of each figure is specified. Should have a length equal to the
          number of figures.
  
      grid_plot : boolean
          If True then the plots will be organized in a grid_plot structure.
  
      grid_lines : int
          Number of lines of grid plot.
  
      grid_columns : int
          Number of columns of grid plot.
  
      hor_lines : list of lists
          The parent list must have the same shape of time and each of its elements (child lists)
          must be formed by numbers defining the y axis position of the horizontal lines.
  
      hor_lines_leg : list of lists
          Legends of the horizontal lines (same shape of hor_lines).
  
      vert_lines : list of lists
          The parent list must have the same shape of time and each of its elements (child lists)
          must be formed by numbers defining the x axis position of the vertical lines.
  
      vert_lines_leg : list of lists
          Legends of the vertical lines (same shape of vert_lines).
  
      apply_opensignals_style : boolean
          If True then the OpenSignals style will be applied.
  
  
      show_plot : boolean
          If True the generated figures will be shown.
  
      warn_print : bool
          If True some warnings about invalid kwargs keys will be prompted.
  
      get_fig_list : bool
          If True then it will be returned a list containing the figure objects generated during
          the function execution.
  
      file_name : str
          Path containing the destination folder where the Bokeh figure will be stored.
  
      **kwargs : dict
          Keyword values for applying in bokeh figures, lines and gridplots.
  
      Returns
      -------
      out : bokeh figure or gridplot
          Object that is produced during the execution of the present function.
  
      """
  
      # Generation of the HTML file where the plot will be stored.
      #file_name = _generate_bokeh_file(file_name)
  
      # Data conversion for ensuring that the function only works with lists.
      if len(args) == 1:
          time = numpy.linspace(1, len(args[0]) + 1, len(args[0]))
          data = args[0]
      elif len(args) == 2:
          time = list(args[0])
          data = list(args[1])
      else:
          raise RuntimeError("biosignalsnotebooks plot function only accepts 1 or 2 arguments in *args"
                             " input. If only 1 input is given it should be a list with data samples,"
                             "otherwise if 2 inputs are given then the first one defines the time"
                             "axis and the second one data values.")
  
      # This function offers two input mechanisms (easy and complex). The easiest one consists in
      # the representation of a single plot in a single figure, so, the user only needs to specify as
      # inputs "time" and "data" lists. On the other hand, for the complex mechanism, the user can
      # represent plots in different figures, using for that lists of lists as "time" and "data"
      # inputs.
      # In the following lines is ensured that independently of the input given, the function will
      # achieve is purpose correctly.
      if _is_instance(Number, data, condition="all") and not _is_instance(bool, data, condition="any") \
              and _is_instance(Number, time, condition="all") \
              and not _is_instance(bool, time, condition="any"):
          time = [time]
          data = [data]
          if y_axis_label is not None:
              y_axis_label = [y_axis_label]
          if hor_lines is not None:
              hor_lines = [hor_lines]
          if hor_lines_leg is not None:
              hor_lines_leg = [hor_lines_leg]
          if vert_lines is not None:
              vert_lines = [vert_lines]
          if vert_lines_leg is not  None:
              vert_lines_leg = [vert_lines_leg]
          if title is not None:
              title = [title]
          if legend is not None:
              legend = [legend]
      elif _is_instance(numpy.ndarray, data, condition="any") \
              or _is_instance(numpy.ndarray, time, condition="any"):
          time = list(map(list, time))
          data = list(map(list, data))
  
      # Ensures the application or not of opensignals graphical style.
      if apply_opensignals_style is True:
          style_figure = {**opensignals_kwargs("figure"), **_filter_keywords(FigureOptions, kwargs,
                                                                             is_class=True,
                                                                             warn_print=warn_print)}
          style_line = {**opensignals_kwargs("line"), **_filter_keywords(Line, kwargs,
                                                                         warn_print=warn_print)}
          style_gridplot = {**opensignals_kwargs("gridplot"),
                            **_filter_keywords(gridplot, kwargs, warn_print=warn_print)}
      else:
          style_figure = _filter_keywords(FigureOptions, kwargs, is_class=True, warn_print=warn_print)
          style_line = _filter_keywords(Line, kwargs, warn_print=warn_print)
          style_gridplot = _filter_keywords(gridplot, kwargs, warn_print=warn_print)
  
      # ------------------------ Verification if the input arguments are valid ----------------------
      if legend is not None:
          if isinstance(legend, list):
              if len(legend) != len(time) or len(legend) != len(data):
                  raise RuntimeError("The shape of legend does not match with time input.")
          else:
              raise RuntimeError("The specified data type of legend field is not valid. Input must "
                                 "be a list.")
      else:
          legend = [None] * len(time)
  
      if title is not None:
          if isinstance(title, list):
              if len(title) != len(time) or len(title) != len(data):
                  raise RuntimeError("The shape of title does not match with time input.")
          elif isinstance(title, str):
              if grid_plot is True:
                  raise RuntimeError("Each figure of the gridplot must have a title, i.e., the shape"
                                     " of time, data and title inputs needs to match.")
              else:
                  title = [title] * len(time)
          elif grid_plot is False and len(title) != 1:
              raise RuntimeError("The number of titles is not compatible with the number of figures "
                                 "(only one title is needed).")
          else:
              raise RuntimeError("The specified data type of title field is not valid. Input must be "
                                 "a list.")
      else:
          title = [None] * len(time)
  
      if y_axis_label is not None:
          if isinstance(y_axis_label, list):
              if len(y_axis_label) != len(time) or len(y_axis_label) != len(data):
                  raise RuntimeError("The shape of y_axis_label does not match with time input.")
          elif isinstance(y_axis_label, str):
              y_axis_label = [y_axis_label] * len(time)
          elif grid_plot is False and len(y_axis_label) != 1:
              raise RuntimeError("The number of y axis labels is not compatible with the number of "
                                 "figures.")
          else:
              raise RuntimeError("The specified data type of y_axis_label field is not valid. Input "
                                 "must be a list or a string when grid_plot field is False.")
      else:
          y_axis_label = [None] * len(time)
  
      # Coherence between grid_plot, grid_lines and grid_columns inputs.
      if grid_lines is not None or grid_columns is not None:
          if grid_plot is not True:
              raise RuntimeError("When grid_lines and grid_columns inputs are used the field grid_"
                                 "plot must be True.")
          else:
              if not isinstance(grid_lines, int) or not isinstance(grid_columns, int):
                  raise RuntimeError("At least one of the grid_lines or grid_columns values is not "
                                     "an integer.")
  
      # Horizontal Lines.
      if hor_lines is not None:
          if isinstance(hor_lines, list):
              if len(hor_lines) != len(time) or len(hor_lines) != len(data):
                  raise RuntimeError("The shape of hor_lines does not match with time input.")
          else:
              raise RuntimeError("The specified data type of hor_lines field is not valid. Input "
                                 "must be a list of lists.")
  
          # Each sublist entry must be numeric.
          for cell in hor_lines:
              if not _is_instance(Number, cell, condition="all") \
                      or _is_instance(bool, cell, condition="any"):
                  raise RuntimeError("At least one of the list elements, specified in hor_lines, "
                                     "is not numeric.")
              elif vert_lines_leg is not None:
                  if len(hor_lines) != len(hor_lines_leg):
                      raise RuntimeError("The shape of hor_lines and hor_lines_leg is not the same.")
  
      # Vertical Lines.
      if vert_lines is not None:
          if isinstance(vert_lines, list):
              if len(vert_lines) != len(time) or len(vert_lines) != len(data):
                  raise RuntimeError("The shape of vert_lines does not match with time input.")
          else:
              raise RuntimeError("The specified data type of vert_lines field is not valid. "
                                 "Input must be a list of lists.")
  
          # Each sublist entry must be numeric.
          for cell in vert_lines:
              if not _is_instance(Number, cell, condition="all") \
                      or _is_instance(bool, cell, condition="any"):
                  raise RuntimeError("At least one of the list elements, specified in vert_lines, "
                                     "is not numeric.")
              elif vert_lines_leg is not None:
                  if len(vert_lines) != len(vert_lines_leg):
                      raise RuntimeError("The shape of vert_lines and vert_lines_leg is not "
                                         "the same.")
  
      # --------------------------------------- Plotting Stage --------------------------------------
      fig_list = []
      # If all data entries are lists, then it is considered that we are in a multiplot situation.
      if _is_instance(list, data, condition="all") and _is_instance(list, time, condition="all"):
          for list_entry in range(0, len(time)):  # Generation of a figure per plot.
              # Verification if all elements inside list are numbers.
              if _is_instance(Number, data[list_entry], condition="all") \
                      and not _is_instance(bool, data[list_entry], condition="any") \
                      and _is_instance(Number, time[list_entry], condition="all") \
                      and not _is_instance(bool, time[list_entry], condition="any"):
                  if len(time[list_entry]) == len(data[list_entry]):  # Shape verification
                      if grid_plot is True:  # Generation of multiple figures.
                          fig_list.append(figure(title=title[list_entry],
                                                 y_axis_label=y_axis_label[list_entry],
                                                 x_axis_label=x_axis_label,
                                                 **style_figure))
                      elif grid_plot is False and list_entry == 0:
                          fig_list.append(figure(title=title[list_entry],
                                                 y_axis_label=y_axis_label[list_entry],
                                                 x_axis_label=x_axis_label,
                                                 sizing_mode='scale_both',
                                                 **style_figure))
  
                      fig_list[-1].line(time[list_entry], data[list_entry], legend=legend[list_entry],
                                        **style_line)
  
                      # Representation of horizontal lines.
                      if hor_lines is not None:
                          for hor_line_nbr, hor_line in enumerate(hor_lines[list_entry]):
                              if hor_lines_leg is not None:
                                  fig_list[-1].line([time[list_entry][0], time[list_entry][-1]],
                                                    [hor_line, hor_line],
                                                    legend=hor_lines_leg[list_entry][hor_line_nbr],
                                                    **opensignals_kwargs("line"))
                              else:
                                  fig_list[-1].line([time[list_entry][0], time[list_entry][-1]],
                                                    [hor_line, hor_line],
                                                    **opensignals_kwargs("line"))
  
                      # Representation of vertical lines.
                      if vert_lines is not None:
                          for vert_line_nbr, vert_line in enumerate(vert_lines[list_entry]):
                              if vert_lines_leg is not None:
                                  fig_list[-1].line([vert_line, vert_line],
                                                    [numpy.min(data[list_entry]),
                                                     numpy.max(data[list_entry])],
                                                    legend=vert_lines_leg[list_entry][vert_line_nbr],
                                                    **opensignals_kwargs("line"))
                              else:
                                  fig_list[-1].line([vert_line, vert_line],
                                                    [numpy.min(data[list_entry]),
                                                     numpy.max(data[list_entry])],
                                                    **opensignals_kwargs("line"))
  
                      # Update of line style.
                      if apply_opensignals_style is True:
                          style_line = {**opensignals_kwargs("line"),
                                        **_filter_keywords(Line, kwargs, warn_print=warn_print)}
                      else:
                          style_line = _filter_keywords(Line, kwargs, warn_print=warn_print)
  
                  else:
                      raise RuntimeError("The shape of time and data inputs does not match.")
              else:
                  raise RuntimeError("At least one of the list elements, specified in data or time, "
                                     "is not numeric.")
  
      # If this happen, then we receive as input a single list for time and data
      # (Single plot perspective).
      elif _is_instance(Number, data, condition="all") \
              and not _is_instance(bool, data, condition="any") \
              and _is_instance(Number, time, condition="all") \
              and not _is_instance(bool, time, condition="any"):
          grid_plot = False
  
          # Verification if all elements inside list are numbers.
          if _is_instance(Number, data, condition="all") \
                  and not _is_instance(bool, data, condition="any") \
                  and _is_instance(Number, time, condition="all") \
                  and not _is_instance(bool, time, condition="any"):
              if len(time) == len(data):  # Shape verification
                  fig_list.append(figure(title=title[0], y_axis_label=y_axis_label[0],
                                         x_axis_label=x_axis_label, **style_figure))
                  fig_list[-1].line(time, data, legend=legend[0], **style_line)
              else:
                  raise RuntimeError("The shape of time and data inputs does not match.")
          else:
              raise RuntimeError("At least one of the list elements, specified in data or time, is "
                                 "not numeric.")
  
      else:
          raise RuntimeError("The input 'data' or/and 'time' does not have a valid format. It should "
                             "be a list of numbers or a list of lists.")
  
      # Application of the OpenSignals Style.
      if apply_opensignals_style is True:
          opensignals_style(fig_list)
  
      # Show of plots.
      if grid_plot is True:
          nbr_of_spaces = grid_lines * grid_columns
          nbr_of_figures = len(fig_list)
  
          if nbr_of_spaces >= nbr_of_figures > (grid_lines - 1) * grid_columns:
              # Organization of data accordingly to the number of rows and columns specified as input
              # arguments.
              grid_layout = []
              fig_nbr = 0
              for row in range(0, grid_lines):
                  grid_layout.append([])
                  for column in range(0, grid_columns):
                      if fig_nbr <= nbr_of_figures - 1:
                          grid_layout[-1].append(fig_list[fig_nbr])
                      else:
                          grid_layout[-1].append(None)
  
                      # Update of auxiliary variable.
                      fig_nbr += 1
  
              # Generation of the gridplot.
              grid = gridplot(grid_layout, **style_gridplot)
  
              if show_plot is True:
                  show(grid)
              #else:
              #    save(grid)
                  #return HTML('<iframe width=100% height=350 src="generated_plots/' + file_name + '"></iframe>')
          else:
              raise RuntimeError("The specified number of lines and columns for the grid plot is not "
                                 "compatible.")
  
      else:
          if show_plot is True:
              show(fig_list[-1])
          #else:
          #    save(fig_list[-1])
              #return HTML('<iframe width=100% height="' + str(fig_list[-1].plot_height) + '" src="generated_plots/' + file_name + '"></iframe>')
  
      if get_fig_list is True:
          return fig_list