Skip to content

Commit

Permalink
Merge pull request #28 from fpicetti/devel_fp
Browse files Browse the repository at this point in the history
Preparation of release v0.1.5
  • Loading branch information
biondiettore authored Apr 25, 2022
2 parents 077df31 + 848da77 commit d72b869
Show file tree
Hide file tree
Showing 86 changed files with 16,033 additions and 9,893 deletions.
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,7 @@
.ipynb_checkpoints/
dask-worker-space
/devel
experiments
publishing.md
tutorials/devito
pykonal-0.2.3b3
**__pycache__
13 changes: 12 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,19 @@
# 0.1.5
* Moved `set_seed_everywhere` in the main utils submodule
* Signal processing operators are called directly from occamypy init (no cupy/torch submodule needed)
* Removed `snr` logic from `rand` and `randn`; now they accept distribution descriptors
* A lot of cleanings in the documentation, names, and methods
* Added [PyLops](tutorials/PyLops%20and%20OccamyPy%20together.ipynb) tutorial
* Added Traveltime tomography tutorials in [1D](tutorials/1D%20Travel-time%20tomography%20using%20the%20Eikonal%20equation.ipynb), [2D](tutorials/2D%20Travel-time%20tomography%20using%20the%20Eikonal%20equation.ipynb), and [Marmousi](tutorials/Traveltime%20tomography%20for%20Seismic%20Exploration.ipynb)
* Added [Devito-based LS-RTM](tutorials/2D%20LS-RTM%20with%20devito,%20dask,%20and%20regularizers.ipynb) tutorial
* Added [autograd](occamypy/torch/autograd.py) torch submodule to cast linear operators to torch automatic differentiation engine (see the [tutorial](tutorials/2D%20LS-RTM%20with%20devito%20and%20Automatic%20Differentiation.ipynb))
* Added a future work tutorial on [automatically differentiated operators](tutorials/Automatic%20Differentiation%20for%20nonlinear%20operators.ipynb)

