Skip to content

Commit 4304eec

Browse files
committed
WIP: Port Slice Ops
This commit is a WIP as although it passes I had to create a lambda Op to pass through to slice to get it to pass. The type of the existing test Op is of the same type as the lambda, so we should figure out why this does not work Also, just make sure that the Ops are complete and correct
1 parent bab64cf commit 4304eec

4 files changed

Lines changed: 575 additions & 0 deletions

File tree

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
/*
2+
* #%L
3+
* ImageJ software for multidimensional image processing and analysis.
4+
* %%
5+
* Copyright (C) 2014 - 2018 ImageJ developers.
6+
* %%
7+
* Redistribution and use in source and binary forms, with or without
8+
* modification, are permitted provided that the following conditions are met:
9+
*
10+
* 1. Redistributions of source code must retain the above copyright notice,
11+
* this list of conditions and the following disclaimer.
12+
* 2. Redistributions in binary form must reproduce the above copyright notice,
13+
* this list of conditions and the following disclaimer in the documentation
14+
* and/or other materials provided with the distribution.
15+
*
16+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17+
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19+
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
20+
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21+
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22+
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23+
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24+
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25+
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26+
* POSSIBILITY OF SUCH DAMAGE.
27+
* #L%
28+
*/
29+
30+
package net.imagej.ops.slice;
31+
32+
import net.imglib2.Cursor;
33+
import net.imglib2.RandomAccessibleInterval;
34+
35+
import org.scijava.Priority;
36+
import org.scijava.ops.core.Op;
37+
import org.scijava.ops.core.computer.Computer;
38+
import org.scijava.ops.core.computer.Computer4;
39+
import org.scijava.param.Parameter;
40+
import org.scijava.plugin.Plugin;
41+
import org.scijava.struct.ItemIO;
42+
43+
/**
44+
* {@link SliceOp} implementation for {@link RandomAccessibleInterval} input and
45+
* {@link RandomAccessibleInterval} output.
46+
*
47+
* <p>
48+
* The input {@link RandomAccessibleInterval} will be wrapped into a
49+
* {@link SlicesII}, so that the given Op can compute on a per-slice base.
50+
* </p>
51+
*
52+
* @author Christian Dietz (University of Konstanz)
53+
* @author Martin Horn (University of Konstanz)
54+
*/
55+
@Plugin(type = Op.class, name = "slice", priority = Priority.VERY_HIGH)
56+
@Parameter(key = "input")
57+
@Parameter(key = "Op")
58+
@Parameter(key = "axisIndices")
59+
@Parameter(key = "dropSingleDimensions")
60+
@Parameter(key = "output", type = ItemIO.BOTH)
61+
public class SliceRAI2RAI<I, O> implements
62+
Computer4<RandomAccessibleInterval<I>, Computer<RandomAccessibleInterval<I>, RandomAccessibleInterval<O>>, int[], Boolean, RandomAccessibleInterval<O>> {
63+
64+
@Override
65+
public void compute(final RandomAccessibleInterval<I> input,
66+
final Computer<RandomAccessibleInterval<I>, RandomAccessibleInterval<O>> op, final int[] axisIndices,
67+
final Boolean dropSingleDimensions, final RandomAccessibleInterval<O> output) {
68+
SlicesII<I> slicedInput = new SlicesII<>(input, axisIndices, dropSingleDimensions);
69+
SlicesII<O> slicedOutput = new SlicesII<>(output, axisIndices, dropSingleDimensions);
70+
71+
//TODO: can we make this more efficient?
72+
Cursor<RandomAccessibleInterval<I>> slicedInputCursor = slicedInput.cursor();
73+
Cursor<RandomAccessibleInterval<O>> slicedOutputCursor = slicedOutput.cursor();
74+
while(slicedInputCursor.hasNext()) {
75+
op.compute(slicedInputCursor.next(), slicedOutputCursor.next());
76+
}
77+
}
78+
79+
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
/*
2+
* #%L
3+
* ImageJ software for multidimensional image processing and analysis.
4+
* %%
5+
* Copyright (C) 2014 - 2018 ImageJ developers.
6+
* %%
7+
* Redistribution and use in source and binary forms, with or without
8+
* modification, are permitted provided that the following conditions are met:
9+
*
10+
* 1. Redistributions of source code must retain the above copyright notice,
11+
* this list of conditions and the following disclaimer.
12+
* 2. Redistributions in binary form must reproduce the above copyright notice,
13+
* this list of conditions and the following disclaimer in the documentation
14+
* and/or other materials provided with the distribution.
15+
*
16+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17+
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19+
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
20+
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21+
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22+
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23+
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24+
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25+
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26+
* POSSIBILITY OF SUCH DAMAGE.
27+
* #L%
28+
*/
29+
30+
package net.imagej.ops.slice;
31+
32+
import net.imagej.axis.AxisType;
33+
import net.imagej.space.TypedSpace;
34+
35+
public class SliceUtils {
36+
37+
/**
38+
* @param input for which the {@link AxisType}s indices will be determined
39+
* @param axisTypes which will be used to determine the indices
40+
*/
41+
public static synchronized int[] getAxesIndices(final TypedSpace<?> input,
42+
final AxisType[] axisTypes)
43+
{
44+
if (axisTypes == null) return null;
45+
46+
int[] indices = new int[axisTypes.length];
47+
48+
for (int i = 0; i < axisTypes.length; i++) {
49+
indices[i] = input.dimensionIndex(axisTypes[i]);
50+
51+
if (indices[i] == -1) {
52+
// TODO nicer exception handling
53+
throw new IllegalArgumentException(
54+
"AxisType not available in TypedSpace<?>");
55+
}
56+
}
57+
58+
return indices;
59+
}
60+
61+
}
Lines changed: 226 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,226 @@
1+
/*
2+
* #%L
3+
* ImageJ software for multidimensional image processing and analysis.
4+
* %%
5+
* Copyright (C) 2014 - 2018 ImageJ developers.
6+
* %%
7+
* Redistribution and use in source and binary forms, with or without
8+
* modification, are permitted provided that the following conditions are met:
9+
*
10+
* 1. Redistributions of source code must retain the above copyright notice,
11+
* this list of conditions and the following disclaimer.
12+
* 2. Redistributions in binary form must reproduce the above copyright notice,
13+
* this list of conditions and the following disclaimer in the documentation
14+
* and/or other materials provided with the distribution.
15+
*
16+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17+
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19+
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
20+
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21+
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22+
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23+
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24+
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25+
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26+
* POSSIBILITY OF SUCH DAMAGE.
27+
* #L%
28+
*/
29+
30+
package net.imagej.ops.slice;
31+
32+
import java.util.Iterator;
33+
34+
import net.imglib2.AbstractInterval;
35+
import net.imglib2.Cursor;
36+
import net.imglib2.FinalInterval;
37+
import net.imglib2.FlatIterationOrder;
38+
import net.imglib2.Interval;
39+
import net.imglib2.IterableInterval;
40+
import net.imglib2.RandomAccessibleInterval;
41+
import net.imglib2.Sampler;
42+
import net.imglib2.img.Img;
43+
import net.imglib2.iterator.IntervalIterator;
44+
import net.imglib2.util.Intervals;
45+
import net.imglib2.view.IntervalView;
46+
import net.imglib2.view.Views;
47+
48+
/**
49+
* Helper class to iterate through subsets of {@link RandomAccessibleInterval}s
50+
* (e.g. {@link Img}s)
51+
*
52+
* @author Christian Dietz (University of Konstanz)
53+
*/
54+
public class SlicesII<T> extends AbstractInterval implements IterableInterval<RandomAccessibleInterval<T>> {
55+
56+
private final Interval slice;
57+
58+
private final RandomAccessibleInterval<T> source;
59+
60+
private boolean dropSingltonDimensions;
61+
62+
/**
63+
* @param source
64+
* {@link RandomAccessibleInterval} which will be virtually
65+
* cropped
66+
* @param axesOfInterest
67+
* axes which define a plane, cube, hypercube, ...! All other
68+
* axes will be iterated.
69+
* @param dropSingletonDimensions
70+
* if true, dimensions of size one will be discarded in the
71+
* sliced images
72+
*/
73+
public SlicesII(final RandomAccessibleInterval<T> source, final int[] axesOfInterest,
74+
final boolean dropSingletonDimensions) {
75+
super(initIntervals(source, axesOfInterest));
76+
77+
final long[] sliceMin = new long[source.numDimensions()];
78+
final long[] sliceMax = new long[source.numDimensions()];
79+
80+
for (int d = 0; d < source.numDimensions(); d++) {
81+
if (dimension(d) == 1) {
82+
sliceMin[d] = source.min(d);
83+
sliceMax[d] = source.max(d);
84+
}
85+
}
86+
87+
this.dropSingltonDimensions = dropSingletonDimensions;
88+
this.slice = new FinalInterval(sliceMin, sliceMax);
89+
this.source = source;
90+
}
91+
92+
/**
93+
* @param source
94+
* {@link RandomAccessibleInterval} which will be virtually
95+
* cropped
96+
* @param axesOfInterest
97+
* axes which define a plane, cube, hypercube, ...! All other
98+
* axes will be iterated.
99+
*/
100+
public SlicesII(final RandomAccessibleInterval<T> source, final int[] axesOfInterest) {
101+
this(source, axesOfInterest, true);
102+
}
103+
104+
// init method
105+
private static Interval initIntervals(final Interval src, final int[] axesOfInterest) {
106+
107+
final long[] dimensionsToIterate = new long[src.numDimensions()];
108+
src.dimensions(dimensionsToIterate);
109+
110+
// determine axis to iterate
111+
for (int i = 0; i < src.numDimensions(); i++) {
112+
for (int j = 0; j < axesOfInterest.length; j++) {
113+
114+
if (axesOfInterest[j] == i) {
115+
dimensionsToIterate[i] = 1;
116+
break;
117+
}
118+
}
119+
}
120+
121+
return new FinalInterval(dimensionsToIterate);
122+
}
123+
124+
@Override
125+
public Cursor<RandomAccessibleInterval<T>> cursor() {
126+
return new SlicesIICursor(source, this, slice);
127+
}
128+
129+
@Override
130+
public Cursor<RandomAccessibleInterval<T>> localizingCursor() {
131+
return cursor();
132+
}
133+
134+
@Override
135+
public long size() {
136+
return Intervals.numElements(this);
137+
}
138+
139+
@Override
140+
public RandomAccessibleInterval<T> firstElement() {
141+
return cursor().next();
142+
}
143+
144+
@Override
145+
public Object iterationOrder() {
146+
return new FlatIterationOrder(this);
147+
}
148+
149+
@Override
150+
public Iterator<RandomAccessibleInterval<T>> iterator() {
151+
return cursor();
152+
}
153+
154+
/**
155+
* Help class.
156+
*
157+
* @author Christian Dietz (University of Konstanz)
158+
*/
159+
private class SlicesIICursor extends IntervalIterator implements Cursor<RandomAccessibleInterval<T>> {
160+
161+
private final long[] tmpPosition;
162+
private final RandomAccessibleInterval<T> src;
163+
private final long[] sliceDims;
164+
private final long[] sliceOffset;
165+
166+
public SlicesIICursor(final RandomAccessibleInterval<T> src, final Interval fixedAxes, final Interval slice) {
167+
super(fixedAxes);
168+
169+
this.src = src;
170+
this.tmpPosition = new long[fixedAxes.numDimensions()];
171+
this.sliceDims = new long[slice.numDimensions()];
172+
this.sliceOffset = new long[slice.numDimensions()];
173+
174+
slice.dimensions(sliceDims);
175+
slice.min(sliceOffset);
176+
}
177+
178+
private SlicesIICursor(final SlicesIICursor cursor) {
179+
super(cursor);
180+
181+
this.src = cursor.src;
182+
this.sliceDims = cursor.sliceDims;
183+
this.sliceOffset = cursor.sliceOffset;
184+
this.tmpPosition = cursor.tmpPosition;
185+
186+
// set to the current position
187+
jumpFwd(cursor.index);
188+
}
189+
190+
@Override
191+
public RandomAccessibleInterval<T> get() {
192+
localize(tmpPosition);
193+
194+
final long[] offset = tmpPosition.clone();
195+
for (int d = 0; d < max.length; d++) {
196+
offset[d] += sliceOffset[d];
197+
}
198+
199+
final IntervalView<T> res = Views.offsetInterval(src, offset, sliceDims);
200+
201+
return dropSingltonDimensions ? Views.dropSingletonDimensions(res) : res;
202+
}
203+
204+
@Override
205+
public Sampler<RandomAccessibleInterval<T>> copy() {
206+
return copyCursor();
207+
}
208+
209+
@Override
210+
public RandomAccessibleInterval<T> next() {
211+
fwd();
212+
return get();
213+
}
214+
215+
@Override
216+
public void remove() {
217+
throw new UnsupportedOperationException("Not supported");
218+
}
219+
220+
@Override
221+
public Cursor<RandomAccessibleInterval<T>> copyCursor() {
222+
return new SlicesIICursor(this);
223+
}
224+
}
225+
226+
}

0 commit comments

Comments
 (0)