Skip to content

Commit 15980d2

Browse files
ctruedenimagejan
authored andcommitted
Aggregate display of simple outputs into a table
This change is an attempt to address two related problems: 1. There are no Display plugins (and hence no DisplayViewers) for numbers or booleans. 2. The DisplayPostprocessor tries to handle each output using its own Display, which is pretty clunky when there are several simple (text/number/boolean) outputs and several windows pop up. This postprocessor acts just before the display postprocessor, aggregating all simple outputs into a single GenericTable, which is then shown to the user via the UIService. The heuristic on whether and how to use a table is as follows: - Only simple outputs are included: text, numbers and booleans. - If there is only a single simple output, and it is text, no table is created. This minimizes negative impact on certain existing plugins which produce a large amount of text output and expect it to be displayed in a TextDisplay.
1 parent 809133c commit 15980d2

1 file changed

Lines changed: 112 additions & 0 deletions

File tree

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
/*
2+
* #%L
3+
* ImageJ software for multidimensional image processing and analysis.
4+
* %%
5+
* Copyright (C) 2009 - 2016 Board of Regents of the University of
6+
* Wisconsin-Madison, Broad Institute of MIT and Harvard, and Max Planck
7+
* Institute of Molecular Cell Biology and Genetics.
8+
* %%
9+
* Redistribution and use in source and binary forms, with or without
10+
* modification, are permitted provided that the following conditions are met:
11+
*
12+
* 1. Redistributions of source code must retain the above copyright notice,
13+
* this list of conditions and the following disclaimer.
14+
* 2. Redistributions in binary form must reproduce the above copyright notice,
15+
* this list of conditions and the following disclaimer in the documentation
16+
* and/or other materials provided with the distribution.
17+
*
18+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19+
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21+
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
22+
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23+
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24+
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25+
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26+
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27+
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28+
* POSSIBILITY OF SUCH DAMAGE.
29+
* #L%
30+
*/
31+
32+
package net.imagej.table.process;
33+
34+
import java.util.ArrayList;
35+
36+
import net.imagej.table.DefaultColumn;
37+
import net.imagej.table.DefaultGenericTable;
38+
import net.imagej.table.GenericTable;
39+
40+
import org.scijava.Priority;
41+
import org.scijava.module.Module;
42+
import org.scijava.module.ModuleItem;
43+
import org.scijava.module.process.AbstractPostprocessorPlugin;
44+
import org.scijava.module.process.PostprocessorPlugin;
45+
import org.scijava.plugin.Parameter;
46+
import org.scijava.plugin.Plugin;
47+
import org.scijava.ui.UIService;
48+
import org.scijava.util.ClassUtils;
49+
50+
/**
51+
* A postprocessor which aggregates simple output values into a single table,
52+
* for a nicer UI experience.
53+
*
54+
* @author Curtis Rueden
55+
*/
56+
@Plugin(type = PostprocessorPlugin.class,
57+
priority = Priority.VERY_LOW_PRIORITY + 1)
58+
public class ResultsPostprocessor extends AbstractPostprocessorPlugin {
59+
60+
@Parameter
61+
private UIService ui;
62+
63+
// -- ModuleProcessor methods --
64+
65+
@Override
66+
public void process(final Module module) {
67+
// filter the compatible outputs (simple types: number, boolean, text)
68+
final ArrayList<ModuleItem<?>> outputs = new ArrayList<>();
69+
module.getInfo().outputs().forEach(output -> {
70+
final String name = output.getName();
71+
if (module.isOutputResolved(name)) return;
72+
if (module.getOutput(name) == null) return;
73+
if (!isSimpleType(output.getType())) return;
74+
outputs.add(output);
75+
});
76+
77+
if (outputs.isEmpty()) return; // no compatible outputs
78+
if (outputs.size() == 1 && ClassUtils.isText(outputs.get(0).getType())) {
79+
// sole compatible output is a string; let the TextDisplay handle it
80+
return;
81+
}
82+
83+
// create a table to house the output values
84+
final GenericTable outputTable = new DefaultGenericTable();
85+
final DefaultColumn<String> names = //
86+
new DefaultColumn<>(String.class, "Name");
87+
final DefaultColumn<Object> values = //
88+
new DefaultColumn<>(Object.class, "Value");
89+
90+
// populate the columns
91+
for (final ModuleItem<?> output : outputs) {
92+
final String name = output.getName();
93+
names.addValue(name);
94+
values.addValue(module.getOutput(name));
95+
module.resolveOutput(name);
96+
}
97+
98+
// show the table
99+
outputTable.add(names);
100+
outputTable.add(values);
101+
final String title = module.getInfo().getTitle();
102+
ui.show(title, outputTable);
103+
}
104+
105+
// -- Helper methods --
106+
107+
private boolean isSimpleType(final Class<?> type) {
108+
return ClassUtils.isText(type) || //
109+
ClassUtils.isNumber(type) || //
110+
ClassUtils.isBoolean(type);
111+
}
112+
}

0 commit comments

Comments
 (0)