class_docstr: A data generator for node prediction with homogeneous GraphSAGE models
  on directed graphs.
  
  At minimum, supply the StellarDiGraph, the batch size, and the number of
  node samples (separately for in-nodes and out-nodes)
  for each layer of the GraphSAGE model.
  
  The supplied graph should be a StellarDiGraph object with node features.
  
  Use the :meth:`flow` method supplying the nodes and (optionally) targets
  to get an object that can be used as a Keras data generator.
  
  Example::
  
      G_generator = DirectedGraphSAGENodeGenerator(G, 50, [10,5], [5,1])
      train_data_gen = G_generator.flow(train_node_ids, train_node_labels)
      test_data_gen = G_generator.flow(test_node_ids)
  
  .. seealso::
  
     Model using this generator: :class:`.DirectedGraphSAGE`.
  
     Example using this generator: `node classification <https://stellargraph.readthedocs.io/en/stable/demos/connector/neo4j/directed-graphsage-on-cora-neo4j-example.html>`__.
  
     Related functionality: :class:`.DirectedGraphSAGENodeGenerator` for using :class:`.DirectedGraphSAGE` without Neo4j.
  
  Args:
      graph (Neo4jStellarDiGraph): Neo4jStellarGraph object
      batch_size (int): Size of batch to return.
      in_samples (list): The number of in-node samples per layer (hop) to take.
      out_samples (list): The number of out-node samples per layer (hop) to take.
      name (string, optional): Optional name for the generator
class_docstr_tok: ["A","data","generator","for","node","prediction","with","homogeneous","GraphSAGE","models","on","directed","graphs",".","At","minimum",",","supply","the","StellarDiGraph",",","the","batch","size",",","and","the","number","of","node","samples","(","separately","for","in-nodes","and","out-nodes",")","for","each","layer","of","the","GraphSAGE","model",".","The","supplied","graph","should","be","a","StellarDiGraph","object","with","node","features",".","Use","the",":","meth",":","`","flow","`","method","supplying","the","nodes","and","(","optionally",")","targets","to","get","an","object","that","can","be","used","as","a","Keras","data","generator",".","Example",":",":","G_generator","=","DirectedGraphSAGENodeGenerator","(","G",",","50",",","[","10,5","]",",","[","5,1","]",")","train_data_gen","=","G_generator.flow","(","train_node_ids",",","train_node_labels",")","test_data_gen","=","G_generator.flow","(","test_node_ids",")","..","seealso",":",":","Model","using","this","generator",":",":","class",":","`",".DirectedGraphSAGE","`",".","Example","using","this","generator",":","`","node","classification","<","https",":","\/\/stellargraph.readthedocs.io\/en\/stable\/demos\/connector\/neo4j\/directed-graphsage-on-cora-neo4j-example.html",">","`","__",".","Related","functionality",":",":","class",":","`",".DirectedGraphSAGENodeGenerator","`","for","using",":","class",":","`",".DirectedGraphSAGE","`","without","Neo4j",".","Args",":","graph","(","Neo4jStellarDiGraph",")",":","Neo4jStellarGraph","object","batch_size","(","int",")",":","Size","of","batch","to","return",".","in_samples","(","list",")",":","The","number","of","in-node","samples","per","layer","(","hop",")","to","take",".","out_samples","(","list",")",":","The","number","of","out-node","samples","per","layer","(","hop",")","to","take",".","name","(","string",",","optional",")",":","Optional","name","for","the","generator"]
docstr: Collect the features of the sampled nodes from Neo4j,
  and return these as a list of feature arrays for the GraphSAGE algorithm.
  
  Args:
      head_nodes: An iterable of head nodes to perform sampling on.
      batch_num: Ignored, because this is not reproducible.
  
  Returns:
      A list of feature tensors from the sampled nodes at each layer, each of shape:
      ``(len(head_nodes), num_sampled_at_layer, feature_size)``
      where ``num_sampled_at_layer`` is the total number (cumulative product)
      of nodes sampled at the given number of hops from each head node,
      given the sequence of in/out directions.
docstr_tok: ["Collect","the","features","of","the","sampled","nodes","from","Neo4j",",","and","return","these","as","a","list","of","feature","arrays","for","the","GraphSAGE","algorithm",".","Args",":","head_nodes",":","An","iterable","of","head","nodes","to","perform","sampling","on",".","batch_num",":","Ignored",",","because","this","is","not","reproducible",".","Returns",":","A","list","of","feature","tensors","from","the","sampled","nodes","at","each","layer",",","each","of","shape",":","``","(","len","(","head_nodes",")",",","num_sampled_at_layer",",","feature_size",")","``","where","``","num_sampled_at_layer","``","is","the","total","number","(","cumulative","product",")","of","nodes","sampled","at","the","given","number","of","hops","from","each","head","node",",","given","the","sequence","of","in\/out","directions","."]
code: def sample_features(self, head_nodes, batch_num):
      """
      Collect the features of the sampled nodes from Neo4j,
      and return these as a list of feature arrays for the GraphSAGE algorithm.
  
      Args:
          head_nodes: An iterable of head nodes to perform sampling on.
          batch_num: Ignored, because this is not reproducible.
  
      Returns:
          A list of feature tensors from the sampled nodes at each layer, each of shape:
          ``(len(head_nodes), num_sampled_at_layer, feature_size)``
          where ``num_sampled_at_layer`` is the total number (cumulative product)
          of nodes sampled at the given number of hops from each head node,
          given the sequence of in/out directions.
      """
      node_samples = self.sampler.run(
          nodes=head_nodes,
          n=1,
          in_size=self.in_samples,
          out_size=self.out_samples,
      )
  
      # Reshape node samples to sensible format
      # Each 'slot' represents the list of nodes sampled from some neighbourhood, and will have a corresponding
      # NN input layer. Every hop potentially generates both in-nodes and out-nodes, held separately,
      # and thus the slot (or directed hop sequence) structure forms a binary tree.
  
      max_hops = len(self.in_samples)
      max_slots = 2 ** (max_hops + 1) - 1
      features = [None] * max_slots  # flattened binary tree
  
      batch_nodes = np.concatenate(node_samples)
      batch_features = self.graph.node_features(batch_nodes)
  
      idx = 0
      for slot in range(max_slots):
          features_for_slot = batch_features[
              idx : idx + len(node_samples[slot])
          ]
          resize = -1 if np.size(features_for_slot) > 0 else 0
          features[slot] = np.reshape(
              features_for_slot,
              (len(head_nodes), resize, features_for_slot.shape[1]),
          )
          idx += len(node_samples[slot])
  
      return features
  
file_path: stellargraph/stellargraph/connector/neo4j/mapper.py
imports: import numpy
  import random
  from .sampler import Neo4jDirectedBreadthFirstNeighbors, Neo4jSampledBreadthFirstWalk
  from ...core.graph import GraphSchema
  from ...mapper import NodeSequence
  from ...mapper.sampled_node_generators import BatchedNodeGenerator
  from ...core.experimental import experimental
  from .graph import Neo4jStellarGraph
label_desc: Use image node_id 2 for calling the Neo4jDirectedGraphSAGENodeGenerator obj's underlying member method code with example usage: obj.sample_features(head_nodes, batch_num) and returns: features