Source code for arkouda.sparrayclass

from __future__ import annotations

import builtins
from typing import List, Optional, Sequence, Union, cast

import numpy as np
from typeguard import typechecked

from arkouda.client import generic_msg
from arkouda.numpy.dtypes import NumericDTypes, dtype, int_scalars
from arkouda.logger import getArkoudaLogger
from arkouda.pdarrayclass import create_pdarrays, pdarray

logger = getArkoudaLogger(name="sparrayclass")

__all__ = [
    "sparray",
    "create_sparray",
]


[docs] class sparray: """ The class for sparse arrays. This class contains only the attributies of the array; the data resides on the arkouda server. When a server operation results in a new array, arkouda will create a sparray instance that points to the array data on the server. As such, the user should not initialize sparray instances directly. Attributes ---------- name : str The server-side identifier for the array dtype : dtype The element type of the array size : int_scalars The size of any one dimension of the array (all dimensions are assumed to be equal sized for now) nnz: int_scalars The number of non-zero elements in the array ndim : int_scalars The rank of the array (currently only rank 2 arrays supported) shape : Sequence[int] A list or tuple containing the sizes of each dimension of the array layout: str The layout of the array ("CSR" or "CSC" are the only valid values) itemsize : int_scalars The size in bytes of each element """ def __init__( self, name: str, mydtype: Union[np.dtype, str], size: int_scalars, nnz: int_scalars, ndim: int_scalars, shape: Sequence[int], layout: str, itemsize: int_scalars, max_bits: Optional[int] = None, ) -> None: self.name = name self.dtype = dtype(mydtype) self.size = size self.nnz = nnz self.ndim = ndim self.shape = shape self.layout = layout self.itemsize = itemsize if max_bits: self.max_bits = max_bits def __del__(self): try: logger.debug(f"deleting sparray with name {self.name}") generic_msg(cmd="delete", args={"name": self.name}) except (RuntimeError, AttributeError): pass def __bool__(self) -> builtins.bool: if self.size != 1: raise ValueError( "The truth value of an array with more than one element is ambiguous." "Use a.any() or a.all()" ) return builtins.bool(self[0]) def __len__(self): return self.nnz # This is the number of non-zero elements in the matrix def __getitem__(self, key): raise NotImplementedError("sparray does not support __getitem__") def __str__(self): from arkouda.client import sparrayIterThresh return generic_msg(cmd="str", args={"array": self, "printThresh": sparrayIterThresh}) # def __repr__(self): # from arkouda.client import sparrayIterThresh # print("Called repr") # return generic_msg(cmd="repr", args={"array": self, "printThresh": sparrayIterThresh}) """ Converts the sparse matrix to a list of 3 pdarrays (rows, cols, vals) Returns ------- List[ak.pdarray] A list of 3 pdarrays which contain the row indices, the column indices, and the values at the respective indices within the sparse matrix. Examples -------- >>> a = ak.random_sparse_matrix(100,0.2,"CSR"); >>> a.to_pdarray() [array([1 1 1 ... 100 100 100]), array([17 21 29 ... 75 77 85]), array([0 0 0 ... 0 0 0])] """
[docs] @typechecked def to_pdarray(self) -> List[pdarray]: dtype = self.dtype dtype_name = cast(np.dtype, dtype).name # check dtype for error if dtype_name not in NumericDTypes: raise TypeError(f"unsupported dtype {dtype}") responseArrays = generic_msg( cmd=f"sparse_to_pdarrays<{self.dtype},{self.layout}>", args={"matrix": self} ) array_list = create_pdarrays(responseArrays) return array_list
""""""
[docs] def fill_vals(self, a: pdarray): if self.dtype != a.dtype: raise ValueError("sparray and pdarray must have the same dtype for fill_vals") if a.ndim != 1: raise ValueError("pdarray must be 1D for fill_vals") generic_msg( cmd=f"fill_sparse_vals<{self.dtype},2,{self.layout},{a.dtype},1>", args={"matrix": self, "vals": a}, )
# creates sparray object # only after: # all values have been checked by python module and... # server has created pdarray already before this is called
[docs] @typechecked def create_sparray(repMsg: str, max_bits=None) -> sparray: """ Return a sparray instance pointing to an array created by the arkouda server. The user should not call this function directly. Parameters ---------- repMsg : str space-delimited string containing the sparray name, datatype, size dimension, shape,and itemsize Returns ------- sparray A sparray with the same attributes as on the server Raises ----- ValueError If there's an error in parsing the repMsg parameter into the six values needed to create the pdarray instance RuntimeError Raised if a server-side error is thrown in the process of creating the pdarray instance """ try: fields = repMsg.split() name = fields[1] mydtype = fields[2] size = int(fields[3]) nnz = int(fields[4]) ndim = int(fields[5]) if fields[6] == "[]": shape = [] else: trailing_comma_offset = -2 if fields[6][len(fields[6]) - 2] == "," else -1 shape = [int(el) for el in fields[6][1:trailing_comma_offset].split(",")] layout = fields[7] itemsize = int(fields[8]) except Exception as e: raise ValueError(e) logger.debug( f"created Chapel sparse array with name: {name} dtype: {mydtype} ndim: {ndim} " + f"nnz:{nnz} shape: {shape} layout: {layout} itemsize: {itemsize}" ) return sparray(name, dtype(mydtype), size, nnz, ndim, shape, layout, itemsize, max_bits)