Skip to content

shared windows paths are badly interpreted when opened on *nix #1786

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

Open
4 tasks done
carlocastoldi opened this issue Mar 5, 2025 · 9 comments · May be fixed by #1889
Open
4 tasks done

shared windows paths are badly interpreted when opened on *nix #1786

carlocastoldi opened this issue Mar 5, 2025 · 9 comments · May be fixed by #1889
Labels

Comments

@carlocastoldi
Copy link
Contributor

Before we begin...

Before submitting your bug report, please check the following:

  • I've definitely found a bug (it you're not sure, please use image.sc instead)
  • I've checked https://qupath.github.io for a new release that might already have fixed the issue
  • I've checked the Changelog to see if the bug has already been fixed in the next release
  • I've checked for existing GitHub issues describing the same problem

Bug report

Describe the bug

This bug arises only on *nix systems when opening a QuPath project that was last opened on Windows and that has images on a shared network.
On windows, shared resources path follow the following convention:

\\ServerComputerName\ShareName\Path\To\Image

When opening the project on linux, however, you are not prompted by QuPath that it can't find the associated images. Instead, you get an error when trying to opening an image:

java.io.FileNotFoundException
Unable to open file://v7ku1.techosp.it/ricerca/Lab%20Matteoli/Silva/projects/data/APP_PNS/Cohort%204/GABA_cfos/images_females/7728_new/7728_female_GABAcFos.czi: file:/v7ku1.techosp.it/ricerca/Lab%20Matteoli/Silva/projects/data/APP_PNS/Cohort%204/GABA_cfos/images_females/7728_new/7728_female_GABAcFos.czi (No such file or directory)
java.io.FileNotFoundException: file:/v7ku1.techosp.it/ricerca/Lab%20Matteoli/Silva/projects/data/APP_PNS/Cohort%204/GABA_cfos/images_females/7728_new/7728_female_GABAcFos.czi (No such file or directory)
	at java.base/java.io.RandomAccessFile.open0(Native Method)
	at java.base/java.io.RandomAccessFile.open(Unknown Source)
	at java.base/java.io.RandomAccessFile.<init>(Unknown Source)
	at java.base/java.io.RandomAccessFile.<init>(Unknown Source)
	at loci.common.NIOFileHandle.<init>(NIOFileHandle.java:130)
	at loci.common.NIOFileHandle.<init>(NIOFileHandle.java:151)
	at loci.common.NIOFileHandle.<init>(NIOFileHandle.java:165)
	at loci.common.Location.getHandle(Location.java:522)
	at loci.common.Location.getHandle(Location.java:462)
	at loci.common.Location.getHandle(Location.java:443)
	at loci.common.Location.getHandle(Location.java:426)
	at loci.common.Location.checkValidId(Location.java:551)
	at loci.formats.ImageReader.getReader(ImageReader.java:182)
	at loci.formats.ImageReader.setId(ImageReader.java:858)
	at qupath.lib.images.servers.bioformats.BioFormatsImageServer$ReaderPool.createReader(BioFormatsImageServer.java:1296)
	at qupath.lib.images.servers.bioformats.BioFormatsImageServer$ReaderPool.<init>(BioFormatsImageServer.java:1079)
	at qupath.lib.images.servers.bioformats.BioFormatsImageServer.<init>(BioFormatsImageServer.java:327)
	at qupath.lib.images.servers.bioformats.BioFormatsImageServer.<init>(BioFormatsImageServer.java:235)
	at qupath.lib.images.servers.bioformats.BioFormatsServerBuilder.buildServer(BioFormatsServerBuilder.java:55)
	at qupath.lib.images.servers.ImageServerBuilder$DefaultImageServerBuilder.buildOriginal(ImageServerBuilder.java:350)
	at qupath.lib.images.servers.ImageServerBuilder$AbstractServerBuilder.build(ImageServerBuilder.java:174)
	at qupath.lib.projects.DefaultProject$DefaultProjectImageEntry.readImageData(DefaultProject.java:693)
	at qupath.lib.gui.QuPathGUI.openImageEntry(QuPathGUI.java:1486)
	at qupath.lib.gui.panes.ProjectBrowser.lambda$new$5(ProjectBrowser.java:223)
	at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:86)
	at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:232)
	at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:189)
	at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
	at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
	at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
	at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
	at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
	at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
	at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
	at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
	at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
	at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
	at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
	at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
	at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
	at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
	at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
	at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
	at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
	at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
	at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
	at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
	at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
	at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
	at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:54)
	at javafx.event.Event.fireEvent(Event.java:198)
	at javafx.scene.Scene$ClickGenerator.postProcess(Scene.java:3684)
	at javafx.scene.Scene$MouseHandler.process(Scene.java:3989)
	at javafx.scene.Scene.processMouseEvent(Scene.java:1890)
	at javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2704)
	at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:411)
	at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:301)
	at java.base/java.security.AccessController.doPrivileged(Unknown Source)
	at com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleMouseEvent$2(GlassViewEventHandler.java:450)
	at com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:424)
	at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:449)
	at com.sun.glass.ui.View.handleMouseEvent(View.java:551)
	at com.sun.glass.ui.View.notifyMouse(View.java:937)
	at com.sun.glass.ui.gtk.GtkApplication._runLoop(Native Method)
	at com.sun.glass.ui.gtk.GtkApplication.lambda$runLoop$11(GtkApplication.java:316)
	at java.base/java.lang.Thread.run(Unknown Source)

