Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Istvan N. Huszar, MD
tirl
Commits
47a21f26
Commit
47a21f26
authored
Feb 25, 2020
by
ihuszar
Browse files
Slice-to-volume protocol for BigMac dataset.
parent
7a44410b
Changes
12
Expand all
Hide whitespace changes
Inline
Side-by-side
misc/adaptive_points.py
0 → 100644
View file @
47a21f26
#!/usr/bin/env python
import
tirl
import
numpy
as
np
from
tirl.costs.mind
import
CostMIND
from
skimage.segmentation
import
slic
from
skimage.future
import
graph
from
skimage.exposure
import
rescale_intensity
import
matplotlib
matplotlib
.
use
(
"macosx"
)
import
matplotlib.pyplot
as
plt
from
skimage.measure
import
regionprops
N_POINTS
=
16
MASK_UTHR
=
1
MASK_LTHR
=
0.1
img
=
tirl
.
load
(
"/Users/inhuszar/bigmac/reg/stage2.timg"
)
vol
=
tirl
.
load
(
"/Users/inhuszar/bigmac/reg/vol.timg"
)
mri
=
vol
.
evaluate
(
img
.
domain
)
mask
=
np
.
logical_and
(
img
.
data
>
MASK_LTHR
,
img
.
data
<=
MASK_UTHR
)
cost
=
CostMIND
(
mri
,
img
,
precompute
=
False
,
normalise
=
True
)
cm
=
cost
.
costmap
().
reduce_tensors
(
copy
=
True
)
im
=
rescale_intensity
(
cm
.
data
,
out_range
=
np
.
uint8
).
astype
(
np
.
float64
)
\
*
mask
.
astype
(
np
.
int64
)
test_cases
=
(
1
,)
#2 ** np.arange(2, 8)
shape_measure
=
[]
distance_measure
=
[]
for
n_segments
in
test_cases
:
# Segment cost function map given the number of segments
im
=
rescale_intensity
(
cm
.
data
,
out_range
=
np
.
uint8
).
astype
(
np
.
float64
)
\
*
mask
.
astype
(
np
.
int64
)
segments
=
slic
(
im
,
n_segments
=
150
,
sigma
=
5
,
compactness
=
50
)
\
*
mask
.
astype
(
np
.
int64
)
g
=
graph
.
rag_mean_color
(
cm
.
data
,
segments
)
segments
=
graph
.
cut_normalized
(
segments
,
g
,
thresh
=
0.1
,
in_place
=
False
)
N
=
np
.
unique
(
segments
).
size
-
1
print
(
N
)
regions
=
regionprops
(
segments
,
cm
.
data
)
regions
=
sorted
(
regions
,
key
=
lambda
r
:
np
.
std
(
r
.
intensity_image
))[::
-
1
]
# Measure the average shape parameter of the segments
convexity
=
np
.
mean
([
r
.
equivalent_diameter
for
r
in
regions
])
shape_measure
.
append
((
N
,
convexity
))
# Measure the average distance between segment centroids
centroids
=
[
r
.
centroid
for
r
in
regions
]
xi
=
np
.
stack
(
centroids
,
axis
=
0
)
edges
=
np
.
max
(
xi
,
axis
=
0
)
-
np
.
min
(
xi
,
axis
=
0
)
edges
=
edges
[
np
.
nonzero
(
edges
)]
epsilon
=
np
.
power
(
np
.
prod
(
edges
)
/
len
(
regions
),
1.
/
edges
.
size
)
distance_measure
.
append
((
N
,
epsilon
))
# Create new figure for current segment map
mapfig
,
mapax
=
plt
.
subplots
(
1
,
1
)
label
=
np
.
zeros_like
(
segments
)
im
=
mapax
.
imshow
(
label
,
vmin
=
segments
.
min
(),
vmax
=
segments
.
max
(),
zorder
=
1
)
for
region
in
regions
:
label
[
segments
==
region
.
label
]
=
region
.
label
im
.
set_data
(
label
)
y
,
x
=
region
.
centroid
mapax
.
plot
(
x
,
y
,
"ro"
,
zorder
=
2
)
mapfig
.
canvas
.
draw_idle
()
plt
.
pause
(
0.25
)
else
:
pass
plt
.
pause
(
1
)
else
:
# Plot the measured properties versus the number of segments
measfig
,
measax
=
plt
.
subplots
(
1
,
1
)
measax
.
plot
(
*
tuple
(
zip
(
*
shape_measure
)),
"b-"
)
measax
.
plot
(
*
tuple
(
zip
(
*
distance_measure
)),
"r-"
)
plt
.
show
()
protocols/cnf_slice_to_volume.json
View file @
47a21f26
...
...
@@ -5,14 +5,14 @@
"author"
:
"Istvan N Huszar, Amy FD Howard"
},
"slice"
:
{
"file"
:
"/Users/inhuszar/bigmac/histo/H092x/mosaic_colour
_mrires
.tif"
,
"alternative"
:
"/Users/inhuszar/bigmac/reg/stage4.timg"
,
"file"
:
"/Users/inhuszar/bigmac/histo/H092x/mosaic_colour.tif"
,
"alternative"
:
null
,
"storage"
:
"mem"
,
"mask"
:
{
"file"
:
null
,
"normalise"
:
false
},
"resolution"
:
0.
3
,
"resolution"
:
0.
0045
,
"preview"
:
false
,
"actions"
:
[
"resample_image"
,
"lab_b"
]
},
...
...
@@ -30,14 +30,13 @@
},
"general"
:
{
"verbosity"
:
"debug"
,
"system"
:
"macos"
,
"system"
:
"macos
x
"
,
"logfile"
:
"/Users/inhuszar/bigmac/reg/tirl_slice_to_volume.log"
,
"outdir"
:
"/Users/inhuszar/bigmac/reg"
,
"stages"
:
[
5
,
2
,
3
,
4
],
"stage_index"
:
8
,
"stages"
:
[
1
,
2
,
3
,
4
,
5
,
2
,
3
,
4
],
"stage_index"
:
3
,
"snapshot_ext"
:
"png"
,
"randomseed"
:
1
,
"warnings"
:
false
"warnings"
:
false
},
"regparams"
:
{
"init"
:
{
...
...
@@ -56,16 +55,22 @@
"visualise"
:
true
,
"verbose"
:
4
,
"slab"
:
{
"centre"
:
[
0
,
-4
.3
,
0
],
"centre"
:
[
0
,
-4
,
0
],
"normal"
:
[
0
,
1
,
0
],
"thickness"
:
1.5
,
"inits"
:
5
"thickness"
:
3
,
"inits"
:
7
},
"iterations"
:
1
,
"iterations"
:
2
,
"scaling"
:
[
8
,
4
,
4
,
2
,
2
,
1
,
1
],
"smoothing"
:
[
0
,
1
,
0
,
1
,
0
,
1
,
0
],
"constrained"
:
true
,
"opt_step"
:
0.1
,
"stage_1a"
:
{
"xtol_abs"
:
[
0.01
,
0.01
,
0.01
,
0.01
,
0.01
]
},
"stage_1b"
:
{
"xtol_abs"
:
[
0.01
,
0.01
,
0.01
,
0.01
,
0.01
,
0.01
,
0.01
,
0.01
]
},
"x0"
:
{
"scale2d"
:
[
1.0
,
1.0
],
"rot2d"
:
-90
,
...
...
@@ -77,16 +82,16 @@
"dx0"
:
{
"scale2d_lower_delta"
:
[
0.2
,
0.2
],
"scale2d_upper_delta"
:
[
0.2
,
0.2
],
"rot2d_lower_delta"
:
3
0.0
,
"rot2d_upper_delta"
:
3
0.0
,
"trans2d_lower_delta"
:
[
1
0
.0
,
1
0
.0
],
"trans2d_upper_delta"
:
[
1
0
.0
,
1
0
.0
],
"rot2d_lower_delta"
:
1
0.0
,
"rot2d_upper_delta"
:
1
0.0
,
"trans2d_lower_delta"
:
[
1
5
.0
,
1
5
.0
],
"trans2d_upper_delta"
:
[
1
5
.0
,
1
5
.0
],
"warp_lower_dxy"
:
2.5
,
"warp_lower_dz"
:
2.5
,
"warp_upper_dxy"
:
2.5
,
"warp_upper_dz"
:
2.5
,
"rot3d_lower_delta"
:
[
20
.0
,
20
.0
,
20
.0
],
"rot3d_upper_delta"
:
[
20
.0
,
20
.0
,
20
.0
],
"rot3d_lower_delta"
:
[
15
.0
,
15
.0
,
15
.0
],
"rot3d_upper_delta"
:
[
15
.0
,
15
.0
,
15
.0
],
"affine3d_lower_delta"
:
[
0.1
,
0.1
,
0.1
,
2.5
,
0.1
,
0.1
,
0.1
,
2.5
,
0.1
,
0.1
,
0.1
,
2.5
],
"affine3d_upper_delta"
:
[
0.1
,
0.1
,
0.1
,
2.5
,
0.1
,
0.1
,
0.1
,
2.5
,
0.1
,
0.1
,
0.1
,
2.5
],
"trans3d_lower_delta"
:
[
0.3
,
0.3
,
0.3
],
...
...
@@ -116,7 +121,7 @@
"image"
:
true
,
"snapshot"
:
true
},
"visualise"
:
tru
e
,
"visualise"
:
fals
e
,
"verbose"
:
4
,
"scaling"
:
[
4
,
2
,
1
,
1
],
"smoothing"
:
[
0
,
0
,
1
,
0
],
...
...
@@ -129,33 +134,46 @@
"export"
:
{
"image"
:
true
,
"snapshot"
:
true
,
"halton"
:
true
"cpoints"
:
true
,
"mask"
:
true
},
"mask"
:
{
"lthr"
:
0.1
,
"uthr"
:
1
},
"n_points"
:
16
,
"visualise"
:
true
,
"adaptive"
:
{
"max_points"
:
32
},
"visualise"
:
false
,
"verbose"
:
4
,
"smoothing"
:
[
2
,
1
,
0
],
"lower_dz"
:
3
,
"upper_dz"
:
3
,
"lower_dz"
:
1.5
,
"upper_dz"
:
1.5
,
"reg_weight"
:
0
,
"opt_step"
:
0.2
,
"xtol_abs"
:
0.1
,
"randomseed"
:
1
"opt_step"
:
0.4
,
"xtol_abs"
:
0.1
},
"stage_4"
:
{
"export"
:
{
"image"
:
true
,
"snapshot"
:
true
,
"halton"
:
true
"cpoints"
:
true
,
"mask"
:
true
},
"mask"
:
{
"lthr"
:
0.1
,
"uthr"
:
1
},
"adaptive"
:
{
"max_points"
:
32
},
"n_points"
:
16
,
"visualise"
:
false
,
"verbose"
:
4
,
"smoothing"
:
[
2
],
"smoothing"
:
[
2
,
1
,
0
],
"lower_dxy"
:
3
,
"lower_dz"
:
3
,
"lower_dz"
:
1
,
"upper_dxy"
:
3
,
"upper_dz"
:
3
,
"upper_dz"
:
1
,
"reg_weight"
:
0
,
"opt_step"
:
0.2
,
"xtol_abs"
:
0.1
...
...
@@ -164,13 +182,13 @@
"export"
:
{
"image"
:
true
,
"snapshot"
:
true
,
"mask"
:
true
"mask"
:
true
},
"visualise"
:
false
,
"mask"
:
{
"lthr"
:
0.1
,
"uthr"
:
1
}
"mask"
:
{
"lthr"
:
0.1
,
"uthr"
:
1
}
}
}
}
protocols/tirl_slice_to_volume
View file @
47a21f26
This diff is collapsed.
Click to expand it.
tirl/interpolators/interpolator.py
View file @
47a21f26
...
...
@@ -578,7 +578,7 @@ class Interpolator(TIRLObject):
# Resurrect the specific type of interpolator instance
obj
=
cls
(
source
=
values
,
n_threads
=
threads
,
verbose
=
verbose
,
**
kwargs
)
obj
.
tensor_axes
=
taxes
#
obj.tensor_axes = taxes
return
obj
def
_dump
(
self
):
...
...
tirl/interpolators/rbfinterpolator.py
View file @
47a21f26
...
...
@@ -6,6 +6,9 @@ from scipy.interpolate import Rbf
import
tirl.settings
as
ts
from
tirl.interpolators.interpolator
import
Interpolator
MODELS
=
(
"multiquadric"
,
"inverse"
,
"gaussian"
,
"linear"
,
"cubic"
,
"quintic"
,
"thin_plate"
)
class
RbfInterpolator
(
Interpolator
):
"""
...
...
@@ -81,10 +84,6 @@ class RbfInterpolator(Interpolator):
domain
=
dump
[
"kwargs"
].
get
(
"domain"
,
None
)
if
domain
is
not
None
:
obj
.
kwargs
.
update
({
"domain"
:
domain
})
# if domain is not None:
# from pydoc import locate
# dc = locate(domain["type"])
# obj.kwargs.update({"domain": dc._load(domain)})
return
obj
def
_dump
(
self
):
...
...
@@ -106,3 +105,16 @@ class RbfInterpolator(Interpolator):
coordinates
=
np
.
asarray
(
coordinates
).
reshape
(
1
,
-
1
)
ipol
=
Rbf
(
*
self
.
basis
.
T
,
input_array
.
ravel
(),
**
kwargs
)
return
ipol
(
*
coordinates
.
T
)
@
property
def
model
(
self
):
return
self
.
kwargs
.
get
(
"model"
)
@
model
.
setter
def
model
(
self
,
m
):
m
=
str
(
m
).
lower
()
if
m
in
MODELS
:
self
.
kwargs
.
update
({
"model"
:
m
})
else
:
raise
ValueError
(
f
"Unrecognised interpolation model:
{
m
}
. Choose "
f
"from the following:
{
MODELS
}
"
)
tirl/operations/spatial.py
View file @
47a21f26
...
...
@@ -96,12 +96,14 @@ class SpatialOperator(Operator):
taxes
=
tuple
(
range
(
result
.
ndim
-
tf
.
vdim
))
result_vshape
=
result
.
shape
[
len
(
taxes
):]
# Preserve domain
od
=
tf
.
domain
.
copy
()
# Preserve domain with original transformations for non-trimming OP
trimming_operation
=
result_vshape
!=
tf
.
vshape
if
not
trimming_operation
:
new_domain
=
od
.
copy
()
new_domain
=
tf
.
domain
# Copy domain for trimming OP
else
:
od
=
tf
.
domain
.
copy
()
margins
=
np
.
subtract
(
tf
.
vshape
,
result_vshape
)
//
2
assert
all
(
m
==
self
.
radius
for
m
in
margins
)
offset
=
[
TxTranslation
(
*
margins
)]
+
od
.
offset
...
...
@@ -109,7 +111,7 @@ class SpatialOperator(Operator):
od
.
kwargs
=
{
k
:
v
for
k
,
v
in
od
.
kwargs
.
items
()
if
k
not
in
od
.
RESERVED_KWARGS
}
new_domain
=
od
.
__class__
.
__new__
(
od
.
__class__
,
result_vshape
,
*
od
.
transformations
,
offset
=
offset
,
od
.
__class__
,
result_vshape
,
od
.
transformations
,
offset
=
offset
,
name
=
new_name
,
storage
=
od
.
storage
,
dtype
=
od
.
dtype
,
instance_mem_limit
=
od
.
instance_mem_limit
,
n_threads
=
od
.
threads
,
**
od
.
kwargs
)
...
...
@@ -242,11 +244,14 @@ class SpatialOperator(Operator):
# Create new TField instance for output
else
:
# Preserve domain
od
=
tf
.
domain
.
copy
()
# Preserve domain
with transformations for non-trimming OP
if
not
trimming_operation
:
new_domain
=
od
.
copy
()
new_domain
=
tf
.
domain
# Copy domain for trimming OP
else
:
od
=
tf
.
domain
.
copy
()
offset_tx
=
TxTranslation
(
*
((
self
.
radius
,)
*
self
.
input
.
vdim
))
offset
=
[
offset_tx
]
+
od
.
offset
new_name
=
"%s_%s"
%
(
od
.
name
,
self
.
name
)
...
...
tirl/operations/tensor.py
View file @
47a21f26
...
...
@@ -54,7 +54,7 @@ class TensorOperator(Operator):
def
_no_chunker
(
self
,
tf
,
op
,
out
,
*
opargs
,
**
opkwargs
):
"""
Performs operation with less overhead. Suitable for small in-memory
arrays only.
arrays only.
A new instance is returned with the original Domain.
"""
orig_order
=
tf
.
order
...
...
@@ -65,7 +65,7 @@ class TensorOperator(Operator):
result
=
result
.
reshape
(
*
tf
.
vshape
,
*
result
.
shape
[
1
:])
name
=
"{}_{}"
.
format
(
tf
.
name
,
self
.
name
)
result
=
tf
.
__class__
.
fromarray
(
arr
=
result
,
tensor_axes
=
taxes
,
copy
=
False
,
domain
=
tf
.
domain
.
copy
()
,
arr
=
result
,
tensor_axes
=
taxes
,
copy
=
False
,
domain
=
tf
.
domain
,
order
=
None
,
dtype
=
None
,
interpolator
=
tf
.
interpolator
.
__class__
,
name
=
name
,
storage
=
tf
.
storage
,
**
tf
.
kwargs
.
copy
())
result
.
order
=
orig_order
...
...
@@ -179,7 +179,7 @@ class TensorOperator(Operator):
else
:
name
=
"{}_{}"
.
format
(
tf
.
name
,
self
.
name
)
out
=
tf
.
__class__
.
__new__
(
tf
.
__class__
,
extent
=
tf
.
domain
.
copy
()
,
tf
.
__class__
,
extent
=
tf
.
domain
,
tensor_shape
=
output_tensor_shape
,
order
=
input_orig_order
,
dtype
=
output_dtype
,
buffer
=
None
,
offset
=
0
,
interpolator
=
tf
.
interpolator
.
__class__
,
name
=
name
,
...
...
tirl/tfield.py
View file @
47a21f26
...
...
@@ -1053,7 +1053,7 @@ class TField(TIRLObject, np.lib.mixins.NDArrayOperatorsMixin):
# Create interpolator instance from class specification
if
issubclass
(
type
(
ip
),
type
)
and
issubclass
(
ip
,
Interpolator
):
ip
=
ip
(
self
.
data
,
n_threads
=-
1
)
ip
=
ip
(
self
,
n_threads
=-
1
)
ip
.
_tensor_axes
=
self
.
taxes
# direct access for speed
ip
.
_threads
=
reduce
(
mul
,
self
.
tshape
)
# direct access for speed
...
...
tirl/timage.py
View file @
47a21f26
...
...
@@ -1964,7 +1964,7 @@ class TImage(TField):
"""
self
.
domain
.
reset
()
def
smooth
(
self
,
radius
,
*
radii
,
spatial_op
=
None
,
copy
=
Fals
e
):
def
smooth
(
self
,
radius
,
*
radii
,
spatial_op
=
None
,
copy
=
Tru
e
):
"""
Smooths the image uniformly for every tensor component. Anisotropic
smoothing can be applied by specifying smoothing radii for each spatial
...
...
@@ -1994,9 +1994,12 @@ class TImage(TField):
as leading arguments.
:type spatial_op: SpatialOperator
:param copy:
If True, the smoothing result is returned as a copy of the original
TImage. If False, the values will be changed in place.
:return:
If True (default), the smoothing result is returned as a copy of
the original TImage (the Domain is preserved). If False, the values
will be changed in place.
:returns: smoothed image
:rtype: TImage
"""
# Verify smoothing radii
...
...
@@ -2233,8 +2236,11 @@ class TImage(TField):
return
tuple
(
tx
.
parameters
)
@
resolution
.
setter
def
resolution
(
self
,
*
resolution
):
self
.
set_resolution
(
*
resolution
)
def
resolution
(
self
,
resolution
):
if
hasattr
(
resolution
,
"__iter__"
):
self
.
set_resolution
(
*
resolution
)
else
:
self
.
set_resolution
(
resolution
)
def
preview
(
self
,
centre
=
None
,
normal
=
None
,
resolution
=
1
,
**
kwargs
):
"""
...
...
tirl/transformations/basic/embedding.py
View file @
47a21f26
...
...
@@ -12,8 +12,19 @@ class TxEmbed(Transformation):
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ INITIALISER ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #
def
__init__
(
self
,
source_dim
,
target_dim
,
homogeneous
=
True
,
**
kwargs
):
""" Initialisation of TxEmbed. """
"""
Initialisation of TxEmbed.
:param source_dim: number of input dimensions
:type source_dim: int
:param target_dim: number of output dimensions
:type target_dim: int
:param homogeneous: use homogeneous coordinates
:type homogeneous: bool
:param kwargs: additional keyword arguments for TxEmbed
:type kwargs: Any
"""
# Set dimensions
if
not
tu
.
isdimension
(
source_dim
):
raise
ValueError
(
"The number of input dimensions must be a "
...
...
tirl/transformations/nonlinear/rbf_displacement.py
View file @
47a21f26
...
...
@@ -630,23 +630,13 @@ class TxRbfDisplacementField(TxNonLinear):
order
=
tensor
.
get
(
"order"
)
ipol
=
tensor
.
get
(
"interpolator"
)
fkwargs
=
tensor
.
get
(
"kwargs"
)
# TODO: Emergency bugfix: use ipol class, because of 'taxes' mismatch
field
=
TField
(
domain
,
tensor_shape
=
tshape
,
buffer
=
params
,
order
=
order
,
interpolator
=
ipol
,
**
fkwargs
)
order
=
order
,
interpolator
=
ipol
.
__class__
,
**
fkwargs
)
# Resurrect the TxDisplacementField instance
obj
=
TxRbfDisplacementField
(
field
,
axes
=
axes
,
**
meta
)
return
obj
# def dump(self):
# field = self.field()
# meta = self.metaparameters.copy()
# meta.pop("tensor")
# meta.pop("domain", None)
# dtx = {"type": ".".join([type(self).__module__,
# type(self).__name__]),
# "field": field.dump(),
# "metaparameters": meta}
# return dtx
def
regrid
(
self
,
domain
):
"""
Returns a transformation object with identical metaparameters. The
...
...
tirl/transformations/transformation.py
View file @
47a21f26
...
...
@@ -391,21 +391,6 @@ class Transformation(TIRLObject):
"parameters"
:
self
.
parameters
,
"metaparameters"
:
rcopy
(
self
.
metaparameters
)
})
# meta = dict()
# for key, item in self.metaparameters.items():
# if isinstance(item, TIRLObject):
# if hasattr(item, "dump"):
# meta[key] = getattr(item, "dump")()
# else:
# raise AttributeError(
# "No 'dump' method was found for TIRLObject {}."
# .format(item.__class__.__name__))
# else:
# meta[key] = item
# objdump.update({
# "parameters": self.parameters,
# "metaparameters": meta
# })
return
objdump
@
classmethod
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment