Skip to content

Commit

Permalink
Merge pull request #504 from cmhulbert/feat/smoothAction
Browse files Browse the repository at this point in the history
Feat/smooth action
  • Loading branch information
cmhulbert authored Sep 1, 2023
2 parents b6eac3d + 606731c commit 84e364b
Show file tree
Hide file tree
Showing 19 changed files with 314 additions and 395 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,6 @@
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static org.janelia.saalfeldlab.util.n5.N5Helpers.getReaderOrGetWriterIfExistsAndWritable;

@Command(name = "Paintera", showDefaultValues = true, resourceBundle = "org.janelia.saalfeldlab.paintera.PainteraCommandLineArgs", usageHelpWidth = 120,
parameterListHeading = "%n@|bold,underline Parameters|@:%n",
optionListHeading = "%n@|bold,underline Options|@:%n")
Expand Down Expand Up @@ -649,7 +647,7 @@ private void addToViewer(final PainteraBaseView viewer, final Supplier<String> p
for (final String container : containers) {
LOG.debug("Adding datasets for container {}", container);

N5Reader n5Container = getReaderOrGetWriterIfExistsAndWritable(container);
N5Reader n5Container = Paintera.getN5Factory().openWriterElseOpenReader(container);

final Predicate<String> datasetFilter = options.useDataset();
final ExecutorService es = getDiscoveryExecutorService();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,7 @@
import org.janelia.saalfeldlab.labels.blocks.LabelBlockLookupKey;
import org.janelia.saalfeldlab.labels.blocks.n5.IsRelativeToContainer;
import org.janelia.saalfeldlab.labels.downsample.WinnerTakesAll;
import org.janelia.saalfeldlab.n5.ByteArrayDataBlock;
import org.janelia.saalfeldlab.n5.DataBlock;
import org.janelia.saalfeldlab.n5.DatasetAttributes;
import org.janelia.saalfeldlab.n5.LongArrayDataBlock;
import org.janelia.saalfeldlab.n5.N5Reader;
import org.janelia.saalfeldlab.n5.N5Writer;
import org.janelia.saalfeldlab.n5.*;
import org.janelia.saalfeldlab.n5.imglib2.N5LabelMultisets;
import org.janelia.saalfeldlab.n5.imglib2.N5Utils;
import org.janelia.saalfeldlab.paintera.data.mask.persist.PersistCanvas;
Expand All @@ -57,7 +52,6 @@

import java.io.IOException;
import java.lang.invoke.MethodHandles;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
Expand Down Expand Up @@ -136,7 +130,8 @@ public void updateLabelBlockLookup(final List<TLongObjectMap<BlockDiff>> blockDi

LOG.debug("Found scale datasets {}", (Object)scaleUniqueLabels);
for (int level = 0; level < scaleUniqueLabels.length; ++level) {
final DatasetSpec datasetUniqueLabels = DatasetSpec.of(n5Writer, Paths.get(uniqueLabelsPath, scaleUniqueLabels[level]).toString());
final String uniqueLabelScalePath = N5URI.normalizeGroupPath(uniqueLabelsPath + n5Writer.getGroupSeparator() + scaleUniqueLabels[level]);
final DatasetSpec datasetUniqueLabels = DatasetSpec.of(n5Writer, uniqueLabelScalePath);
final TLongObjectMap<TLongHashSet> removedById = new TLongObjectHashMap<>();
final TLongObjectMap<TLongHashSet> addedById = new TLongObjectHashMap<>();
final TLongObjectMap<BlockDiff> blockDiffs = blockDiffsByLevel.get(level);
Expand Down Expand Up @@ -262,8 +257,8 @@ public List<TLongObjectMap<BlockDiff>> persistCanvas(final CachedCellImg<Unsigne

final TLongObjectHashMap<BlockDiff> blockDiffsAt = new TLongObjectHashMap<>();
blockDiffs.add(blockDiffsAt);
final DatasetSpec targetDataset = DatasetSpec.of(n5Writer, Paths.get(dataset, scaleDatasets[level]).toString());
final DatasetSpec previousDataset = DatasetSpec.of(n5Writer, Paths.get(dataset, scaleDatasets[level - 1]).toString());
final DatasetSpec targetDataset = DatasetSpec.of(n5Writer, N5URI.normalizeGroupPath(dataset + n5Writer.getGroupSeparator() + scaleDatasets[level]));
final DatasetSpec previousDataset = DatasetSpec.of(n5Writer, N5URI.normalizeGroupPath(dataset + n5Writer.getGroupSeparator() + scaleDatasets[level - 1]));

final double[] targetDownsamplingFactors = N5Helpers.getDownsamplingFactors(n5Writer, targetDataset.dataset);
final double[] previousDownsamplingFactors = N5Helpers.getDownsamplingFactors(n5Writer, previousDataset.dataset);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -406,10 +406,11 @@ public BooleanProperty discoveryIsActive() {

public FragmentSegmentAssignmentState assignments() throws IOException {

if (getContainer().isReadOnly())
throw new N5ReadOnlyException();

final var writer = getContainer().getWriter();

if (writer == null) {
throw new N5ReadOnlyException();
}
return N5Helpers.assignments(writer, getDatasetPath());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,7 @@
import javafx.beans.value.ObservableValue;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.control.Alert;
import javafx.scene.control.MenuButton;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.scene.control.Tooltip;
import javafx.scene.input.KeyCode;
Expand All @@ -25,12 +23,10 @@
import org.janelia.saalfeldlab.fx.Tasks;
import org.janelia.saalfeldlab.fx.ui.ObjectField;
import org.janelia.saalfeldlab.n5.N5Reader;
import org.janelia.saalfeldlab.n5.N5Writer;
import org.janelia.saalfeldlab.n5.hdf5.N5HDF5Reader;
import org.janelia.saalfeldlab.paintera.Paintera;
import org.janelia.saalfeldlab.paintera.PainteraConfigYaml;
import org.janelia.saalfeldlab.paintera.state.metadata.N5ContainerState;
import org.janelia.saalfeldlab.paintera.ui.PainteraAlerts;
import org.janelia.saalfeldlab.util.PainteraCache;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
Expand Down Expand Up @@ -162,37 +158,6 @@ private Optional<N5Reader> openN5Reader(final String url) {
return Optional.empty();
}

/**
* Open {@code url} as an N5Writer if possible, else empty.
*
* @param url location of the container we wish to open as an N5Writer.
* @return N5Writer of {@code url} if valid N5 container which we can write to; else empty
*/
private Optional<N5Writer> openN5Writer(final String url) {

try {
final var writer = Paintera.getN5Factory().openWriter(url);
LOG.debug("{} was opened as an N5Writer.", url);
return Optional.of(writer);
} catch (Exception e) {
LOG.debug("{} cannot be opened as an N5Writer.", url);
}
return Optional.empty();
}

private static boolean isN5Container(final String pathToDirectory) {

try {
final var reader = Paintera.getN5Factory().openReader(pathToDirectory);
boolean openableAsN5 = reader != null;
if (reader instanceof N5HDF5Reader)
reader.close();
return openableAsN5;
} catch (Exception e) {
return false;
}
}

private void updateFromFileChooser(final File initialDirectory, final Window owner) {

final FileChooser fileChooser = new FileChooser();
Expand All @@ -214,8 +179,7 @@ private void updateFromDirectoryChooser(final File initialDirectory, final Windo
.ifPresent(directoryChooser::setInitialDirectory);
Optional.ofNullable(directoryChooser.showDialog(ownerWindow)).ifPresent(updatedRoot -> {
LOG.debug("Updating root to {} (was {})", updatedRoot, selectionProperty.get());

if (fileOpenableAsN5(updatedRoot)) {
if (Paintera.getN5Factory().openReaderOrNull(updatedRoot.getAbsolutePath()) != null) {
// set null first to make sure that selectionProperty will be invalidated even if directory is the same
String updatedAbsPath = updatedRoot.getAbsolutePath();
if (updatedAbsPath.equals(selectionProperty.get())) {
Expand All @@ -224,26 +188,6 @@ private void updateFromDirectoryChooser(final File initialDirectory, final Windo
selectionProperty.set(updatedAbsPath);
}
});

}

private boolean fileOpenableAsN5(File updatedRoot) {

if (updatedRoot == null) {
/* They probably just canceled out of browse; just silently return false; */
return false;
} else if (!isN5Container(updatedRoot.getAbsolutePath())) {
final Alert alert = PainteraAlerts.alert(Alert.AlertType.INFORMATION);
alert.setHeaderText("Selected path cannot be opened as an N5 container.");
final TextArea ta = new TextArea("The selected path is not a valid N5 container\n\n" + updatedRoot.getAbsolutePath() + "\n\n" +
"A valid N5 container is a directory that contains a file attributes.json with a key \"n5\"."); //FIXME meta need a more accurate message
ta.setEditable(false);
ta.setWrapText(true);
alert.getDialogPane().setContent(ta);
alert.show();
return false;
}
return true;
}

private void selectionChanged(ObservableValue<? extends String> obs, String oldSelection, String newSelection) {
Expand All @@ -258,44 +202,12 @@ private void selectionChanged(ObservableValue<? extends String> obs, String oldS
invoke(() -> this.isOpeningContainer.set(true));
final var newContainerState = Optional.ofNullable(n5ContainerStateCache.get(newSelection)).orElseGet(() -> {

/* This particular shortcut is if the N5Reader/Writer is cached, but from
* deserialization, not from open source */
N5Reader initialReader = Paintera.getN5Factory().getFromCache(newSelection);
if (initialReader != null) return new N5ContainerState(initialReader);

/* Ok we don't want to do the writer first, even though it means we need to create a separate writer in the case that it can have both.
* This is because if the path provided doesn't currently contain a writer, but it has permissions to create a writer, it will do so.
* This means that if there is no N5 container, it will create one.
*
* In this case, we only want to create a writer if there is already an N5 container. To check, we create a reader first, and see if it
* exists. */
final var optReader = openN5Reader(newSelection);
if (optReader.isEmpty()) {
return null;
} else {
initialReader = optReader.get();
var container = Paintera.getN5Factory().openReaderOrNull(newSelection);
if (container == null) return null;
if (container instanceof N5HDF5Reader) {
container.close();
container = Paintera.getN5Factory().openWriterElseOpenReader(newSelection);
}

/* Another wrinkle though; For HDF5, you can't open a reader and a writer at the same time, even with permission. So
* Now that we know the container actually exists, we need to check if it's HDF5. If it is, we need to close the reader,
* Then try to open a writer. If that isn't possible, we need to re-open a reader. */

final N5Reader container;
if (initialReader instanceof N5HDF5Reader) { /* Check if we are an HDF5 container*/
initialReader.close();
final var optWriter = openN5Writer(newSelection);
if (optWriter.isEmpty()) { /* if we don't have a writer, re-open the reader */
container = openN5Reader(newSelection).orElseThrow(() ->
new RuntimeException("HDF5 container at " + newSelection
+ " was initially opened as a reader, but failed after attempt to open as a writer")
);
} else { /* if we have the writer, use it as a reader also */
container = optWriter.get();
}
} else {
container = openN5Writer(newSelection).map(N5Reader.class::cast).orElse(initialReader);
}

return new N5ContainerState(container);
});
if (newContainerState == null)
Expand Down
10 changes: 5 additions & 5 deletions src/main/java/org/janelia/saalfeldlab/util/n5/N5Data.java
Original file line number Diff line number Diff line change
Expand Up @@ -380,7 +380,7 @@ ImagesWithTransform<T, V>[] openRawMultiscale(

final double[] initialDonwsamplingFactors = N5Helpers.getDownsamplingFactors(
reader,
Paths.get(dataset, scaleDatasets[0]).toString()
N5URI.normalizeGroupPath(dataset + reader.getGroupSeparator() + scaleDatasets[0])
);
LOG.debug("Initial transform={}", transform);
final ExecutorService es = Executors.newFixedThreadPool(
Expand All @@ -393,7 +393,7 @@ ImagesWithTransform<T, V>[] openRawMultiscale(
final int fScale = scale;
futures.add(es.submit(ThrowingSupplier.unchecked(() -> {
LOG.debug("Populating scale level {}", fScale);
final String scaleDataset = Paths.get(dataset, scaleDatasets[fScale]).toString();
final String scaleDataset = N5URI.normalizeGroupPath(dataset + reader.getGroupSeparator() + scaleDatasets[fScale]);
imagesWithInvalidate[fScale] = openRaw(reader, scaleDataset, transform.copy(), queue, priority);
final double[] downsamplingFactors = N5Helpers.getDownsamplingFactors(reader, scaleDataset);
LOG.debug("Read downsampling factors: {}", Arrays.toString(downsamplingFactors));
Expand Down Expand Up @@ -685,7 +685,7 @@ public static ImagesWithTransform<LabelMultisetType, VolatileLabelMultisetType>[

final double[] initialDonwsamplingFactors = N5Helpers.getDownsamplingFactors(
reader,
Paths.get(dataset, scaleDatasets[0]).toString());
N5URI.normalizeGroupPath(dataset + reader.getGroupSeparator() + scaleDatasets[0]));
final ExecutorService es = Executors.newFixedThreadPool(
scaleDatasets.length,
new NamedThreadFactory("populate-mipmap-scales-%d", true));
Expand All @@ -695,7 +695,7 @@ public static ImagesWithTransform<LabelMultisetType, VolatileLabelMultisetType>[
final int fScale = scale;
futures.add(es.submit(ThrowingSupplier.unchecked(() -> {
LOG.debug("Populating scale level {}", fScale);
final String scaleDataset = Paths.get(dataset, scaleDatasets[fScale]).toString();
final String scaleDataset = N5URI.normalizeGroupPath(dataset + reader.getGroupSeparator() + scaleDatasets[fScale]);
imagesWithInvalidate[fScale] = openLabelMultiset(reader, scaleDataset, transform.copy(), queue, priority);
final double[] downsamplingFactors = N5Helpers.getDownsamplingFactors(reader, scaleDataset);
LOG.debug("Read downsampling factors: {}", Arrays.toString(downsamplingFactors));
Expand Down Expand Up @@ -795,7 +795,7 @@ public static void createEmptyLabelDataset(

final Map<String, String> pd = new HashMap<>();
pd.put("type", "label");
final N5Writer n5 = Paintera.getN5Factory().openWriter(container);
final N5Writer n5 = Paintera.getN5Factory().createWriter(container);
final String uniqueLabelsGroup = String.format("%s/unique-labels", group);

if (!ignoreExisiting && n5.datasetExists(group))
Expand Down

This file was deleted.

Loading

0 comments on commit 84e364b

Please sign in to comment.