class_docstr: Computes some statistics on marker extraction results.
  
  (1) Number of sessions where markers apply:
  
  For each marker, we compute the total number (as well as the percentage) of
  sessions in which a marker applies at least once.
  Moreover, we output the total number of sessions that were parsed.
  
  (2) Number of user turns preceding relevant events - per sessions:
  
  For each marker, we consider all relevant events where that marker applies.
  Everytime a marker applies, we check how many user turns precede that event.
  We collect all these numbers and compute basic statistics (e.g. count and mean)
  on them.
  
  This means, per session, we compute how often a marker applies and how many
  user turns precede a relevant marker application on average, in that session.
  
  (3) Number of user turns preceding relevant events - over all sessions:
  
  Here, for each marker, we consider all relevant events where a marker applies
  *in any of the sessions*. Then, we again calculate basic statistics over the
  respective number of user turns that precede each of these events.
  
  This means, we compute how many events the marker applies in total and we
  compute an estimate of the expected number of user turns preceding that
  precede an (relevant) event where a marker applies.
class_docstr_tok: ["Computes","some","statistics","on","marker","extraction","results",".","(","1",")","Number","of","sessions","where","markers","apply",":","For","each","marker",",","we","compute","the","total","number","(","as","well","as","the","percentage",")","of","sessions","in","which","a","marker","applies","at","least","once",".","Moreover",",","we","output","the","total","number","of","sessions","that","were","parsed",".","(","2",")","Number","of","user","turns","preceding","relevant","events","-","per","sessions",":","For","each","marker",",","we","consider","all","relevant","events","where","that","marker","applies",".","Everytime","a","marker","applies",",","we","check","how","many","user","turns","precede","that","event",".","We","collect","all","these","numbers","and","compute","basic","statistics","(","e.g",".","count","and","mean",")","on","them",".","This","means",",","per","session",",","we","compute","how","often","a","marker","applies","and","how","many","user","turns","precede","a","relevant","marker","application","on","average",",","in","that","session",".","(","3",")","Number","of","user","turns","preceding","relevant","events","-","over","all","sessions",":","Here",",","for","each","marker",",","we","consider","all","relevant","events","where","a","marker","applies","*","in","any","of","the","sessions","*",".","Then",",","we","again","calculate","basic","statistics","over","the","respective","number","of","user","turns","that","precede","each","of","these","events",".","This","means",",","we","compute","how","many","events","the","marker","applies","in","total","and","we","compute","an","estimate","of","the","expected","number","of","user","turns","preceding","that","precede","an","(","relevant",")","event","where","a","marker","applies","."]
docstr: Processes the meta data that was extracted from a single session.
  
  Internally, this method ..
  1. computes some statistics for the given meta data and saves it for later
  2. keeps track of the total number of sessions processed and the
     collects all metadata to be able to compute meta data over *all*
  
  Args:
      sender_id: an id that, together with the `session_idx` identifies
          the session from which the markers where extracted
      session_idx: an index that, together with the `sender_id` identifies
          the session from which the markers where extracted
      meta_data_on_relevant_events_per_marker: marker extraction results,
          i.e. a dictionary mapping
          marker names to the meta data describing relevant events
          for those markers
docstr_tok: ["Processes","the","meta","data","that","was","extracted","from","a","single","session",".","Internally",",","this","method","..","1.","computes","some","statistics","for","the","given","meta","data","and","saves","it","for","later","2.","keeps","track","of","the","total","number","of","sessions","processed","and","the","collects","all","metadata","to","be","able","to","compute","meta","data","over","*","all","*","Args",":","sender_id",":","an","id","that",",","together","with","the","`","session_idx","`","identifies","the","session","from","which","the","markers","where","extracted","session_idx",":","an","index","that",",","together","with","the","`","sender_id","`","identifies","the","session","from","which","the","markers","where","extracted","meta_data_on_relevant_events_per_marker",":","marker","extraction","results",",","i.e",".","a","dictionary","mapping","marker","names","to","the","meta","data","describing","relevant","events","for","those","markers"]
code: def process(
      self,
      sender_id: Text,
      session_idx: int,
      meta_data_on_relevant_events_per_marker: Dict[
          Text, List[EventMetaData]
      ],
  ) -> None:
      """Processes the meta data that was extracted from a single session.
  
      Internally, this method ..
      1. computes some statistics for the given meta data and saves it for later
      2. keeps track of the total number of sessions processed and the
         collects all metadata to be able to compute meta data over *all*
  
      Args:
          sender_id: an id that, together with the `session_idx` identifies
              the session from which the markers where extracted
          session_idx: an index that, together with the `sender_id` identifies
              the session from which the markers where extracted
          meta_data_on_relevant_events_per_marker: marker extraction results,
              i.e. a dictionary mapping
              marker names to the meta data describing relevant events
              for those markers
      """
      if len(self._marker_names) == 0:
          # sort and initialise here once so our result tables are sorted
          self._marker_names = sorted(
              meta_data_on_relevant_events_per_marker.keys()
          )
          self.count_if_applied_at_least_once = {
              marker_name: 0 for marker_name in self._marker_names
          }
          self.num_preceding_user_turns_collected = {
              marker_name: [] for marker_name in self._marker_names
          }
          # NOTE: we could stream / compute them later instead of collecting them...
          stat_names = sorted(compute_statistics([]).keys())
          self.session_results = {
              marker_name: {stat_name: [] for stat_name in stat_names}
              for marker_name in self._marker_names
          }
      else:
          given_markers = meta_data_on_relevant_events_per_marker.keys()
          if set(given_markers) != set(self._marker_names):
              raise RuntimeError(
                  f"Expected all processed extraction results to contain information"
                  f"for the same set of markers. But found "
                  f"{sorted(given_markers)} which differs from "
                  f"the marker extracted so far (i.e. {sorted(self._marker_names)})."
              )
  
      # update session identifiers / count
      self.num_sessions += 1
      self.session_identifier.append((sender_id, session_idx))
  
      for (
          marker_name,
          meta_data,
      ) in meta_data_on_relevant_events_per_marker.items():
          num_preceding_user_turns = [
              event_meta_data.preceding_user_turns
              for event_meta_data in meta_data
          ]
  
          # update per session statistics
          statistics = compute_statistics(num_preceding_user_turns)
          for stat_name, stat_value in statistics.items():
              self.session_results[marker_name][stat_name].append(
                  stat_value
              )
  
          # update overall statistics
          self.num_preceding_user_turns_collected[marker_name].extend(
              num_preceding_user_turns
          )
          if len(num_preceding_user_turns):
              self.count_if_applied_at_least_once[marker_name] += 1
  
imports: from __future__ import annotations
  from typing import Dict, Text, Union, List, Tuple
  from rasa.utils.io import WriteRow
  from pathlib import Path
  import csv
  import numpy
  from rasa.core.evaluation.marker_base import EventMetaData
label_desc: Use image node_id 3 for calling the MarkerStatistics obj's underlying member method code with example usage: obj.process(sender_id, session_idx, meta_data_on_relevant_events_per_marker) without return types