def updateSpatialElements(self, active_columns):
        """
        Update elements regarding spatial pooler
        """

        # Update proximal segments and synapses according to active columns
        for col_idx in range(len(self.columns)):
            column = self.columns[col_idx]

            # Update proximal segment
            segment = column.segment
            if active_columns[col_idx] == 1:
                segment.is_active.setForCurrStep(True)
            else:
                segment.is_active.setForCurrStep(False)

            # Check if proximal segment is predicted by check if the column has any predicted cell
            for cell in column.cells:
                if cell.index in self.temporal_pooler.predictiveCells:
                    segment.is_predicted.setForCurrStep(True)

            # Update proximal synapses
            if segment.is_active.atCurrStep(
            ) or segment.is_predicted.atCurrStep():
                permanences_synapses = []
                self.spatial_pooler.getPermanence(col_idx,
                                                  permanences_synapses)
                connected_synapses = []
                self.spatial_pooler.getConnectedSynapses(
                    col_idx, connected_synapses)
                for syn_idx in range(len(permanences_synapses)):
                    # Get the proximal synapse given its position in the input map
                    # Create a new one if it doesn't exist
                    synapse = segment.getSynapse(syn_idx)

                    # Update proximal synapse
                    if permanences_synapses[syn_idx] > 0.0:
                        if synapse == None:
                            # Create a new synapse to a input element
                            # An input element is a column if feeder is a region
                            # or then a bit if feeder is a sensor
                            synapse = Synapse()
                            synapse.input_elem = self.input_map[syn_idx]
                            synapse.index_sp = syn_idx
                            segment.synapses.append(synapse)

                        # Update state
                        synapse.is_removed.setForCurrStep(False)
                        synapse.permanence.setForCurrStep(
                            permanences_synapses[syn_idx])
                        if connected_synapses[syn_idx] == 1:
                            synapse.is_connected.setForCurrStep(True)
                        else:
                            synapse.is_connected.setForCurrStep(False)
                    else:
                        if synapse != None:
                            synapse.is_removed.setForCurrStep(True)
    def updateTemporalElements(self):
        """
        Update elements regarding temporal pooler
        """

        # Update cells, distal segments and synapses according to active columns
        for col_idx in range(len(self.columns)):
            column = self.columns[col_idx]

            # Mark proximal segment and its connected synapses as predicted
            if column.segment.is_predicted.atCurrStep():
                for synapse in column.segment.synapses:
                    if synapse.is_connected.atCurrStep():
                        synapse.is_predicted.setForCurrStep(True)
                        synapse.input_elem.is_predicted.setForCurrStep(True)

            # Mark proximal segment and its connected synapses that were predicted but are not active now
            if column.segment.is_predicted.atPreviousStep():
                if not column.segment.is_active.atCurrStep():
                    column.segment.is_falsely_predicted.setForCurrStep(True)
                for synapse in column.segment.synapses:
                    if (synapse.is_predicted.atPreviousStep()
                            and not synapse.is_connected.atCurrStep()) or (
                                synapse.is_connected.atCurrStep() and synapse.
                                input_elem.is_falsely_predicted.atCurrStep()):
                        synapse.is_falsely_predicted.setForCurrStep(True)

            for cell in column.cells:
                cell_idx = cell.index

                # Update cell's states
                if cell_idx in self.temporal_pooler.winnerCells:
                    cell.is_learning.setForCurrStep(True)
                if cell_idx in self.temporal_pooler.activeCells:
                    cell.is_active.setForCurrStep(True)
                if cell_idx in self.temporal_pooler.predictiveCells:
                    cell.is_predicted.setForCurrStep(True)
                if cell.is_predicted.atPreviousStep(
                ) and not cell.is_active.atCurrStep():
                    cell.is_falsely_predicted.setForCurrStep(True)

                # Get the indexes of the distal segments of this cell
                segments_for_cell = self.temporal_pooler.connections.segmentsForCell(
                    cell_idx)

                # Add the segments that appeared after last iteration
                for seg_idx in segments_for_cell:
                    # Check if segment already exists in the cell
                    seg_found = False
                    for segment in cell.segments:
                        if segment.index_tp == seg_idx:
                            seg_found = True
                            break

                    # If segment is new, add it to cell
                    if not seg_found:
                        segment = Segment(SegmentType.DISTAL)
                        segment.index_tp = seg_idx
                        cell.segments.append(segment)

                # Update distal segments
                for segment in cell.segments:
                    seg_idx = segment.index_tp

                    # If segment not found in segments indexes returned in last iteration mark it as removed
                    if seg_idx in segments_for_cell:

                        # Update segment's state
                        if seg_idx in self.temporal_pooler.activeSegments:
                            segment.is_active.setForCurrStep(True)
                        else:
                            segment.is_active.setForCurrStep(False)

                        # Get the indexes of the synapses of this segment
                        synapses_for_segment = self.temporal_pooler.connections.synapsesForSegment(
                            seg_idx)

                        # Add the synapses that appeared after last iteration
                        for syn_idx in synapses_for_segment:
                            # Check if synapse already exists in the segment
                            syn_found = False
                            for synapse in segment.synapses:
                                if synapse.index_tp == syn_idx:
                                    syn_found = True
                                    break

                            # If synapse is new, add it to segment
                            if not syn_found:
                                synapse = Synapse()
                                synapse.index_tp = syn_idx
                                segment.synapses.append(synapse)

                        # Update synapses
                        for synapse in segment.synapses:
                            syn_idx = synapse.index_tp

                            # If synapse not found in synapses indexes returned in last iteration mark it as removed
                            if syn_idx in synapses_for_segment:

                                # Update synapse's state
                                synapse_data = self.temporal_pooler.connections.dataForSynapse(
                                    syn_idx)
                                synapse.permanence.setForCurrStep(
                                    synapse_data.permanence)
                                if synapse_data.permanence >= self.distal_syn_connected_perm:
                                    synapse.is_connected.setForCurrStep(True)
                                else:
                                    synapse.is_connected.setForCurrStep(False)

                                # Get cell given cell's index
                                source_col_idx = synapse_data.presynapticCell / self.cells_per_column
                                source_cell_rel_idx = synapse_data.presynapticCell % self.cells_per_column
                                source_cell = self.columns[
                                    source_col_idx].cells[source_cell_rel_idx]
                                synapse.input_elem = source_cell
                            else:
                                synapse.is_removed.setForCurrStep(True)
                    else:
                        segment.is_removed.setForCurrStep(True)