Skip to content

OBF: Support complex data stacks#4362

Open
ngladitz wants to merge 1 commit intoome:developfrom
ngladitz:obf-complex
Open

OBF: Support complex data stacks#4362
ngladitz wants to merge 1 commit intoome:developfrom
ngladitz:obf-complex

Conversation

@ngladitz
Copy link
Member

This is intended to add support for OBF complex number image pixel data.

I've attached a corresponding simulated test dataset here:
IMG0005_Lifetime3.zip

The OME XML schema has a PixelType "complex" which the dataset does use but bioformats and imagej presumably have no direct support for it. I tried to work around that here by making it look like each pixel has two interleaved float samples.

It beats not being able to open the file at all but I am not entirely happy with the result.
I would appreciate any insights into how this might be improved or done differently.

@sbesson
Copy link
Member

sbesson commented Sep 2, 2025

@ngladitz thanks for opening the PR and starting this conversation. Could you upload your sample file to the Zenodo Bio-Formats community so that it can be used with the proper licensing/attribution?

As you already found out, complex and double-complex are valid PixelType enums in the OME schema but the Bio-Formats APIs such as FormatTools currently lack support for these types. Most readers detecting imaging data with complex pixel types currently throw a FormatException. See also some relevant past discussions at #1105

It would be useful to know more about the workflow of how you would expect this data to be read and displayed in a downstream application. Is your target one of the built-in tools, either the Bio-Formats command-line utility or the ImageJ/Fiji plugin or are you using the API in your own library?

@ngladitz
Copy link
Member Author

ngladitz commented Sep 2, 2025

@sbesson thanks I've re-uploaded the file via Zenodo (this is my first such upload so let me know if my submission looks OK. I hope I triggered the process correctly and you actually see my submission. I am unsure if there is a link I could / should have shared while the file is still in the review process).

Workflow wise I think most important might be that the presence of complex data within an OBF does not prevent users from accessing any non-complex data within the file. The sample file contains both regular / already supported intensity data as well as complex data but as-is the file can not be opened in ImageJ / Fiji at all due to the reader failing on complex data.

Beyond that I ideally would like users to be able to access the complex data as well of course. Any way they like or need for their own use cases or at least as far as is possible with the tools as they are. We don't currently have any internal workflows where this would play a direct role. Our own software implements this independently but is C++ and proprietary.

@melissalinkert
Copy link
Member

Thanks, @ngladitz, we have received and approved https://zenodo.org/records/17039369.

@ngladitz
Copy link
Member Author

@sbesson Is there anything else I should do to move this forward?

@sbesson
Copy link
Member

sbesson commented Sep 30, 2025

@ngladitz we discussed this PR as part of our Formats meeting 2 weeks ago and I hadn't updated this PR with the summary. Thanks for reminding me.

From the perspective of Bio-Formats and generally the OME stack, we discussed various options, which are ordered from the most expensive to the cheapest:

  1. properly represent complex data in Bio-Formats
  2. represent complex images using existing strategies for additional dimensionalities
    a. the modulo annotation
    b. the interleaved flag (current proposal)
  3. eliminate complex images fully from the reader initialization

Option 1 is mostly listed for completeness, this is a stack wide effort that we are not planning currently. Options 2 and 3 could additionally be activated using reader options to enable some partial support of OBF files with complex images.

@ngladitz
Copy link
Member Author

ngladitz commented Oct 1, 2025

@sbesson thank you for the update.

I am not sure I understand why a reader option would be desirable in this context.

Assuming you'd use it to opt into the complex data workaround anyone not using the option would not be able to open the dataset by default. Presumably nobody gains anything from not being able to open the dataset so why wouldn't that be the default. The other way around I can't imagine anyone wanting to opt into failure either. In the foreseeable future some of our systems will produce acquisitions with complex data by default so I'd really like them to be openable by default too.

Option 1 would obviously be ideal but I can certainly see that not being trivial or realistically on the horizon nor would it help short term.

