def process_input(self, stream, value, rpc_executor):
        """Process an input through this sensor graph.

        The tick information in value should be correct and is transfered
        to all results produced by nodes acting on this tick.

        Args:
            stream (DataStream): The stream the input is part of
            value (IOTileReading): The value to process
            rpc_executor (RPCExecutor): An object capable of executing RPCs
                in case we need to do that.
        """

        self.sensor_log.push(stream, value)

        # FIXME: This should be specified in our device model
        if stream.important:
            associated_output = stream.associated_stream()
            self.sensor_log.push(associated_output, value)

        to_check = deque([x for x in self.roots])

        while len(to_check) > 0:
            node = to_check.popleft()
            if node.triggered():
                try:
                    results = node.process(rpc_executor, self.mark_streamer)
                    for result in results:
                        result.raw_time = value.raw_time
                        self.sensor_log.push(node.stream, result)
                except:
                    self._logger.exception("Unhandled exception in graph node processing function for node %s", str(node))

                # If we generated any outputs, notify our downstream nodes
                # so that they are also checked to see if they should run.
                if len(results) > 0:
                    to_check.extend(node.outputs)
Process an input through this sensor graph.

        The tick information in value should be correct and is transfered
        to all results produced by nodes acting on this tick.

        Args:
            stream (DataStream): The stream the input is part of
            value (IOTileReading): The value to process
            rpc_executor (RPCExecutor): An object capable of executing RPCs
                in case we need to do that.