Skip to content

Commit

Permalink
Updated docstrings 2
Browse files Browse the repository at this point in the history
  • Loading branch information
fpicetti committed Apr 19, 2022
1 parent c55edd3 commit 2695201
Show file tree
Hide file tree
Showing 40 changed files with 1,649 additions and 1,719 deletions.
8 changes: 4 additions & 4 deletions occamypy/__init__.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
from .__version__ import __version__
from .dask import *
from .numpy import *
from .vector import *
from .operator import *
from .numpy import *
from .problem import *
from .solver import *
from .torch import *
from .dask import *
from .utils import *
from .torch import *
from .utils import plot
from .vector import *

if CUPY_ENABLED:
from .cupy import *
Expand Down
2 changes: 1 addition & 1 deletion occamypy/cupy/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from .operator import *
from .vector import *
from .operator import *

__all__ = [
"VectorCupy",
Expand Down
75 changes: 38 additions & 37 deletions occamypy/cupy/operator/signal.py
Original file line number Diff line number Diff line change
@@ -1,36 +1,34 @@
from __future__ import division, print_function, absolute_import

from typing import Union, Tuple

import cupy as cp
import numpy as np
import cupy as cp
from cupyx.scipy.ndimage import gaussian_filter

try:
from cusignal.convolution import convolve, correlate
except ModuleNotFoundError:
raise ModuleNotFoundError("cuSIGNAL is not installed. Please install it")
from occamypy.operator.base import Operator, Dstack
from occamypy.vector.base import Vector, superVector
from occamypy.cupy.vector import VectorCupy
from occamypy import Operator, Dstack, Vector, superVector
from occamypy.cupy import VectorCupy


class GaussianFilter(Operator):
"""Gaussian smoothing operator using scipy smoothing"""
def __init__(self, domain: VectorCupy, sigma: Tuple[float]):

def __init__(self, model, sigma):
"""
GaussianFilter (cupy) constructor
Args:
domain: domain vector
sigma: standard deviation along the domain directions
"""
self.sigma = sigma
self.scaling = np.sqrt(np.prod(np.array(self.sigma) / cp.pi)) # in order to have the max amplitude 1

super(GaussianFilter, self).__init__(domain, domain)
self.name = "GausFilt"
super(GaussianFilter, self).__init__(model, model)
return

def __str__(self):
return "GausFilt"

def forward(self, add, model, data):
self.checkDomainRange(model, data)
Expand All @@ -49,11 +47,11 @@ def adjoint(self, add, model, data):

class ConvND(Operator):
"""ND convolution square operator in the domain space"""
def __init__(self, domain: VectorCupy, kernel: Union[VectorCupy, cp.ndarray], method: str = 'auto'):

def __init__(self, domain, kernel, method='auto'):
"""
ConvND (cupy) constructor
Args:
domain: domain vector
kernel: kernel vector
Expand Down Expand Up @@ -85,7 +83,9 @@ def __init__(self, domain: VectorCupy, kernel: Union[VectorCupy, cp.ndarray], me
self.method = method

super(ConvND, self).__init__(domain, domain)
self.name = "Convolve"

def __str__(self):
return " ConvOp "

def forward(self, add, model, data):
self.checkDomainRange(model, data)
Expand All @@ -106,7 +106,7 @@ def adjoint(self, add, model, data):
return


def Padding(domain: Union[VectorCupy, superVector], pad: Union[Tuple[int], Tuple[Tuple[int]]], mode: str = "constant"):
def Padding(model, pad, mode: str = "constant"):
"""
Padding operator
Expand All @@ -119,17 +119,16 @@ def Padding(domain: Union[VectorCupy, superVector], pad: Union[Tuple[int], Tuple
pad: number of samples to be added at each end of the dimension, for each dimension
mode: padding mode (see https://numpy.org/doc/stable/reference/generated/numpy.pad.html)
"""

if isinstance(domain, VectorCupy):
return _Padding(domain, pad, mode)
elif isinstance(domain, superVector):
if isinstance(model, VectorCupy):
return _Padding(model, pad, mode)
elif isinstance(model, superVector):
# TODO add the possibility to have different padding for each sub-vector
return Dstack([_Padding(v, pad, mode) for v in domain.vecs])
return Dstack([_Padding(v, pad, mode) for v in model.vecs])
else:
raise ValueError("ERROR! Provided domain has to be either vector or superVector")


def ZeroPad(domain: VectorCupy, pad: Union[Tuple[int], Tuple[Tuple[int]]]):
def ZeroPad(model, pad):
"""
Zero-Padding operator
Expand All @@ -141,8 +140,7 @@ def ZeroPad(domain: VectorCupy, pad: Union[Tuple[int], Tuple[Tuple[int]]]):
domain: domain vector
pad: number of samples to be added at each end of the dimension, for each dimension
"""

return Padding(domain=domain, pad=pad, mode="constant")
return Padding(model, pad, mode="constant")


def _pad_VectorCupy(vec, pad):
Expand All @@ -159,20 +157,23 @@ def _pad_VectorCupy(vec, pad):


class _Padding(Operator):

def __init__(self, domain, pad, mode: str = "constant"):

self.dims = domain.shape
pad = [(pad, pad)] * len(self.dims) if pad is cp.isscalar else list(pad)
if (cp.array(pad) < 0).any():
raise ValueError('Padding must be positive or zero')
self.pad = pad
self.mode = mode
super(_Padding, self).__init__(domain, _pad_VectorCupy(domain, self.pad))
self.name = "Padding"

if isinstance(domain, VectorCupy):
self.dims = domain.shape
pad = [(pad, pad)] * len(self.dims) if pad is cp.isscalar else list(pad)
if (cp.array(pad) < 0).any():
raise ValueError('Padding must be positive or zero')
self.pad = pad
self.mode = mode
super(_Padding, self).__init__(domain, _pad_VectorCupy(domain, self.pad))

def __str__(self):
return "Padding "

def forward(self, add, model, data):
"""Padding the domain"""
"""Pad the domain"""
self.checkDomainRange(model, data)
if add:
temp = data.clone()
Expand Down
25 changes: 9 additions & 16 deletions occamypy/cupy/vector.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,25 @@
import numpy as np
from GPUtil import getGPUs, getFirstAvailable

from occamypy.vector.base import Vector
from occamypy.numpy.vector import VectorNumpy
from occamypy import Vector, VectorNumpy


class VectorCupy(Vector):
"""Vector class based on cupy.ndarray"""
def __init__(self, in_content, device: int = None, *args, **kwargs):

def __init__(self, in_content, device=None, *args, **kwargs):
"""
VectorCupy constructor
Args:
in_content: numpy.ndarray, cupy.ndarray, tuple or VectorNumpy
device: computation device (None for CPU, -1 for least used GPU)
*args: list of arguments for Vector construction
**kwargs: dict of arguments for Vector construction
"""
if isinstance(in_content, cp.ndarray) or isinstance(in_content, np.ndarray):
if cp.isfortran(in_content):
raise TypeError('Input array not a C contiguous array!')
self.arr = cp.array(in_content, copy=False)
elif isinstance(in_content, tuple): # Tuple size passed to constructor
# self.arr = cp.zeros(tuple(reversed(in_content)))
Expand Down Expand Up @@ -114,16 +115,7 @@ def rand(self, snr=1.):
amp_noise = cp.sqrt(3. / snr) * rms # sqrt(3*Power_signal/SNR)
self.getNdArray()[:] = amp_noise * (2. * cp.random.random(self.getNdArray().shape) - 1.)
return self

def randn(self, snr=1.):
rms = cp.sqrt(cp.mean(cp.square(self.getNdArray())))
amp_noise = 1.0
if rms != 0.:
amp_noise = cp.sqrt(3. / snr) * rms # sqrt(3*Power_signal/SNR)
self.getNdArray()[:] = cp.random.normal(0., 1., self.shape)
self.scale(amp_noise)
return self


def clone(self):
vec_clone = deepcopy(self) # Deep clone of vector
# Checking if a vector space was provided
Expand Down Expand Up @@ -241,6 +233,7 @@ def multiply(self, other):
return self

def isDifferent(self, other):
# Checking whether the input is a vector or not
if not isinstance(other, VectorCupy):
raise TypeError("Provided input vector not a %s!" % self.whoami)
if not self._check_same_device(other):
Expand All @@ -260,7 +253,7 @@ def isDifferent(self, other):
isDiff = (not cp.equal(self.getNdArray(), other.getNdArray()).all())
return isDiff

def clip(self, low, high):
def clipVector(self, low, high):
if not isinstance(low, VectorCupy):
raise TypeError("Provided input low vector not a %s!" % self.whoami)
if not isinstance(high, VectorCupy):
Expand Down
2 changes: 1 addition & 1 deletion occamypy/dask/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from .vector import *
from .operator import *
from .utils import *
from .vector import *

__all__ = [
"DaskClient",
Expand Down
51 changes: 27 additions & 24 deletions occamypy/dask/operator.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
from collections.abc import Iterable
from typing import Union, List, Tuple

import dask.distributed as daskD
import numpy as np
import dask.distributed as daskD
from collections.abc import Iterable

from occamypy.operator.base import Operator
from occamypy.vector.base import Vector
from occamypy.dask.utils import DaskClient
from occamypy.dask.vector import DaskVector, scatter_large_data
from occamypy import Vector, Operator
from .vector import DaskVector
from .utils import DaskClient
from .vector import scatter_large_data


def call_constructor(constr, args, kwargs=None):
Expand Down Expand Up @@ -80,7 +78,7 @@ def _check_dask_error(futures):
class DaskOperator(Operator):
"""Class to apply multiple operators in parallel through Dask and DaskVectors"""

def __init__(self, dask_client: DaskClient, op_constructor, op_args: Union[List, Tuple], chunks: Union[List, Tuple], **kwargs):
def __init__(self, dask_client, op_constructor, op_args, chunks, **kwargs):
"""
DaskOperator constructor
Expand All @@ -100,6 +98,7 @@ def __init__(self, dask_client: DaskClient, op_constructor, op_args: Union[List,
set_aux_name: name of the function to set the auxiliary vector. Useful for VpOperator.
spread_op_aux: spreading operator to distribute an auxiliary vector to the set_aux functions
"""
# Client to submit tasks
if not isinstance(dask_client, DaskClient):
raise TypeError("Passed client is not a Dask Client object!")
if not isinstance(op_args, list):
Expand Down Expand Up @@ -219,7 +218,10 @@ def __init__(self, dask_client: DaskClient, op_constructor, op_args: Union[List,
if not isinstance(self.SprdAux, DaskSpread):
raise TypeError("Provided spread_op_aux not a DaskSpreadOp class!")
self.tmp_aux = self.SprdAux.getRange().clone()
self.name = "DaskOp" if isinstance(op_constructor, list) else f"Dask({op_constructor.__name__})"
return

def __str__(self):
return " DaskOp "

def forward(self, add, model, data):
if not isinstance(model, DaskVector):
Expand Down Expand Up @@ -269,7 +271,7 @@ def adjoint(self, add, model, data):

def set_background(self, model):
"""Function to call set_background function of each dask operator"""
if self.set_background_name is None:
if self.set_background_name == None:
raise NameError("setbackground_func_name was not defined when constructing the operator!")
if self.Sprd:
self.Sprd.forward(False, model, self.model_tmp)
Expand All @@ -284,7 +286,7 @@ def set_background(self, model):

def set_aux(self, aux_vec):
"""Function to call set_nl or set_lin_jac functions of each dask operator"""
if self.set_aux_name is None:
if self.set_aux_name == None:
raise NameError("set_aux_name was not defined when constructing the operator!")
if self.SprdAux:
self.SprdAux.forward(False, aux_vec, self.tmp_aux)
Expand All @@ -304,14 +306,13 @@ class DaskSpread(Operator):
| v1 | | I |
fwd: | v2 | = | I | v
| v3 | | I |
adj: | v | = | I | v1 + | I | v2 + | I | v3
"""

def __init__(self, dask_client: DaskClient, domain: Vector, chunks: Union[List, Tuple]):
def __init__(self, dask_client, domain, chunks):
"""
DaskSpread constructor
Args:
dask_client: client object to use when submitting tasks (see dask_util module)
domain: vector template to be spread/stack (note this is also the domain of the operator)
Expand All @@ -325,8 +326,11 @@ def __init__(self, dask_client: DaskClient, domain: Vector, chunks: Union[List,
self.dask_client = dask_client
self.client = self.dask_client.getClient()
self.chunks = chunks
super(DaskSpread, self).__init__(domain=domain, range=DaskVector(self.dask_client, vector_template=domain, chunks=chunks))
self.name = ""
self.setDomainRange(domain, DaskVector(self.dask_client, vector_template=domain, chunks=chunks))
return

def __str__(self):
return "DaskSprd"

def forward(self, add, model, data):
"""Distribute local domain through dask"""
Expand All @@ -340,10 +344,10 @@ def forward(self, add, model, data):
# Getting the future to the first vector in the Dask vector
modelNd = self.client.submit(getNdfuture, model.vecDask[0], pure=False)
else:
# Getting the numpy array to the local domain vector
# Getting the numpy array to the local model vector
modelNd = model.getNdArray()

# Spreading domain array to workers
# Spreading model array to workers
if len(self.chunks) == self.dask_client.getNworkers():
dataVecList = data.vecDask.copy()
for iwrk, wrkId in enumerate(self.dask_client.getWorkerIds()):
Expand Down Expand Up @@ -376,7 +380,7 @@ def adjoint(self, add, model, data):
daskD.wait(self.client.submit(_add_from_NdArray, model, sum_array, pure=False))
else:
arrD_list = data.getNdArray()
# Getting the numpy array to the local domain vector
# Getting the numpy array to the local model vector
modelNd = model.getNdArray()
for arr_i in arrD_list:
modelNd[:] += arr_i
Expand All @@ -386,10 +390,10 @@ def adjoint(self, add, model, data):
class DaskCollect(Operator):
"""Class to Collect/Scatter a Dask vector into/from a local vector"""

def __init__(self, domain: DaskVector, range: Vector):
def __init__(self, domain, range):
"""
DaskCollect constructor
Args:
domain: dask vector to be collected from remote
range: vector class to be locally stored
Expand All @@ -403,7 +407,6 @@ def __init__(self, domain: DaskVector, range: Vector):
if domain.size != range.size:
raise ValueError("number of elements in domain and range is not equal!")
super(DaskCollect, self).__init__(domain, range)
self.name = ""

def forward(self, add, model, data):
"""Collect dask vector arrays to local one"""
Expand Down
Loading

0 comments on commit 2695201

Please sign in to comment.