# 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 member of `eqc_direct.utils.LockCheckStatus` as a dict:

      - 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

    Acquires exclusive lock for running health check or submitting job

    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 running health check or submitting job

    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
    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. Reset Reservoir 3. Calculate input coefficients 4. Run data through reservoir 5. Combine data from reservoir and reformat 6. Release lock

    Parameters:

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

      - input_data – data or series to process via reservoir

      - num_taps – defines connectivity of neurons in the reservoir higher taps can lead to overfitting it is not recommended to not set num_taps significantly higher than num_nodes

      - 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 register 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}