# 0.1.4
* Added support for F-contiguous arrays
* Added [PyLops](https://pylops.readthedocs.io/en/stable/) interface [operators](ea8505947c926e376a6def40b1fccfbadf3940d2)
* Added plot utilities
* Added [`AxInfo`](tutorials/ax_info.py) class for handling physical vectors
* Added [`AxInfo`](tutorials/AxInfo%20-%20exploit%20physical%20vectors.ipynb) class for handling physical vectors
* Added Padding operators different from ZeroPad
* Improvements on VectorTorch methods and attributes
* Added FISTA solver wrapper
Expand Down
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ pip install occamypy
In order to have Cupy-based vectors and operators, you should install also [Cupy](https://docs.cupy.dev/en/stable/install.html#install-cupy) and [cuSIGNAL](https://github.com/rapidsai/cusignal#installation).
They are not included in this installation as they are dependent on the target CUDA device and compiler.

As this library strongly relies on Numpy, we suggest installing OccamyPy in a conda environment like [this](./envs/env.yml).

### History
This library was initially developed at
[Stanford Exploration Project](http://zapad.stanford.edu/ettore88/python-solver)
Expand Down Expand Up @@ -83,6 +85,8 @@ We provide some [tutorials](./tutorials) that demonstrate the flexibility of occ
Please refer to them as a good starting point for developing your own code.
If you have a good application example, contact us! We will be happy to see OccamyPy in action.

Check out the [tutorial](https://curvenote.com/@swung/transform-2022-occamypy-an-oo-optimizaton-library/overview) we gave at SWUNG's Transform 2022!

### Contributing
Follow the following instructions and read carefully the [CONTRIBUTING](CONTRIBUTING.md) file before getting started.

Expand Down
20 changes: 20 additions & 0 deletions envs/devel.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
channels:
- conda-forge
- defaults
dependencies:
- jupyter
- numpy>=1.15
- scipy>=1.4
- numba
- matplotlib
- imageio
- dask
- dask-jobqueue
- dask-kubernetes
- bokeh>=2.1.1
- pylops
- pip
- pip:
- gputil
- torch>=1.7 # here for automatic cuda installation
- functorch
23 changes: 23 additions & 0 deletions envs/devel_cupy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
channels:
- conda-forge
- defaults
- rapidsai
dependencies:
- jupyter
- numpy>=1.15
- scipy>=1.4
- numba
- matplotlib
- imageio
- dask
- dask-jobqueue
- dask-kubernetes
- bokeh>=2.1.1
- pylops
- cupy # if cuda driver is correctly compiled
- cusignal # to use cupy signal
- pip
- pip:
- gputil
- torch>=1.7 # here for automatic cuda installation
- functorch
3 changes: 1 addition & 2 deletions env.yml → envs/env.yml
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
channels:
- conda-forge
- defaults
- pytorch
dependencies:
- jupyter
- numpy>=1.15
- scipy>=1.4
- numba
- pytorch>=1.7.0
- matplotlib
- imageio
- dask
Expand All @@ -18,4 +16,5 @@ dependencies:
- pip
- pip:
- gputil
- torch>=1.7 # here for automatic cuda installation
- occamypy
23 changes: 23 additions & 0 deletions envs/env_cupy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
channels:
- conda-forge
- defaults
- rapidsai
dependencies:
- jupyter
- numpy>=1.15
- scipy>=1.4
- numba
- matplotlib
- imageio
- dask
- dask-jobqueue
- dask-kubernetes
- bokeh>=2.1.1
- pylops
- cupy
- cusignal
- pip
- pip:
- gputil
- torch>=1.7 # here for automatic cuda installation
- occamypy
24 changes: 24 additions & 0 deletions envs/swung.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
channels:
- conda-forge
- defaults
dependencies:
- jupyter
- numpy>=1.15
- scipy>=1.4
- numba
- matplotlib
- imageio
- dask
- dask-jobqueue
- dask-kubernetes
- bokeh>=2.1.1
- pylops
- cython # for the tomography example
- pip
- pip:
- gputil
- torch>=1.7 # here for automatic cuda installation
- functorch
- git+https://github.com/devitocodes/devito.git # for the LS-RTM example
- git+https://github.com/malcolmw/[email protected] # for the tomography example
- occamypy
2 changes: 1 addition & 1 deletion occamypy/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
from .utils import *
from .torch import *
from .utils import plot
from .utils import backend

if CUPY_ENABLED:
from .cupy import *

from .numpy.operator import pylops_interface
2 changes: 1 addition & 1 deletion occamypy/__version__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = "0.1.4"
__version__ = "0.1.5"
98 changes: 56 additions & 42 deletions occamypy/cupy/operator/signal.py
Original file line number Diff line number Diff line change
@@ -1,35 +1,37 @@
from __future__ import division, print_function, absolute_import
import numpy as np
import cupy as cp
import numpy as np
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 import Operator, Dstack, Vector, superVector
from occamypy.cupy import VectorCupy

from occamypy.vector.base import Vector, superVector
from occamypy.operator.base import Operator, Dstack
from occamypy.cupy.vector import VectorCupy


class GaussianFilter(Operator):
def __init__(self, model, sigma):
"""Gaussian smoothing operator using scipy smoothing"""

def __init__(self, domain, sigma):
"""
Gaussian smoothing operator using scipy smoothing:
:param model : vector class;
domain vector
:param sigma : scalar or sequence of scalars;
standard deviation along the model directions
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__(model, model)
return
super(GaussianFilter, self).__init__(domain, domain)

def __str__(self):
return "GausFilt"

def forward(self, add, model, data):
"""Forward operator"""
self.checkDomainRange(model, data)
if not add:
data.zero()
Expand All @@ -40,23 +42,22 @@ def forward(self, add, model, data):
return

def adjoint(self, add, model, data):
"""Self-adjoint operator"""
self.forward(add, data, model)
return


class ConvND(Operator):
"""
ND convolution square operator in the domain space
"""ND convolution square operator in the domain space"""

:param domain : [no default] - vector class; domain vector
:param kernel : [no default] - vector class; kernel vector
:param method : [auto] - str; how to compute the convolution [auto, direct, fft]
:return : Convolution Operator
"""

def __init__(self, domain, kernel, method='auto'):

"""
ConvND (cupy) constructor
Args:
domain: domain vector
kernel: kernel vector
method: how to compute the convolution [auto, direct, fft]
"""
if isinstance(kernel, Vector):
self.kernel = kernel.clone().getNdArray()
elif isinstance(kernel, cp.ndarray):
Expand Down Expand Up @@ -106,18 +107,41 @@ def adjoint(self, add, model, data):
return


def Padding(model, pad, mode: str = "constant"):
if isinstance(model, VectorCupy):
return _Padding(model, pad, mode)
elif isinstance(model, superVector):
def Padding(domain, pad, mode: str = "constant"):
"""
Padding operator
Notes:
To pad 2 values to each side of the first dim, and 3 values to each side of the second dim, use:
pad=((2,2), (3,3))
Args:
domain: domain vector
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):
# TODO add the possibility to have different padding for each sub-vector
return Dstack([_Padding(v, pad, mode) for v in model.vecs])
return Dstack([_Padding(v, pad, mode) for v in domain.vecs])
else:
raise ValueError("ERROR! Provided domain has to be either vector or superVector")


def ZeroPad(model, pad):
return Padding(model, pad, mode="constant")
def ZeroPad(domain, pad):
"""
Zero-Padding operator
Notes:
To pad 2 values to each side of the first dim, and 3 values to each side of the second dim, use:
pad=((2,2), (3,3))
Args:
domain: domain vector
pad: number of samples to be added at each end of the dimension, for each dimension
"""
return Padding(domain, pad, mode="constant")


def _pad_VectorCupy(vec, pad):
Expand All @@ -136,20 +160,10 @@ def _pad_VectorCupy(vec, pad):
class _Padding(Operator):

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

To pad 2 values to each side of the first dim, and 3 values to each side of the second dim, use:
pad=((2,2), (3,3))
:param domain: vectorIC class
:param pad: scalar or sequence of scalars
Number of samples to pad in each dimension.
If a single scalar is provided, it is assigned to every dimension.
:param mode: str
Padding mode (see https://docs.cupy.dev/en/stable/reference/generated/cupy.pad.html)
"""
if isinstance(domain, VectorCupy):
self.dims = domain.shape
pad = [(pad, pad)] * len(self.dims) if pad is cp.isscalar else list(pad)
pad = [(pad, pad)] * len(self.dims) if isinstance(pad, int) else list(pad)
if (cp.array(pad) < 0).any():
raise ValueError('Padding must be positive or zero')
self.pad = pad
Expand All @@ -160,7 +174,7 @@ def __str__(self):
return "Padding "

def forward(self, add, model, data):
"""Padding"""
"""Pad the domain"""
self.checkDomainRange(model, data)
if add:
temp = data.clone()
Expand Down
Loading

0 comments on commit d72b869

Please sign in to comment.