# emucore_direct.client

Client gRPC services for running on FPGA reservoir computer EmuCore developed by QCi.

class emucore_direct.client.StatusMessage

  Bases: `TypedDict`

  Structure of responses for configuration requests to EmuCore device.

  Parameters:

    - status – the status of the request

    - message – a description for the recieved status

  status: int
  message: str

exception emucore_direct.client.InactiveRpcError

  Bases: `Exception`

  Custom exception wrapper around grpc._channel._InactiveRpcError.

class emucore_direct.client.EmuCoreClient(ip_addr: str = 'localhost', port: str = '50051', max_data_size: int = 536870912)

  Bases: `object`

  Provides services for accessing EmuCore server

  Parameters:

    - ip_addr – the IP address of the gRPC server

    - port – The port that the RPC server is running on

    - max_data_size – int The max send and recieve message length for RPC server

  Note

  `lock_id` is used by a variety of class functions. It is set to an empty string by default since default for device server `lock_id` is also an empty string. This allows for single user processing without having to acquire a device lock.

  check_lock(lock_id: str = '') → dict

    Checks if submitted `lock_id` has execution lock on the device

    Parameters:

      lock_id – a UUID which will be checked to determine if has exclusive device execution lock

    Returns:

      a dict with following keys:

      - status_code: int- status code for lock check

      - status_desc: str- a description for the associated status code

  reservoir_reset(lock_id) → StatusMessage

    Resets a reservoir instance by clearing RAM on the server

    Parameters:

      lock_id – a lock_id which has an active reserve on the device

    Returns:

      dictionary with with values from members of `emucore_direct.types.StatusResponses`

  system_info() → dict

    Provides system info on call

    Returns:

      dict with following keys:

      - system_name: str- product name

      - system_version: str- server version

  acquire_lock() → dict

    Attempts to acquire exclusive lock for submitting jobs

    Returns:

      a member of `emucore_direct.types.LockManageStatus` as a dict along with an additional key `lock_id`:

      - lock_id: str- if acquired the current device lock_id else empty string

      - status: int- status code for lock id acquisition

      - message: str- a description for the associated status code

  release_lock(lock_id)

    Releases exclusive lock for submitting data to reservoir

    Parameters:

      lock_id – a UUID with currently acquired exclusive device lock

    Returns:

      a dict with the following keys:

      - lock_released: bool- if released is True else False

      - message: str- a description of release operation result

  rc_config(lock_id: str, vbias: float, gain: float, num_nodes: int, num_taps: int) → StatusMessage

    Configures reservoir model and how data will be processed by the reservoir.

    Parameters:

      - lock_id – a lock_id which has an active reserve on the device

      - vbias – bias to apply to each node in reservoir. Range for parameter [0,1].

      - gain – memory setting for system how long should inputs effect reservoir similar to beta in adaptive gradient descent range for parameter [0,1]

      - num_nodes – the total number of hidden nodes to instantiate within the reservoir, a single hidden layer

      - num_taps – number of connections in reservoir, generally should be set to less than the number of nodes in reservoir. Defines interconnection between nodes.

    Returns:

      dictionary with with values from one of the members of `emucore_direct.types.StatusResponses`

  rc_run(lock_id: str, reservoir_input: List[int])

    Runs a series of data through the reservoir and returns response from device based on current reservoir configuration.

    Parameters:

      - lock_id – a lock_id which has an active reserve on the device

      - reservoir_input – a list of digitized values to input to the reservoir must be less than MAX_INPUT_SIZE

    Returns:

      a dictionary with the folowing keys:

      - status: int- the status for the reservoir submission

      - message: str- a description of the status for the submission

      - states: bytes- response from reservoir as bytes.

  wait_for_lock()

    Waits for lock indefinitely calling `acquire_lock()`

    Returns:

      a tuple of the following items:

      - lock_id: str- exclusive lock for device execution with a timeout

      - start_queue_ts: int- time in ns when began lock acquisition.

      - end_queue_ts: int- time in ns when lock was acquired.

  process_all_data(lock_id: str, input_data: ndarray, num_nodes: int, density: float, feature_scaling: float, max_scale_val: float | None = None, weights: ndarray | None = None, seed_val_weights: int = 13)

    Run dataset through reservoir:

    1. Get lock

    2. Apply scaling and random weights mask to input data

    3. Run data through reservoir

    4. Combine data from reservoir responses and reshape based on number of nodes

    5. Release lock

    Parameters:

      - lock_id – a UUID that currently has lock on the device

      - input_data – data or series to process via reservoir

      - num_nodes – the total number of hidden nodes to instantiate within the reservoir, a single hidden layer (this is also used to apply random weights to to the data as well as reshape data recieved from reservoir back to correct output dimension)

      - feature_scaling – after applying max abs scalar feature scaling factor applied

      - max_scale_val – max absolute value used to scale data if provided

      - seed_val_weights – seeds randomness for weigths to allow for reproducibility

    Note:

      if doing multiple runs without reset the max value mustn’t exceed original data max value in order for results to be processed properly.

    Returns:

      a tuple of the following elements:

      - reservoir_response: np.ndarray- reservoir response represented as an array dimension of array will be nrows of input matrix by num nodes.

      - max_scale_value: np.ndarray- the scaling value that was applied to the input data before it was processed by the reservoir.

      - weights: np.ndarray- the weights that were used to apply the random mask to the data prior to being processed by the reservoir.

# emucore_direct.types

Documents possible responses from gRPC server for bumblebee client

class emucore_direct.types.StatusResponses

  Bases: `object`

  status codes paired with their descriptions

  NORMAL = {'message': 'Success', 'status': 0}
  MISMATCH = {'message': "lock_id doesn't match current device lock", 'status': 1}
  DEVICE_BUSY = {'message': 'Device currently processing other request', 'status': 2}

class emucore_direct.types.LockManageStatus

  Bases: `object`

  Statuses and descriptions for acquiring and releasing lock

  SUCCESS = {'message': 'Success', 'status': 0}
  MISMATCH = {'message': 'lock_id does not match current device lock_id', 'status': 1}
  BUSY = {'message': 'Lock currently in use unable to perform operation', 'status': 2}