parameters: (skeleton_id, tree, reviews, max_gap)
return_statement: return epochs
docstring: Split the arbor into one or more review epochs.
      An epoch is defined as a continuous range of time containing gaps
      of up to max_gap (e.g. 3 days) and fully reviewed by the same reviewer.
      Treenodes reviewed within an epoch may not form a coherent subset of the arbor,
      given that different subsets of the arbor may have been joined at a later time.
docstring_summary: Split the arbor into one or more review epochs.
      An epoch is defined as a continuous range of time containing gaps
      of up to max_gap (e.g. 3 days) and fully reviewed by the same reviewer.
      Treenodes reviewed within an epoch may not form a coherent subset of the arbor,
      given that different subsets of the arbor may have been joined at a later time.
docstring_tokens: Split the arbor into one or more review epochs . An epoch is defined as a continuous range of time containing gaps of up to max_gap ( e . g . 3 days ) and fully reviewed by the same reviewer . Treenodes reviewed within an epoch may not form a coherent subset of the arbor given that different subsets of the arbor may have been joined at a later time .
function: def _split_into_epochs(skeleton_id, tree, reviews, max_gap) -> List:
      """ Split the arbor into one or more review epochs.
      An epoch is defined as a continuous range of time containing gaps
      of up to max_gap (e.g. 3 days) and fully reviewed by the same reviewer.
      Treenodes reviewed within an epoch may not form a coherent subset of the arbor,
      given that different subsets of the arbor may have been joined at a later time. """
  
      # Sort nodes by date of most recent review (first in list)
      def get_review_time(e):
          return reviews[e[0]][0].review_time
      nodes = sorted(tree.nodes(data=True), key=get_review_time)
  
      # Grab the oldest node
      oldest = nodes[0]
      last_id = oldest[0] # id of first node
      last = oldest[1] # props of first node
  
      # First epoch contains the oldest node
      epoch = [last_id]
  
      # Most recent review of first node
      last_review = reviews[last_id][0]
  
      # Collect epochs
      epochs = [(last_review.reviewer_id, epoch)]
  
      # Iterate from second-oldest node forward in time
      for node, props in nodes:
          # Most recent review of current node
          node_review = reviews[node][0]
          # Add to current epoch if same reviewer and we are within max_gap
          if node_review.reviewer_id == last_review.reviewer_id and \
                  node_review.review_time - last_review.review_time < max_gap:
              epoch.append(node)
          else:
              # Start new epoch
              epoch = [node]
              epochs.append((node_review.reviewer_id, epoch))
  
          last_review = reviews[node][0]
  
      return epochs
function_tokens: def _split_into_epochs ( skeleton_id , tree , reviews , max_gap ) -> List : # Sort nodes by date of most recent review (first in list) def get_review_time ( e ) : return reviews [ e [ 0 ] ] [ 0 ] . review_time nodes = sorted ( tree . nodes ( data = True ) , key = get_review_time ) # Grab the oldest node oldest = nodes [ 0 ] last_id = oldest [ 0 ] # id of first node last = oldest [ 1 ] # props of first node # First epoch contains the oldest node epoch = [ last_id ] # Most recent review of first node last_review = reviews [ last_id ] [ 0 ] # Collect epochs epochs = [ ( last_review . reviewer_id , epoch ) ] # Iterate from second-oldest node forward in time for node , props in nodes : # Most recent review of current node node_review = reviews [ node ] [ 0 ] # Add to current epoch if same reviewer and we are within max_gap if node_review . reviewer_id == last_review . reviewer_id and node_review . review_time - last_review . review_time < max_gap : epoch . append ( node ) else : # Start new epoch epoch = [ node ] epochs . append ( ( node_review . reviewer_id , epoch ) ) last_review = reviews [ node ] [ 0 ] return epochs