def uwt_pysap(img, lvl, Filter='Bspline', n_omp_threads=None): import pysap lvl -= 1 # TODO !!!!! def pysap2muscadet(a_list): return np.asarray(a_list) nb_scale = lvl + 1 # + 1 for the coarsest scale if Filter == 'Bspline': # = 1st starlet (2nd gen not yet implemented in PySAP) transform_name = 'BsplineWaveletTransformATrousAlgorithm' transf_kwargs = {} if n_omp_threads is not None: transf_kwargs['nb_procs'] = n_omp_threads # note that if 'n_omp_threads' is not provided, # PySAP will automatically set it the # max number of CPUs available minus 1 transform_obj = pysap.load_transform(transform_name) transform = transform_obj(nb_scale=nb_scale, verbose=False, **transf_kwargs) else: raise NotImplementedError("Only sarlet transform is supported for now") # set the image transform.data = img transform.analysis() coeffs = transform.analysis_data return pysap2muscadet(coeffs), transform
def uwt_pysap(img, lvl, Filter='Bspline', n_omp_threads=0): """private function : Wavelet transform through PySAP""" import pysap lvl -= 1 # TODO : should be cleaned def pysap2muscadet(a_list): return np.asarray(a_list) nb_scale = lvl+1 # + 1 for the coarsest scale if Filter == 'Bspline': # = 1st starlet (2nd gen not yet implemented in PySAP) transform_name = 'BsplineWaveletTransformATrousAlgorithm' # note that if 'n_omp_threads' is not provided, # PySAP will automatically set it the # max number of CPUs available minus 1 transform_obj = pysap.load_transform(transform_name) transform = transform_obj(nb_scale=nb_scale, verbose=1, padding_mode='symmetric', nb_procs=n_omp_threads) else: raise NotImplementedError("Only sarlet transform is supported for now") # set the image transform.data = img transform.analysis() coeffs = transform.analysis_data return pysap2muscadet(coeffs), transform
def __init__(self, wavelet_name, nb_scale=4, verbose=0, dim=2, n_coils=1, n_jobs=1, backend="threading", **kwargs): """ Initialize the 'WaveletN' class. Parameters ---------- wavelet_name: str the wavelet name to be used during the decomposition. nb_scales: int, default 4 the number of scales in the decomposition. n_coils: int, default 1 the number of coils for multichannel reconstruction n_jobs: int, default 1 the number of cores to use for multichannel. backend: str, default "threading" the backend to use for parallel multichannel linear operation. verbose: int, default 0 the verbosity level. """ self.nb_scale = nb_scale self.flatten = flatten self.unflatten = unflatten self.n_jobs = n_jobs self.n_coils = n_coils self.backend = backend self.verbose = verbose if wavelet_name not in pysap.AVAILABLE_TRANSFORMS: raise ValueError( "Unknown transformation '{0}'.".format(wavelet_name)) transform_klass = pysap.load_transform(wavelet_name) self.transform = transform_klass( nb_scale=self.nb_scale, verbose=verbose, dim=dim, **kwargs) self.coeffs_shape = None
def get_mr_filters(data_shape, opt, n_scales=3, coarse=False, trim=False): r"""Get transform filters. This method obtains wavelet filters. Parameters ---------- data_shape : tuple 2D data shape opt : str Name of wavelet transform (in Pysap convention, see Notes) n_scales : int, optional Number of transform scales. Default is ``4``. coarse : bool, optional Option to keep coarse scale. Default is ``False``. trim: bool, optional Option to trim the filters down to their minimal size Default is ``False``. Returns ------- numpy.ndarray 3D array of wavelet filters. Notes ----- Function copied from Pysap package's astro plugin. Added the trim_filter() functionality from the ModOpt package. The name of the wavelet transform must be in Pysap convention that differs from the sparse2d input arguments. To see the available transforms in Pysap, you need to import the python module (``import pysap``) and then call ``pysap.AVAILABLE_TRANSFORMS``. """ # Adjust the shape of the input data. data_shape = np.array(data_shape) data_shape += data_shape % 2 - 1 # Create fake data. fake_data = np.zeros(data_shape) fake_data[tuple(zip(data_shape // 2))] = 1 # Transform fake data wavelet_transform = (load_transform(opt)(nb_scale=n_scales, verbose=True)) wavelet_transform.data = fake_data wavelet_transform.analysis() filters = np.array(wavelet_transform.analysis_data) # Added function to replicate ModOpt's get_mr_transform() if trim: filters = np.array([trim_filter(f) for f in filters]) # Return filters if coarse: return filters else: return filters[:-1]
def __init__(self, wavelet_name, nb_scale=4, verbose=0, dim=2, n_coils=1, n_jobs=1, backend="threading", **kwargs): """ Initialize the 'WaveletN' class. Parameters ---------- wavelet_name: str the wavelet name to be used during the decomposition. nb_scales: int, default 4 the number of scales in the decomposition. n_coils: int, default 1 the number of coils for multichannel reconstruction n_jobs: int, default 1 the number of cores to use for multichannel. backend: str, default "threading" the backend to use for parallel multichannel linear operation. verbose: int, default 0 the verbosity level. """ self.nb_scale = nb_scale self.flatten = flatten self.unflatten = unflatten self.n_jobs = n_jobs self.n_coils = n_coils if self.n_coils == 1 and self.n_jobs != 1: print("Making n_jobs = 1 for WaveletN as n_coils = 1") self.n_jobs = 1 self.backend = backend self.verbose = verbose if wavelet_name not in pysap.AVAILABLE_TRANSFORMS: raise ValueError( "Unknown transformation '{0}'.".format(wavelet_name)) transform_klass = pysap.load_transform(wavelet_name) self.transform_queue = [] n_proc = self.n_jobs if n_proc < 0: n_proc = joblib.cpu_count() + self.n_jobs + 1 if n_proc > 0: if wavelet_name in wavelist()['isap-2d'] or \ wavelet_name in wavelist()['isap-3d']: warnings.warn("n_jobs is currently unsupported " "for ISAP wavelets, setting n_jobs=1") self.n_jobs = 1 n_proc = 1 # Create transform queue for parallel execution for i in range(min(n_proc, self.n_coils)): self.transform_queue.append( transform_klass(nb_scale=self.nb_scale, verbose=verbose, dim=dim, **kwargs)) self.coeffs_shape = None
def setUp(self): """ Get the data from the server. """ self.images = [ # get_sample_data(dataset_name="astro-fits"), get_sample_data(dataset_name="mri-slice-nifti") ] print("[info] Image loaded for test: {0}.".format( [i.data.shape for i in self.images])) self.transforms = [ pysap.load_transform(name) for name in pysap.AVAILABLE_TRANSFORMS ] print("[info] Found {0} transformations.".format(len(self.transforms))) self.nb_scales = [3] # [2, 3, 4] self.nb_iter = 10
def test_speed(self): """ Test the bindings time advantages. """ # With/without bindings for strategy, name in ((True, "Without"), (False, "With")): tic = time.time() transform = pysap.load_transform( "LinearWaveletTransformATrousAlgorithm") transform = transform(nb_scale=4, verbose=0) transform.use_wrapping = strategy transform.data = self.images[0] for i in range(self.nb_iter): transform.analysis() recim = transform.synthesis() toc = time.time() print("[result] {0} bindings execution time: {1}.".format( name, toc - tic))
def setUp(self): """ Get the data from the server. """ self.images = [ # get_sample_data(dataset_name="astro-fits"), get_sample_data(dataset_name="mri-slice-nifti") ] print("[info] Image loaded for test: {0}.".format( [i.data.shape for i in self.images])) transforms_struct = pysap.wavelist(["isap-2d", "isap-3d"]) transforms_names = (transforms_struct["isap-2d"] + transforms_struct["isap-3d"]) self.transforms = [ pysap.load_transform(name) for name in transforms_names ] print("[info] Found {0} transformations.".format(len(self.transforms))) self.nb_scales = [3] # [2, 3, 4] self.nb_iter = 10
def test_accessors(self): """ Test all the accessors. """ # With/without bindings for strategy, name in ((True, "without"), (False, "with")): # Test 3-bands undecimated transform nb_scale = 4 print("[info] Test {0} bindings.".format(name)) transform = pysap.load_transform( "NonOrthogonalUndecimatedTransform") transform = transform(nb_scale=nb_scale, verbose=0) transform.use_wrapping = strategy transform.data = self.images[0] transform.analysis() # Get with scale index only for scale in range(nb_scale - 1): band_data = transform[scale] self.assertEqual(len(band_data), 3) for band_array in band_data: self.assertEqual(band_array.shape, (512, 512)) band_array = transform[nb_scale - 1] self.assertEqual(band_array.shape, (512, 512)) # Get with scale and band self.assertEqual(transform[0, 0].shape, (512, 512)) # Get with scale and band as slice band_data = transform[2, 1:3:1] self.assertEqual(len(band_data), 2) for band_array in band_data: self.assertEqual(band_array.shape, (512, 512)) # Get with scale as slice and band band_data = transform[1:3, 0] self.assertEqual(len(band_data), 2) for band_array in band_data: self.assertEqual(band_array.shape, (512, 512)) # Modify a band on the fly band_array = transform[0, 0] band_array[:, :] = 10 self.assertTrue(numpy.allclose(transform[0, 0], band_array))
def get_cospy_filters(data_shape, transform_name, n_scales=4, coarse=False): """Get cospy transform filters This method obtains wavelet filters by calling cospy Parameters ---------- data_shape : tuple 2D data shape transform_name : str Name of wavelet transform n_scales : int, optional Number of transform scales (default is 4) coarse : bool, optional Option to keep coarse scale (default is 'False') Returns ------- np.ndarray 3D array of wavelet filters """ # Adjust the shape of the input data. data_shape = np.array(data_shape) data_shape += data_shape % 2 - 1 # Create fake data. fake_data = np.zeros(data_shape) fake_data[list(zip(data_shape // 2))] = 1 # Transform fake data wavelet_transform = (load_transform(transform_name)(nb_scale=n_scales, verbose=True)) wavelet_transform.data = fake_data wavelet_transform.analysis() filters = np.array(wavelet_transform.analysis_data) # Return filters if coarse: return filters else: return filters[:-1]
def __init__(self, wavelet_name, nb_scale=4, verbose=0, dim=2, n_coils=1, n_jobs=1, backend="threading", **kwargs): self.nb_scale = nb_scale self.flatten = flatten self.unflatten = unflatten self.n_jobs = n_jobs self.n_coils = n_coils if self.n_coils == 1 and self.n_jobs != 1: print("Making n_jobs = 1 for WaveletN as n_coils = 1") self.n_jobs = 1 self.backend = backend self.verbose = verbose if wavelet_name not in pysap.AVAILABLE_TRANSFORMS: raise ValueError(f"Unknown transformation '{wavelet_name}'.") transform_klass = pysap.load_transform(wavelet_name) self.transform_queue = [] n_proc = self.n_jobs if n_proc < 0: n_proc = joblib.cpu_count() + self.n_jobs + 1 if n_proc > 0: if wavelet_name in wavelist()['isap-2d'] or \ wavelet_name in wavelist()['isap-3d']: warnings.warn("n_jobs is currently unsupported " "for ISAP wavelets, setting n_jobs=1") self.n_jobs = 1 n_proc = 1 # Create transform queue for parallel execution for _ in range(min(n_proc, self.n_coils)): self.transform_queue.append( transform_klass(nb_scale=self.nb_scale, verbose=verbose, dim=dim, **kwargs)) self.coeffs_shape = None
def __init__(self, wavelet_name, nb_scale=4, verbose=0, **kwargs): """ Initialize the 'Wavelet2' class. Parameters ---------- wavelet_name: str the wavelet name to be used during the decomposition. nb_scales: int, default 4 the number of scales in the decomposition. verbose: int, default 0 the verbosity level. """ self.nb_scale = nb_scale self.flatten = flatten self.unflatten = unflatten if wavelet_name not in pysap.AVAILABLE_TRANSFORMS: raise ValueError( "Unknown transformation '{0}'.".format(wavelet_name)) transform_klass = pysap.load_transform(wavelet_name) self.transform = transform_klass( nb_scale=self.nb_scale, verbose=verbose, **kwargs) self.coeffs_shape = None
def decompose(data, n_scales=4): """ Decompose Obtain the wavelet decomposition of the input date using an isotropic undecimated wavelet transform. Parameters ---------- data : np.ndarray Input 2D-array n_scales : int, optional Number of wavelet scales, default is 4 Returns ------- np.ndarray Wavelet decomposition 3D-array Raises ------ TypeError For invalid input data type TypeError For invalid input n_scales type Examples -------- >>> import numpy as np >>> from tutorial_utils import decompose >>> np.random.seed(0) >>> data = np.random.ranf((3, 3)) >>> decompose(data) array([[[-0.06020004, 0.09427285, -0.03005594], [-0.06932276, -0.21794325, -0.02309608], [-0.22873539, 0.17666274, 0.19976479]], [[-0.04426706, -0.02943552, -0.01460403], [-0.0475564 , -0.01650959, 0.01453722], [-0.0240097 , 0.02943558, 0.08288085]], [[-0.0094105 , -0.0110383 , -0.01266617], [-0.00393927, -0.00619102, -0.00844282], [ 0.01415205, 0.0110383 , 0.00792474]], [[ 0.66269112, 0.6613903 , 0.66008949], [ 0.66570163, 0.66429865, 0.6628958 ], [ 0.67618024, 0.67463636, 0.67309237]]]) """ if not isinstance(data, np.ndarray) or data.ndim != 2: raise TypeError('Input data must be a 2D numpy array.') if not isinstance(n_scales, int) or n_scales < 1: raise TypeError('n_scales must be a positive integer.') if import_pysap: trans_name = 'BsplineWaveletTransformATrousAlgorithm' trans = load_transform(trans_name)(nb_scale=n_scales, padding_mode="symmetric") trans.data = data trans.analysis() res = np.array(trans.analysis_data, dtype=np.float) else: filters = np.load('data/filters_{}.npy'.format(n_scales)) res = np.array([convolve(data, f) for f in filters]) return res
from pprint import pprint import pysap pprint(pysap.wavelist()) pprint(pysap.wavelist(family="isap-3d")) ############################################################################# # We illustrate the the decompose/recompose using a 'Daubechies' from pywt # and 4 scales: import pysap from pysap.data import get_sample_data image = get_sample_data("mri-slice-nifti") transform_klass = pysap.load_transform("Db3") transform = transform_klass(nb_scale=4, verbose=1) transform.data = image transform.analysis() transform.show() rec_image = transform.synthesis() rec_image.show() ############################################################################# # We illustrate the the decompose/recompose using a 'FastCurveletTransform' # from ISAP and 4 scales: image = get_sample_data("mri-slice-nifti") transform_klass = pysap.load_transform("FastCurveletTransform") transform = transform_klass(nb_scale=4, verbose=1) transform.data = image
def decompose(data, n_scales=4): """Decompose. Obtain the wavelet decomposition of the input date using an isotropic undecimated wavelet transform. Parameters ---------- data : np.ndarray Input 2D-array n_scales : int, optional Number of wavelet scales, default is 4 Returns ------- np.ndarray Wavelet decomposition 3D-array Raises ------ TypeError For invalid input data type TypeError For invalid input n_scales type Examples -------- >>> import numpy as np >>> from pysap.astro.denoising.wavelet import decompose >>> data = np.arange(9).reshape((3, 3)) * 0.1 >>> decompose(data) array([[[-1.50000006e-01, -1.12500034e-01, -7.50000030e-02], [-3.75000238e-02, -2.98023224e-08, 3.74999642e-02], [ 7.49999881e-02, 1.12499952e-01, 1.49999976e-01]], [[-1.56250030e-01, -1.17187500e-01, -7.81250298e-02], [-3.90625000e-02, 0.00000000e+00, 3.90625000e-02], [ 7.81250000e-02, 1.17187500e-01, 1.56250000e-01]], [[-5.85937500e-02, -4.39453125e-02, -2.92968750e-02], [-1.46484375e-02, 0.00000000e+00, 1.46484375e-02], [ 2.92968750e-02, 4.39453125e-02, 5.85937500e-02]], [[ 3.64843786e-01, 3.73632848e-01, 3.82421911e-01], [ 3.91210973e-01, 4.00000036e-01, 4.08789098e-01], [ 4.17578161e-01, 4.26367223e-01, 4.35156286e-01]]]) """ if not isinstance(data, np.ndarray) or data.ndim != 2: raise TypeError('Input data must be a 2D numpy array.') if not isinstance(n_scales, int) or n_scales < 1: raise TypeError('n_scales must be a positive integer.') trans_name = 'BsplineWaveletTransformATrousAlgorithm' trans = load_transform(trans_name)( nb_scale=n_scales, padding_mode="symmetric", ) trans.data = data trans.analysis() res = np.array(trans.analysis_data, dtype=np.float) return res