Skip to content

Add copy&paste of BDV state as JSON strings #205

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
wants to merge 8 commits into
base: master
Choose a base branch
from
Open

Add copy&paste of BDV state as JSON strings #205

wants to merge 8 commits into from

Conversation

tpietzsch
Copy link
Member

The JSON "link" includes viewer transform, color and intensity, visibility, and display mode settings.

Additionally, the link also includes ResourceSpecs for re-creating Sources (or matching existing sources) if they are registered with the new ResourceManager. (This is already implemented for SpimData sources in this PR).

When copying and pasting links, it is not clear what the user wants:

  • Copy&paste everything?
  • Copy&paste only the current transformation, but leave the color settings untouched?
  • etc...

The approach to this is to copy as much information as possible, and allow the user to configure what to use when pasting.
This can be configured in the Preferences dialog and is saved to a settings YAML file:
Screenshot 2025-03-25 at 13 30 57

In case the user often wants to change the pasting behaviour, this configuration page can also be added to the side panel.
Screenshot 2025-03-25 at 13 31 35

Default shortcuts for copying and pasting are command/ctrl-C and command/ctrl-V, obviously...
Screenshot 2025-03-25 at 13 32 02

Typed<T> instances of any T with a @JsonIo-annotated adapter are
serialized as json objects with a "type" attribute with the value of the
JsonIo.type() annotation, and an "obj" attribute, which is serialized
using the annotated adapter. For deserialization, the correct adapter is
looked up via the "type" attribute.
@imagesc-bot
Copy link

This pull request has been mentioned on Image.sc Forum. There might be relevant details there:

https://forum.image.sc/t/fiji-friends-weekly-dev-update-thread/103718/80

@StephanPreibisch
Copy link
Member

StephanPreibisch commented Apr 5, 2025

Hi @tpietzsch, sorry, I get two errors when using this pull request in bigstitcher, and it does not seem to work (I assumed copy&paste is somehow obvious, I couldn't find really any hints of it in the GUI)

1) it's of course not there, not sure if it has any consequences:

java.io.FileNotFoundException: /Users/preibischs/Library/Application Support/sc.fiji.bigdataviewer/linksettings.yaml (No such file or directory)
	at java.io.FileInputStream.open0(Native Method)
	at java.io.FileInputStream.open(FileInputStream.java:195)
	at java.io.FileInputStream.<init>(FileInputStream.java:138)
	at java.io.FileInputStream.<init>(FileInputStream.java:93)
	at java.io.FileReader.<init>(FileReader.java:58)
	at bdv.ui.links.LinkSettingsIO.load(LinkSettingsIO.java:64)
	at bdv.ui.links.LinkSettingsManager.load(LinkSettingsManager.java:79)
	at bdv.ui.links.LinkSettingsManager.load(LinkSettingsManager.java:72)
	at bdv.ui.links.LinkSettingsManager.<init>(LinkSettingsManager.java:62)
	at bdv.BigDataViewer.<init>(BigDataViewer.java:435)
	at bdv.BigDataViewer.<init>(BigDataViewer.java:393)
	at bdv.BigDataViewer.open(BigDataViewer.java:629)
	at net.preibisch.mvrecon.fiji.spimdata.explorer.popup.BDVPopup.createBDV(BDVPopup.java:336)
	at net.preibisch.mvrecon.fiji.spimdata.explorer.ViewSetupExplorerPanel.<init>(ViewSetupExplorerPanel.java:173)
	at net.preibisch.mvrecon.fiji.spimdata.explorer.ViewSetupExplorer.<init>(ViewSetupExplorer.java:47)
	at net.preibisch.mvrecon.fiji.plugin.Data_Explorer.run(Data_Explorer.java:77)
	at net.preibisch.mvrecon.fiji.plugin.Data_Explorer.main(Data_Explorer.java:117)

2) this one goes into an infinite loop (when pressing Apple+c):

