<commit_before>import collections
import logging
import numpy as np
import sys
import threading
import time

from nengo.utils.compat import is_callable

from pacman103.core import control
from pacman103 import conf

from . import builder
from . import nodes

logger = logging.getLogger(__name__)


class Simulator(object):
    def __init__(self, model, dt=0.001, seed=None, io=None):
        # Build the model
        self.builder = builder.Builder()

        # Set up the IO
        self.machinename = conf.config.get('Machine', 'machineName')
        if io is None:
            io = nodes.Ethernet(self.machinename)
        self.io = io

        (self.dao, self.nodes, self.node_node_connections) = self.builder(
            model, dt, seed, node_builder=io
        )
        self.dao.writeTextSpecs = True

        self.dt = dt

    def get_node_input(self, node):
        """Return the latest input for the given Node

        :return: an array of data for the Node, or None if no data received
        :raises KeyError: if the Node is not a valid Node
        """
        # Get the input from the board
        try:
            i = self.node_io.get_node_input(node)
        except KeyError:
            # Node does not receive input from the board
            i = np.zeros(node.size_in)

        if i is None or None in i:
            # Incomplete input, return None
            return None

        # Add Node->Node input if required
        if node not in self._internode_cache:
            return i

        i_s = self._internode_cache[node].values()

        if None in i_s:
            # Incomplete input, return None
            return None

        # Return input from board + input from other Nodes on host
        return np.sum([i, np.sum(i_s, axis=0)], axis=0)

    def set_node_output(self, node, output):
        """Set the output of the given Node

        :raises KeyError: if the Node is not a valid Node
        """
        # Output to board
        self.node_io.set_node_output(node, output)

        # Output to other Nodes on host
        if node in self._internode_out_maps:
            for (post, transform) in self._internode_out_maps[node]:
                self._internode_cache[post][node] = np.dot(transform, output)

    def run(self, time_in_seconds=None):
        """Run the model, currently ignores the time."""
        self.controller = control.Controller(
            sys.modules[__name__],
            conf.config.get('Machine', 'machineName')
        )

        # Preparation functions
        for vertex in self.dao.vertices:
            if hasattr(vertex, 'prepare_vertex'):
                vertex.prepare_vertex()

        # Create some caches for Node->Node connections, and a map of Nodes to
        # other Nodes on host
        # TODO: Filters on Node->Node connections
        self._internode_cache = collections.defaultdict(dict)
        self._internode_out_maps = collections.defaultdict(list)
        for c in self.node_node_connections:
            self._internode_cache[c.post][c.pre] = None
            self._internode_out_maps[c.pre].append((c.post, c.transform))

        # PACMANify!
        self.controller.dao = self.dao
        self.dao.set_hostname(self.machinename)
        self.dao.run_time = None  # TODO: Modify Transceiver so that we can
                                  # manually check for application termination
                                  # i.e., we want to do something during the
                                  # simulation time, not pause in the TxRx.
        self.controller.set_tag_output(1, 17895)  # Only required for Ethernet

        # TODO: All of the following will become more modular!
        self.controller.map_model()<commit_msg>Lock the Node->Node cache during reading/writing values.<commit_after>import collections
import logging
import numpy as np
import sys
import threading
import time

from nengo.utils.compat import is_callable

from pacman103.core import control
from pacman103 import conf

from . import builder
from . import nodes

logger = logging.getLogger(__name__)


class Simulator(object):
    def __init__(self, model, dt=0.001, seed=None, io=None):
        # Build the model
        self.builder = builder.Builder()

        # Set up the IO
        self.machinename = conf.config.get('Machine', 'machineName')
        if io is None:
            io = nodes.Ethernet(self.machinename)
        self.io = io

        (self.dao, self.nodes, self.node_node_connections) = self.builder(
            model, dt, seed, node_builder=io
        )
        self.dao.writeTextSpecs = True

        self.dt = dt

    def get_node_input(self, node):
        """Return the latest input for the given Node

        :return: an array of data for the Node, or None if no data received
        :raises KeyError: if the Node is not a valid Node
        """
        # Get the input from the board
        try:
            i = self.node_io.get_node_input(node)
        except KeyError:
            # Node does not receive input from the board
            i = np.zeros(node.size_in)

        if i is None or None in i:
            # Incomplete input, return None
            return None

        # Add Node->Node input if required
        if node not in self._internode_cache:
            return i

        with self._internode_cache_lock:
            i_s = self._internode_cache[node].values()

        if None in i_s:
            # Incomplete input, return None
            return None

        # Return input from board + input from other Nodes on host
        return np.sum([i, np.sum(i_s, axis=0)], axis=0)

    def set_node_output(self, node, output):
        """Set the output of the given Node

        :raises KeyError: if the Node is not a valid Node
        """
        # Output to board
        self.node_io.set_node_output(node, output)

        # Output to other Nodes on host
        if node in self._internode_out_maps:
            with self._internode_cache_lock:
                for (post, transform) in self._internode_out_maps[node]:
                    self._internode_cache[post][node] = np.dot(transform,
                                                               output)

    def run(self, time_in_seconds=None):
        """Run the model, currently ignores the time."""
        self.controller = control.Controller(
            sys.modules[__name__],
            conf.config.get('Machine', 'machineName')
        )

        # Preparation functions
        for vertex in self.dao.vertices:
            if hasattr(vertex, 'prepare_vertex'):
                vertex.prepare_vertex()

        # Create some caches for Node->Node connections, and a map of Nodes to
        # other Nodes on host
        # TODO: Filters on Node->Node connections
        self._internode_cache = collections.defaultdict(dict)
        self._internode_out_maps = collections.defaultdict(list)
        for c in self.node_node_connections:
            self._internode_cache[c.post][c.pre] = None
            self._internode_out_maps[c.pre].append((c.post, c.transform))

        self._internode_cache_lock = threading.Lock()

        # PACMANify!
        self.controller.dao = self.dao
        self.dao.set_hostname(self.machinename)
        self.dao.run_time = None  # TODO: Modify Transceiver so that we can
                                  # manually check for application termination
                                  # i.e., we want to do something during the
                                  # simulation time, not pause in the TxRx.
        self.controller.set_tag_output(1, 17895)  # Only required for Ethernet

        # TODO: All of the following will become more modular!
        self.controller.map_model()
{'fraction_non_alphanumeric': 0.07824056052938887, 'fraction_numerical': 0.004671078240560529, 'mean_word_length': 2.014470082127493, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 10, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 8, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '898040', 'n_tokens_mistral': 2172, 'n_tokens_neox': 2093, 'n_words': 679}