code: def make_subplots(
      rows=1,
      cols=1,
      shared_xaxes=False,
      shared_yaxes=False,
      start_cell="top-left",
      print_grid=False,
      horizontal_spacing=None,
      vertical_spacing=None,
      subplot_titles=None,
      column_widths=None,
      row_heights=None,
      specs=None,
      insets=None,
      column_titles=None,
      row_titles=None,
      x_title=None,
      y_title=None,
      figure=None,
      **kwargs,
  ):
      """
      Return an instance of plotly.graph_objs.Figure with predefined subplots
      configured in 'layout'.
  
      Parameters
      ----------
      rows: int (default 1)
          Number of rows in the subplot grid. Must be greater than zero.
  
      cols: int (default 1)
          Number of columns in the subplot grid. Must be greater than zero.
  
      shared_xaxes: boolean or str (default False)
          Assign shared (linked) x-axes for 2D cartesian subplots
  
            - True or 'columns': Share axes among subplots in the same column
            - 'rows': Share axes among subplots in the same row
            - 'all': Share axes across all subplots in the grid.
  
      shared_yaxes: boolean or str (default False)
          Assign shared (linked) y-axes for 2D cartesian subplots
  
            - 'columns': Share axes among subplots in the same column
            - True or 'rows': Share axes among subplots in the same row
            - 'all': Share axes across all subplots in the grid.
  
      start_cell: 'bottom-left' or 'top-left' (default 'top-left')
          Choose the starting cell in the subplot grid used to set the
          domains_grid of the subplots.
  
            - 'top-left': Subplots are numbered with (1, 1) in the top
                          left corner
            - 'bottom-left': Subplots are numbererd with (1, 1) in the bottom
                             left corner
  
      print_grid: boolean (default True):
          If True, prints a string representation of the plot grid.  Grid may
          also be printed using the `Figure.print_grid()` method on the
          resulting figure.
  
      horizontal_spacing: float (default 0.2 / cols)
          Space between subplot columns in normalized plot coordinates. Must be
          a float between 0 and 1.
  
          Applies to all columns (use 'specs' subplot-dependents spacing)
  
      vertical_spacing: float (default 0.3 / rows)
          Space between subplot rows in normalized plot coordinates. Must be
          a float between 0 and 1.
  
          Applies to all rows (use 'specs' subplot-dependents spacing)
  
      subplot_titles: list of str or None (default None)
          Title of each subplot as a list in row-major ordering.
  
          Empty strings ("") can be included in the list if no subplot title
          is desired in that space so that the titles are properly indexed.
  
      specs: list of lists of dict or None (default None)
          Per subplot specifications of subplot type, row/column spanning, and
          spacing.
  
          ex1: specs=[[{}, {}], [{'colspan': 2}, None]]
  
          ex2: specs=[[{'rowspan': 2}, {}], [None, {}]]
  
          - Indices of the outer list correspond to subplot grid rows
            starting from the top, if start_cell='top-left',
            or bottom, if start_cell='bottom-left'.
            The number of rows in 'specs' must be equal to 'rows'.
  
          - Indices of the inner lists correspond to subplot grid columns
            starting from the left. The number of columns in 'specs'
            must be equal to 'cols'.
  
          - Each item in the 'specs' list corresponds to one subplot
            in a subplot grid. (N.B. The subplot grid has exactly 'rows'
            times 'cols' cells.)
  
          - Use None for a blank a subplot cell (or to move past a col/row span).
  
          - Note that specs[0][0] has the specs of the 'start_cell' subplot.
  
          - Each item in 'specs' is a dictionary.
              The available keys are:
              * type (string, default 'xy'): Subplot type. One of
                  - 'xy': 2D Cartesian subplot type for scatter, bar, etc.
                  - 'scene': 3D Cartesian subplot for scatter3d, cone, etc.
                  - 'polar': Polar subplot for scatterpolar, barpolar, etc.
                  - 'ternary': Ternary subplot for scatterternary
                  - 'mapbox': Mapbox subplot for scattermapbox
                  - 'domain': Subplot type for traces that are individually
                              positioned. pie, parcoords, parcats, etc.
                  - trace type: A trace type which will be used to determine
                                the appropriate subplot type for that trace
  
              * secondary_y (bool, default False): If True, create a secondary
                  y-axis positioned on the right side of the subplot. Only valid
                  if type='xy'.
              * colspan (int, default 1): number of subplot columns
                  for this subplot to span.
              * rowspan (int, default 1): number of subplot rows
                  for this subplot to span.
              * l (float, default 0.0): padding left of cell
              * r (float, default 0.0): padding right of cell
              * t (float, default 0.0): padding right of cell
              * b (float, default 0.0): padding bottom of cell
  
          - Note: Use 'horizontal_spacing' and 'vertical_spacing' to adjust
            the spacing in between the subplots.
  
      insets: list of dict or None (default None):
          Inset specifications.  Insets are subplots that overlay grid subplots
  
          - Each item in 'insets' is a dictionary.
              The available keys are:
  
              * cell (tuple, default=(1,1)): (row, col) index of the
                  subplot cell to overlay inset axes onto.
              * type (string, default 'xy'): Subplot type
              * l (float, default=0.0): padding left of inset
                    in fraction of cell width
              * w (float or 'to_end', default='to_end') inset width
                    in fraction of cell width ('to_end': to cell right edge)
              * b (float, default=0.0): padding bottom of inset
                    in fraction of cell height
              * h (float or 'to_end', default='to_end') inset height
                    in fraction of cell height ('to_end': to cell top edge)
  
      column_widths: list of numbers or None (default None)
          list of length `cols` of the relative widths of each column of suplots.
          Values are normalized internally and used to distribute overall width
          of the figure (excluding padding) among the columns.
  
          For backward compatibility, may also be specified using the
          `column_width` keyword argument.
  
      row_heights: list of numbers or None (default None)
          list of length `rows` of the relative heights of each row of subplots.
          If start_cell='top-left' then row heights are applied top to bottom.
          Otherwise, if start_cell='bottom-left' then row heights are applied
          bottom to top.
  
          For backward compatibility, may also be specified using the
          `row_width` kwarg. If specified as `row_width`, then the width values
          are applied from bottom to top regardless of the value of start_cell.
          This matches the legacy behavior of the `row_width` argument.
  
      column_titles: list of str or None (default None)
          list of length `cols` of titles to place above the top subplot in
          each column.
  
      row_titles: list of str or None (default None)
          list of length `rows` of titles to place on the right side of each
          row of subplots. If start_cell='top-left' then row titles are
          applied top to bottom. Otherwise, if start_cell='bottom-left' then
          row titles are applied bottom to top.
  
      x_title: str or None (default None)
          Title to place below the bottom row of subplots,
          centered horizontally
  
      y_title: str or None (default None)
          Title to place to the left of the left column of subplots,
          centered vertically
  
      figure: go.Figure or None (default None)
          If None, a new go.Figure instance will be created and its axes will be
          populated with those corresponding to the requested subplot geometry and
          this new figure will be returned.
          If a go.Figure instance, the axes will be added to the
          layout of this figure and this figure will be returned. If the figure
          already contains axes, they will be overwritten.
  
      Examples
      --------
  
      Example 1:
  
      >>> # Stack two subplots vertically, and add a scatter trace to each
      >>> from plotly.subplots import make_subplots
      >>> import plotly.graph_objects as go
      >>> fig = make_subplots(rows=2)
  
      This is the format of your plot grid:
      [ (1,1) xaxis1,yaxis1 ]
      [ (2,1) xaxis2,yaxis2 ]
  
      >>> fig.add_scatter(y=[2, 1, 3], row=1, col=1) # doctest: +ELLIPSIS
      Figure(...)
      >>> fig.add_scatter(y=[1, 3, 2], row=2, col=1) # doctest: +ELLIPSIS
      Figure(...)
  
      or see Figure.append_trace
  
      Example 2:
  
      >>> # Stack a scatter plot
      >>> fig = make_subplots(rows=2, shared_xaxes=True)
  
      This is the format of your plot grid:
      [ (1,1) xaxis1,yaxis1 ]
      [ (2,1) xaxis2,yaxis2 ]
  
      >>> fig.add_scatter(y=[2, 1, 3], row=1, col=1) # doctest: +ELLIPSIS
      Figure(...)
      >>> fig.add_scatter(y=[1, 3, 2], row=2, col=1) # doctest: +ELLIPSIS
      Figure(...)
  
      Example 3:
  
      >>> # irregular subplot layout (more examples below under 'specs')
      >>> fig = make_subplots(rows=2, cols=2,
      ...                     specs=[[{}, {}],
      ...                     [{'colspan': 2}, None]])
  
      This is the format of your plot grid:
      [ (1,1) xaxis1,yaxis1 ]  [ (1,2) xaxis2,yaxis2 ]
      [ (2,1) xaxis3,yaxis3           -              ]
  
      >>> fig.add_trace(go.Scatter(x=[1,2,3], y=[2,1,2]), row=1, col=1) # doctest: +ELLIPSIS
      Figure(...)
      >>> fig.add_trace(go.Scatter(x=[1,2,3], y=[2,1,2]), row=1, col=2) # doctest: +ELLIPSIS
      Figure(...)
      >>> fig.add_trace(go.Scatter(x=[1,2,3], y=[2,1,2]), row=2, col=1) # doctest: +ELLIPSIS
      Figure(...)
  
      Example 4:
  
      >>> # insets
      >>> fig = make_subplots(insets=[{'cell': (1,1), 'l': 0.7, 'b': 0.3}])
  
      This is the format of your plot grid:
      [ (1,1) xaxis1,yaxis1 ]
  
      With insets:
      [ xaxis2,yaxis2 ] over [ (1,1) xaxis1,yaxis1 ]
  
      >>> fig.add_scatter(x=[1,2,3], y=[2,1,1]) # doctest: +ELLIPSIS
      Figure(...)
      >>> fig.add_scatter(x=[1,2,3], y=[2,1,2], xaxis='x2', yaxis='y2') # doctest: +ELLIPSIS
      Figure(...)
  
      Example 5:
  
      >>> # include subplot titles
      >>> fig = make_subplots(rows=2, subplot_titles=('Plot 1','Plot 2'))
  
      This is the format of your plot grid:
      [ (1,1) x1,y1 ]
      [ (2,1) x2,y2 ]
  
      >>> fig.add_scatter(x=[1,2,3], y=[2,1,2], row=1, col=1) # doctest: +ELLIPSIS
      Figure(...)
      >>> fig.add_bar(x=[1,2,3], y=[2,1,2], row=2, col=1) # doctest: +ELLIPSIS
      Figure(...)
  
      Example 6:
  
      Subplot with mixed subplot types
  
      >>> fig = make_subplots(rows=2, cols=2,
      ...                     specs=[[{'type': 'xy'},    {'type': 'polar'}],
      ...                            [{'type': 'scene'}, {'type': 'ternary'}]])
  
      >>> fig.add_traces(
      ...     [go.Scatter(y=[2, 3, 1]),
      ...      go.Scatterpolar(r=[1, 3, 2], theta=[0, 45, 90]),
      ...      go.Scatter3d(x=[1, 2, 1], y=[2, 3, 1], z=[0, 3, 5]),
      ...      go.Scatterternary(a=[0.1, 0.2, 0.1],
      ...                        b=[0.2, 0.3, 0.1],
      ...                        c=[0.7, 0.5, 0.8])],
      ...     rows=[1, 1, 2, 2],
      ...     cols=[1, 2, 1, 2]) # doctest: +ELLIPSIS
      Figure(...)
      """
  
      import plotly.graph_objs as go
  
      # Handle backward compatibility
      # -----------------------------
      use_legacy_row_heights_order = "row_width" in kwargs
      row_heights = kwargs.pop("row_width", row_heights)
      column_widths = kwargs.pop("column_width", column_widths)
  
      if kwargs:
          raise TypeError(
              "make_subplots() got unexpected keyword argument(s): {}".format(
                  list(kwargs)
              )
          )
  
      # Validate coerce inputs
      # ----------------------
      #  ### rows ###
      if not isinstance(rows, int) or rows <= 0:
          raise ValueError(
              """
  The 'rows' argument to make_suplots must be an int greater than 0.
      Received value of type {typ}: {val}""".format(
                  typ=type(rows), val=repr(rows)
              )
          )
  
      #  ### cols ###
      if not isinstance(cols, int) or cols <= 0:
          raise ValueError(
              """
  The 'cols' argument to make_suplots must be an int greater than 0.
      Received value of type {typ}: {val}""".format(
                  typ=type(cols), val=repr(cols)
              )
          )
  
      # ### start_cell ###
      if start_cell == "bottom-left":
          col_dir = 1
          row_dir = 1
      elif start_cell == "top-left":
          col_dir = 1
          row_dir = -1
      else:
          raise ValueError(
              """
  The 'start_cell` argument to make_subplots must be one of \
  ['bottom-left', 'top-left']
      Received value of type {typ}: {val}""".format(
                  typ=type(start_cell), val=repr(start_cell)
              )
          )
  
      # ### Helper to validate coerce elements of lists of dictionaries ###
      def _check_keys_and_fill(name, arg, defaults):
          def _checks(item, defaults):
              if item is None:
                  return
              if not isinstance(item, dict):
                  raise ValueError(
                      """
  Elements of the '{name}' argument to make_suplots must be dictionaries \
  or None.
      Received value of type {typ}: {val}""".format(
                          name=name, typ=type(item), val=repr(item)
                      )
                  )
  
              for k in item:
                  if k not in defaults:
                      raise ValueError(
                          """
  Invalid key specified in an element of the '{name}' argument to \
  make_subplots: {k}
      Valid keys include: {valid_keys}""".format(
                              k=repr(k),
                              name=name,
                              valid_keys=repr(list(defaults)),
                          )
                      )
              for k, v in defaults.items():
                  item.setdefault(k, v)
  
          for arg_i in arg:
              if isinstance(arg_i, (list, tuple)):
                  # 2D list
                  for arg_ii in arg_i:
                      _checks(arg_ii, defaults)
              elif isinstance(arg_i, dict):
                  # 1D list
                  _checks(arg_i, defaults)
  
      # ### specs ###
      if specs is None:
          specs = [[{} for c in range(cols)] for r in range(rows)]
      elif not (
          isinstance(specs, (list, tuple))
          and specs
          and all(isinstance(row, (list, tuple)) for row in specs)
          and len(specs) == rows
          and all(len(row) == cols for row in specs)
          and all(
              all(v is None or isinstance(v, dict) for v in row)
              for row in specs
          )
      ):
          raise ValueError(
              """
  The 'specs' argument to make_subplots must be a 2D list of dictionaries with \
  dimensions ({rows} x {cols}).
      Received value of type {typ}: {val}""".format(
                  rows=rows, cols=cols, typ=type(specs), val=repr(specs)
              )
          )
  
      for row in specs:
          for spec in row:
              # For backward compatibility,
              # convert is_3d flag to type='scene' kwarg
              if spec and spec.pop("is_3d", None):
                  spec["type"] = "scene"
  
      spec_defaults = dict(
          type="xy",
          secondary_y=False,
          colspan=1,
          rowspan=1,
          l=0.0,
          r=0.0,
          b=0.0,
          t=0.0,
      )
      _check_keys_and_fill("specs", specs, spec_defaults)
  
      # Validate secondary_y
      has_secondary_y = False
      for row in specs:
          for spec in row:
              if spec is not None:
                  has_secondary_y = (
                      has_secondary_y or spec["secondary_y"]
                  )
              if spec and spec["type"] != "xy" and spec["secondary_y"]:
                  raise ValueError(
                      """
  The 'secondary_y' spec property is not supported for subplot of type '{s_typ}'
       'secondary_y' is only supported for subplots of type 'xy'
  """.format(
                          s_typ=spec["type"]
                      )
                  )
  
      # ### insets ###
      if insets is None or insets is False:
          insets = []
      elif not (
          isinstance(insets, (list, tuple))
          and all(isinstance(v, dict) for v in insets)
      ):
          raise ValueError(
              """
  The 'insets' argument to make_suplots must be a list of dictionaries.
      Received value of type {typ}: {val}""".format(
                  typ=type(insets), val=repr(insets)
              )
          )
  
      if insets:
          for inset in insets:
              if inset and inset.pop("is_3d", None):
                  inset["type"] = "scene"
  
          inset_defaults = dict(
              cell=(1, 1),
              type="xy",
              l=0.0,
              w="to_end",
              b=0.0,
              h="to_end",
          )
          _check_keys_and_fill("insets", insets, inset_defaults)
  
      # ### shared_xaxes / shared_yaxes
      valid_shared_vals = [None, True, False, "rows", "columns", "all"]
      shared_err_msg = """
  The {arg} argument to make_subplots must be one of: {valid_vals}
      Received value of type {typ}: {val}"""
  
      if shared_xaxes not in valid_shared_vals:
          val = shared_xaxes
          raise ValueError(
              shared_err_msg.format(
                  arg="shared_xaxes",
                  valid_vals=valid_shared_vals,
                  typ=type(val),
                  val=repr(val),
              )
          )
      if shared_yaxes not in valid_shared_vals:
          val = shared_yaxes
          raise ValueError(
              shared_err_msg.format(
                  arg="shared_yaxes",
                  valid_vals=valid_shared_vals,
                  typ=type(val),
                  val=repr(val),
              )
          )
  
      def _check_hv_spacing(
          dimsize, spacing, name, dimvarname, dimname
      ):
          if spacing < 0 or spacing > 1:
              raise ValueError(
                  "%s spacing must be between 0 and 1." % (name,)
              )
          if dimsize <= 1:
              return
          max_spacing = 1.0 / float(dimsize - 1)
          if spacing > max_spacing:
              raise ValueError(
                  """{name} spacing cannot be greater than (1 / ({dimvarname} - 1)) = {max_spacing:f}.
  The resulting plot would have {dimsize} {dimname} ({dimvarname}={dimsize}).""".format(
                      dimvarname=dimvarname,
                      name=name,
                      dimname=dimname,
                      max_spacing=max_spacing,
                      dimsize=dimsize,
                  )
              )
  
      # ### horizontal_spacing ###
      if horizontal_spacing is None:
          if has_secondary_y:
              horizontal_spacing = 0.4 / cols
          else:
              horizontal_spacing = 0.2 / cols
      # check horizontal_spacing can be satisfied:
      _check_hv_spacing(
          cols, horizontal_spacing, "Horizontal", "cols", "columns"
      )
  
      # ### vertical_spacing ###
      if vertical_spacing is None:
          if subplot_titles is not None:
              vertical_spacing = 0.5 / rows
          else:
              vertical_spacing = 0.3 / rows
      # check vertical_spacing can be satisfied:
      _check_hv_spacing(
          rows, vertical_spacing, "Vertical", "rows", "rows"
      )
  
      # ### subplot titles ###
      if subplot_titles is None:
          subplot_titles = [""] * rows * cols
  
      # ### column_widths ###
      if has_secondary_y:
          # Add room for secondary y-axis title
          max_width = 0.94
      elif row_titles:
          # Add a little breathing room between row labels and legend
          max_width = 0.98
      else:
          max_width = 1.0
  
      if column_widths is None:
          widths = [
              (max_width - horizontal_spacing * (cols - 1)) / cols
          ] * cols
      elif (
          isinstance(column_widths, (list, tuple))
          and len(column_widths) == cols
      ):
          cum_sum = float(sum(column_widths))
          widths = []
          for w in column_widths:
              widths.append(
                  (max_width - horizontal_spacing * (cols - 1))
                  * (w / cum_sum)
              )
      else:
          raise ValueError(
              """
  The 'column_widths' argument to make_suplots must be a list of numbers of \
  length {cols}.
      Received value of type {typ}: {val}""".format(
                  cols=cols,
                  typ=type(column_widths),
                  val=repr(column_widths),
              )
          )
  
      # ### row_heights ###
      if row_heights is None:
          heights = [
              (1.0 - vertical_spacing * (rows - 1)) / rows
          ] * rows
      elif (
          isinstance(row_heights, (list, tuple))
          and len(row_heights) == rows
      ):
          cum_sum = float(sum(row_heights))
          heights = []
          for h in row_heights:
              heights.append(
                  (1.0 - vertical_spacing * (rows - 1)) * (h / cum_sum)
              )
          if row_dir < 0 and not use_legacy_row_heights_order:
              heights = list(reversed(heights))
      else:
          raise ValueError(
              """
  The 'row_heights' argument to make_suplots must be a list of numbers of \
  length {rows}.
      Received value of type {typ}: {val}""".format(
                  rows=rows,
                  typ=type(row_heights),
                  val=repr(row_heights),
              )
          )
  
      # ### column_titles / row_titles ###
      if column_titles and not isinstance(column_titles, (list, tuple)):
          raise ValueError(
              """
  The column_titles argument to make_subplots must be a list or tuple
      Received value of type {typ}: {val}""".format(
                  typ=type(column_titles), val=repr(column_titles)
              )
          )
  
      if row_titles and not isinstance(row_titles, (list, tuple)):
          raise ValueError(
              """
  The row_titles argument to make_subplots must be a list or tuple
      Received value of type {typ}: {val}""".format(
                  typ=type(row_titles), val=repr(row_titles)
              )
          )
  
      # Init layout
      # -----------
      layout = go.Layout()
  
      # Build grid reference
      # --------------------
      # Built row/col sequence using 'row_dir' and 'col_dir'
      col_seq = range(cols)[::col_dir]
      row_seq = range(rows)[::row_dir]
  
      # Build 2D array of tuples of the start x and start y coordinate of each
      # subplot
      grid = [
          [
              (
                  (sum(widths[:c]) + c * horizontal_spacing),
                  (sum(heights[:r]) + r * vertical_spacing),
              )
              for c in col_seq
          ]
          for r in row_seq
      ]
  
      domains_grid = [[None for _ in range(cols)] for _ in range(rows)]
  
      # Initialize subplot reference lists for the grid and insets
      grid_ref = [[None for c in range(cols)] for r in range(rows)]
  
      list_of_domains = []  # added for subplot titles
  
      max_subplot_ids = _get_initial_max_subplot_ids()
  
      # Loop through specs -- (r, c) <-> (row, col)
      for r, spec_row in enumerate(specs):
          for c, spec in enumerate(spec_row):
              if spec is None:  # skip over None cells
                  continue
  
              # ### Compute x and y domain for subplot ###
              c_spanned = c + spec["colspan"] - 1  # get spanned c
              r_spanned = r + spec["rowspan"] - 1  # get spanned r
  
              # Throw exception if 'colspan' | 'rowspan' is too large for grid
              if c_spanned >= cols:
                  raise Exception(
                      "Some 'colspan' value is too large for "
                      "this subplot grid."
                  )
              if r_spanned >= rows:
                  raise Exception(
                      "Some 'rowspan' value is too large for "
                      "this subplot grid."
                  )
  
              # Get x domain using grid and colspan
              x_s = grid[r][c][0] + spec["l"]
  
              x_e = (
                  grid[r][c_spanned][0] + widths[c_spanned] - spec["r"]
              )
              x_domain = [x_s, x_e]
  
              # Get y domain (dep. on row_dir) using grid & r_spanned
              if row_dir > 0:
                  y_s = grid[r][c][1] + spec["b"]
                  y_e = (
                      grid[r_spanned][c][1]
                      + heights[r_spanned]
                      - spec["t"]
                  )
              else:
                  y_s = grid[r_spanned][c][1] + spec["b"]
                  y_e = grid[r][c][1] + heights[-1 - r] - spec["t"]
              y_domain = [y_s, y_e]
  
              list_of_domains.append(x_domain)
              list_of_domains.append(y_domain)
  
              domains_grid[r][c] = [x_domain, y_domain]
  
              # ### construct subplot container ###
              subplot_type = spec["type"]
              secondary_y = spec["secondary_y"]
              subplot_refs = _init_subplot(
                  layout,
                  subplot_type,
                  secondary_y,
                  x_domain,
                  y_domain,
                  max_subplot_ids,
              )
              grid_ref[r][c] = subplot_refs
  
      _configure_shared_axes(
          layout, grid_ref, specs, "x", shared_xaxes, row_dir
      )
      _configure_shared_axes(
          layout, grid_ref, specs, "y", shared_yaxes, row_dir
      )
  
      # Build inset reference
      # ---------------------
      # Loop through insets
      insets_ref = (
          [None for inset in range(len(insets))] if insets else None
      )
      if insets:
          for i_inset, inset in enumerate(insets):
              r = inset["cell"][0] - 1
              c = inset["cell"][1] - 1
  
              # Throw exception if r | c is out of range
              if not (0 <= r < rows):
                  raise Exception(
                      "Some 'cell' row value is out of range. "
                      "Note: the starting cell is (1, 1)"
                  )
              if not (0 <= c < cols):
                  raise Exception(
                      "Some 'cell' col value is out of range. "
                      "Note: the starting cell is (1, 1)"
                  )
  
              # Get inset x domain using grid
              x_s = grid[r][c][0] + inset["l"] * widths[c]
              if inset["w"] == "to_end":
                  x_e = grid[r][c][0] + widths[c]
              else:
                  x_e = x_s + inset["w"] * widths[c]
              x_domain = [x_s, x_e]
  
              # Get inset y domain using grid
              y_s = grid[r][c][1] + inset["b"] * heights[-1 - r]
              if inset["h"] == "to_end":
                  y_e = grid[r][c][1] + heights[-1 - r]
              else:
                  y_e = y_s + inset["h"] * heights[-1 - r]
              y_domain = [y_s, y_e]
  
              list_of_domains.append(x_domain)
              list_of_domains.append(y_domain)
  
              subplot_type = inset["type"]
  
              subplot_refs = _init_subplot(
                  layout,
                  subplot_type,
                  False,
                  x_domain,
                  y_domain,
                  max_subplot_ids,
              )
  
              insets_ref[i_inset] = subplot_refs
  
      # Build grid_str
      # This is the message printed when print_grid=True
      grid_str = _build_grid_str(
          specs, grid_ref, insets, insets_ref, row_seq
      )
  
      # Add subplot titles
      plot_title_annotations = _build_subplot_title_annotations(
          subplot_titles, list_of_domains
      )
  
      layout["annotations"] = plot_title_annotations
  
      # Add column titles
      if column_titles:
          domains_list = []
          if row_dir > 0:
              for c in range(cols):
                  domain_pair = domains_grid[-1][c]
                  if domain_pair:
                      domains_list.extend(domain_pair)
          else:
              for c in range(cols):
                  domain_pair = domains_grid[0][c]
                  if domain_pair:
                      domains_list.extend(domain_pair)
  
          # Add subplot titles
          column_title_annotations = _build_subplot_title_annotations(
              column_titles, domains_list
          )
  
          layout["annotations"] += tuple(column_title_annotations)
  
      if row_titles:
          domains_list = []
          for r in range(rows):
              domain_pair = domains_grid[r][-1]
              if domain_pair:
                  domains_list.extend(domain_pair)
  
          # Add subplot titles
          column_title_annotations = _build_subplot_title_annotations(
              row_titles, domains_list, title_edge="right"
          )
  
          layout["annotations"] += tuple(column_title_annotations)
  
      if x_title:
          domains_list = [(0, max_width), (0, 1)]
  
          # Add subplot titles
          column_title_annotations = _build_subplot_title_annotations(
              [x_title], domains_list, title_edge="bottom", offset=30
          )
  
          layout["annotations"] += tuple(column_title_annotations)
  
      if y_title:
          domains_list = [(0, 1), (0, 1)]
  
          # Add subplot titles
          column_title_annotations = _build_subplot_title_annotations(
              [y_title], domains_list, title_edge="left", offset=40
          )
  
          layout["annotations"] += tuple(column_title_annotations)
  
      # Handle displaying grid information
      if print_grid:
          print(grid_str)
  
      # Build resulting figure
      if figure is None:
          figure = go.Figure()
      figure.update_layout(layout)
  
      # Attach subplot grid info to the figure
      figure.__dict__["_grid_ref"] = grid_ref
      figure.__dict__["_grid_str"] = grid_str
  
      return figure
  
file_path: catboost/contrib/python/plotly/py2/plotly/subplots.py
imports: from __future__ import absolute_import, unicode_literals
  import collections
label_desc: Use image node_id 2 for calling a global function with example usage: make_subplots(rows, cols, shared_xaxes, shared_yaxes, start_cell, print_grid, horizontal_spacing, vertical_spacing, subplot_titles, column_widths, row_heights, specs, insets, column_titles, row_titles, x_title, y_title, figure) and returns: figure