class_docstr: Check for under annotated data segments.
code: def _generate_scatter_plot_display(
      self,
      encoded_data: pd.DataFrame,
      is_annotated: pd.Series,
      text: np.ndarray,
      weak_segments: pd.DataFrame,
      avg_score: float,
  ) -> DisplayMap:
      display_tabs = {}
      if weak_segments.shape[0] > self.n_to_show:
          weak_segments = weak_segments.iloc[: self.n_to_show, :]
      encoded_data["text"] = [
          break_to_lines_and_trim(sample) for sample in text
      ]
  
      # Handle categorical features
      jitter = 0.25
      for feature in self.encoder_mapping.keys():
          encoded_data[feature] = encoded_data[
              feature
          ] + np.random.uniform(-jitter, jitter, len(encoded_data))
  
      # virtual col is used when we have only one feature controlling the segment
      encoded_data["virtual_col"] = np.random.uniform(
          -jitter, jitter, len(encoded_data)
      )
  
      sampled_data = encoded_data.sample(
          min(MAX_SAMPLES_IN_FIGURE, len(encoded_data)), random_state=42
      )
      is_annotated_sampled = is_annotated.loc[
          sampled_data.index
      ]  # Get the corresponding boolean series
      annotated_data = sampled_data.loc[is_annotated_sampled == 1]
      not_annotated_data = sampled_data.loc[is_annotated_sampled == 0]
      for _, row in weak_segments.iterrows():
          fig = go.Figure()
          feature_1, feature_2 = row["Feature1"], row["Feature2"]
          feature_1_lower, feature_1_upper = self._get_box_boundaries(
              encoded_data[feature_1], row["Feature1 Range"]
          )
          if feature_2 != "":  # segment by two features
              (
                  feature_2_lower,
                  feature_2_upper,
              ) = self._get_box_boundaries(
                  encoded_data[feature_2], row["Feature2 Range"]
              )
              hover_template = (
                  "<b>"
                  + feature_1
                  + "</b>: %{x}<br><b>"
                  + feature_2
                  + "</b>: %{y}<br><b>text</b>: %{text}<br><b>Annotated</b>: "
              )
              tab_title = f"{feature_1} vs {feature_2}"
              range_f1 = self._format_partition_vec_for_display(
                  [feature_1_lower, feature_1_upper], feature_1, ", "
              )
              range_f2 = self._format_partition_vec_for_display(
                  [feature_2_lower, feature_2_upper], feature_2, ", "
              )
              msg = (
                  f"Under annotated segment contains samples with {feature_1} in "
                  f"{range_f1[0]} and {feature_2} in {range_f2[0]}."
              )
          else:  # segment by one feature
              feature_2 = "virtual_col"
              feature_2_lower = encoded_data["virtual_col"].min() * 1.3
              feature_2_upper = encoded_data["virtual_col"].max() * 1.3
              hover_template = (
                  "<b>"
                  + feature_1
                  + "</b>: %{x}<br><b>text</b>: %{text}<br><b>Annotated</b>: "
              )
              tab_title = feature_1
              range_f1 = self._format_partition_vec_for_display(
                  [feature_1_lower, feature_1_upper], feature_1, ", "
              )
              msg = f"Under annotated segment contains samples with {feature_1} in {range_f1[0]}."
              fig.update_yaxes(
                  range=[feature_2_lower * 1.2, feature_2_upper * 1.2],
                  tickvals=[],
                  ticktext=[],
              )
  
          # Add box trace to the legend using lines
          fig.add_trace(
              go.Scatter(
                  x=[
                      feature_1_lower,
                      feature_1_lower,
                      feature_1_upper,
                      feature_1_upper,
                      feature_1_lower,
                  ],
                  y=[
                      feature_2_lower,
                      feature_2_upper,
                      feature_2_upper,
                      feature_2_lower,
                      feature_2_lower,
                  ],
                  mode="lines",
                  line=dict(
                      color="rgb(121, 100, 255)", width=3, dash="dot"
                  ),
                  name="Under Annotated Segment",
                  fill="toself",
                  fillcolor="rgb(121, 100, 255)",
                  opacity=0.4,
                  legendgroup="box",
              )
          )
  
          # Add annotated scatter plot
          fig.add_trace(
              go.Scatter(
                  x=annotated_data[feature_1],
                  y=annotated_data[feature_2],
                  mode="markers",
                  opacity=0.7,
                  marker=dict(
                      symbol="circle",
                      color="lightgreen",
                      size=10,
                      line=dict(color="black", width=1),
                  ),
                  hovertemplate=hover_template + "True",
                  text=annotated_data["text"],
                  name="Annotated Samples",
              )
          )
  
          # Add not annotated scatter plot
          fig.add_trace(
              go.Scatter(
                  x=not_annotated_data[feature_1],
                  y=not_annotated_data[feature_2],
                  mode="markers",
                  opacity=0.5,
                  marker=dict(
                      symbol="x",
                      color="red",
                      size=10,
                      line=dict(color="black", width=1),
                  ),
                  hovertemplate=hover_template + "False",
                  text=not_annotated_data["text"],
                  name="Not Annotated Samples",
              )
          )
  
          # Update figure layout
          fig.update_layout(
              title=dict(
                  text=f'Under Annotated Segment ({row["% of Data"]}% of Data)<br><sub>Annotation ratio in segment '
                  f'is {format_percent(row["Annotation Ratio"])} (vs. {format_percent(avg_score)}'
                  f" in whole data)</sub>",
                  font=dict(size=24),
              ),
              xaxis_title=feature_1,
              yaxis_title=feature_2
              if feature_2 != "virtual_col"
              else "",
              font=dict(size=14),
              plot_bgcolor="rgba(245, 245, 245, 1)",
              xaxis=dict(
                  gridcolor="rgba(200, 200, 200, 0.5)",
                  zerolinecolor="rgba(200, 200, 200, 0.5)",
              ),
              yaxis=dict(
                  gridcolor="rgba(200, 200, 200, 0.5)",
                  zerolinecolor="rgba(200, 200, 200, 0.5)",
              ),
          )
  
          # Use original categorical values in the axis ticks
          if feature_1 in self.encoder_mapping.keys():
              mapping = self.encoder_mapping[feature_1]
              fig.update_xaxes(
                  title=feature_1,
                  tickvals=mapping["encoded_value"].to_list(),
                  ticktext=mapping["original_category"].to_list(),
              )
          if feature_2 in self.encoder_mapping.keys():
              mapping = self.encoder_mapping[feature_2]
              fig.update_yaxes(
                  title=feature_2,
                  tickvals=mapping["encoded_value"].to_list(),
                  ticktext=mapping["original_category"].to_list(),
              )
  
          display_tabs[tab_title] = [
              fig,
              f"Check ran on {encoded_data.shape[0]} data samples.<br>{msg}",
          ]
  
      return DisplayMap(display_tabs)
  
imports: from typing import Dict, List, Optional, Tuple, Union
  import numpy
  import pandas
  import plotly.graph_objects
  from deepchecks import ConditionCategory, ConditionResult
  from deepchecks.core import CheckResult
  from deepchecks.core.check_result import DisplayMap
  from deepchecks.core.errors import NotEnoughSamplesError
  from deepchecks.nlp import Context, SingleDatasetCheck
  from deepchecks.nlp.utils.text import break_to_lines_and_trim
  from deepchecks.nlp.utils.weak_segments import get_relevant_data_table
  from deepchecks.utils.abstracts.weak_segment_abstract import WeakSegmentAbstract
  from deepchecks.utils.metrics import is_label_none
  from deepchecks.utils.strings import format_percent
  from deepchecks.utils.typing import Hashable
label_desc: Use image node_id 4 for calling the UnderAnnotatedSegments obj's underlying member method code with example usage: obj._generate_scatter_plot_display(encoded_data, is_annotated, text, weak_segments, avg_score) and returns: DisplayMap