Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

discoverable axes index lookup #14

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open

discoverable axes index lookup #14

wants to merge 6 commits into from

Conversation

axtimwalde
Copy link
Contributor

  • add discoverable axes index lookup method as proposed by @d-v-b
  • rename N5Utils to N5 and deprecate N5Utils

@axtimwalde
Copy link
Contributor Author

@hanslovsky @igorpisarev, I mainly want you to familiarize with this before making it public so we can start using it immediately. Of course, if you find any shortcomings, please let me know. Thanks!

├── ...
```
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't really like that .axes is in the root of the container. This makes datasets less portable (i.e. I can't just copy the dataset itself but I will have to remember to also copy the appropriate dataset in .axes. Also, what if a dataset with the same name already exists in .axes of the target container?

We could also store .axes inside the actual dataset, e.g.

├── "dataset"
│   ├── "attributes.json"
│   ├── ".axes"
│   │   ├── "attributes.json"

That would make datasets more portable and you would not need any global container information to copy a dataset.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

then we cannot use the dataset loader to resolve the ordering because there cannot be a dataset in a dataset (e.g. in HDF5). I agree about it making portability harder which is only an issue if this feature is used which it currently isn't.

```
-1 0 -> -1 0 1 -1
1 -1
```
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a more detailed specification of what

-1  0
 1 -1

and

-1 0 1 -1

mean? I have a hard time understanding how they are generated.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking at the source code helps a lot (thanks @igorpisarev for pointing out the correct names), so maybe doc/axes.md could be more specific about what exactly is happening to create tensors like

-1  0
 1 -1

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree but currenty have no better idea. Will work on it.


The ImgLib2 bindings offer API methods to create and use such lookups. Naturally, the mapping is defined as coming from ImgLib2 F-order:

```java
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I could not find createAxes or any of the readVectorAttribute/writeVectorAttribute methods in n5-imglib2. Are they supposed to be part of n5-imglib2 or do they live in n5?

$ ag 'createAxes'
doc/axes.md
40:createAxes(
$ ag '(read|write).*Vect'
doc/axes.md
44:readDoubleVectorAttribute(
49:writeDoubleVectorAttribute(
55:readLongVectorAttribute(
60:writeLongVectorAttribute(

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems that the actual naming is a bit different, and they are called setAxes(), getAxes(), getDoubleVector(), setVector() in the code

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @igorpisarev

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Point taken.


public class N5Test {

static private String testDirPath = System.getProperty("user.home") + "/tmp/n5-imglib2-test";
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not simply use Files.createTempDirectory?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point, Tobias had a fix for that earlier and I will find out where that was and adjust.

private static final String EMPTY_DATASET = "/test/group/empty-dataset";

private static final int EMPTY_BLOCK_VALUE = 123;

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Order of keywords is inconsistent: static private vs private static. I suggest we follow this order

public protected private static final transient volatile

as is the recommendation of the Java docs:

If two or more (distinct) field modifiers appear in a field declaration, it is customary, though not required, that they appear in the order consistent with that shown above in the production for FieldModifier.

Similarly, for method modifiers and class modifiers

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree, I also want to change the formatter to saalfeldlab instead of imglib2, will do in a separate commit.

@igorpisarev
Copy link
Contributor

I understand the way how n5-imglib2 permutes the vectors back and forth, but how would for example N5 HDF5 and Python N5 API interoperate with it? Do they need to account for their inverse access order (with respect to n5-imglib2)? Such as saving all vector attributes with the axes lookup [2,1,0], and applying the inverse permutation when reading them on top of the stored lookup.

Also, my understanding is that the axes lookup is not particularly imglib2-specific and can be also supported by other N5 implementations later down the road (Python, Rust). Would it make sense then to move the axes lookup support into the main N5 repository?

Comment on lines -2 to +3
* Copyright (c) 2017-2018, Stephan Saalfeld, Philipp Hanslovsky, Igor Pisarev
* Copyright (c) 2017-2019, Stephan Saalfeld, Philipp Hanslovsky, Igor Pisarev
* John Bogovic
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we're deprecating N5Utils, this file probably needs to be marked as deprecated as well

for (int s = 0; s < numScales; ++s) {
final String datasetName = group + "/s" + s;
final long[] dimensions = n5.getAttribute(datasetName, "dimensions", long[].class);
final long[] downsamplingFactors = n5.getAttribute(datasetName, "downsamplingFactors", long[].class);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to try to read downsamplingFactors as a vector attribute here? (and similarly in other places, it seems that there are more vector-like attributes in N5DisplacementField)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. This can come in later as we start using the feature more.

@igorpisarev
Copy link
Contributor

Another a bit confusing thing to me about interoperability: do we always assume that the essential attributes dimensions and blockSize are always stored in F-order, such as [x,y,z]? Since they're basically vector attributes too, I would expect them to be written and read via the same vector attribute API that supports axes lookup.

@hanslovsky
Copy link
Collaborator

I think one way around the issue of axes stored in /.axes vs /path/to/dataset/.axes could be resolved by creating a method that simple creates an axes dataset with an arbitrary name. This method could then also be used to store the axes in /.axes. In other words, n5-imglib2 would only be concerned with storing axes as a dataset but would not impose a convention at all of where these axes should be located.

@axtimwalde
Copy link
Contributor Author

Python, C++ or Rust can find out by loading the axes volume, that 's the whole point of the exercise.
dimensions and blockSize are API attributes and are F-order by spec.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants