Skip to content

Commit 13e7c80

Browse files
authored
Update ScaleImage.py
# v1_20: - Adding time handling (but not rescale with time dimension) # v1_30: - Fusing with parallel version updating aivia_path using new API params value
1 parent e8330ec commit 13e7c80

1 file changed

Lines changed: 41 additions & 37 deletions

File tree

Recipes/TransformImages/ScaleImage.py

Lines changed: 41 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,12 @@
66
from tifffile import imread, imwrite
77
from skimage import transform, img_as_uint, img_as_ubyte
88
import sys
9-
from os.path import dirname as up
10-
from os.path import isfile
119

1210

1311
"""
1412
Scales the input channel up or down (isotropic factor). Option for interpolation is in the code.
15-
Works only for 2D/3D (not timelapses) and for single channels.
13+
Works only for 2D/3D rescaling (not timelapses) but can be applied on a per timepoint basis.
14+
Works for single channels.
1615
1716
Documentation
1817
-------------
@@ -39,19 +38,16 @@
3938
Opens Aivia to display the new scaled image.
4039
4140
"""
42-
interpolation_mode = 1 # 0: Nearest-neighbor, 1: Bi-linear , 2: Bi-quadratic, 3: Bi-cubic, 4: Bi-quartic, 5: Bi-quintic
43-
44-
45-
# automatic parameters
4641

42+
interpolation_mode = 1 # 0: Nearest-neighbor, 1: Bi-linear , 2: Bi-quadratic, 3: Bi-cubic, 4: Bi-quartic, 5: Bi-quintic
4743

4844
# [INPUT Name:inputImagePath Type:string DisplayName:'Input Channel']
4945
# [INPUT Name:scaleDirection Type:int DisplayName:'Down or Upscale (0 or 1)' Default:0 Min:0 Max:1]
5046
# [INPUT Name:scaleFactorZ Type:double DisplayName:'Z scale factor' Default:1.0 Min:0.01 Max:20.0]
5147
# [INPUT Name:scaleFactorXY Type:double DisplayName:'XY scale factor' Default:1.0 Min:0.01 Max:20.0]
5248
# [OUTPUT Name:resultPath Type:string DisplayName:'Duplicate of input']
5349
def run(params):
54-
image_org=params['EntryPoint']
50+
image_org = params['EntryPoint']
5551
image_location = params['inputImagePath']
5652
result_location = params['resultPath']
5753
scale_factor_xy = float(params['scaleFactorXY'])
@@ -66,6 +62,7 @@ def run(params):
6662
# Getting XY and Z values # Expecting only 'Micrometers' in this code
6763
XY_cal = float(pixel_cal[0].split(' ')[0])
6864
Z_cal = float(pixel_cal[2].split(' ')[0])
65+
T_cal = float(pixel_cal[3].split(' ')[0])
6966

7067
if not os.path.exists(image_location):
7168
print(f"Error: {image_location} does not exist")
@@ -77,17 +74,12 @@ def run(params):
7774

7875
image_data = imread(image_location)
7976
dims = image_data.shape
80-
print('-- Input dimensions (expected (Z), Y, X): ', np.asarray(dims), ' --')
81-
82-
# Checking image is not 2D+t or 3D+t
83-
if len(dims) > 3 or (len(dims) == 3 and tCount > 1):
84-
print('Error: Cannot handle timelapses yet.')
85-
return
77+
print('-- Input dimensions (expected (T) (Z), Y, X): ', np.asarray(dims), ' --')
8678

8779
if scale_factor_xy == 0.0:
88-
scale_factor_xy = 1.0 #TODO: manual input for batch
80+
scale_factor_xy = 1.0
8981
if scale_factor_z == 0.0:
90-
scale_factor_z = 1.0 #TODO
82+
scale_factor_z = 1.0
9183

9284
if scale_direction == 0:
9385
scale_factor_xy = 1/scale_factor_xy
@@ -102,8 +94,17 @@ def run(params):
10294

