use of uk.ac.sussex.gdsc.core.utils.LocalList in project GDSC-SMLM by aherbert.
the class Fire method run.
@Override
public void run(String arg) {
extraOptions = ImageJUtils.isExtraOptions();
SmlmUsageTracker.recordPlugin(this.getClass(), arg);
// Require some fit results and selected regions
final int size = MemoryPeakResults.countMemorySize();
if (size == 0) {
IJ.error(pluginTitle, "There are no fitting results in memory");
return;
}
settings = Settings.load();
settings.save();
if ("q".equals(arg)) {
pluginTitle += " Q estimation";
runQEstimation();
return;
}
IJ.showStatus(pluginTitle + " ...");
if (!showInputDialog()) {
return;
}
MemoryPeakResults inputResults1 = ResultsManager.loadInputResults(settings.inputOption, false, null, null);
if (MemoryPeakResults.isEmpty(inputResults1)) {
IJ.error(pluginTitle, "No results could be loaded");
return;
}
MemoryPeakResults inputResults2 = ResultsManager.loadInputResults(settings.inputOption2, false, null, null);
inputResults1 = cropToRoi(inputResults1);
if (inputResults1.size() < 2) {
IJ.error(pluginTitle, "No results within the crop region");
return;
}
if (inputResults2 != null) {
inputResults2 = cropToRoi(inputResults2);
if (inputResults2.size() < 2) {
IJ.error(pluginTitle, "No results2 within the crop region");
return;
}
}
initialise(inputResults1, inputResults2);
if (!showDialog()) {
return;
}
final long start = System.currentTimeMillis();
// Compute FIRE
String name = inputResults1.getName();
final double fourierImageScale = Settings.scaleValues[settings.imageScaleIndex];
final int imageSize = Settings.imageSizeValues[settings.imageSizeIndex];
if (this.results2 != null) {
name += " vs " + this.results2.getName();
final FireResult result = calculateFireNumber(fourierMethod, samplingMethod, thresholdMethod, fourierImageScale, imageSize);
if (result != null) {
logResult(name, result);
if (settings.showFrcCurve) {
showFrcCurve(name, result, thresholdMethod);
}
}
} else {
FireResult result = null;
final int repeats = (settings.randomSplit) ? Math.max(1, settings.repeats) : 1;
setProgress(repeats);
if (repeats == 1) {
result = calculateFireNumber(fourierMethod, samplingMethod, thresholdMethod, fourierImageScale, imageSize);
if (result != null) {
logResult(name, result);
if (settings.showFrcCurve) {
showFrcCurve(name, result, thresholdMethod);
}
}
} else {
// Multi-thread this ...
final int nThreads = MathUtils.min(repeats, getThreads());
final ExecutorService executor = Executors.newFixedThreadPool(nThreads);
final LocalList<Future<?>> futures = new LocalList<>(repeats);
final LocalList<FireWorker> workers = new LocalList<>(repeats);
IJ.showProgress(0);
IJ.showStatus(pluginTitle + " computing ...");
for (int i = 1; i <= repeats; i++) {
final FireWorker w = new FireWorker(i, fourierImageScale, imageSize);
workers.add(w);
futures.add(executor.submit(w));
}
// Wait for all to finish
executor.shutdown();
ConcurrencyUtils.waitForCompletionUnchecked(futures);
IJ.showProgress(1);
// Show a combined FRC curve plot of all the smoothed curves if we have multiples.
final LUT valuesLut = LutHelper.createLut(LutColour.FIRE_GLOW);
final LutHelper.DefaultLutMapper mapper = new LutHelper.DefaultLutMapper(0, repeats);
final FrcCurvePlot curve = new FrcCurvePlot();
final Statistics stats = new Statistics();
final WindowOrganiser wo = new WindowOrganiser();
boolean oom = false;
for (int i = 0; i < repeats; i++) {
final FireWorker w = workers.get(i);
if (w.oom) {
oom = true;
}
if (w.result == null) {
continue;
}
result = w.result;
if (!Double.isNaN(result.fireNumber)) {
stats.add(result.fireNumber);
}
if (settings.showFrcCurveRepeats) {
// Output each FRC curve using a suffix.
logResult(w.name, result);
wo.add(ImageJUtils.display(w.plot.getTitle(), w.plot));
}
if (settings.showFrcCurve) {
final int index = mapper.map(i + 1);
curve.add(name, result, thresholdMethod, LutHelper.getColour(valuesLut, index), Color.blue, null);
}
}
if (result != null) {
wo.cascade();
final double mean = stats.getMean();
logResult(name, result, mean, stats);
if (settings.showFrcCurve) {
curve.addResolution(mean);
final Plot plot = curve.getPlot();
ImageJUtils.display(plot.getTitle(), plot);
}
}
if (oom) {
// @formatter:off
IJ.error(pluginTitle, "ERROR - Parallel computation out-of-memory.\n \n" + TextUtils.wrap("The number of results will be reduced. " + "Please reduce the size of the Fourier image " + "or change the number of threads " + "using the extra options (hold down the 'Shift' " + "key when running the plugin).", 80));
// @formatter:on
}
}
// Only do this once
if (settings.showFrcTimeEvolution && result != null && !Double.isNaN(result.fireNumber)) {
showFrcTimeEvolution(name, result.fireNumber, thresholdMethod, nmPerUnit / result.getNmPerPixel(), imageSize);
}
}
IJ.showStatus(pluginTitle + " complete : " + TextUtils.millisToString(System.currentTimeMillis() - start));
}
use of uk.ac.sussex.gdsc.core.utils.LocalList in project GDSC-SMLM by aherbert.
the class ImageJ3DResultsViewer method createShape.
@SuppressWarnings("unused")
private static Shape3D createShape(Builder settings) {
final LocalList<Point3f> points = new LocalList<>(1);
points.push(new Point3f());
// We try and match the geometry and appearance of the standard mesh.
// Do this by creating a mesh with a single point and get the Geometry and Appearance.
GeometryArray ga;
CustomMesh mesh;
final float transparency = getTransparency(settings);
// Support drawing as points ...
if (settings.getRendering() == 0) {
mesh = new TransparentItemPointMesh(points, null, transparency);
((ItemPointMesh) mesh).setPointSize((float) settings.getPixelSize());
updateAppearance(mesh, settings);
// Assume the TransparentItemPointMesh sets COLOR_4
ga = (GeometryArray) mesh.getGeometry();
} else {
final Rendering r = Rendering.forNumber(settings.getRendering());
final List<Point3f> point = Shape3DHelper.createLocalisationObject(r);
final Point3f[] vertices = point.toArray(new Point3f[1]);
// Correct the direction
ItemTriangleMesh.checkFacets(vertices);
final double creaseAngle = (r.isHighResolution()) ? 44 : 0;
mesh = new ItemTriangleMesh(vertices, points.toArray(new Point3f[1]), null, null, transparency, creaseAngle, null);
updateAppearance(mesh, settings);
final int nVertices = vertices.length;
ga = new TriangleArray(nVertices, GeometryArray.COORDINATES | GeometryArray.NORMALS);
// Copy the coords and normals. We don't require the vertex colours.
final float[] coords = new float[nVertices * 3];
final float[] normals = new float[nVertices * 3];
final GeometryArray gaToCopy = (GeometryArray) mesh.getGeometry();
gaToCopy.getCoordinates(0, coords);
gaToCopy.getNormals(0, normals);
ga.setCoordinates(0, coords);
ga.setNormals(0, normals);
ga.setValidVertexCount(nVertices);
}
return new Shape3D(ga, mesh.getAppearance());
}
use of uk.ac.sussex.gdsc.core.utils.LocalList in project GDSC-SMLM by aherbert.
the class ImageJ3DResultsViewer method run.
@Override
public void run(String arg) {
// For testing
// if (true || Utils.isExtraOptions())
// {
// new ImageJ3DResultsViewerDemo().run(arg);
// return;
// }
SmlmUsageTracker.recordPlugin(this.getClass(), arg);
if (ImageJ3DViewerUtils.JAVA_3D_VERSION == null) {
IJ.error(TITLE, "Java 3D is not available");
return;
}
if (MemoryPeakResults.isMemoryEmpty()) {
IJ.error(TITLE, "There are no fitting results in memory");
return;
}
final ImageJ3DResultsViewerSettings.Builder settings = SettingsManager.readImageJ3DResultsViewerSettings(0).toBuilder();
addToSelection.set(settings.getAddToSelection());
// Get a list of the window titles available. Allow the user to select
// an existing window or a new one.
final String title = TITLE;
final List<Image3DUniverse> univList = new LocalList<>();
final List<String> titleList = new LocalList<>();
titleList.add("New window");
buildWindowList(title, univList, titleList);
final String[] titles = titleList.toArray(new String[0]);
final ExtendedGenericDialog gd = new ExtendedGenericDialog(TITLE);
gd.addMessage("Select a dataset to display");
ResultsManager.addInput(gd, settings.getInputOption(), InputSource.MEMORY);
// The behaviour is to allow the settings to store if the user prefers a new window
// or to reuse an existing window. If 'new window' then a new window should always
// be selected. Otherwise open in the same window as last time. If there was no last
// window then the settings will carried over from the last ImageJ session.
final String window = (settings.getNewWindow()) ? "" : lastWindow.get();
gd.addChoice("Window", titles, window);
gd.addSlider("Transparancy", 0, 0.9, settings.getTransparency(), new OptionListener<Double>() {
@Override
public boolean collectOptions(Double value) {
return collectOptions(false);
}
@Override
public boolean collectOptions() {
return collectOptions(true);
}
private boolean collectOptions(boolean silent) {
final ExtendedGenericDialog egd = new ExtendedGenericDialog("Transparancy options", null);
egd.addCheckbox("Support_dynamic_transparency", settings.getSupportDynamicTransparency());
egd.addCheckbox("Enable_dynamic_transparency", settings.getEnableDynamicTransparency());
egd.setSilent(silent);
egd.showDialog(true, gd);
if (egd.wasCanceled()) {
return false;
}
settings.setSupportDynamicTransparency(egd.getNextBoolean());
settings.setEnableDynamicTransparency(egd.getNextBoolean());
return true;
}
});
gd.addChoice("Colour", LutHelper.getLutNames(), settings.getLut());
gd.addChoice("Rendering", RENDERING, settings.getRendering(), new OptionListener<Integer>() {
@Override
public boolean collectOptions(Integer value) {
settings.setRendering(value);
return collectOptions(false);
}
@Override
public boolean collectOptions() {
return collectOptions(true);
}
private boolean collectOptions(boolean silent) {
final ExtendedGenericDialog egd = new ExtendedGenericDialog("Drawing mode options", null);
final int rendering = settings.getRendering();
if (rendering != 0) {
return false;
}
egd.addNumericField("Pixel_size", settings.getPixelSize(), 2, 6, "px");
egd.setSilent(silent);
egd.showDialog(true, gd);
if (egd.wasCanceled()) {
return false;
}
settings.setPixelSize(egd.getNextNumber());
return true;
}
});
gd.addCheckbox("Shaded", settings.getShaded());
gd.addChoice("Size_mode", SIZE_MODE, settings.getSizeMode(), new OptionListener<Integer>() {
@Override
public boolean collectOptions(Integer value) {
settings.setSizeMode(value);
return collectOptions(false);
}
@Override
public boolean collectOptions() {
return collectOptions(true);
}
private boolean collectOptions(boolean silent) {
final ExtendedGenericDialog egd = new ExtendedGenericDialog("Size mode options", null);
final SizeMode mode = SizeMode.forNumber(settings.getSizeMode());
if (mode == SizeMode.FIXED_SIZE) {
egd.addNumericField("Size", settings.getSize(), 2, 6, "nm");
} else {
// Other modes do not require options
return false;
}
egd.setSilent(silent);
egd.showDialog(true, gd);
if (egd.wasCanceled()) {
return false;
}
settings.setSize(egd.getNextNumber());
return true;
}
});
gd.addChoice("Sort_mode", SORT_MODE, settings.getSortMode(), new OptionListener<Integer>() {
@Override
public boolean collectOptions(Integer value) {
settings.setSortMode(value);
return collectOptions(false);
}
@Override
public boolean collectOptions() {
return collectOptions(true);
}
private boolean collectOptions(boolean silent) {
final ExtendedGenericDialog egd = new ExtendedGenericDialog("Sort mode options", null);
final SortMode mode = SortMode.forNumber(settings.getSortMode());
if (mode == SortMode.NONE) {
return false;
}
egd.addMessage(TextUtils.wrap("Note: The sort mode is used to correctly render transparent objects. " + "For non-transparent objects faster rendering is achieved with a reverse " + "sort to put close objects at the front.", 80));
egd.addMessage(TextUtils.wrap(mode.getDetails(), 80));
egd.addMessage("Define the direction of the view");
egd.addNumericField("Direction_x", settings.getSortDirectionX(), 3, 10, "");
egd.addNumericField("Direction_y", settings.getSortDirectionY(), 3, 10, "");
egd.addNumericField("Direction_z", settings.getSortDirectionZ(), 3, 10, "");
if (mode == SortMode.PERSPECTIVE) {
egd.addMessage("Define the view eye position");
egd.addNumericField("Eye_x", settings.getSortEyeX(), 3, 10, "nm");
egd.addNumericField("Eye_y", settings.getSortEyeY(), 3, 10, "nm");
egd.addNumericField("Eye_z", settings.getSortEyeZ(), 3, 10, "nm");
}
egd.setSilent(silent);
egd.showDialog(true, gd);
if (egd.wasCanceled()) {
return false;
}
settings.setSortDirectionX(egd.getNextNumber());
settings.setSortDirectionY(egd.getNextNumber());
settings.setSortDirectionZ(egd.getNextNumber());
if (mode == SortMode.PERSPECTIVE) {
settings.setSortEyeX(egd.getNextNumber());
settings.setSortEyeY(egd.getNextNumber());
settings.setSortEyeZ(egd.getNextNumber());
}
return true;
}
});
gd.addChoice("Transparency_mode", TRANSPARENCY_MODE, settings.getTransparencyMode(), new OptionListener<Integer>() {
@Override
public boolean collectOptions(Integer value) {
settings.setTransparencyMode(value);
return collectOptions(false);
}
@Override
public boolean collectOptions() {
return collectOptions(true);
}
private boolean collectOptions(boolean silent) {
final ExtendedGenericDialog egd = new ExtendedGenericDialog("Transparency mode options", null);
final TransparencyMode mode = TransparencyMode.forNumber(settings.getTransparencyMode());
if (mode == TransparencyMode.NONE) {
return false;
}
egd.addSlider("Min_transparancy", 0, 0.95, settings.getMinTransparency());
egd.addSlider("Max_transparancy", 0, 0.95, settings.getMaxTransparency());
egd.setSilent(silent);
egd.showDialog(true, gd);
if (egd.wasCanceled()) {
return false;
}
settings.setMinTransparency(egd.getNextNumber());
settings.setMaxTransparency(egd.getNextNumber());
return true;
}
});
addColourMode(settings, gd);
gd.addMessage("2D options");
gd.addChoice("Depth_mode", DEPTH_MODE, settings.getDepthMode(), new OptionListener<Integer>() {
@Override
public boolean collectOptions(Integer value) {
settings.setDepthMode(value);
return collectOptions(false);
}
@Override
public boolean collectOptions() {
return collectOptions(true);
}
private boolean collectOptions(boolean silent) {
final ExtendedGenericDialog egd = new ExtendedGenericDialog("Depth mode options", null);
final DepthMode mode = DepthMode.forNumber(settings.getDepthMode());
if (mode == DepthMode.NONE) {
return false;
}
egd.addNumericField("Depth_range", settings.getDepthRange(), 2, 6, "nm");
if (mode == DepthMode.DITHER) {
egd.addNumericField("Dither_seed", settings.getDitherSeed(), 0);
}
egd.setSilent(silent);
egd.showDialog(true, gd);
if (egd.wasCanceled()) {
return false;
}
settings.setDepthRange(egd.getNextNumber());
if (mode == DepthMode.DITHER) {
settings.setDitherSeed((int) egd.getNextNumber());
}
return true;
}
});
addHelp(gd);
gd.showDialog();
if (gd.wasCanceled()) {
return;
}
final String name = ResultsManager.getInputSource(gd);
final int windowChoice = gd.getNextChoiceIndex();
lastWindow.set(titles[windowChoice]);
settings.setInputOption(name);
settings.setTransparency(gd.getNextNumber());
settings.setLut(gd.getNextChoiceIndex());
settings.setRendering(gd.getNextChoiceIndex());
settings.setShaded(gd.getNextBoolean());
settings.setSizeMode(gd.getNextChoiceIndex());
settings.setSortMode(gd.getNextChoiceIndex());
settings.setTransparencyMode(gd.getNextChoiceIndex());
settings.setColourMode(gd.getNextChoiceIndex());
settings.setDepthMode(gd.getNextChoiceIndex());
gd.collectOptions();
if (windowChoice == 0) {
// Store if the user chose a new window when they had a choice of an existing window
if (titleList.size() > 1) {
settings.setNewWindow(true);
// Otherwise they had no choice so leave the preferences as they are.
}
} else {
// This was not a new window
settings.setNewWindow(false);
}
SettingsManager.writeSettings(settings);
MemoryPeakResults results = ResultsManager.loadInputResults(name, false, null, null);
if (MemoryPeakResults.isEmpty(results)) {
IJ.error(TITLE, "No results could be loaded");
return;
}
// Determine if the drawing mode is supported and compute the point size
final Point3f[] sphereSize = createSphereSize(results, settings);
if (sphereSize == null) {
return;
}
// Cache the table settings
resultsTableSettings.set(settings.getResultsTableSettings());
// Create a 3D viewer.
if (windowChoice == 0) {
univ = createImage3DUniverse(title, titleList);
} else {
// Ignore the new window
univ = univList.get(windowChoice - 1);
}
lastWindow.set(univ.getWindow().getTitle());
results = results.copy();
// Commence a digest
final Future<PeakResultsDigest> futureDigest = PeakResultsDigest.digestLater(executorService, results.toArray());
final LocalList<Point3f> points = getPoints(results, settings);
final ResultsMetaData data = new ResultsMetaData(settings.build(), results, points, sphereSize);
sort(data);
final float[] alpha = createAlpha(results, settings, sphereSize);
final float transparency = getTransparency(settings);
final Color3f[] colors = createColour(results, settings);
ContentNode contentNode;
// Build to support true transparency (depends on settings).
// Currently this is not supported for PointArrays as they require colouring
// in the coordinate data.
IJ.showStatus("Creating 3D geometry ...");
if (settings.getSupportDynamicTransparency()) {
final ItemGeometryGroup pointGroup = createItemGroup(settings, sphereSize, points, alpha, transparency, colors);
if (pointGroup == null) {
IJ.showStatus("");
return;
}
if (settings.getEnableDynamicTransparency()) {
final long total = points.size() + getTotalTransparentObjects(univ, name);
activateDynamicTransparency(univ, total, settings.getEnableDynamicTransparency());
} else {
activateDynamicTransparency(univ, 0, settings.getEnableDynamicTransparency());
}
contentNode = new ItemGroupNode(pointGroup);
} else {
final ItemMesh mesh = createItemMesh(settings, points, sphereSize, transparency, alpha);
if (mesh == null) {
IJ.showStatus("");
return;
}
setColour(mesh, colors);
contentNode = new CustomMeshNode(mesh);
}
IJ.showStatus("Creating 3D content ...");
// Use custom content to support adding new switchable nodes
final CustomContent content = new CustomContent(name, !settings.getSupportDynamicTransparency());
final CustomContentInstant contentInstant = (CustomContentInstant) content.getCurrent();
contentInstant.setTransparency((float) settings.getTransparency());
contentInstant.setShaded(settings.getShaded());
contentInstant.showCoordinateSystem(UniverseSettings.showLocalCoordinateSystemsByDefault);
contentInstant.display(contentNode);
createHighlightColour(settings.getHighlightColour());
content.setUserData(data);
// Prevent relative rotation
content.setLocked(true);
// Set up the click selection node
data.createClickSelectionNode(contentInstant);
// Set up the results selection model
data.digest = PeakResultsDigest.waitForDigest(futureDigest, -1);
if (data.digest == null) {
IJ.error(TITLE, "Failed to identify repeat results set");
IJ.showStatus("");
return;
}
Triple<PeakResultTableModel, ListSelectionModel, PeakResultTableModelFrame> triplet = resultsTables.get(data.digest);
if (triplet == null) {
triplet = Triple.of(new PeakResultTableModel(results, false, // Note the settings do not matter until the table is set live
resultsTableSettings.get()), new DefaultListSelectionModel(), null);
triplet.getLeft().setCheckDuplicates(true);
resultsTables.put(data.digest, triplet);
}
// Preserve orientation on the content
final boolean auto = univ.getAutoAdjustView();
final Content oldContent = univ.getContent(name);
if (oldContent == null) {
univ.setAutoAdjustView(true);
} else {
univ.removeContent(name);
univ.setAutoAdjustView(false);
}
IJ.showStatus("Drawing 3D content ... ");
final StopWatch sw = StopWatch.createStarted();
final Future<Content> future = univ.addContentLater(content);
Content added = null;
for (; ; ) {
try {
// Wait for 1 second
for (int i = 0; i < 20; i++) {
Thread.sleep(50);
if (future.isDone()) {
// Only get the result when finished, so avoiding a blocking wait
added = future.get();
break;
}
}
if (added != null) {
break;
}
final long seconds = sw.getTime(TimeUnit.SECONDS);
if (seconds % 20 == 0) {
final ExtendedGenericDialog egd = new ExtendedGenericDialog(TITLE, null);
egd.addMessage("Current wait time is " + sw.toString());
egd.setOKLabel("Wait");
egd.showDialog();
if (egd.wasCanceled()) {
future.cancel(true);
break;
}
}
IJ.showStatus("Drawing 3D content ... " + seconds);
} catch (final InterruptedException ex) {
Thread.currentThread().interrupt();
} catch (final ExecutionException ex) {
break;
}
}
univ.setAutoAdjustView(auto);
// Initialise the selection model
if (added != null) {
data.addSelectionModel(triplet);
}
IJ.showStatus("");
}
use of uk.ac.sussex.gdsc.core.utils.LocalList in project GDSC-SMLM by aherbert.
the class TextFilePeakResults method sort.
@Override
protected void sort() throws IOException {
final LocalList<Result> results = new LocalList<>(size);
final StringBuilder header = new StringBuilder(2048);
final Path path = Paths.get(filename);
try (BufferedReader input = Files.newBufferedReader(path)) {
// Skip optional columns before the slice
final int skipCount = (isShowId() ? 1 : 0) + (isShowCategory() ? 1 : 0);
String line;
// Skip the header
while ((line = input.readLine()) != null) {
if (!line.isEmpty() && line.charAt(0) != '#') {
// This is the first record
results.add(new Result(line, skipCount));
break;
}
header.append(line).append(System.lineSeparator());
}
while ((line = input.readLine()) != null) {
results.add(new Result(line, skipCount));
}
}
// Sort by slice number
Collections.sort(results, (r1, r2) -> Integer.compare(r1.slice, r2.slice));
try (BufferedWriter output = Files.newBufferedWriter(path)) {
output.write(header.toString());
for (int i = 0; i < results.size(); i++) {
output.write(results.unsafeGet(i).line);
output.newLine();
}
}
}
use of uk.ac.sussex.gdsc.core.utils.LocalList in project GDSC-SMLM by aherbert.
the class MalkFilePeakResults method sort.
@Override
protected void sort() throws IOException {
final LocalList<Result> results = new LocalList<>(size);
final StringBuilder header = new StringBuilder();
final Path path = Paths.get(filename);
try (BufferedReader input = Files.newBufferedReader(path)) {
String line;
// Skip the header
while ((line = input.readLine()) != null) {
if (line.charAt(0) != '#') {
// This is the first record
results.add(new Result(line));
break;
}
header.append(line).append(System.lineSeparator());
}
while ((line = input.readLine()) != null) {
results.add(new Result(line));
}
}
Collections.sort(results, (r1, r2) -> Integer.compare(r1.slice, r2.slice));
try (BufferedWriter output = Files.newBufferedWriter(path)) {
output.write(header.toString());
for (int i = 0; i < results.size(); i++) {
output.write(results.unsafeGet(i).line);
output.newLine();
}
}
}
Aggregations