and

java.io.IOException
Unable to build ImageServer for file://v7ku1.techosp.it/ricerca/Lab Matteoli/Silva/projects/data/APP_PNS/Cohort 4/GABA_cfos/images_females/7728_new/7728_female_GABAcFos.czi (args=[--series, 0]) with requested provider qupath.lib.images.servers.bioformats.BioFormatsServerBuilder
java.io.IOException: Unable to build ImageServer for file://v7ku1.techosp.it/ricerca/Lab Matteoli/Silva/projects/data/APP_PNS/Cohort 4/GABA_cfos/images_females/7728_new/7728_female_GABAcFos.czi (args=[--series, 0]) with requested provider qupath.lib.images.servers.bioformats.BioFormatsServerBuilder
	at qupath.lib.images.servers.ImageServerBuilder$DefaultImageServerBuilder.buildOriginal(ImageServerBuilder.java:369)
	at qupath.lib.images.servers.ImageServerBuilder$AbstractServerBuilder.build(ImageServerBuilder.java:174)
	at qupath.lib.projects.DefaultProject$DefaultProjectImageEntry.readImageData(DefaultProject.java:693)
	at qupath.lib.gui.QuPathGUI.openImageEntry(QuPathGUI.java:1486)
	at qupath.lib.gui.panes.ProjectBrowser.lambda$new$5(ProjectBrowser.java:223)
	at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:86)
	at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:232)
	at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:189)
	at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
	at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
	at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
	at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
	at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
	at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
	at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
	at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
	at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
	at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
	at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
	at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
	at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
	at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
	at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
	at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
	at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
	at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
	at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
	at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
	at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
	at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
	at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:54)
	at javafx.event.Event.fireEvent(Event.java:198)
	at javafx.scene.Scene$ClickGenerator.postProcess(Scene.java:3684)
	at javafx.scene.Scene$MouseHandler.process(Scene.java:3989)
	at javafx.scene.Scene.processMouseEvent(Scene.java:1890)
	at javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2704)
	at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:411)
	at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:301)
	at java.base/java.security.AccessController.doPrivileged(Unknown Source)
	at com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleMouseEvent$2(GlassViewEventHandler.java:450)
	at com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:424)
	at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:449)
	at com.sun.glass.ui.View.handleMouseEvent(View.java:551)
	at com.sun.glass.ui.View.notifyMouse(View.java:937)
	at com.sun.glass.ui.gtk.GtkApplication._runLoop(Native Method)
	at com.sun.glass.ui.gtk.GtkApplication.lambda$runLoop$11(GtkApplication.java:316)
	at java.base/java.lang.Thread.run(Unknown Source)
