Skip to content

Commit 5e14795

Browse files
authored
Add files via upload
1 parent 8ad4b4d commit 5e14795

File tree

1 file changed

+172
-0
lines changed

1 file changed

+172
-0
lines changed
Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
# -------- Activate virtual environment -------------------------
2+
import os
3+
import ctypes
4+
import sys
5+
from pathlib import Path
6+
7+
def search_activation_path():
8+
for i in range(5):
9+
final_path = str(Path(__file__).parents[i]) + '\\env\\Scripts\\activate_this.py'
10+
if os.path.exists(final_path):
11+
return final_path
12+
return ''
13+
14+
activate_path = search_activation_path()
15+
if os.path.exists(activate_path):
16+
exec(open(activate_path).read(), {'__file__': activate_path})
17+
print(f'Aivia virtual environment activated\nUsing python: {activate_path}')
18+
else:
19+
error_mess = f'Error: {activate_path} was not found.\n\nPlease check that:\n' \
20+
f' 1/ The \'FirstTimeSetup.py\' script was already run in Aivia,\n' \
21+
f' 2/ The current python recipe is in one of the "\\PythonEnvForAivia\\" subfolders.'
22+
ctypes.windll.user32.MessageBoxW(0, error_mess, 'Error', 0)
23+
sys.exit(error_mess)
24+
# ---------------------------------------------------------------
25+
26+
from magicgui import magicgui
27+
from skimage.io import imread, imsave
28+
import numpy as np
29+
from pystackreg import StackReg
30+
from pystackreg.util import to_uint16
31+
import imagecodecs
32+
33+
# Manual input parameters (only used if 'use' is True below)
34+
noGUI_params = {'use': False,
35+
'reg_type': 'Rigid Body',
36+
'reg_method': 'previous'
37+
}
38+
39+
"""
40+
Performs a 2D registration for timelapses, using PyStackReg. No parameters available (default ones only).
41+
Methods:
42+
- Previous = Use previous image to calculate registration
43+
- First = First timepoint is used as the fixed reference.
44+
45+
Documentation: https://pypi.org/project/pystackreg/
46+
Paper for citation available at the bottom of page above.
47+
48+
Requirements
49+
------------
50+
scikit-image
51+
numpy
52+
imagecodecs
53+
pystackreg
54+
PySide2
55+
magicgui
56+
57+
Parameters
58+
----------
59+
Input:
60+
Channel/image in Aivia to be aligned
61+
62+
Output
63+
------
64+
New channel with registered images
65+
"""
66+
67+
reg_methods = {
68+
'Previous image is the reference (original StackReg ImageJ plugin)': 'previous',
69+
'First image is the reference': 'first',
70+
'Mean of all images is the reference': 'mean'
71+
}
72+
reg_types = {
73+
'Translation only': StackReg.TRANSLATION,
74+
'Rigid Body (translation + rotation)': StackReg.RIGID_BODY,
75+
'Affine (translation + rotation + scaling + shearing)': StackReg.AFFINE,
76+
'Bilinear (non-linear transformation; does not preserve straight lines)': StackReg.BILINEAR
77+
}
78+
79+
# [INPUT Name:inputRawImagePath Type:string DisplayName:'Unregistered stack']
80+
# [OUTPUT Name:resultPath Type:string DisplayName:'Registered stack']
81+
def run(params):
82+
global reg_methods, reg_types
83+
84+
rawImageLocation = params['inputRawImagePath']
85+
resultLocation = params['resultPath']
86+
calibration = params['Calibration']
87+
tCount = int(params['TCount'])
88+
zCount = int(params['ZCount'])
89+
90+
if tCount < 2:
91+
show_error(f'Error: detected dimensions do not contain time. (t={tCount})')
92+
if zCount > 1 and tCount > 1:
93+
show_error(f'Error: detected dimensions contain time and depth. This script is for 2D only. (t={tCount}, z={zCount})')
94+
95+
# Checking existence of temporary files (individual channels)
96+
if not os.path.exists(rawImageLocation):
97+
show_error(f'Error: {rawImageLocation} does not exist')
98+
99+
# Parsing calibration string
100+
# calib_values = calibration[calibration.find(':') + 2:].split(', ')
101+
# calib_indiv_values = [single.split(' ') for single in calib_values]
102+
103+
# pix_res_XY = float(calib_indiv_values[0][0])
104+
# pix_res_Z = float(calib_indiv_values[2][0])
105+
106+
# Loading input image
107+
raw_npimg = imread(rawImageLocation)
108+
raw_dims = np.asarray(raw_npimg.shape)
109+
print('-- Input dimensions (expected T, Z, Y, X): ', raw_dims, ' --')
110+
111+
# Preparing output
112+
final_img = np.zeros(raw_npimg.shape).astype(raw_npimg.dtype)
113+
114+
# Check manual inputs
115+
if noGUI_params['use']:
116+
reg_type = noGUI_params['reg_type']
117+
reg_method = noGUI_params['reg_method']
118+
119+
else: # Choose csv/xlsx table (Aivia format) with GUI
120+
gui.called.connect(lambda x: gui.close())
121+
gui.show(run=True)
122+
123+
# Parameters collected from the GUI
124+
reg_type = reg_types[gui.reg_typ.value]
125+
reg_method = reg_methods[gui.reg_meth.value]
126+
127+
# Prepare parameters for registration
128+
sr = StackReg(reg_type)
129+
130+
# Register 2D timelapse
131+
out_npimg = to_uint16(sr.register_transform_stack(raw_npimg, reference=reg_method)) # 16-bit
132+
133+
# Formatting result array
134+
print(raw_npimg.dtype)
135+
if raw_npimg.dtype is np.dtype('uint8'):
136+
final_img[...] = out_npimg[...]
137+
print('Note: Output converted from 16-bit to 8-bit.')
138+
else:
139+
final_img = out_npimg
140+
141+
# Save result
142+
imsave(resultLocation, final_img)
143+
144+
145+
@magicgui(layout='vertical',
146+
reg_typ={'label': 'Registration type: ', 'choices': reg_types.keys()},
147+
reg_meth={'label': 'Registration reference: ', 'choices': reg_methods.keys()},
148+
call_button="Continue")
149+
def gui(reg_typ=[*reg_types][0], reg_meth=[*reg_methods][0]):
150+
pass
151+
152+
153+
def show_error(message):
154+
ctypes.windll.user32.MessageBoxW(0, message, 'Error', 0)
155+
sys.exit(message)
156+
157+
158+
if __name__ == '__main__':
159+
params = {}
160+
params['inputRawImagePath'] = r'D:\PythonCode\_tests\2D-TL-toalign_8b.aivia.tif'
161+
# params['inputRawImagePath'] = r'D:\Data\__Leica Images\UK\Alain Stewart\23-03-13 Tara Spires-Jones' \
162+
# r'\211027_SD001_16_ba17_b1_1_Dapi_405_spyh_488_T22_555_PSD95_647.lif - Series003-1.tif'
163+
params['resultPath'] = r'D:\PythonCode\_tests\2D-TL-aligned.tif'
164+
params['Calibration'] = ' : 0.4 microns, 0.4 microns, 1.2 microns, 2 seconds'
165+
params['TCount'] = 16
166+
params['ZCount'] = 1
167+
168+
run(params)
169+
170+
# CHANGELOG
171+
# v1_00 PM: - Registration with default parameters of PyStackReg
172+
# v1_01 PM: - New virtual env code for auto-activation

0 commit comments

Comments
 (0)