Option 3 I don't really like because I assume it would just add to confusion and might break stack identification / indexing. Assuming a dataset with 3 stacks where the middle one is complex I'd prefer if index 1 would refer to the same stack when using Bioformats vs. other readers. Also presumably some customers might genuinely want to access the data.

Option 2 I would like to reiterate that metadata wise this can and is already being properly encoded by using the complex PixelType. Adding alternative / competing metadata via e.g. modulo annotation for this feels counterproductive. Me mutating or coercing the metadata in the Bioformats reader (rather than in the dataset) is a workaround to make this work with the existing infrastructure. The workaround is not necessarily required in other readers and the metadata is already sufficient for them as-is and also feels like the most correct.

TLDR If I have a vote I'd prefer option 2 without a reader option

@sbesson
Copy link
Member

sbesson commented Oct 6, 2025

Thanks @ngladitz. Our next step is going to evaluate the current proposal in the context of OMERO/OMERO Plus and assess how OBF datasets with different data types including complex would be ingested and rendered with the new proposed behavior. We will report our findings probably by the end of October.

If you have additional sample files that would capture the diversity of data that can be generated by the instrument and could be used for this evaluation, do not hesitate to upload them to Zenodo.


private int getPixelType(int type) throws FormatException {
switch (type) {
switch (type & 0xFFFFFFF) {
Copy link

Choose a reason for hiding this comment

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

I don't understand why type & 0xFFFFFFF. Is it worth adding a comment to make it clear? :)

Copy link
Member Author

Choose a reason for hiding this comment

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

@gerring In theory any non-complex OBF pixel type (e.g. "float") can be turned into a complex pixel type (e.g. "complex float") by additionally setting the complex bit (0x40000000). The mask is intended to return the underlying pixel type without the complex bit (both "complex float" and "float" become "float").

There are unused / undefined bits between the complex bit and the currently defined types so right now the mask could also be e.g. 0x3FFFFFFF.

Also I say in theory because I assume we'll never see e.g. "complex bool".
Currently I only really care about "complex float" though I also covered "complex double".

The values and their meaning is documented here https://imspectordocs.readthedocs.io/en/latest/fileformat.html#the-obf-file-format

A reference to that documentation is also included at the top of the source file.

@sbesson
Copy link
Member

sbesson commented Oct 27, 2025

@ngladitz I got back to this and tried to used this patch to import the sample file uploaded to https://zenodo.org/records/17039369 in an OMERO environment with a modified version of OBFReader.

Unfortunately, the import failed server-side side while storing the OME metadata the database with the following exception:

$ omero import /mnt/bioformats_test_data/automated-tests/curated/obf/public/zenodo-17039369/IMG0005_Lifetime3.obf
...
2025-10-27 11:22:53,931 3188       [2-thread-1] INFO   ormats.importer.cli.LoggingImportMonitor - FILESET_UPLOAD_END
2025-10-27 11:22:54,032 3289       [2-thread-1] INFO   ormats.importer.cli.LoggingImportMonitor - IMPORT_STARTED Logfile: 1049750
2025-10-27 11:22:54,369 3626       [l.Client-1] ERROR     ome.formats.importer.cli.ErrorHandler - INTERNAL_EXCEPTION: /mnt/bioformats_test_data/automated-tests/curated/obf/public/zenodo-17039369/IMG0005_Lifetime3.obf
java.lang.RuntimeException: Failure response on import!
Category: ::omero::grid::ImportRequest
Name: import-request-failure
Parameters: {stacktrace=java.lang.RuntimeException: omero.ValidationException
    serverStackTrace = "ome.conditions.ValidationException: not-null property references a null or transient value: ome.model.containers.Folder.name; nested exception is org.hibernate.PropertyValueException: not-null property references a null or transient value: ome.model.containers.Folder.name
                        	at org.springframework.orm.hibernate3.SessionFactoryUtils.convertHibernateAccessException(SessionFactoryUtils.java:681)
                        	at org.springframework.orm.hibernate3.HibernateAccessor.convertHibernateAccessException(HibernateAccessor.java:416)
                        	at org.springframework.orm.hibernate3.HibernateInterceptor.invoke(HibernateInterceptor.java:125)
                        	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
                        	at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:99)
                        	at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:283)
                        	at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
                        	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
                        	at ome.tools.hibernate.ProxyCleanupFilter$Interceptor.invoke(ProxyCleanupFilter.java:249)
                        	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
                        	at ome.services.util.ServiceHandler.invoke(ServiceHandler.java:121)
                        	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
                        	at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:213)
                        	at com.sun.proxy.$Proxy74.doWork(Unknown Source)
                        	at ome.services.util.Executor$Impl.execute(Executor.java:447)
                        	at ome.services.util.Executor$Impl.execute(Executor.java:392)
                        	at ome.services.throttling.Adapter.run(Adapter.java:50)
                        	at ome.services.throttling.InThreadThrottlingStrategy.runnableCall(InThreadThrottlingStrategy.java:89)
                        	at ome.services.blitz.impl.AbstractAmdServant.runnableCall(AbstractAmdServant.java:154)
                        	at ome.services.blitz.impl.MetadataStoreI.saveToDB_async(MetadataStoreI.java:208)
                        	at jdk.internal.reflect.GeneratedMethodAccessor1820.invoke(Unknown Source)
                        	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
                        	at java.base/java.lang.reflect.Method.invoke(Method.java:566)
                        	at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:333)
                        	at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190)
                        	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
                        	at omero.cmd.CallContext.invoke(CallContext.java:85)
                        	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
                        	at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:213)
                        	at com.sun.proxy.$Proxy122.saveToDB_async(Unknown Source)
                        	at omero.api._MetadataStoreTie.saveToDB_async(_MetadataStoreTie.java:84)
                        	at omero.api._MetadataStoreDisp.___saveToDB(_MetadataStoreDisp.java:258)
                        	at omero.api._MetadataStoreDisp.__dispatch(_MetadataStoreDisp.java:416)
                        	at IceInternal.Incoming.invoke(Incoming.java:221)
                        	at Ice.ConnectionI.invokeAll(ConnectionI.java:2536)
                        	at Ice.ConnectionI.dispatch(ConnectionI.java:1145)
                        	at Ice.ConnectionI.message(ConnectionI.java:1056)
                        	at IceInternal.ThreadPool.run(ThreadPool.java:395)
                        	at IceInternal.ThreadPool.access$300(ThreadPool.java:12)
                        	at IceInternal.ThreadPool$EventHandlerThread.run(ThreadPool.java:832)
                        	at java.base/java.lang.Thread.run(Thread.java:829)
                        "
    serverExceptionClass = "ome.conditions.ValidationException"