This, i suppose, happens due to how paths and escapes are handled differently between systems.

Interestingly, project uri is well escaped from Windows (i.e. it starts with file:////). It's the image server uris that aren't (i.e. they start with file://) in .qpproj files.

Workaround

Open the .qpproj file and rename all occurrences of file://ServerComputerName to anything else (e.g. file:////ServerComputerName)

To Repro duce

Steps to reproduce the behavior:

  1. Create a QP project with images on a SMB server from Windows
  2. Share it to a Linux system
  3. Open the project from Windows
  4. Open any image
  5. See error

Expected behavior

I'd expect QP to warn that it can't find the images specified in the project, and later it suggests to specify a path where to search for them.

Desktop (please complete the following information):

  • OS: Windows 10/11 + Ubuntu 24.0/Debian 12
  • QuPath Version: 0.5.1 and 0.6.0rc3
@alanocallaghan
Copy link
Contributor

I couldn't reproduce this on my local network.

I followed the following steps:

  1. Create samba share
  2. Mount from windows (11)
  3. Add image and create project, create annotations/detections
  4. Save project
  5. Open project on QuPath on Linux
  6. Standard image not found dialog appears, with automated suggestion showing the correct file path.

In fact for me it's the other way around; projects created from windows behave fine on Linux, but Linux projects present with the behaviour you described when opened on windows.

The project URI is "file:/run/user/1000/gvfs/smb-share:server\u003d192.168.0.14,share\u003dsambashare/qpproj/project.qpproj", and the server URI is "file:///run/user/1000/gvfs/smb-share:server\u003d192.168.0.14,share\u003dsambashare/LuCa-7color_%5B13860,52919%5D_1x1component_data.tif"

In contrast, Windows projects have file paths such as "file:/Z:/LuCa-7color_%5B13860,52919%5D_1x1component_data.tif"

@carlocastoldi
Copy link
Contributor Author

I'm a bit short on time, so i apologise for the short comment.

However i feel like for you Windows->Linux worked because you mounted the SMB address to a local drive (i.e. Z:/). Could you please try choosing your image paths using the Shared Network window in the file explorer?
Ultimately the path should start with two slashes+the hostname/address of the server.

@alanocallaghan
Copy link
Contributor

please try choosing your image paths using the Shared Network window in the file explorer?

I don't follow, I do not have a "Shared Network window in the file explorer"

@carlocastoldi
Copy link
Contributor Author

Oh, it should be something like this:

@alanocallaghan
Copy link
Contributor

alanocallaghan commented Mar 7, 2025 via email

@carlocastoldi
Copy link
Contributor Author

I am afraid i can't as I've been using my institute's services, and I'm not an expert when it comes to windows.

Best i can do is study and try find guides to replicate this :/

@alanocallaghan
Copy link
Contributor

Right, well I'll see if I can debug using the share I created, but if there's a way around it (mounting locally) then I'd suggest using that for the time being

@petebankhead
Copy link
Member

Note that if the images in the project aren’t changing, you can fix the paths once and have both

  • project-windows.qpproj
  • project-nix.qpproj

within the same directory, and just drag the correct one on to QuPath to open it. If you drag the entire project directory onto QuPath, then you will see a prompt asking you which to use.

Both projects will work on the same data files, but of course anything stored only in the project file won’t be synced (e.g. if images are added or removed).

There is described here in the docs, where it is proposed as a way to handle the use of shared drives. Even though this situation sounds a little different, I’d still suggest it as a workaround as we’re quite limited in the setups we can test against.

@carlocastoldi
Copy link
Contributor Author

Note that if the images in the project aren’t changing, you can fix the paths once and have both

  • project-windows.qpproj
  • project-nix.qpproj

Oh yes, thank you for reminding me!

However the assumption that images in the project aren't changing is often valid, but not always, i am afraid...
I'll make sure to employ this workaround, for now, tho!

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

Successfully merging a pull request may close this issue.

3 participants