nodes: 0, module; 1, function_definition; 2, function_name:compute; 3, parameters; 4, block; 5, identifier:self; 6, identifier:sensorToBodyByColumn; 7, identifier:sensorToSpecificObjectByColumn; 8, expression_statement; 9, expression_statement; 10, expression_statement; 11, for_statement; 12, expression_statement; 13, comment:# If possible, select only from current active cells.; 14, comment:#; 15, comment:# If we were to always activate all candidates, there would be an explosive; 16, comment:# back-and-forth between this layer and the sensorToSpecificObject layer.; 17, expression_statement; 18, if_statement; 19, expression_statement; 20, comment:"""
      Compute the
        "body's location relative to a specific object"
      from an array of
        "sensor's location relative to a specific object"
      and an array of
        "sensor's location relative to body"
  
      These arrays consist of one module per cortical column.
  
      This is a metric computation, similar to that of the
      SensorToSpecificObjectModule, but with voting. In effect, the columns vote
      on "the body's location relative to a specific object".
  
      Note: Each column can vote for an arbitrary number of cells, but it can't
      vote for a single cell more than once. This is necessary because we don't
      want ambiguity in a column to cause some cells to get extra votes. There are
      a few ways that this could be biologically plausible:
  
      - Explanation 1: Nearby dendritic segments are independent coincidence
        detectors, but perhaps their dendritic spikes don't sum. Meanwhile,
        maybe dendritic spikes from far away dendritic segments do sum.
      - Explanation 2: Dendritic spikes from different columns are separated
        temporally, not spatially. All the spikes from one column "arrive" at
        the cell at the same time, but the dendritic spikes from other columns
        arrive at other times. With each of these temporally-separated dendritic
        spikes, the unsupported cells are inhibited, or the spikes' effects are
        summed.
      - Explanation 3: Another population of cells within the cortical column
        might calculate the "body's location relative to a specific object" in
        this same "metric" way, but without tallying any votes. Then it relays
        this SDR subcortically, voting 0 or 1 times for each cell.
  
      @param sensorToBodyInputs (list of numpy arrays)
      The "sensor's location relative to the body" input from each cortical column
  
      @param sensorToSpecificObjectInputs (list of numpy arrays)
      The "sensor's location relative to specific object" input from each
      cortical column
      """; 21, assignment; 22, assignment; 23, tuple_pattern; 24, call; 25, block; 26, assignment; 27, assignment; 28, comparison_operator:self.activeCells.size == 0; 29, comment:# Otherwise, activate all cells with the maximum number of active; 30, comment:# segments.; 31, block; 32, assignment; 33, identifier:votesByCell; 34, call; 35, attribute; 36, list; 37, identifier:connections; 38, identifier:activeSensorToBodyCells; 39, identifier:activeSensorToSpecificObjectCells; 40, identifier:zip; 41, argument_list; 42, expression_statement; 43, expression_statement; 44, expression_statement; 45, expression_statement; 46, comment:# Only allow a column to vote for a cell once.; 47, expression_statement; 48, expression_statement; 49, identifier:candidates; 50, subscript; 51, attribute; 52, call; 53, attribute; 54, integer:0; 55, expression_statement; 56, attribute; 57, call; 58, attribute; 59, argument_list; 60, identifier:self; 61, identifier:activeSegmentsByColumn; 62, attribute; 63, identifier:sensorToBodyByColumn; 64, identifier:sensorToSpecificObjectByColumn; 65, assignment; 66, assignment; 67, assignment; 68, assignment; 69, augmented_assignment; 70, call; 71, call; 72, integer:0; 73, identifier:self; 74, identifier:activeCells; 75, attribute; 76, argument_list; 77, attribute; 78, identifier:size; 79, assignment; 80, identifier:self; 81, identifier:inhibitedCells; 82, attribute; 83, argument_list; 84, identifier:np; 85, identifier:zeros; 86, attribute; 87, keyword_argument; 88, identifier:self; 89, identifier:connectionsByColumn; 90, identifier:overlaps; 91, call; 92, identifier:activeSegments; 93, subscript; 94, identifier:votes; 95, call; 96, identifier:votes; 97, call; 98, subscript; 99, integer:1; 100, attribute; 101, argument_list; 102, attribute; 103, argument_list; 104, identifier:np; 105, identifier:intersect1d; 106, attribute; 107, identifier:candidates; 108, identifier:self; 109, identifier:activeCells; 110, attribute; 111, identifier:candidates; 112, identifier:np; 113, identifier:setdiff1d; 114, subscript; 115, attribute; 116, identifier:self; 117, identifier:cellCount; 118, identifier:dtype; 119, string:"int"; 120, attribute; 121, argument_list; 122, call; 123, integer:0; 124, attribute; 125, argument_list; 126, attribute; 127, argument_list; 128, identifier:votesByCell; 129, identifier:votes; 130, attribute; 131, identifier:append; 132, identifier:activeSegments; 133, identifier:np; 134, identifier:where; 135, comparison_operator:votesByCell == np.max(votesByCell); 136, identifier:self; 137, identifier:activeCells; 138, identifier:self; 139, identifier:activeCells; 140, call; 141, integer:0; 142, identifier:self; 143, identifier:activeCells; 144, identifier:connections; 145, identifier:computeActivity; 146, dictionary; 147, attribute; 148, argument_list; 149, identifier:connections; 150, identifier:mapSegmentsToCells; 151, identifier:activeSegments; 152, identifier:np; 153, identifier:unique; 154, identifier:votes; 155, identifier:self; 156, identifier:activeSegmentsByColumn; 157, identifier:votesByCell; 158, call; 159, attribute; 160, argument_list; 161, pair; 162, pair; 163, identifier:np; 164, identifier:where; 165, comparison_operator:overlaps >= 2; 166, attribute; 167, argument_list; 168, identifier:np; 169, identifier:where; 170, comparison_operator:votesByCell > 0; 171, string:"sensorToBody"; 172, identifier:activeSensorToBodyCells; 173, string:"sensorToSpecificObject"; 174, identifier:activeSensorToSpecificObjectCells; 175, identifier:overlaps; 176, integer:2; 177, identifier:np; 178, identifier:max; 179, identifier:votesByCell; 180, identifier:votesByCell; 181, integer:0
code: def compute(self, sensorToBodyByColumn, sensorToSpecificObjectByColumn):
      """
      Compute the
        "body's location relative to a specific object"
      from an array of
        "sensor's location relative to a specific object"
      and an array of
        "sensor's location relative to body"
  
      These arrays consist of one module per cortical column.
  
      This is a metric computation, similar to that of the
      SensorToSpecificObjectModule, but with voting. In effect, the columns vote
      on "the body's location relative to a specific object".
  
      Note: Each column can vote for an arbitrary number of cells, but it can't
      vote for a single cell more than once. This is necessary because we don't
      want ambiguity in a column to cause some cells to get extra votes. There are
      a few ways that this could be biologically plausible:
  
      - Explanation 1: Nearby dendritic segments are independent coincidence
        detectors, but perhaps their dendritic spikes don't sum. Meanwhile,
        maybe dendritic spikes from far away dendritic segments do sum.
      - Explanation 2: Dendritic spikes from different columns are separated
        temporally, not spatially. All the spikes from one column "arrive" at
        the cell at the same time, but the dendritic spikes from other columns
        arrive at other times. With each of these temporally-separated dendritic
        spikes, the unsupported cells are inhibited, or the spikes' effects are
        summed.
      - Explanation 3: Another population of cells within the cortical column
        might calculate the "body's location relative to a specific object" in
        this same "metric" way, but without tallying any votes. Then it relays
        this SDR subcortically, voting 0 or 1 times for each cell.
  
      @param sensorToBodyInputs (list of numpy arrays)
      The "sensor's location relative to the body" input from each cortical column
  
      @param sensorToSpecificObjectInputs (list of numpy arrays)
      The "sensor's location relative to specific object" input from each
      cortical column
      """
      votesByCell = np.zeros(self.cellCount, dtype="int")
  
      self.activeSegmentsByColumn = []
  
      for (connections,
           activeSensorToBodyCells,
           activeSensorToSpecificObjectCells) in zip(self.connectionsByColumn,
                                                     sensorToBodyByColumn,
                                                     sensorToSpecificObjectByColumn):
        overlaps = connections.computeActivity({
          "sensorToBody": activeSensorToBodyCells,
          "sensorToSpecificObject": activeSensorToSpecificObjectCells,
        })
        activeSegments = np.where(overlaps >= 2)[0]
        votes = connections.mapSegmentsToCells(activeSegments)
        votes = np.unique(votes)  # Only allow a column to vote for a cell once.
        votesByCell[votes] += 1
  
        self.activeSegmentsByColumn.append(activeSegments)
  
      candidates = np.where(votesByCell == np.max(votesByCell))[0]
  
      # If possible, select only from current active cells.
      #
      # If we were to always activate all candidates, there would be an explosive
      # back-and-forth between this layer and the sensorToSpecificObject layer.
      self.activeCells = np.intersect1d(self.activeCells, candidates)
  
      if self.activeCells.size == 0:
        # Otherwise, activate all cells with the maximum number of active
        # segments.
        self.activeCells = candidates
  
      self.inhibitedCells = np.setdiff1d(np.where(votesByCell > 0)[0],
                                         self.activeCells)