..

Looking at the metadata of the file with the command-line utilities, I believe the above is unrelated to the complex type support but instead due to the usage of Folder in the metadata. Specifically, running showinf -omexml yields the following:

   <Folder ID="Folder:Sample" Name="Lifetime3">
      <FolderRef ID="Folder:Region"/>
   </Folder>
   <Folder ID="Folder:Region" Name="IMG0005_Lifetime3">
      <FolderRef ID="Folder:Timepoint"/>
   </Folder>
   <Folder ID="Folder:Timepoint">
      <ImageRef ID="Image:3"/>
      <ImageRef ID="Image:4"/>
      <ImageRef ID="Image:5"/>
      <ImageRef ID="Image:0"/>
      <ImageRef ID="Image:1"/>
      <ImageRef ID="Image:2"/>
   </Folder>

Using this metadata in OME-XML sample files suggests the issue comes with the fact that <Folder ID="Folder:Timepoint"> does not have a Name property. This is valid according to the OME specification but the importer is expecting this to present. Would you be able to regenerate another version of the sample OBF file with the Name attribute set for all Folder elements?

@ngladitz
Copy link
Member Author

@sbesson Thank you for testing. I've uploaded / submitted a new dataset to Zenodo with the Name attribute set for all Folders.

case 0x20: return 32;
case 0x40: return 32;
case 0x80: return 64;
case 0x40000040: return 64;
Copy link
Member

Choose a reason for hiding this comment

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

