From b61034b6aa3d0516cc9cf90d4b545ae42dca1c19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20Bj=C3=B6rling?= Date: Tue, 11 Feb 2020 22:08:30 +0100 Subject: [PATCH 1/7] Intact storages can now be constructed from dicts --- ptypy/core/classes.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/ptypy/core/classes.py b/ptypy/core/classes.py index 84381ab0e..df4138d71 100644 --- a/ptypy/core/classes.py +++ b/ptypy/core/classes.py @@ -461,6 +461,13 @@ def __init__(self, container, ID=None, data=None, shape=DEFAULT_SHAPE, # solution required # self._origin = None + @classmethod + def _from_dict(cls, dct, container): + obj = super()._from_dict(dct) + obj.owner = container + container._new_ptypy_object(obj) + return obj + @property def ndim(self): """ From 41a78cd7471c532aafddb471eb749bcb21840b83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20Bj=C3=B6rling?= Date: Tue, 11 Feb 2020 22:13:19 +0100 Subject: [PATCH 2/7] Ptyr entries can now be loaded as Storage objects --- ptypy/utils/scripts.py | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/ptypy/utils/scripts.py b/ptypy/utils/scripts.py index afbf74c53..9b30ee72f 100644 --- a/ptypy/utils/scripts.py +++ b/ptypy/utils/scripts.py @@ -659,7 +659,7 @@ def stxm_init(storage, probe=None): trans, dpc_row, dpc_col = stxm_analysis(storage,probe) storage.data = trans * np.exp(-1j*phase_from_dpc(dpc_row, dpc_col)) -def load_from_ptyr(filename, what='probe', ID=None, layer=None): +def load_from_ptyr(filename, what='probe', how='array', ID=None, layer=None): """ Convenience script to extract data from ``*.ptyr``-file. @@ -671,19 +671,20 @@ def load_from_ptyr(filename, what='probe', ID=None, layer=None): what : str Type of container to retrieve. Only `'probe'` and `'obj'` makes sense. Default is `'probe'` + how : str + Type of object to return. Only ``array`` and ``storage`` are + accepted. Default is ``array``. ID : str ID of storage in chosen container. If ``None`` the first stored storage is chosen. layer : int, optional If an integer, the data buffer of chosen storage gets sliced - with `layer` for its first index. + with `layer` for its first index. Has no effect if how is + ``storage``. Returns ------- - data : ndarray - If `layer` is provided, that layer ``storage,data[layer]`` - will be sliced from the 3d data buffer, else the whole buffer - ``storage.data`` will be returned. + data : ndarray or Storage """ from .. import io header = io.h5read(filename, 'header')['header'] @@ -698,10 +699,15 @@ def load_from_ptyr(filename, what='probe', ID=None, layer=None): address = 'content/' + str(what) conti = io.h5read(filename, address)[address] storage = list(conti.values())[0] - if layer is None: - return storage['data'] - else: - return storage['data'][layer] + if how == 'array': + if layer is None: + return storage['data'] + else: + return storage['data'][layer] + elif how == 'storage': + from ..core import Storage, Container + C = Container(data_dims=2, data_type='complex') + return Storage._from_dict(dct=storage, container=C) def phase_from_dpc(dpc_row, dpc_col): """ From 6f045a974c1bce4bc4eb57a8382259b7b2456f81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20Bj=C3=B6rling?= Date: Tue, 11 Feb 2020 23:35:51 +0100 Subject: [PATCH 3/7] The illumination module now takes Storages as well as ptyr files, and resamples if needed --- ptypy/core/illumination.py | 35 ++++++++++++++++++++++++++++------- 1 file changed, 28 insertions(+), 7 deletions(-) diff --git a/ptypy/core/illumination.py b/ptypy/core/illumination.py index ce4430400..4ff56671c 100644 --- a/ptypy/core/illumination.py +++ b/ptypy/core/illumination.py @@ -11,9 +11,11 @@ """ import numpy as np +from scipy.ndimage.interpolation import map_coordinates from .. import utils as u from ..core import geometry +from ..core import Storage from ..utils.verbose import logger from .. import resources from ..utils.descriptor import EvalDescriptor @@ -280,7 +282,7 @@ def aperture(A, grids=None, pars=None, **kwargs): return np.resize(ap, sh) -def init_storage(storage, pars, energy=None, **kwargs): +def init_storage(storage, pars, energy=None): """ Initializes :any:`Storage` `storage` with parameters from `pars` @@ -367,17 +369,36 @@ def init_storage(storage, pars, energy=None, **kwargs): model = p.model elif p.model in resources.probes: model = resources.probes[p.model](s.shape) + elif type(p.model) is Storage: + # resample the incoming probe storage based on the current pixel + #size and shape + layer = p.recon.get('layer') + layer = 0 if layer is None else layer + if (np.allclose(p.model.psize, s.psize) and + np.allclose(p.model.shape, s.shape)): + model = p.model.data[layer] + else: + logger.info( + prefix + + 'Attempt to resample layer %s from Storage %s' + % (str(layer), str(p.model.ID))) + y, x = np.array(s.grids())[:, layer] + ii = (y - p.model.origin[0]) / p.model.psize[0] + jj = (x - p.model.origin[1]) / p.model.psize[1] + model = np.empty(shape=ii.shape, dtype=np.complex128) + model[:] = map_coordinates(np.abs(p.model.data[layer]), np.array((ii, jj)), mode='constant', cval=0) + model[:] = model * np.exp(1j * map_coordinates(np.angle(p.model.data[layer]), (ii, jj), mode='constant', cval=0)) elif str(p.model) == 'recon': # Loading from a reconstruction file - layer = p.recon.get('layer') ID = p.recon.get('ID') logger.info( prefix + - 'Attempt to load layer `%s` of probe storage with ID `%s` from `%s`' - % (str(layer), str(ID), p.recon.rfile)) - model = u.load_from_ptyr(p.recon.rfile, 'probe', ID, layer) - # This could be more sophisticated, - # i.e. matching the real space grids etc. + 'Attempt to load probe storage with ID `%s` from `%s`' + % (str(ID), p.recon.rfile)) + model = u.load_from_ptyr(p.recon.rfile, 'probe', how='storage', ID=ID) + p.model = model + init_storage(s, p, energy) + return elif str(p.model) == 'stxm': logger.info( prefix + 'Probe initialization using averaged diffraction data.') From 42b2334cde787e639e042acff4354df35662d06c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20Bj=C3=B6rling?= Date: Wed, 12 Feb 2020 00:26:12 +0100 Subject: [PATCH 4/7] Reverted b61034b6, the dict can be manipulated instead --- ptypy/core/classes.py | 7 ------- ptypy/utils/scripts.py | 3 ++- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/ptypy/core/classes.py b/ptypy/core/classes.py index df4138d71..84381ab0e 100644 --- a/ptypy/core/classes.py +++ b/ptypy/core/classes.py @@ -461,13 +461,6 @@ def __init__(self, container, ID=None, data=None, shape=DEFAULT_SHAPE, # solution required # self._origin = None - @classmethod - def _from_dict(cls, dct, container): - obj = super()._from_dict(dct) - obj.owner = container - container._new_ptypy_object(obj) - return obj - @property def ndim(self): """ diff --git a/ptypy/utils/scripts.py b/ptypy/utils/scripts.py index 9b30ee72f..dadfda346 100644 --- a/ptypy/utils/scripts.py +++ b/ptypy/utils/scripts.py @@ -707,7 +707,8 @@ def load_from_ptyr(filename, what='probe', how='array', ID=None, layer=None): elif how == 'storage': from ..core import Storage, Container C = Container(data_dims=2, data_type='complex') - return Storage._from_dict(dct=storage, container=C) + storage['owner'] = C + return Storage._from_dict(storage) def phase_from_dpc(dpc_row, dpc_col): """ From e4ebe2d427949f9cbf504119b96135befc471ccf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20Bj=C3=B6rling?= Date: Wed, 12 Feb 2020 11:02:08 +0100 Subject: [PATCH 5/7] Fixed bug in probe initialization --- ptypy/core/illumination.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ptypy/core/illumination.py b/ptypy/core/illumination.py index 4ff56671c..435896134 100644 --- a/ptypy/core/illumination.py +++ b/ptypy/core/illumination.py @@ -368,7 +368,7 @@ def init_storage(storage, pars, energy=None): elif type(p.model) is np.ndarray: model = p.model elif p.model in resources.probes: - model = resources.probes[p.model](s.shape) + model = resources.probes[p.model](s.shape[1:]) elif type(p.model) is Storage: # resample the incoming probe storage based on the current pixel #size and shape From 3d1d31a7ca54ca306eb9fd623275a7e5c02074ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20Bj=C3=B6rling?= Date: Wed, 12 Feb 2020 11:21:08 +0100 Subject: [PATCH 6/7] u.report now accepts Storages and Containers --- ptypy/utils/verbose.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ptypy/utils/verbose.py b/ptypy/utils/verbose.py index 6e6ae300c..d35c1239b 100644 --- a/ptypy/utils/verbose.py +++ b/ptypy/utils/verbose.py @@ -238,6 +238,8 @@ def _format_None(key,level, obj): def _format(key,level, obj): if hasattr(obj,'items'): stringout = _format_dict(key,level, obj) + elif hasattr(obj, 'views'): + stringout = _format(key, level, str(obj)) elif type(obj) is np.ndarray: stringout = _format_numpy(key,level, obj) elif str(obj)==obj: From c78c35e6815cc16d86d3023f5893701dcf12d91e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20Bj=C3=B6rling?= Date: Wed, 12 Feb 2020 11:22:14 +0100 Subject: [PATCH 7/7] illumination.model can now be a storage too --- ptypy/core/illumination.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ptypy/core/illumination.py b/ptypy/core/illumination.py index 435896134..0967d7374 100644 --- a/ptypy/core/illumination.py +++ b/ptypy/core/illumination.py @@ -122,7 +122,7 @@ [model] default = None - type = str, ndarray + type = str, ndarray, Storage help = Type of illumination model doc = One of: - ``None`` : model initialitziation defaults to flat array filled with the specified number of photons