Skip to content

Commit b1b7637

Browse files
authored
Merge pull request #13 from tlnagy/tn/position-as-axis
add prelim support for position as an additional axis
2 parents dbf70eb + 0ffadc4 commit b1b7637

File tree

3 files changed

+50
-13
lines changed

3 files changed

+50
-13
lines changed

src/loader.jl

+41-13
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,45 @@ function load(io::Stream{format"OMETIFF"})
1818
images = find(omexml, "/ns:OME/ns:Image",["ns"=>namespace(omexml)])
1919
results = Array{AxisArray}(length(images))
2020

21-
for (idx, image) in enumerate(images)
22-
files = Dict{String, TiffFile}()
21+
pos_names = nodecontent.(find(omexml, "/ns:OME/ns:Image/ns:StageLabel[@Name]/@Name",["ns"=>namespace(omexml)]))
22+
# if all position names aren't unique then substitute names
23+
if length(pos_names) == 0 || !allunique(pos_names)
24+
pos_names = ["Pos$i" for i in 1:length(images)]
25+
end
2326

27+
pixels = []
28+
master_rawtype = Nullable{DataType}()
29+
mappedtype = Int64
30+
master_dims = []
31+
axes_dims = Nullable{Vector{AxisArrays.Axis}}()
32+
for (idx, image) in enumerate(images)
2433
pixel = findfirst(image, "./ns:Pixels", ["ns"=>namespace(omexml)])
25-
tiffdatas = find(pixel, "./ns:TiffData", ["ns"=>namespace(omexml)])
26-
34+
dims, axes_info = build_axes(pixel)
2735
rawtype, mappedtype = type_mapping[pixel["Type"]]
2836

29-
dims, axes_info = build_axes(pixel)
37+
if isnull(master_rawtype)
38+
master_rawtype = Nullable(rawtype)
39+
elseif get(master_rawtype) != rawtype
40+
throw(FileIO.LoaderError("OMETIFF", "Multiple different storage types not supported in a multi position image"))
41+
end
42+
43+
if isnull(axes_dims)
44+
axes_dims = Nullable(axes_info)
45+
master_dims = dims
46+
elseif get(axes_dims) != axes_info
47+
throw(FileIO.LoaderError("OMETIFF", "Axes changing between multiple imaging positions is not supported yet"))
48+
end
49+
push!(pixels, pixel)
50+
end
51+
push!(get(axes_dims), Axis{:position}(Symbol.(pos_names)))
52+
push!(master_dims, length(pos_names))
53+
54+
data = Array{get(master_rawtype), length(master_dims)}(master_dims...)
55+
56+
for (pos_idx, pixel) in enumerate(pixels)
57+
files = Dict{String, TiffFile}()
58+
59+
tiffdatas = find(pixel, "./ns:TiffData", ["ns"=>namespace(omexml)])
3060

3161
# TODO: Only the IFDs with a corresponding slice should be loaded.
3262
slices = DefaultDict{String, Dict{Int, ImageSlice}}(Dict{Int, ImageSlice}())
@@ -35,8 +65,7 @@ function load(io::Stream{format"OMETIFF"})
3565
slices[slice.file.filepath][slice.ifd_idx] = slice
3666
end
3767

38-
data = Array{rawtype, length(dims)}(dims...)
39-
height, width = dims[1:2]
68+
height, width = master_dims[1:2]
4069

4170
for (filepath, ifds) in slices
4271
file = files[filepath]
@@ -49,26 +78,25 @@ function load(io::Stream{format"OMETIFF"})
4978
read_dims = n_strips > 1 ? (strip_len) : (height, width)
5079

5180
# TODO: This shouldn't be allocated for each ifd
52-
tmp = Array{rawtype}(read_dims...)
81+
tmp = Array{get(master_rawtype)}(read_dims...)
5382
for j in 1:n_strips
5483
seek(file.io, strip_offsets[j])
5584
read!(file.io, tmp)
5685
tmp = file.need_bswap ? bswap.(tmp) : tmp
5786
if n_strips > 1
58-
data[j, :, ifd.z_idx, ifd.c_idx, ifd.t_idx]= tmp
87+
data[j, :, ifd.z_idx, ifd.c_idx, ifd.t_idx, pos_idx]= tmp
5988
else
60-
data[:, :, ifd.z_idx, ifd.c_idx, ifd.t_idx] = tmp
89+
data[:, :, ifd.z_idx, ifd.c_idx, ifd.t_idx, pos_idx] = tmp
6190
end
6291
end
6392
end
6493
end
6594

6695
# drop unnecessary axes
6796
# TODO: Reduce the number of allocations here
68-
squeezed_data = squeeze(Gray.(reinterpret(mappedtype, data)), (find(dims .== 1)...))
69-
results[idx] = AxisArray(squeezed_data, axes_info[dims .> 1]...)
7097
end
71-
length(results) == 1 ? results[1] : results
98+
squeezed_data = squeeze(Gray.(reinterpret(mappedtype, data)), (find(master_dims .== 1)...))
99+
AxisArray(squeezed_data, get(axes_dims)[master_dims .> 1]...)
72100
end
73101

74102
"""Corresponding Julian types for OME-XML types"""

test/runtests.jl

+9
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,15 @@ using Base.Test
4242
@test size(img[Axis{:z}(1)]) == (167, 439, 3)
4343
end
4444
end
45+
@testset "Multi position OME-TIFF" begin
46+
open("testdata/singles/background_1_MMStack.ome.tif") do f
47+
s = Stream(format"OMETIFF", f, OMETIFF.extract_filename(f))
48+
img = OMETIFF.load(s)
49+
@test size(img) == (1024, 1024, 9)
50+
# check position indexing
51+
@test size(img[Axis{:position}(:Pos1)]) == (1024, 1024)
52+
end
53+
end
4554
end
4655
@testset "Multi file OME-TIFFs" begin
4756
@testset "Multi file Z stack with master file" begin
Binary file not shown.

0 commit comments

Comments
 (0)