10395
# Defining axes for output metadata and scale factor variable
10496
final_scale = None
105-
if tCount == 1 and zCount > 1: # 3D
106-
axes = 'ZYX' # Data is 'YXZ'
97+
axes = ''
98+
if tCount > 1 and zCount > 1: # 3D + T
99+
axes = 'TZYX'
100+
final_scale = (1, scale_factor_z, scale_factor_xy, scale_factor_xy)
101+
102+
elif tCount > 1 and zCount == 1: # 2D + T
103+
axes = 'TYX'
104+
final_scale = (1, scale_factor_xy, scale_factor_xy)
105+
106+
elif tCount == 1 and zCount > 1: # 3D
107+
axes = 'ZYX' # should be 'YXZ'
107108
final_scale = (scale_factor_z, scale_factor_xy, scale_factor_xy)
108109

109110
elif tCount == 1 and zCount == 1: # 2D
@@ -120,38 +121,41 @@ def run(params):
120121
else:
121122
out_data = img_as_ubyte(scaled_img)
122123
print('img_as_ubyte')
123-
124-
# Formatting voxel calibration values
125-
formatted_XY_cal = '{0:.4g}'.format(final_XY_cal)
126124

127125
tmp_path = result_location.replace('.tif', '-scaled.tif')
128-
meta_info = {'axes': axes,
129-
'PhysicalSizeX': formatted_XY_cal,
130-
'PhysicalSizeY': formatted_XY_cal,
131-
'PhysicalSizeZ': str(final_Z_cal),
132-
'PhysicalSizeXUnit': '\xb5m',
133-
'PhysicalSizeYUnit': '\xb5m',
134-
'PhysicalSizeZUnit': '\xb5m'} # '\xb5m' for microns?
126+
meta_info = {'axes': axes, 'spacing': str(final_Z_cal), 'unit': 'um',
127+
'TimeIncrement': T_cal, 'TimeIncrementUnit': 's'}
128+
129+
# Formatting voxel calibration values
130+
inverted_XY_cal = 1 / final_XY_cal
131+
print(final_XY_cal)
135132

136133
print('Saving image in temp location:\n', tmp_path)
137-
imwrite(tmp_path, out_data, ome=True, photometric='minisblack', metadata=meta_info)
134+
imwrite(tmp_path, out_data, imagej=True, photometric='minisblack', metadata=meta_info,
135+
resolution=(inverted_XY_cal, inverted_XY_cal))
138136

139137
# Dummy save
140-
imwrite(result_location, image_data)
138+
dummy_data = np.zeros(image_data.shape, dtype=image_data.dtype)
139+
imwrite(result_location, dummy_data)
141140

142141
# Run external program
143142
cmdLine = 'start \"\" \"' + aivia_path + '\" \"' + tmp_path + '\"'
144-
# cmdLine = 'start \"\" \"' + IJ_path + '\" \"' + tmp_path + '\"'
145143

146144
args = shlex.split(cmdLine)
147145
subprocess.run(args, shell=True)
148146

149147

150148
if __name__ == '__main__':
151-
params = {'inputImagePath': 'D:\\python-tests\\3D-image.aivia.tif',
152-
'resultPath': 'D:\\python-tests\\scaled.tif',
153-
'TCount': 1,
154-
'ZCount': 51}
149+
params = {'inputImagePath': 'D:\\PythonCode\\_tests\\3D-TL-toalign.aivia.tif',
150+
'resultPath': 'D:\\PythonCode\\_tests\\Output.tif',
151+
'TCount': 16,
152+
'ZCount': 41,
153+
'Calibration': 'XYZT: 0.4 Micrometers, 0.4 Micrometers, 1.2 Micrometers, 599.9996 Seconds',
154+
'scaleFactorXY': 2,
155+
'scaleFactorZ': 1,
156+
'scaleDirection': 0,
157+
'EntryPoint': '',
158+
'CallingExecutable': ''}
155159
run(params)
156160

157161
# CHANGELOG
@@ -160,5 +164,5 @@ def run(params):
160164
# v1_11: - tkinter not installed by default so removing all code and adding parameters in Aivia UI
161165
# v1_13: - Fallback values if factors equal 0 / automated detection of latest Aivia version on PC
162166
# v1_14: - Adding pixel/voxel calibration
163-
# v1_15: - Update Aivia path for Aivia community
164-
# v1_16: - Update aivia_path using new API
167+
# v1_20: - Adding time handling (but not rescale with time dimension)
168+
# v1_30: - Fusing with parallel version updating aivia_path using new API params value

0 commit comments

Comments
 (0)