class_docstr: Scatter matrix (aka pair plot) with scatters, KDE and correlation Heatmap.
class_docstr_tok: ["Scatter","matrix","(","aka","pair","plot",")","with","scatters",",","KDE","and","correlation","Heatmap","."]
code: def _create_figure(self) -> go.Figure:
      nrows, ncols = self.corr.shape
      opt_xaxis = deepcopy(self.VIZBASE_LAYOUT_OPTS.get("xaxis", {}))
      opt_yaxis = deepcopy(self.VIZBASE_LAYOUT_OPTS.get("yaxis", {}))
      cmap_pos = cmapper(0, 1, cmap="Blues")
      cmap_neg = cmapper(-1, 0, cmap="Purples_r")
  
      fig = make_subplots(
          rows=nrows,
          cols=ncols,
          start_cell="top-left",
          shared_xaxes=False,
          shared_yaxes=False,
          horizontal_spacing=0,
          vertical_spacing=0,
      )
      ix = 0
      tcolors = []
      annotations = []
      for ix_row in range(nrows):
          for ix_col in range(ncols):
              ix += 1
              col_x = self.data.columns[ix_row]
              col_y = self.data.columns[ix_col]
              corr = self.corr.loc[col_x, col_y]
              color = (cmap_pos if corr > 0 else cmap_neg)(corr)
              if ix_row == ix_col:
                  series = self.data[col_x].dropna()
                  x = np.linspace(series.min(), series.max(), 500)
                  y = gaussian_kde(series).evaluate(x)
                  trace = go.Scatter(
                      x=x,
                      y=y,
                      mode="lines",
                      marker={"color": self.PALETTE[0]},
                      textposition="middle center",
                      name=col_x,
                  )
                  annotations.append(
                      (ix, x.mean(), (y.max() + y.min()) / 2, col_x)
                  )
  
              elif ix_row > ix_col:
                  trace = go.Scatter(
                      x=self.data[col_x],
                      y=self.data[col_y],
                      meta={"label_xaxis": col_x, "label_yaxis": col_y},
                      mode="markers",
                      marker={"color": color},
                      textposition="middle center",
                      name=f"{col_x} x {col_y}",
                      hovertemplate=self.hovertemplate,
                  )
              else:
                  tcolors.append((ix, color))
                  trace = go.Scatter(
                      x=[0.5],
                      y=[0.5],
                      mode="text",
                      textposition="middle center",
                      text=[f"{corr: .3f}"],
                      textfont={
                          "color": "black"
                          if abs(corr) < 0.6
                          else "white"
                      },
                      name=f"{col_x} x {col_y}",
                      hovertemplate=f"<b>{col_x}</b> x <b>{col_y}</b>: "
                      f"{corr:.3f}<extra></extra>",
                  )
  
              if isinstance(trace, list):
                  for t in trace:
                      fig.add_trace(t, row=ix_row + 1, col=ix_col + 1)
              else:
                  fig.add_trace(trace, row=ix_row + 1, col=ix_col + 1)
              fig.update_xaxes(
                  {
                      **opt_xaxis,  # type: ignore
                      "mirror": ix_row == 0,
                      "visible": True,
                      "showgrid": False,
                      "showticklabels": False,
                      "tickangle": self.xrotation,
                  },
                  row=ix_row + 1,
                  col=ix_col + 1,
              )
              fig.update_yaxes(
                  {
                      **opt_yaxis,  # type: ignore
                      "mirror": ix_col == ncols - 1,
                      "visible": True,
                      "showgrid": False,
                      "showticklabels": False,
                  },
                  row=ix_row + 1,
                  col=ix_col + 1,
              )
  
      fig = fig.update_layout(
          {
              "shapes": [
                  {
                      "type": "rect",
                      "x0": 0,
                      "y0": 0,
                      "x1": 1,
                      "y1": 1,
                      "opacity": 1,
                      "layer": "below",
                      "line_width": 0,
                      "xref": f"x{ix}",
                      "yref": f"y{ix}",
                      "fillcolor": c,
                  }
                  for ix, c in tcolors
              ]
          }
      )
      for ix, x, y, text in annotations:
          fig.add_annotation(
              go.layout.Annotation(
                  text=text,
                  x=x,
                  y=y,
                  xref=f"x{ix}",
                  yref=f"y{ix}",
                  showarrow=False,
                  font=dict(size=10),
                  textangle=-45,
              )
          )
      return fig
  
imports: from typing import Union, Optional, Any
  from copy import deepcopy
  import pandas
  import numpy
  from scipy.stats import gaussian_kde
  from tslumen.plot.interactive.base import VizBase, go, make_subplots
  from tslumen.plot.utils import cmapper
label_desc: Use image node_id 2 for calling the ScatterMatrix obj's underlying member method code with example usage: obj._create_figure() and returns: fig