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

Download models #54

Merged
merged 19 commits into from
Sep 5, 2024
Merged

Download models #54

merged 19 commits into from
Sep 5, 2024

Conversation

alanocallaghan
Copy link
Collaborator

@alanocallaghan alanocallaghan commented Aug 28, 2024

Enable downloading models. Checks the most recent release for zip files and adds these to the model search box. Remote models are downloaded and unzipped on request into the user local directory.

Local models now go in: [my-model-directory]/local, while downloaded models go in [my-model-directory]/ directly.
Doesn't overwrite any existing files for the time being (in future it should check for content/checksums). Should show already-downloaded models as downloaded without needing to hit the download button to check.

Adds README popover to icon button

Resolve #46

@alanocallaghan

This comment was marked as outdated.

@alanocallaghan alanocallaghan marked this pull request as ready for review September 4, 2024 17:21
Copy link
Member

@petebankhead petebankhead left a comment

Choose a reason for hiding this comment

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

I wasn't able to get this working

  • I had an exception first because I didn't have the directory
  • When I click download, I get q.l.g.QuPathUncaughtExceptionHandler - Cannot invoke "qupath.ext.instanseg.core.InstanSegModel.getName()" because "model" is null... and if I choose a different model, the download option disappears.

I think some of our changes conflict - especially around pixel sizes (although I think I introduced an inconsistency when I switched to downsample with DetectionMeasurer and forgot to update the name...). It's important that we try to ensure a consistent downsample is used, and it is always calculated from the model spec... unless the user overrides it in a script.

From reading the code, it looks to me like it will always query the available models online. If that's right, it makes me uneasy; I feel the user should be explicitly requesting any check, and it should not happen automatically.

@@ -352,8 +466,9 @@ private void handleModelDirectory(String n) {
var path = Path.of(n);
if (Files.exists(path) && Files.isDirectory(path)) {
try {
watcher.register(path); // todo: unregister
addModelsFromPath(n, modelChoiceBox);
var localPath = path.resolve("local");
Copy link
Member

Choose a reason for hiding this comment

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

I get a java.nio.file.NoSuchFileException: here the first time I run it.

var instanSeg = InstanSeg.builder()
.model(model)
.imageData(imageData)
.device(deviceChoices.getSelectionModel().getSelectedItem())
.numOutputChannels(nucleiOnlyCheckBox.isSelected() ? 1 : 2)
.channels(channels.stream().map(ChannelSelectItem::getTransform).toList())
.tileDims(InstanSegPreferences.tileSizeProperty().get())
// .outputAnnotations()
.downsample(pixelSize.get().doubleValue() / (double) server.getPixelCalibration().getAveragedPixelSize())
Copy link
Member

Choose a reason for hiding this comment

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

This shouldn't be here. I've tried to remove setting the downsample explicitly - it results in scripts that don't work properly when applied to images with a different resolution.

I didn't remove downsample as an option entirely because it can be handy to adjust in a script, but routinely it shouldn't be set so that elsewhere the model spec can be queried - and a (possibly-rounded) downsample value used instead.

deviceChoices.getSelectionModel().getSelectedItem(),
nucleiOnlyCheckBox.isSelected() ? 1 : 2,
ChannelSelectItem.toConstructorString(channels),
InstanSegPreferences.tileSizeProperty().get(),
pixelSize.get().doubleValue() / (double) server.getPixelCalibration().getAveragedPixelSize(),
Copy link
Member

Choose a reason for hiding this comment

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

Not entirely where where we are in the code (checking on GitHub) but I don't think this should be here. See the use of getPreferredDownsample that I introduced to reduce inconsistencies, and help ensure scripts don't end up being locked to a single resolution by encoding a fixed downsample value.

@@ -83,15 +136,15 @@ private Number getPixelSizeY() {
* Otherwise, it is the value of whichever value is available - or null if neither is found.
Copy link
Member

Choose a reason for hiding this comment

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

Update javadocs if you want to switch to Optional.

* @return the pixel size in the X dimension.
*/
private Number getPixelSizeX() {
return getPixelSize().getOrDefault("x", null);
public Optional<Number> getPixelSizeX() {
Copy link
Member

Choose a reason for hiding this comment

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

I had made these private - I'm not sure why they are ever needed to be public? We can't handle resizing differently in x and y anyway, and introduced getPreferredDownsample as a method to consistently get the value we are most likely to need.

I'd rather these were private unless there's a good reason, since it increases the likelihood that we forget to use getPreferredDownsample (or getPreferredPixelSize).

@alanocallaghan
Copy link
Collaborator Author

When I click download, I get q.l.g.QuPathUncaughtExceptionHandler - Cannot invoke "qupath.ext.instanseg.core.InstanSegModel.getName()" because "model" is null... and if I choose a different model, the download option disappears.

was this with no model selected, or?

@alanocallaghan
Copy link
Collaborator Author

alanocallaghan commented Sep 4, 2024

From reading the code, it looks to me like it will always query the available models online. If that's right, it makes me uneasy; I feel the user should be explicitly requesting any check, and it should not happen automatically.

I was mostly copying the logic from wsinfer, albeit without saving the "zoo" json locally. Do realise this means that if you download models, then run the extension offline, you won't see any available models because we're only scanning the "local" directory for existing models, and the downloaded ones are identified from the GitHub curl query

Objection to me doing as with wsinfer and caching the JSON response?

I suspect the downsample stuff is all just failed merges.

@petebankhead
Copy link
Member

Not entirely sure I understand, but don't see an issue with caching the json.

What happens if models are updated, so that the local ones no longer match? Or do we assume that models are permanent and not updated...?

For reproducibility, not updating seems wise. But in the early days, I can imagine that might not happen.

@alanocallaghan
Copy link
Collaborator Author

What happens if models are updated, so that the local ones no longer match? Or do we assume that models are permanent and not updated...?

There's currently no versioning. New versions of a model would be skipped, because it just checks if the model exists on disk.

Questions then arise on how we handle versions: overwrite? Present all possible versions (distinguished by...?) etc. Similar headaches to WSInfer

@petebankhead
Copy link
Member

I think that's ok, the more important thing is not to update automatically.

alanocallaghan and others added 6 commits September 4, 2024 23:14
There were not checks to ensure that `InstanSegPreferences.modelDirectoryProperty().get()` didn't return null, and therefore lots of `Path.of` calls would fail if it was null.
Padding is currently 80 and we subtract 2 x padding from tile size to get the valid area. So 512 is a better default than 256, which has a tiny valid area.
@petebankhead
Copy link
Member

I was still having trouble with this, but I think they are mostly resolved - please check out my commits.

With this kind of change, testing with 'Edit → Reset preferences' is important to see how it will be with a new installation. This gave lots of errors because of unchecked calls to Path.of(null) when the model directory wasn't set.

I'll merge this now but plan to work more on it later this morning.

@petebankhead petebankhead merged commit 8e8d05b into main Sep 5, 2024
1 check passed
@petebankhead petebankhead deleted the download-models branch September 5, 2024 05:53
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.

Ensure directory watching works as expected
2 participants