Exception in thread "AWT-EventQueue-0" java.lang.StackOverflowError
	at sun.reflect.UnsafeFieldAccessorImpl.ensureObj(UnsafeFieldAccessorImpl.java:57)
	at sun.reflect.UnsafeDoubleFieldAccessorImpl.getDouble(UnsafeDoubleFieldAccessorImpl.java:68)
	at sun.reflect.UnsafeDoubleFieldAccessorImpl.get(UnsafeDoubleFieldAccessorImpl.java:36)
	at java.lang.reflect.Field.get(Field.java:393)
	at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:187)
	at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:368)
	at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:70)
	at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:196)
	at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:368)
	at com.google.gson.Gson$FutureTypeAdapter.write(Gson.java:1371)
	at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:70)
	at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:196)
	at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:368)
	at com.google.gson.Gson$FutureTypeAdapter.write(Gson.java:1371)
	at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:70)
	at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:196)
	at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:368)
	at com.google.gson.Gson$FutureTypeAdapter.write(Gson.java:1371)
	at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:70)
	at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:196)
	at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:368)
	at com.google.gson.Gson$FutureTypeAdapter.write(Gson.java:1371)
	at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:70)
	at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:196)
	at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:368)
	at com.google.gson.Gson$FutureTypeAdapter.write(Gson.java:1371)

@tpietzsch
Copy link
Member Author

tpietzsch commented Apr 7, 2025

@StephanPreibisch The first exception is expected and not a problem.

The second one, I have not seen, but @bogovicj has the same.
The JsonAdapters are annotated and discovered using scijava annotations. Maybe something is going wrong there? Could you check when you build bigdataviewer-core whether you have an annotation index file that looks like like this:

pietzsch@mycroft:~/workspace/bigdataviewer/bigdataviewer-core (link*)$ cat target/classes/META-INF/json/bdv.tools.JsonUtils\$JsonIo
{"class":"bdv.img.remote.AffineTransform3DJsonSerializer","values":{"jsonType":"AffineTransform3D.Anchor","type":"net.imglib2.realtransform.AffineTransform3D"}}
{"class":"bdv.tools.JsonUtils$Typed$JsonAdapter","values":{"jsonType":"JsonUtils.Typed","type":"bdv.tools.JsonUtils$Typed"}}
{"class":"bdv.tools.JsonUtils$TypedList$JsonAdapter","values":{"jsonType":"TypedList","type":"bdv.tools.JsonUtils$TypedList"}}
{"class":"bdv.tools.links.JsonAdapters$AnchorAdapter","values":{"jsonType":"BdvPropertiesV0.Anchor","type":"bdv.tools.links.BdvPropertiesV0$Anchor"}}
{"class":"bdv.tools.links.JsonAdapters$SourceConverterConfigAdapter","values":{"jsonType":"BdvProperiesV0.SourceConverterConfig","type":"bdv.tools.links.BdvPropertiesV0$SourceConverterConfig"}}
{"class":"bdv.tools.links.JsonAdapters$DisplayModeAdapter","values":{"jsonType":"DisplayMode","type":"bdv.viewer.DisplayMode"}}
{"class":"bdv.tools.links.JsonAdapters$InterpolationAdapter","values":{"jsonType":"Interpolation","type":"bdv.viewer.Interpolation"}}
{"class":"bdv.tools.links.Links$VersionAndProperties$Adapter","values":{"jsonType":"VersionAndProperties","type":"bdv.tools.links.Links$VersionAndProperties"}}
{"class":"bdv.tools.links.resource.SpimDataMinimalFileResource$SpecAdapter","values":{"jsonType":"SpimDataMinimalFileResource.Spec","type":"bdv.tools.links.resource.SpimDataMinimalFileResource$Spec"}}
{"class":"bdv.tools.links.resource.SpimDataMinimalFileResource$ConfigAdapter","values":{"jsonType":"SpimDataMinimalFileResource.Config","type":"bdv.tools.links.resource.SpimDataMinimalFileResource$Config"}}
{"class":"bdv.tools.links.resource.SpimDataSetupSourceResource$JsonAdapter","values":{"jsonType":"SpimDataSetupSourceResource.Spec","type":"bdv.tools.links.resource.SpimDataSetupSourceResource$Spec"}}
{"class":"bdv.tools.links.resource.SpimDataSetupSourceResource$ConfigAdapter","values":{"jsonType":"SpimDataSetupSourceResource.Config","type":"bdv.tools.links.resource.SpimDataSetupSourceResource$Config"}}
{"class":"bdv.tools.links.resource.TransformedSourceResource$SpecAdapter","values":{"jsonType":"TransformedSourceResource.Spec","type":"bdv.tools.links.resource.TransformedSourceResource$Spec"}}
{"class":"bdv.tools.links.resource.TransformedSourceResource$ConfigAdapter","values":{"jsonType":"TransformedSourceResource.Config","type":"bdv.tools.links.resource.TransformedSourceResource$Config"}}
{"class":"bdv.tools.links.resource.UnknownResource$SpecAdapter","values":{"jsonType":"UnknownResource.Spec","type":"bdv.tools.links.resource.UnknownResource$Spec"}}
{"class":"bdv.tools.links.resource.UnknownResource$ConfigAdapter","values":{"jsonType":"UnknownResource.Config","type":"bdv.tools.links.resource.UnknownResource$Config"}}%

