code: def get_feature_data(
      feat, dataframes, groupbys, edges, primitives, layer=0
  ):
      # 1) add feature to dataframes tables:
      feat_name = feat.get_name()
      if feat.dataframe_name not in dataframes:
          add_dataframe(feat.dataframe, dataframes)
      dataframe_dict = dataframes[feat.dataframe_name]
  
      # if we've already explored this feat, continue
      feat_node = "{}:{}".format(feat.dataframe_name, feat_name)
      if (
          feat_name in dataframe_dict["columns"]
          or feat_name in dataframe_dict["feats"]
      ):
          return feat_node, layer
  
      if isinstance(feat, IdentityFeature):
          dataframe_dict["columns"].add(feat_name)
      else:
          dataframe_dict["feats"].add(feat_name)
      base_node = feat_node
  
      # 2) if multi-output, convert feature to generic base
      if isinstance(feat, FeatureOutputSlice):
          feat = feat.base_feature
          feat_name = feat.get_name()
  
      # 3) add primitive node
      if feat.primitive.name or isinstance(feat, DirectFeature):
          prim_name = (
              feat.primitive.name if feat.primitive.name else "join"
          )
          prim_type = ""
          if isinstance(feat, AggregationFeature):
              prim_type = "Aggregation"
          elif isinstance(feat, TransformFeature):
              prim_type = "Transform"
          primitive_node = "{}_{}_{}".format(
              layer, feat_name, prim_name
          )
          primitives.append(
              (primitive_node, prim_name.upper(), layer, prim_type)
          )
  
          edges[1].append([primitive_node, base_node])
          base_node = primitive_node
  
      # 4) add groupby/join edges and nodes
      dependencies = [
          (dep.hash(), dep) for dep in feat.get_dependencies()
      ]
      for is_forward, r in feat.relationship_path:
          if is_forward:
              if r.child_dataframe.ww.name not in dataframes:
                  add_dataframe(r.child_dataframe, dataframes)
              dataframes[r.child_dataframe.ww.name]["columns"].add(
                  r._child_column_name
              )
              child_node = "{}:{}".format(
                  r.child_dataframe.ww.name, r._child_column_name
              )
              edges[0].append([base_node, child_node])
          else:
              if r.child_dataframe.ww.name not in dataframes:
                  add_dataframe(r.child_dataframe, dataframes)
              dataframes[r.child_dataframe.ww.name]["columns"].add(
                  r._child_column_name
              )
              child_node = "{}:{}".format(
                  r.child_dataframe.ww.name, r._child_column_name
              )
              child_name = child_node.replace(":", "--")
              groupby_node = "{}_groupby_{}".format(
                  feat_name, child_name
              )
              groupby_name = "group by\n{}".format(r._child_column_name)
              groupbys.append((groupby_node, groupby_name))
              edges[0].append([child_node, groupby_node])
              edges[1].append([groupby_node, base_node])
              base_node = groupby_node
  
      if hasattr(feat, "groupby"):
          groupby = feat.groupby
          _ = get_feature_data(
              groupby,
              dataframes,
              groupbys,
              edges,
              primitives,
              layer + 1,
          )
          dependencies.remove((groupby.hash(), groupby))
  
          groupby_name = groupby.get_name()
          if isinstance(groupby, IdentityFeature):
              dataframes[groupby.dataframe_name]["columns"].add(
                  groupby_name
              )
          else:
              dataframes[groupby.dataframe_name]["feats"].add(
                  groupby_name
              )
  
          child_node = "{}:{}".format(
              groupby.dataframe_name, groupby_name
          )
          child_name = child_node.replace(":", "--")
          groupby_node = "{}_groupby_{}".format(feat_name, child_name)
          groupby_name = "group by\n{}".format(groupby_name)
          groupbys.append((groupby_node, groupby_name))
          edges[0].append([child_node, groupby_node])
          edges[1].append([groupby_node, base_node])
          base_node = groupby_node
  
      # 5) recurse over dependents
      max_depth = layer
      for _, f in dependencies:
          dependent_node, depth = get_feature_data(
              f,
              dataframes,
              groupbys,
              edges,
              primitives,
              layer + 1,
          )
          edges[1].append([dependent_node, base_node])
  
          max_depth = max(depth, max_depth)
  
      return feat_node, max_depth
  
imports: import html
  from featuretools.feature_base.feature_base import AggregationFeature, DirectFeature, FeatureOutputSlice, IdentityFeature, TransformFeature
  from featuretools.feature_base.feature_descriptions import describe_feature
  from featuretools.utils.plot_utils import check_graphviz, get_graphviz_format, save_graph
label_desc: Use image node_id 2 for calling a global function with example usage: get_feature_data(feat, dataframes, groupbys, edges, primitives, layer) and returns: feat_node,  max_depth, feat_node,  layer