code: def as_annotated_data(raw_data: Any, raw_mapping: Any) -> Tuple:
      data_meta = {}
  
      # data
      data = raw_data
  
      if is_data_pub_stream(data):
          data = {}
          for col_name in raw_data.col_names:
              data[col_name] = []
  
          data_meta.update(
              {
                  "pubsub": {
                      "channel_id": raw_data.channel_id,
                      "col_names": raw_data.col_names,
                  }
              }
          )
  
      # mapping
      mapping = {}
      mapping_meta = []
      # series annotations
      series_meta = []
  
      class VariableMeta:
          def __init__(self):
              self.levels = None
              self.aesthetics = []
              self.order = None
  
      variables_meta: Dict[str, VariableMeta] = {}
  
      if is_data_frame(data):
          dtypes = data.dtypes.to_dict().items()
          for column_name, dtype in dtypes:
              if dtype.name == "category" and dtype.ordered:
                  var_meta = VariableMeta()
                  var_meta.levels = dtype.categories.to_list()
                  variables_meta[column_name] = var_meta
  
      if raw_mapping is not None:
          for aesthetic, variable in raw_mapping.as_dict().items():
              if (
                  aesthetic == "name"
              ):  # ignore FeatureSpec.name property
                  continue
  
              if isinstance(variable, MappingMeta):
                  mapping[aesthetic] = variable.variable
                  if variable.variable in variables_meta:
                      var_meta = variables_meta[variable.variable]
                  else:
                      var_meta = VariableMeta()
                  var_meta.aesthetics.append(aesthetic)
                  if variable.levels is not None:
                      var_meta.levels = variable.levels
                  order = variable.parameters.get("order")
                  if order is not None:
                      var_meta.order = order
                  variables_meta[variable.variable] = var_meta
              else:
                  mapping[aesthetic] = variable
  
      for variableName, settings in variables_meta.items():
          if settings.levels is not None:
              # series annotations
              series_meta.append(
                  {
                      "column": variableName,
                      "factor_levels": settings.levels,
                      "order": settings.order,
                  }
              )
          else:
              # mapping annotations
              for aesthetic in settings.aesthetics:
                  value = raw_mapping.as_dict().get(aesthetic)
                  if value is not None and isinstance(
                      value, MappingMeta
                  ):
                      mapping_meta.append(
                          {
                              "aes": aesthetic,
                              "annotation": value.annotation,
                              "parameters": value.parameters,
                          }
                      )
  
      if is_dict_or_dataframe(data):
          for column_name, values in data.items():
              if isinstance(values, Iterable):
                  not_empty_series = any(True for _ in values)
                  if not_empty_series and all(
                      isinstance(val, datetime) for val in values
                  ):
                      series_meta.append(
                          {"column": column_name, "type": "datetime"}
                      )
  
      if len(series_meta) > 0:
          data_meta.update({"series_annotations": series_meta})
  
      if len(mapping_meta) > 0:
          data_meta.update({"mapping_annotations": mapping_meta})
  
      return data, aes(**mapping), {"data_meta": data_meta}
  
file_path: lets-plot/python-package/lets_plot/plot/util.py
imports: from collections.abc import Iterable
  from datetime import datetime
  from typing import Any, Tuple, Sequence, Optional, Dict
  from lets_plot._type_utils import is_dict_or_dataframe
  from lets_plot.geo_data_internals.utils import find_geo_names
  from lets_plot.mapping import MappingMeta
  from lets_plot.plot.core import aes
label_desc: Use image node_id 2 for calling a global function with example usage: as_annotated_data(raw_data, raw_mapping) and returns: data,  aes,  dict