If you don't have it, could you try to mvn clean install and see whether it is produced?
Which OS are you on? Maybe the nested JsonUtils.JsonIo annotation interface and resulting filename
bdv.tools.JsonUtils\$JsonIo is a problem?

@tischi
Copy link
Contributor

tischi commented May 2, 2025

Hi @tpietzsch,

I also tried and I am getting some other error:

Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
	at bdv.tools.links.BdvPropertiesV0.getSourceConverterConfigs(BdvPropertiesV0.java:120)
	at bdv.tools.links.BdvPropertiesV0.<init>(BdvPropertiesV0.java:94)
	at bdv.tools.links.Links.copyV0(Links.java:89)
	at bdv.tools.links.Links.copyJson(Links.java:49)
	at bdv.tools.links.LinkActions.copyViewerState(LinkActions.java:84)
	at bdv.tools.links.LinkActions.lambda$install$0(LinkActions.java:132)
	at org.scijava.ui.behaviour.util.RunnableAction.actionPerformed(RunnableAction.java:47)
	at javax.swing.SwingUtilities.notifyAction(SwingUtilities.java:1668)
	at javax.swing.JComponent.processKeyBinding(JComponent.java:2876)
	at javax.swing.JComponent.processKeyBindings(JComponent.java:2937)
	at javax.swing.JComponent.processKeyEvent(JComponent.java:2839)
	at java.awt.Component.processEvent(Component.java:6316)
	at java.awt.Container.processEvent(Container.java:2239)
	at java.awt.Component.dispatchEventImpl(Component.java:4889)
	at java.awt.Container.dispatchEventImpl(Container.java:2297)
	at java.awt.Component.dispatchEvent(Component.java:4711)
	at java.awt.KeyboardFocusManager.redispatchEvent(KeyboardFocusManager.java:1954)
	at java.awt.DefaultKeyboardFocusManager.dispatchKeyEvent(DefaultKeyboardFocusManager.java:835)
	at java.awt.DefaultKeyboardFocusManager.preDispatchKeyEvent(DefaultKeyboardFocusManager.java:1103)
	at java.awt.DefaultKeyboardFocusManager.typeAheadAssertions(DefaultKeyboardFocusManager.java:974)
	at java.awt.DefaultKeyboardFocusManager.dispatchEvent(DefaultKeyboardFocusManager.java:800)
	at java.awt.Component.dispatchEventImpl(Component.java:4760)
	at java.awt.Container.dispatchEventImpl(Container.java:2297)
	at java.awt.Window.dispatchEventImpl(Window.java:2746)
	at java.awt.Component.dispatchEvent(Component.java:4711)
	at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:760)
	at java.awt.EventQueue.access$500(EventQueue.java:97)
	at java.awt.EventQueue$3.run(EventQueue.java:709)
	at java.awt.EventQueue$3.run(EventQueue.java:703)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:74)
	at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:84)
	at java.awt.EventQueue$4.run(EventQueue.java:733)
	at java.awt.EventQueue$4.run(EventQueue.java:731)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:74)
	at java.awt.EventQueue.dispatchEvent(EventQueue.java:730)
	at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:205)
	at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116)
	at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105)
	at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
	at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93)
	at java.awt.EventDispatchThread.run(EventDispatchThread.java:82)

I checked and it is here:

final int color = setup.getColor().get();

within getSourceConverterConfigs.

For the SAC where it crashed it shows:

image

Maybe you could change the code such that it does not try to get the color if it does not support colors?

Note that this SAC is one that MoBIE builds for a label image, where I don't use the normal ColorConverter.

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.

4 participants