class_docstr: Pipeline wrapper with 'export_pipeline'/'import_pipeline' methods
  allowing user to upload a pipeline to JSON format and import it from JSON.
  
  :params pipeline: Pipeline object to export or empty Pipeline to import
class_docstr_tok: ["Pipeline","wrapper","with","'export_pipeline'\/'import_pipeline","'","methods","allowing","user","to","upload","a","pipeline","to","JSON","format","and","import","it","from","JSON",".",":","params","pipeline",":","Pipeline","object","to","export","or","empty","Pipeline","to","import"]
docstr: The function recursively traverses all disjoint operations
  and connects the operations in a pipeline.
  
  :params operation_object: operationTemplate or AtomizedOperationTemplate
  :params visited_nodes: array to remember which node was visited
  :params path: path to save
  :return: root_node
docstr_tok: ["The","function","recursively","traverses","all","disjoint","operations","and","connects","the","operations","in","a","pipeline",".",":","params","operation_object",":","operationTemplate","or","AtomizedOperationTemplate",":","params","visited_nodes",":","array","to","remember","which","node","was","visited",":","params","path",":","path","to","save",":","return",":","root_node"]
code: def roll_pipeline_structure(
      self,
      operation_object: Union[
          "OperationTemplate", "AtomizedModelTemplate"
      ],
      visited_nodes: dict,
      path: str = None,
      dict_fitted_operations: dict = None,
  ):
      """
      The function recursively traverses all disjoint operations
      and connects the operations in a pipeline.
  
      :params operation_object: operationTemplate or AtomizedOperationTemplate
      :params visited_nodes: array to remember which node was visited
      :params path: path to save
      :return: root_node
      """
      fitted_operation = None
      if operation_object.operation_id in visited_nodes:
          return visited_nodes[operation_object.operation_id]
  
      if operation_object.operation_type == atomized_model_type():
          atomized_model = operation_object.next_pipeline_template
          node = PipelineNode(operation_type=atomized_model)
      else:
          node = PipelineNode(operation_object.operation_type)
          node.parameters = operation_object.custom_params
          node.rating = operation_object.rating
  
      if (
          hasattr(operation_object, "fitted_operation_path")
          and operation_object.fitted_operation_path
          and path is not None
      ):
          path_to_operation = os.path.join(
              path, operation_object.fitted_operation_path
          )
  
          if "h2o" in operation_object.operation_type:
              fitted_operation = load_h2o(path, self.log)
  
          elif not os.path.isfile(path_to_operation):
              message = f"Fitted operation on the path: {path_to_operation} does not exist."
              self.log.error(message)
          else:
              fitted_operation = joblib.load(path_to_operation)
      elif dict_fitted_operations is not None:
          if "h2o" in operation_object.operation_type:
              message = "Loading h2o models from dict is not supported"
              self.log.error(message)
              raise TypeError(message)
          else:
              fitted_operation = joblib.load(
                  dict_fitted_operations[
                      f"operation_{operation_object.operation_id}"
                  ]
              )
  
      operation_object.fitted_operation = fitted_operation
      node.fitted_operation = fitted_operation
  
      nodes_from = [
          operation_template
          for operation_template in self.operation_templates
          if operation_template.operation_id
          in operation_object.nodes_from
      ]
  
      node.nodes_from = [
          self.roll_pipeline_structure(
              node_from, visited_nodes, path, dict_fitted_operations
          )
          for node_from in nodes_from
      ]
  
      visited_nodes[operation_object.operation_id] = node
      return node
  
imports: import json
  import os
  from collections import Counter
  from datetime import datetime
  from io import BytesIO
  from typing import TYPE_CHECKING, Any, Callable, Dict, List, Optional, Tuple, Union
  from uuid import uuid4
  import joblib
  import numpy
  from golem.core.log import default_log
  from fedot.core.operations.atomized_template import AtomizedModelTemplate
  from fedot.core.operations.operation_template import OperationTemplate, check_existing_path
  from fedot.core.pipelines.node import PipelineNode
  from fedot.core.repository.operation_types_repository import atomized_model_type
  from fedot.preprocessing.dummy_preprocessing import DummyPreprocessor
  from fedot.preprocessing.preprocessing import DataPreprocessor
label_desc: Use image node_id 12 for calling the PipelineTemplate obj's underlying member method code with example usage: obj.roll_pipeline_structure(operation_object, visited_nodes, path, dict_fitted_operations) and returns: node, visited_nodes