Skip to content

Commit

Permalink
Different reconstruction options in holo.py (#121)
Browse files Browse the repository at this point in the history
* Update holo.py

test change #2

* adds optional setting of filtering in frequency domain

* bump python version in lint

* adds option in scaling of output to inverse transform

* adds reconstruction options to Reconstruct class

* updates pipeline-holo example

* bump version

* updates test

* update test

* lint

* bugfix to detault forward_filter_option & test

* fix comment in pipeline-holo

* updates test to account for extra slice

* fix z error

* updates python version in setup.cfg

* bump version

* corrects TypeError with version change

* reverts holo steps to fit with testing

* updates python version for docs

* remove h5py version

* update to napoleon

* revert & update for napoleon

* updates conf.py napoleon

* update .gitignore for testing file

* np.int deprecated

* use default values in example

* bump version

* updates Pipeline docstring

* lint

* reverts test setting after re-adoption of arange

---------

Co-authored-by: Alex Nimmo Smith <[email protected]>
Co-authored-by: Alex Nimmo-Smith <[email protected]>
  • Loading branch information
3 people authored Aug 29, 2023
1 parent c3f51fa commit d3d487b
Show file tree
Hide file tree
Showing 8 changed files with 45 additions and 20 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ jobs:
- name: Set up Python environment
uses: actions/setup-python@v2
with:
python-version: "3.8"
python-version: "3.10"
- name: flake8 Lint
uses: py-actions/flake8@v2
with:
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,7 @@ tags
*.zip
notebooks/header.tfl.txt
notebooks/keras_model.h5
notebooks/github-test-holo.ipynb

test-report/*
docs/.DS_Store
Expand Down
9 changes: 6 additions & 3 deletions notebooks/pipeline-holo.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -181,8 +181,11 @@
" # omit argument for static background removal\n",
" # change to pyopia.background.CorrectBackgroundNone() to not remove a background during pipeline\n",
" 'correct background': pyopia.background.CorrectBackgroundAccurate(pyopia.background.shift_bgstack_accurate),\n",
" # hologram reconstruction step - argument is how much stack cleaning (% dimmest pixels to remove) to apply - set to 0 to omit cleaning\n",
" 'reconstruct': holo.Reconstruct(stack_clean=0.02),\n",
" # hologram reconstruction step - arguments are:\n",
" # stack_clean - is how much stack cleaning (% dimmest pixels to remove) to apply - set to 0 to omit cleaning\n",
" # forward_filter_option - switch to control filtering in frequency domain (0=none,1=DC only,2=zero ferquency/default)\n",
" # inverse_output_option - switch to control optional scaling of output intensity (0=square/default,1=linear)\n",
" 'reconstruct': holo.Reconstruct(stack_clean=0.02, forward_filter_option=2, inverse_output_option=0),\n",
" # focussing step - arguments are which stack summarisation method to use, what global segmentation threshold to apply and what focus method to use:\n",
" # summarisation methods are:\n",
" # pyopia.instrument.holo.std_map (default) - takes standard deviation of values through stack\n",
Expand Down Expand Up @@ -338,7 +341,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.8.15"
"version": "3.10.12"
},
"orig_nbformat": 4,
"vscode": {
Expand Down
2 changes: 1 addition & 1 deletion pyopia/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = '0.0.56'
__version__ = '0.0.57'
41 changes: 30 additions & 11 deletions pyopia/instrument/holo.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,10 @@ class Reconstruct():
----------
stack_clean : float
defines amount of cleaning of stack (fraction of max value below which to zero)
forward_filter_option : int
switch to control filtering in frequency domain (0=none,1=DC only,2=zero ferquency/default)
inverse_output_option : int
switch to control optional scaling of output intensity (0=square/default,1=linear)
Pipeline input data:
---------
Expand All @@ -143,29 +147,32 @@ class Reconstruct():
:attr:`pyopia.pipeline.Data.im_stack`
'''

def __init__(self, stack_clean=0):
def __init__(self, stack_clean=0, forward_filter_option=0, inverse_output_option=0):
self.stack_clean = stack_clean
self.forward_filter_option = forward_filter_option
self.inverse_output_option = inverse_output_option

def __call__(self, data):
imc = data['imc']
kern = data['kern']
im_stack = data['im_stack']

im_fft = forward_transform(imc)
im_stack = inverse_transform(im_fft, kern, im_stack)
im_fft = forward_transform(imc, self.forward_filter_option)
im_stack = inverse_transform(im_fft, kern, im_stack, self.inverse_output_option)
data['im_stack'] = clean_stack(im_stack, self.stack_clean)

return data


def forward_transform(im):
'''Perform forward transform
Remove the zero frequency components and then fftshift
def forward_transform(im, forward_filter_option=2):
'''Perform forward transform with optional filtering
Parameters
----------
im : np.array
hologram (usually background-corrected)
forward_filter_option : int
filtering in frequency domain (0=none/default,1=DC only,2=zero ferquency)
Returns
-------
Expand All @@ -176,9 +183,15 @@ def forward_transform(im):
# Perform forward transform
im_fft = fft.fft2(im, workers=os.cpu_count())

# Remove the zero frequency components
im_fft[:, 0] = 0
im_fft[0, :] = 0
# apply filtering if required
match forward_filter_option:
case 1:
im_fft[0, 0] = 0
case 2:
im_fft[:, 0] = 0
im_fft[0, :] = 0
case _:
pass

# fftshift
im_fft = fft.fftshift(im_fft)
Expand Down Expand Up @@ -233,7 +246,7 @@ def create_kernel(im, pixel_size, wavelength, n, offset, minZ, maxZ, stepZ):
return kern


def inverse_transform(im_fft, kern, im_stack):
def inverse_transform(im_fft, kern, im_stack, inverse_output_option=0):
'''create the reconstructed hologram stack of real images
Parameters
Expand All @@ -244,6 +257,8 @@ def inverse_transform(im_fft, kern, im_stack):
calculated from create_kernel
im_stack : np.array
pre-allocated array to receive output
inverse_output_option: int
optional scaling of output intensity (0=square/default,1=linear)
Returns
-------
Expand All @@ -253,7 +268,11 @@ def inverse_transform(im_fft, kern, im_stack):

for i in range(np.shape(kern)[2]):
im_tmp = np.multiply(im_fft, kern[:, :, i])
im_stack[:, :, i] = (fft.ifft2(im_tmp, workers=os.cpu_count()).real)**2
match inverse_output_option:
case 1:
im_stack[:, :, i] = fft.ifft2(im_tmp, workers=os.cpu_count()).real
case _:
im_stack[:, :, i] = (fft.ifft2(im_tmp, workers=os.cpu_count()).real)**2

return im_stack

Expand Down
6 changes: 4 additions & 2 deletions pyopia/pipeline.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,10 @@ class Pipeline():
pyopia.instrument.holo.load_image),
'load': holo.Load(),
'correct background': pyopia.background.CorrectBackgroundAccurate(pyopia.background.shift_bgstack_accurate),
'reconstruct': holo.Reconstruct(stack_clean=0.02),
'focus': holo.Focus(pyopia.instrument.holo.std_map,threshold=threshold),
'reconstruct': holo.Reconstruct(stack_clean=0.02, forward_filter_option=2, inverse_output_option=0),
'focus': holo.Focus(pyopia.instrument.holo.std_map,threshold=threshold,
focus_function=pyopia.instrument.holo.find_focus_sobel,
increase_depth_of_field=True,merge_adjacent_particles=0),
'segmentation': pyopia.process.Segment(threshold=threshold),
'statextract': pyopia.process.CalculateStats(export_outputpath="proc"),
'output': pyopia.io.StatsH5(datafile_hdf)
Expand Down
2 changes: 1 addition & 1 deletion pyopia/statistics.py
Original file line number Diff line number Diff line change
Expand Up @@ -418,7 +418,7 @@ def gen_roifiles(stats, auto_scaler=500):

# subsample the particles if necessary
print('rofiles: {0}'.format(len(roifiles)))
IMSTEP = np.max([np.int(np.round(len(roifiles) / auto_scaler)), 1])
IMSTEP = np.max([int(np.round(len(roifiles) / auto_scaler)), 1])
print('reducing particles by factor of {0}'.format(IMSTEP))
roifiles = roifiles[np.arange(0, len(roifiles), IMSTEP)]
print('rofiles: {0}'.format(len(roifiles)))
Expand Down
2 changes: 1 addition & 1 deletion pyopia/tests/test_pipeline.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ def test_holo_pipeline():
pyopia.instrument.holo.load_image),
'load': holo.Load(),
'correct background': pyopia.background.CorrectBackgroundAccurate(pyopia.background.shift_bgstack_accurate),
'reconstruct': holo.Reconstruct(stack_clean=0.02),
'reconstruct': holo.Reconstruct(stack_clean=0.02, forward_filter_option=2, inverse_output_option=0),
'focus': holo.Focus(pyopia.instrument.holo.std_map,
threshold=threshold,
focus_function=pyopia.instrument.holo.find_focus_sobel,
Expand Down

0 comments on commit d3d487b

Please sign in to comment.