This implementation creates a mismatch between the pixeltype returned by getPixelType (float or double as per the previous API) and the number of bits per pixel returned by this API.

This results in buffer size issues when calling openBytes e.g. when importing into OMERO:

java.lang.RuntimeException: Failure response on import!
Category: ::omero::grid::ImportRequest
Name: import-file-exception
Parameters: {filename=import.user_2/2025-10/28/08-37-25.231/IMG0002_Lifetime3.obf, stacktrace=loci.formats.FormatException: Buffer too small (got 75012, expected 150024).
	at loci.formats.FormatTools.checkBufferSize(FormatTools.java:1048)
	at loci.formats.FormatTools.checkPlaneParameters(FormatTools.java:1004)
	at loci.formats.in.OBFReader.openBytes(OBFReader.java:1006)
	at loci.formats.ImageReader.openBytes(ImageReader.java:466)
	at loci.formats.ChannelFiller.openBytes(ChannelFiller.java:169)
	at loci.formats.ChannelSeparator.openBytes(ChannelSeparator.java:231)
	at loci.formats.ReaderWrapper.openBytes(ReaderWrapper.java:350)
	at loci.formats.ReaderWrapper.openBytes(ReaderWrapper.java:350)
	at loci.formats.MinMaxCalculator.openBytes(MinMaxCalculator.java:269)
	at ome.services.blitz.repo.ManagedImportRequestI.parseDataByPlane(ManagedImportRequestI.java:872)
	at ome.services.blitz.repo.ManagedImportRequestI.parseData(ManagedImportRequestI.java:803)
	at ome.services.blitz.repo.ManagedImportRequestI.pixelData(ManagedImportRequestI.java:676)
	at ome.services.blitz.repo.ManagedImportRequestI.step(ManagedImportRequestI.java:525)

Either these lines need to be updated to 32 and 64 respectively or the check on type on line 634 needs to be updated to switch(type & 0xFFFFFFF) as in getPixelType

Copy link
Member Author

Choose a reason for hiding this comment

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

@sbesson Thank you. I am not sure I understand. It did seem to work as-is (at least in this context) with ImageJ. The correct buffer size seems to get allocated in that case. The images can be opened and inspected.

The values returned feel correct. A single complex float pixel is 64 bit (2 components with 32bit each).
Maybe not all call paths calculate the require buffer size the same way?

image

Copy link
Member

Choose a reason for hiding this comment

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

I think the primary difference is the addition of the ChannelSeparator API in the stack. The exception above can be reproduced more simply using the Bio-Formats command-line tools with the -separate option:

sbesson@Sebastien-GS-MacBook-Pro-2025 bioformats % ./tools/showinf -series 2 ~/Downloads/IMG0002_Lifetime3.obf -separate
Checking file format [OBF]
Initializing reader
OBFReader initializing /Users/sbesson/Downloads/IMG0002_Lifetime3.obf
Parsing schema path
http://www.openmicroscopy.org/Schemas/OME/2016-06/ome.xsd
Validating OME-XML
No validation errors found.
Initialization took 0.27s

Reading core metadata
filename = /Users/sbesson/Downloads/IMG0002_Lifetime3.obf
Series count = 9
Series #0 :
	Image count = 1
	RGB = false (1) (separated)
	Interleaved = false
	Indexed = false (false color)
	Width = 141
	Height = 133
	SizeZ = 1
	SizeT = 1
	SizeC = 1
	Tile size = 141 x 133
	Thumbnail size = 128 x 120
	Endianness = intel (little)
	Dimension order = XYZTC (certain)
	Pixel type = uint16
	Valid bits per pixel = 16
	Metadata complete = false
	Thumbnail series = false
	-----
	Plane #0 <=> Z 0, C 0, T 0

Series #1 :
	Image count = 1
	RGB = false (1) (separated)
	Interleaved = false
	Indexed = false (false color)
	Width = 141
	Height = 133
	SizeZ = 1
	SizeT = 1
	SizeC = 1
	Tile size = 141 x 133
	Thumbnail size = 128 x 120
	Endianness = intel (little)
	Dimension order = XYZTC (certain)
	Pixel type = uint16
	Valid bits per pixel = 16
	Metadata complete = false
	Thumbnail series = false
	-----
	Plane #0 <=> Z 0, C 0, T 0

Series #2 :
	Image count = 1
	RGB = false (2) (separated)
	************ RGB mismatch ************
	Interleaved = true
	Indexed = false (false color)
	Width = 141
	Height = 133
	SizeZ = 1
	SizeT = 1
	SizeC = 2 (effectively 1)
	Tile size = 141 x 133
	Thumbnail size = 128 x 120
	Endianness = intel (little)
	Dimension order = XYZTC (certain)
	Pixel type = float
	Valid bits per pixel = 64
	Metadata complete = false
	Thumbnail series = false
	-----
	Plane #0 <=> Z 0, C 0, T 0

Series #3 :
	Image count = 1
	RGB = false (1) (separated)
	Interleaved = false
	Indexed = false (false color)
	Width = 141
	Height = 133
	SizeZ = 1
	SizeT = 1
	SizeC = 1
	Tile size = 141 x 133
	Thumbnail size = 128 x 120
	Endianness = intel (little)
	Dimension order = XYZTC (certain)
	Pixel type = uint16
	Valid bits per pixel = 16
	Metadata complete = false
	Thumbnail series = false
	-----
	Plane #0 <=> Z 0, C 0, T 0

Series #4 :
	Image count = 1
	RGB = false (1) (separated)
	Interleaved = false
	Indexed = false (false color)
	Width = 141
	Height = 133
	SizeZ = 1
	SizeT = 1
	SizeC = 1
	Tile size = 141 x 133
	Thumbnail size = 128 x 120
	Endianness = intel (little)
	Dimension order = XYZTC (certain)
	Pixel type = uint16
	Valid bits per pixel = 16
	Metadata complete = false
	Thumbnail series = false
	-----
	Plane #0 <=> Z 0, C 0, T 0

Series #5 :
	Image count = 1
	RGB = false (2) (separated)
	************ RGB mismatch ************
	Interleaved = true
	Indexed = false (false color)
	Width = 141
	Height = 133
	SizeZ = 1
	SizeT = 1
	SizeC = 2 (effectively 1)
	Tile size = 141 x 133
	Thumbnail size = 128 x 120
	Endianness = intel (little)
	Dimension order = XYZTC (certain)
	Pixel type = float
	Valid bits per pixel = 64
	Metadata complete = false
	Thumbnail series = false
	-----
	Plane #0 <=> Z 0, C 0, T 0

Series #6 :
	Image count = 1
	RGB = false (1) (separated)
	Interleaved = false
	Indexed = false (false color)
	Width = 141
	Height = 133
	SizeZ = 1
	SizeT = 1
	SizeC = 1
	Tile size = 141 x 133
	Thumbnail size = 128 x 120
	Endianness = intel (little)
	Dimension order = XYZTC (certain)
	Pixel type = uint16
	Valid bits per pixel = 16
	Metadata complete = false
	Thumbnail series = false
	-----
	Plane #0 <=> Z 0, C 0, T 0

Series #7 :
	Image count = 1
	RGB = false (1) (separated)
	Interleaved = false
	Indexed = false (false color)
	Width = 141
	Height = 133
	SizeZ = 1
	SizeT = 1
	SizeC = 1
	Tile size = 141 x 133
	Thumbnail size = 128 x 120
	Endianness = intel (little)
	Dimension order = XYZTC (certain)
	Pixel type = uint16
	Valid bits per pixel = 16
	Metadata complete = false
	Thumbnail series = false
	-----
	Plane #0 <=> Z 0, C 0, T 0

Series #8 :
	Image count = 1
	RGB = false (2) (separated)
	************ RGB mismatch ************
	Interleaved = true
	Indexed = false (false color)
	Width = 141
	Height = 133
	SizeZ = 1
	SizeT = 1
	SizeC = 2 (effectively 1)
	Tile size = 141 x 133
	Thumbnail size = 128 x 120
	Endianness = intel (little)
	Dimension order = XYZTC (certain)
	Pixel type = float
	Valid bits per pixel = 64
	Metadata complete = false
	Thumbnail series = false
	-----
	Plane #0 <=> Z 0, C 0, T 0


Reading series #2 pixel data (0-0)
Exception in thread "main" loci.formats.FormatException: Buffer too small (got 75012, expected 150024).
	at loci.formats.FormatTools.checkBufferSize(FormatTools.java:1048)
	at loci.formats.FormatTools.checkPlaneParameters(FormatTools.java:1004)
	at loci.formats.in.OBFReader.openBytes(OBFReader.java:1006)
	at loci.formats.ImageReader.openBytes(ImageReader.java:466)
	at loci.formats.ChannelSeparator.openBytes(ChannelSeparator.java:231)
	at loci.formats.ChannelSeparator.openBytes(ChannelSeparator.java:163)
	at loci.formats.ReaderWrapper.openBytes(ReaderWrapper.java:336)
	at loci.formats.gui.BufferedImageReader.openImage(BufferedImageReader.java:86)
	at loci.formats.tools.ImageInfo.readPixels(ImageInfo.java:840)
	at loci.formats.tools.ImageInfo.testRead(ImageInfo.java:1074)
	at loci.formats.tools.ImageInfo.main(ImageInfo.java:1165)

Note also the RGB mismatch warnings in the output above which suggests the value of the CoreMetadata.rgb flag should be conditional depending on the value of CoreMetadata.interleaved with this strategy

Copy link
Member Author

Choose a reason for hiding this comment

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

@sbesson Thank you! Does this work for you as well?

diff --git a/components/formats-bsd/src/loci/formats/in/OBFReader.java b/components/formats-bsd/src/loci/formats/in/OBFReader.java
index 5cc5b87e3d..ccadbacf3d 100644
--- a/components/formats-bsd/src/loci/formats/in/OBFReader.java
+++ b/components/formats-bsd/src/loci/formats/in/OBFReader.java
@@ -386,7 +386,7 @@ public class OBFReader extends FormatReader {
       stack.bytesPerSample = meta_data.bitsPerPixel / 8;
 
       meta_data.indexed = false;
-      meta_data.rgb = false;
+      meta_data.rgb = meta_data.interleaved;
 
       final int compression = in.readInt();
       stack.compression = getCompression(compression);

As you suggested it does seem to make ChannelSeparator happy:
image

Of course the data isn't actually RGB and without ChannelSeparator the results are a little less desirable:
image

image

(The channel slider does nothing here)

I see I can opt into the channel separation from the import dialog in ImageJ and that results in something perhaps slightly more desirable:
image

I would be OK with this. Assuming it also resolves the OMERO import issue.

Copy link
Member

Choose a reason for hiding this comment

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

Hi @ngladitz. From a round of testing, setting the rgb flag as you proposed yields sensible results both in the command-line tools as well and the image import into OMERO (the channel color is off which will warrant separate investigation)

Screenshot 2025-11-03 at 09 02 56

Feel free to push your change to this PR so that we can check the impact on already configured OBF datasets in the nightly CI repositories.

Discussing with @melissalinkert, the change to getBitsPerPixel to return 64/128 for complex data still comes a surprise as it contradicts the API expectation as defined in

/**
* Gets the number of valid bits per pixel. The number of valid bits per
* pixel is always less than or equal to the number of bits per pixel
* that correspond to {@link #getPixelType()}.
*/
. This will need additional investigation on our end.

Copy link
Member Author

Choose a reason for hiding this comment

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

@sbesson Thank you! I pushed the change.

@ngladitz
Copy link
Member Author

ngladitz commented Jan 5, 2026

@sbesson happy new year! Gentle poke ... any updates?

@melissalinkert melissalinkert added this to the 9.0.0 milestone Jan 12, 2026
@melissalinkert
Copy link
Member

Thanks @ngladitz - we still have a couple of things to investigate here, and will update as soon as we've had time to finish that investigation. This pull request is now scheduled for the 9.0.0 release later this year.

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